aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>2009-06-17 10:25:20 +0000
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>2009-06-17 10:25:20 +0000
commit8cd89b7368988067be99bca4cfc4c81fb419a6e2 (patch)
tree0f1ea28e50a627f629174a2bab4cfceac7ebd55f
parente2747d8e52fb729f8c3f0587ba78d6a9f9b557de (diff)
Merged with gcc-4_4-branch@148582.var-tracking-assignments-4_4-merge-148582-after
* rtl.def (VALUE): Move up. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/var-tracking-assignments-4_4-branch@148591 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog302
-rw-r--r--gcc/ChangeLog.vta5
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in3
-rw-r--r--gcc/builtins.c2
-rw-r--r--gcc/cfgrtl.c17
-rw-r--r--gcc/config/arm/arm.c6
-rw-r--r--gcc/config/arm/arm.md2
-rw-r--r--gcc/config/i386/driver-i386.c55
-rw-r--r--gcc/config/i386/i386.c10
-rw-r--r--gcc/config/i386/linux.h4
-rw-r--r--gcc/config/i386/sol2.h8
-rw-r--r--gcc/config/i386/x86-64.h4
-rw-r--r--gcc/config/rs6000/rs6000-c.c8
-rw-r--r--gcc/config/s390/s390.md2
-rw-r--r--gcc/config/sh/sh.c2
-rw-r--r--gcc/config/sh/sh.md43
-rw-r--r--gcc/config/vax/vax.c2
-rw-r--r--gcc/cp/ChangeLog59
-rw-r--r--gcc/cp/call.c56
-rw-r--r--gcc/cp/decl.c4
-rw-r--r--gcc/cp/decl2.c1
-rw-r--r--gcc/cp/parser.c26
-rw-r--r--gcc/cp/semantics.c20
-rw-r--r--gcc/cp/typeck.c36
-rw-r--r--gcc/doc/extend.texi1
-rw-r--r--gcc/doc/gccint.texi2
-rw-r--r--gcc/doc/passes.texi80
-rw-r--r--gcc/doc/rtl.texi8
-rw-r--r--gcc/dse.c1
-rw-r--r--gcc/dwarf2out.c89
-rw-r--r--gcc/expr.c3
-rw-r--r--gcc/fold-const.c8
-rw-r--r--gcc/fortran/ChangeLog70
-rw-r--r--gcc/fortran/data.c6
-rw-r--r--gcc/fortran/module.c8
-rw-r--r--gcc/fortran/simplify.c5
-rw-r--r--gcc/fortran/trans-array.c9
-rw-r--r--gcc/fortran/trans-decl.c15
-rw-r--r--gcc/fortran/trans-expr.c64
-rw-r--r--gcc/fortran/trans-intrinsic.c116
-rw-r--r--gcc/fortran/trans-stmt.c60
-rw-r--r--gcc/fortran/trans-stmt.h2
-rw-r--r--gcc/fortran/trans-types.c2
-rw-r--r--gcc/fortran/trans-types.h1
-rw-r--r--gcc/fortran/trans.c6
-rw-r--r--gcc/fortran/trans.h5
-rw-r--r--gcc/gimple.h78
-rw-r--r--gcc/gimplify.c61
-rw-r--r--gcc/ipa-utils.h3
-rw-r--r--gcc/reg-stack.c24
-rw-r--r--gcc/resource.c55
-rw-r--r--gcc/rtl.def14
-rw-r--r--gcc/testsuite/ChangeLog339
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto14.C29
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto15.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted10.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum3.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist13.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist15.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist16.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist17.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist18.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist19.C8
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/nested-1.C29
-rw-r--r--gcc/testsuite/g++.dg/eh/nested-try.C25
-rw-r--r--gcc/testsuite/g++.dg/ext/packed6.C2
-rw-r--r--gcc/testsuite/g++.dg/opt/memcpy1.C2
-rw-r--r--gcc/testsuite/g++.dg/other/pr40446.C46
-rw-r--r--gcc/testsuite/g++.dg/pr37742.C2
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-1.C18
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-2.C18
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-3.C20
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-4.C22
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-5.C22
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-6.C22
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-7.C21
-rw-r--r--gcc/testsuite/g++.dg/template/dtor6.C10
-rw-r--r--gcc/testsuite/g++.dg/template/dtor7.C24
-rw-r--r--gcc/testsuite/g++.dg/template/error41.C12
-rw-r--r--gcc/testsuite/g++.dg/template/error42.C20
-rw-r--r--gcc/testsuite/g++.dg/template/typedef18.C24
-rw-r--r--gcc/testsuite/g++.dg/template/typedef19.C21
-rw-r--r--gcc/testsuite/g++.dg/template/typedef20.C27
-rw-r--r--gcc/testsuite/g++.dg/torture/20070621-1.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/pr32950.C19
-rw-r--r--gcc/testsuite/g++.dg/torture/pr34222.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/pr34850.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/pr40335.C16
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr22444.C4
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-4.C22
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-5.C22
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/array1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/crash64.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/new3.C2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20000211-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20010328-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20030320-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20030405-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20030902-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20060202-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20080613-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20090519-1.c11
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/920428-2.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/980329-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/980816-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr32584.c7
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr33173.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr33382.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr34334.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr34688.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr35043.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr37669.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr39999.c18
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr40026.c15
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr40035.c20
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr40080.c44
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr40204.c14
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr40233.c10
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr40252.c6
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr40291.c7
-rw-r--r--gcc/testsuite/gcc.dg/20050629-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr33667.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr39666-1.c22
-rw-r--r--gcc/testsuite/gcc.dg/pr39666-2.c22
-rw-r--r--gcc/testsuite/gcc.dg/pr40172-1.c31
-rw-r--r--gcc/testsuite/gcc.dg/pr40172-2.c16
-rw-r--r--gcc/testsuite/gcc.dg/pr40172-3.c16
-rw-r--r--gcc/testsuite/gcc.dg/pr40340-1.c24
-rw-r--r--gcc/testsuite/gcc.dg/pr40340-2.c16
-rw-r--r--gcc/testsuite/gcc.dg/pr40340-3.c15
-rw-r--r--gcc/testsuite/gcc.dg/pr40340-4.c16
-rw-r--r--gcc/testsuite/gcc.dg/pr40340-5.c17
-rw-r--r--gcc/testsuite/gcc.dg/pr40340.h31
-rw-r--r--gcc/testsuite/gcc.dg/prefetch-loop-arrays-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr39204.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr40328.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr36908.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr38250.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr40087.c30
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr40074.c54
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr40238.c35
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr40254.c39
-rw-r--r--gcc/testsuite/gcc.target/i386/pr39543-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-30.c32
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-31.c29
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-types-1.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/asm-support.S2
-rw-r--r--gcc/testsuite/gfortran.dg/alloc_comp_assign_10.f9061
-rw-r--r--gcc/testsuite/gfortran.dg/array_constructor_31.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/array_memset_2.f906
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/backspace_11.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/chmod_1.f903
-rw-r--r--gcc/testsuite/gfortran.dg/chmod_2.f903
-rw-r--r--gcc/testsuite/gfortran.dg/chmod_3.f903
-rw-r--r--gcc/testsuite/gfortran.dg/default_format_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/default_format_denormal_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/dependency_24.f9082
-rw-r--r--gcc/testsuite/gfortran.dg/leadz_trailz_1.f90133
-rw-r--r--gcc/testsuite/gfortran.dg/leadz_trailz_2.f9036
-rw-r--r--gcc/testsuite/gfortran.dg/open_errors.f903
-rw-r--r--gcc/testsuite/gfortran.dg/pr39666-1.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/pr39666-2.f9014
-rw-r--r--gcc/testsuite/lib/target-supports.exp5
-rw-r--r--gcc/tree-ssa-forwprop.c36
-rw-r--r--gcc/tree-ssa-live.c29
-rw-r--r--gcc/tree-ssa-loop-niter.c109
-rw-r--r--gcc/tree-ssa-sccvn.c6
-rw-r--r--gcc/tree-vect-analyze.c9
-rw-r--r--gcc/tree.c30
-rw-r--r--gcc/tree.h5
-rw-r--r--gnattools/ChangeLog6
-rw-r--r--gnattools/Makefile.in2
-rw-r--r--libgfortran/ChangeLog356
-rw-r--r--libgfortran/Makefile.am1
-rw-r--r--libgfortran/Makefile.in21
-rw-r--r--libgfortran/gfortran.map7
-rw-r--r--libgfortran/intrinsics/bit_intrinsics.c138
-rw-r--r--libgfortran/io/fbuf.c257
-rw-r--r--libgfortran/io/file_pos.c80
-rw-r--r--libgfortran/io/format.c76
-rw-r--r--libgfortran/io/intrinsics.c51
-rw-r--r--libgfortran/io/io.h142
-rw-r--r--libgfortran/io/list_read.c116
-rw-r--r--libgfortran/io/open.c15
-rw-r--r--libgfortran/io/read.c496
-rw-r--r--libgfortran/io/transfer.c1285
-rw-r--r--libgfortran/io/unit.c77
-rw-r--r--libgfortran/io/unix.c1060
-rw-r--r--libgfortran/io/write.c79
-rw-r--r--libgfortran/io/write_float.def9
-rw-r--r--libgfortran/libgfortran.h7
-rw-r--r--libgfortran/runtime/backtrace.c2
-rw-r--r--libgfortran/runtime/error.c41
-rw-r--r--libgomp/ChangeLog6
-rw-r--r--libgomp/team.c2
-rw-r--r--libjava/ChangeLog11
-rw-r--r--libjava/Makefile.am6
-rw-r--r--libjava/Makefile.in6
-rw-r--r--libjava/classpath/ChangeLog.gcj10
-rw-r--r--libjava/classpath/tools/classes/gnu/classpath/tools/doclets/htmldoclet/HtmlDoclet.classbin80179 -> 79930 bytes
-rw-r--r--libjava/classpath/tools/classes/gnu/classpath/tools/gjdoc/Main.classbin29564 -> 29338 bytes
-rw-r--r--libjava/classpath/tools/gnu/classpath/tools/doclets/htmldoclet/HtmlDoclet.java15
-rw-r--r--libjava/classpath/tools/gnu/classpath/tools/gjdoc/Main.java11
-rw-r--r--libstdc++-v3/ChangeLog57
-rw-r--r--libstdc++-v3/include/Makefile.am2
-rw-r--r--libstdc++-v3/include/Makefile.in2
-rw-r--r--libstdc++-v3/include/bits/stl_construct.h25
-rw-r--r--libstdc++-v3/include/ext/memory12
-rw-r--r--libstdc++-v3/include/parallel/algo.h4
-rw-r--r--libstdc++-v3/include/std/thread4
-rw-r--r--libstdc++-v3/libsupc++/eh_ptr.cc6
-rw-r--r--libstdc++-v3/libsupc++/exception_ptr.h15
-rw-r--r--libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc30
-rw-r--r--libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc6
-rw-r--r--libstdc++-v3/testsuite/18_support/exception_ptr/move.cc45
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/40192.cc28
-rw-r--r--libstdc++-v3/testsuite/25_algorithms/find/39546.cc43
-rw-r--r--libstdc++-v3/testsuite/ext/rope/40299.cc27
-rw-r--r--libstdc++-v3/testsuite/lib/libstdc++.exp3
223 files changed, 5887 insertions, 2550 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fed7b3c8897..84fe0342d18 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,71 +1,237 @@
-2009-06-17 Jakub Jelinek <jakub@redhat.com>
-
- * dwarf2out.c (last_var_location_insn): New variable.
- (dwarf2out_end_epilogue): Clear last_var_location_insn.
- (dwarf2out_var_location): Don't record anything after last real
- insn. Only change labels if there were any real instructions
- in between last note and this one, or if changed sections.
-
-2009-06-11 Ian Lance Taylor <iant@google.com>
-
- * vec.h (DEF_VEC_ALLOC_I): Use DEF_VEC_NONALLOC_FUNCS_I.
- (DEF_VEC_ALLOC_P): Use DEF_VEC_NONALLOC_FUNCS_P.
- (DEF_VEC_ALLOC_O): Use DEF_VEC_NONALLOC_FUNCS_O.
- (DEF_VEC_ALLOC_FUNC_P): Only define VEC_OP (T,A,alloc).
- (DEF_VEC_NONALLOC_FUNCS_P): New macro, broken out of old
- DEF_VEC_ALLOC_FUNC_P.
- (DEF_VEC_ALLOC_FUNC_O): Only define VEC_OP (T,A,alloc).
- (DEF_VEC_NONALLOC_FUNCS_O): New macro, broken out of old
- DEF_VEC_ALLOC_FUNC_O.
- (DEF_VEC_ALLOC_FUNC_I): Only define VEC_OP (T,A,alloc).
- (DEF_VEC_NONALLOC_FUNCS_I): New macro, broken out of old
- DEF_VEC_ALLOC_FUNC_I.
- (vec_stack_p_reserve, vec_stack_p_reserve_exact): Declare.
- (vec_stack_p_reserve_exact_1): Declare.
- (vec_stack_o_reserve, vec_stack_o_reserve_exact): Declare.
- (vec_stack_free): Declare.
- (VEC_stack_alloc): Define.
- (DEF_VEC_ALLOC_P_STACK, DEF_VEC_ALLOC_FUNC_P_STACK): Define.
- (DEF_VEC_ALLOC_O_STACK, DEF_VEC_ALLOC_FUNC_O_STACK): Define.
- (DEF_VEC_ALLOC_I_STACK, DEF_VEC_ALLOC_FUNC_I_STACK): Define.
- * vec.c (void_p): New type. Call DEF_VEC_P and DEF_VEC_ALLOC_P
- for void_p.
- (stack_vecs): New static variable.
- (vec_stack_p_reserve_exact_1): New function.
- (vec_stack_o_reserve_1): New static function.
- (vec_stack_p_reserve, vec_stack_p_reserve_exact): New functions.
- (vec_stack_o_reserve, vec_stack_o_reserve_exact): New functions.
- (vec_stack_free): New function.
- * df-scan.c (df_ref): Use DEF_VEC_P and DEF_VEC_ALLOC_P_STACK.
- (VEC_df_ref_stack_alloc): Define.
- (df_mw_hardreg_ptr): New type. Use DEF_VEC_P and
- DEF_VEC_ALLOC_P_STACK.
- (VEC_df_mw_hardreg_ptr_stack_alloc): Define.
- (struct df_collection_rec): Change _vec fields to VEC. Remove
- _use fields.
- (df_free_collection_rec): Adjust for new fields.
- (df_insn_rescan): Use new df_collection_rec fields.
- (df_notes_rescan, df_canonize_collection_rec): Likewise.
- (df_ref_create_structure, df_ref_record): Likewise.
- (df_get_conditional_uses, df_get_call_refs): Likewise.
- (df_insn_refs_collect, df_bb_refs_collect): Likewise.
- (df_bb_refs_record, df_record_entry_block_defs): Likewise.
- (df_record_exit_block_uses, df_bb_verify): Likewise.
- (df_swap_refs): Change ref_vec parameter to VEC. Change all
- callers.
- (df_sort_and_compress_refs): Change ref_vec parameter to VEC.
- Remove count parameter. Change return type to void. Change all
- callers.
- (df_sort_and_compress_mws): Change mw_vec parameter to VEC.
- Remove count parameter. Change return type to void. Change all
- callers.
- (df_install_refs): Change old_vec parameter to VEC. Remove count
- parameter. Change all callers.
- (df_install_mws): Change old_vec parameter to VEC. Remove count
- parameter. Change all callers.
- (df_refs_verify): Change new_rec parameter to VEC. Change call
- callers.
- (df_mws_verify): Likewise.
+2009-06-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40446
+ * expr.c (expand_expr_real_1) <case VIEW_CONVERT_EXPR>: Don't
+ use gen_lowpart if op0 has complex mode.
+
+2009-06-14 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * config/s390/s390.md ("bswap<mode>2"): Only available on z900.
+
+2009-06-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-06-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ * doc/extend.texi: Add description for __builtin_ia32_crc32di.
+
+2009-06-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40340
+ * tree-ssa-live.c (remove_unused_scope_block_p): Don't prune
+ inlined_function_outer_scope_p blocks for artificial inlines
+ even at -g0/-g1.
+ * tree.c (tree_nonartificial_location): Rewrite using
+ block_nonartificial_location.
+
+2009-06-03 Jakub Jelinek <jakub@redhat.com>
+
+ * dwarf2out.c (output_cfi_directive): Pass 1 instead of
+ 0 to second argument of DWARF2_FRAME_REG_OUT macros.
+
+2009-06-02 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ Backport from mainline:
+ 2009-05-31 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ * config/sh/sh.md (ashldi3_std): New define_expand.
+ (ashldi3): Use it.
+
+2009-06-02 Jakub Jelinek <jakub@redhat.com>
+
+ * dwarf2out.c (dwarf2out_cfi_label): Add FORCE argument, if true,
+ force output of the label even for dwarf2out_do_cfi_asm.
+ (add_fde_cfi): If -g2 and above and cfi might change CFA,
+ force creation of CFI label and chain DW_CFA_set_loc jumping to it
+ for convert_cfa_to_fb_loc_list. Adjust other dwarf2out_cfi_label
+ caller.
+ (dwarf2out_stack_adjust, dwarf2out_frame_debug): Adjust
+ dwarf2out_cfi_label callers.
+ * tree.h (dwarf2out_cfi_label): Adjust prototype.
+ * config/arm/arm.c (thumb_pushpop, thumb1_output_function_prologue):
+ Adjust dwarf2out_cfi_label callers.
+ * config/vax/vax.c (vax_output_function_prologue): Likewise.
+
+2009-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40291
+ * builtins.c (expand_builtin_memcmp): Convert len to sizetype
+ before expansion.
+
+ PR target/40017
+ * config/rs6000/rs6000-c.c (_Bool_keyword): New variable.
+ (altivec_categorize_keyword, init_vector_keywords,
+ rs6000_cpu_cpp_builtins): Define _Bool as conditional macro
+ similar to bool.
+
+2009-05-28 Alexandre Oliva <aoliva@redhat.com>
+
+ * tree-inline.c (remap_decls): Enable nonlocalized variables
+ when not optimizing.
+
+2009-05-28 Alexandre Oliva <aoliva@redhat.com>
+
+ * tree-ssa-live.c (remove_unused_locals): Skip when not optimizing.
+ Simplify other tests involving optimize.
+
+2009-05-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-05-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/40266
+ * config/i386/driver-i386.c (host_detect_local_cpu): Support
+ AVX, SSE4, AES, PCLMUL and POPCNT.
+
+2009-05-25 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ PR bootstrap/40027
+ * config/i386/i386.c (USE_HIDDEN_LINKONCE): Only define if missing.
+ * config/i386/sol2.h [!TARGET_GNU_LD] (USE_HIDDEN_LINKONCE): Define.
+
+2009-05-24 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ * gcc/config/sh/sh.c (sh_set_return_address): Mark store of
+ return address with a USE.
+
+2009-05-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/passes.texi: Standardize spelling of RTL, Tree and Tree SSA.
+ Remove outdated reference to flow.c and fix nits.
+ * doc/gccint.texi: Tweak RTL description.
+ * doc/rtl.texi: Likewise.
+
+2009-05-22 Zdenek Dvorak <ook@ucw.cz>
+
+ PR tree-optimization/40087
+ * tree-ssa-loop-niter.c (number_of_iterations_ne_max,
+ number_of_iterations_ne): Rename never_infinite argument.
+ (number_of_iterations_lt_to_ne, number_of_iterations_lt,
+ number_of_iterations_le): Handle pointer-type ivs when
+ exit_must_be_taken is false.
+ (number_of_iterations_cond): Do not always assume that
+ exit_must_be_taken if the control variable is a pointer.
+
+2009-05-22 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR target/39856
+ * reg-stack.c (subst_stack_regs_pat): Remove gcc_assert for note
+ for clobber.
+
+2009-05-21 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ PR rtl-optimization/40105
+ Backport from mainline:
+
+ 2009-04-29 Eric Botcazou <ebotcazou@adacore.com>
+ Steven Bosscher <steven@gcc.gnu.org>
+
+ * Makefile.in (cfgrtl.o): Add $(INSN_ATTR_H).
+ * cfgrtl.c: Include insn-attr.h.
+ (rest_of_pass_free_cfg): New function.
+ (pass_free_cfg): Use rest_of_pass_free_cfg as execute function.
+
+ 2009-04-27 Richard Sandiford <rdsandiford@googlemail.com>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ * resource.c (find_basic_block): Use BLOCK_FOR_INSN to look up
+ a label's basic block.
+ (mark_target_live_regs): Tidy and rework obsolete comments.
+ Change back DF problem to LIVE. If a label starts a basic block,
+ assume that all registers that used to be live then still are.
+ (init_resource_info): If a label starts a basic block, set its
+ BLOCK_FOR_INSN accordingly.
+ (free_resource_info): Undo the setting of BLOCK_FOR_INSN.
+
+2009-05-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/39942
+ * config/i386/x86-64.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Don't emit second
+ .p2align 3 if MAX_SKIP is smaller than 7.
+ * config/i386/linux.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Likewise.
+
+2009-05-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40204
+ * fold-const.c (fold_binary) <case BIT_AND_EXPR>: Avoid infinite
+ recursion if build_int_cst_type returns the same INTEGER_CST as
+ arg1.
+
+2009-05-19 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Do
+ not falsely claim to have propagated into all uses.
+
+2009-05-18 Dodji Seketeli <dodji@redhat.com>
+
+ PR debug/40109
+ * dwarf2out.c (gen_type_die_with_usage): Generate the DIE as a
+ child of the containing namespace's DIE.
+
+2009-05-18 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/39999
+ * gimple.h (gimple_expr_type): Use the expression type looking
+ through useless conversions.
+ * tree-ssa-sccvn.c (vn_nary_op_lookup_stmt): Use gimple_expr_type.
+ (vn_nary_op_insert_stmt): Likewise.
+ (simplify_binary_expression): Likewise.
+
+2009-05-16 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/40153
+ * arm.md (cstoresi_nltu_thumb1): Use a neg of ltu as the pattern name
+ implies.
+
+2009-05-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-05-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR middle-end/40147
+ * ipa-utils.h (memory_identifier_string): Moved to ...
+ * tree.h (memory_identifier_string): Here. Add GTY(()).
+
+2009-05-14 Ben Elliston <bje@au.ibm.com>
+
+ Backport from mainline:
+ 2009-05-14 Jakub Jelinek <jakub@redhat.com>
+ Ben Elliston <bje@au.ibm.com>
+
+ PR middle-end/40035
+ * dse.c (check_mem_read_rtx): Guard against width == -1.
+
+2009-05-13 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/37179
+ * config/i386/driver-i386.c (processor_signatures): New enum.
+ (SIG_GEODE): Move from vendor_signatures to processor_signatures.
+ (host_detect_local_cpu): For SIG_AMD vendor, check for SIG_GEODE
+ processor signature to detect geode processor.
+
+2009-05-12 Jakub Jelinek <jakub@redhat.com>
+
+ Backport from mainline:
+ 2009-05-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/39666
+ * gimplify.c (gimplify_switch_expr): If case labels cover the whole
+ range of the type, but default label is missing, add it with one
+ of the existing labels instead of adding a new label for it.
+
+2009-05-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-05-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ * tree-vect-analyze.c (vect_analyze_group_access): Use
+ HOST_WIDE_INT for gap.
+
+2009-05-11 Ira Rosen <irar@il.ibm.com>
+
+ PR tree-optimization/40074
+ * tree-vect-analyze.c (vect_analyze_group_access): Take gaps into
+ account in group size and step comparison.
2009-05-08 Richard Guenther <rguenther@suse.de>
diff --git a/gcc/ChangeLog.vta b/gcc/ChangeLog.vta
index 5e592074b62..2fba35b9765 100644
--- a/gcc/ChangeLog.vta
+++ b/gcc/ChangeLog.vta
@@ -1,5 +1,10 @@
2009-06-17 Alexandre Oliva <aoliva@redhat.com>
+ Merged with gcc-4_4-branch@148582.
+ * rtl.def (VALUE): Move up.
+
+2009-06-17 Alexandre Oliva <aoliva@redhat.com>
+
* dwarf2out.c (mem_loc_descriptor): Handle DIV, MOD, AND, IOR,
XOR, NOT, ABS and NEG. Accept but discard EQ, GE, GT, LE, LT,
NE, COMPARE, IF_THEN_ELSE, SMIN, SMAX, ROTATE, ROTATERT,
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 7a5d9385cf6..1d49b936678 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20090509
+20090617
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 90283e29eb9..f14c2dfd5b1 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2786,7 +2786,8 @@ cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
value-prof.h $(TREE_INLINE_H) $(TARGET_H)
cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
- output.h $(TOPLEV_H) $(FUNCTION_H) except.h $(TM_P_H) insn-config.h $(EXPR_H) \
+ output.h $(TOPLEV_H) $(FUNCTION_H) except.h $(TM_P_H) $(INSN_ATTR_H) \
+ insn-config.h $(EXPR_H) \
$(CFGLAYOUT_H) $(CFGLOOP_H) $(OBSTACK_H) $(TARGET_H) $(TREE_H) \
tree-pass.h $(DF_H) $(GGC_H)
cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
diff --git a/gcc/builtins.c b/gcc/builtins.c
index cc9d93e2311..9dee9a35abb 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -4176,7 +4176,7 @@ expand_builtin_memcmp (tree exp, rtx target, enum machine_mode mode)
arg1_rtx = get_memory_rtx (arg1, len);
arg2_rtx = get_memory_rtx (arg2, len);
- arg3_rtx = expand_normal (len);
+ arg3_rtx = expand_normal (fold_convert (sizetype, len));
/* Set MEM_SIZE as appropriate. */
if (GET_CODE (arg3_rtx) == CONST_INT)
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 8f7b9c1633a..115f5257fa0 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "toplev.h"
#include "tm_p.h"
#include "obstack.h"
+#include "insn-attr.h"
#include "insn-config.h"
#include "cfglayout.h"
#include "expr.h"
@@ -427,13 +428,27 @@ free_bb_for_insn (void)
return 0;
}
+static unsigned int
+rest_of_pass_free_cfg (void)
+{
+#ifdef DELAY_SLOTS
+ /* The resource.c machinery uses DF but the CFG isn't guaranteed to be
+ valid at that point so it would be too late to call df_analyze. */
+ if (optimize > 0 && flag_delayed_branch)
+ df_analyze ();
+#endif
+
+ free_bb_for_insn ();
+ return 0;
+}
+
struct rtl_opt_pass pass_free_cfg =
{
{
RTL_PASS,
NULL, /* name */
NULL, /* gate */
- free_bb_for_insn, /* execute */
+ rest_of_pass_free_cfg, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 662e7de1e49..54dc09d7701 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -16883,7 +16883,7 @@ thumb_pushpop (FILE *f, unsigned long mask, int push, int *cfa_offset,
if (push && pushed_words && dwarf2out_do_frame ())
{
- char *l = dwarf2out_cfi_label ();
+ char *l = dwarf2out_cfi_label (false);
int pushed_mask = real_regs;
*cfa_offset += pushed_words * 4;
@@ -17781,7 +17781,7 @@ thumb1_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
the stack pointer. */
if (dwarf2out_do_frame ())
{
- char *l = dwarf2out_cfi_label ();
+ char *l = dwarf2out_cfi_label (false);
cfa_offset = cfa_offset + crtl->args.pretend_args_size;
dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
@@ -17830,7 +17830,7 @@ thumb1_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
if (dwarf2out_do_frame ())
{
- char *l = dwarf2out_cfi_label ();
+ char *l = dwarf2out_cfi_label (false);
cfa_offset = cfa_offset + 16;
dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index ff217e02c19..5a27f676833 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -8214,7 +8214,7 @@
(define_insn "cstoresi_nltu_thumb1"
[(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (neg:SI (gtu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
+ (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
(match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
"TARGET_THUMB1"
"cmp\\t%1, %2\;sbc\\t%0, %0, %0"
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 69c6c0c7f3b..9aa33d27cc7 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -336,7 +336,11 @@ detect_caches_intel (bool xeon_mp, unsigned max_level, unsigned max_ext_level)
enum vendor_signatures
{
SIG_INTEL = 0x756e6547 /* Genu */,
- SIG_AMD = 0x68747541 /* Auth */,
+ SIG_AMD = 0x68747541 /* Auth */
+};
+
+enum processor_signatures
+{
SIG_GEODE = 0x646f6547 /* Geod */
};
@@ -374,6 +378,9 @@ const char *host_detect_local_cpu (int argc, const char **argv)
/* Extended features */
unsigned int has_lahf_lm = 0, has_sse4a = 0;
unsigned int has_longmode = 0, has_3dnowp = 0, has_3dnow = 0;
+ unsigned int has_sse4_1 = 0, has_sse4_2 = 0;
+ unsigned int has_popcnt = 0, has_aes = 0, has_avx = 0;
+ unsigned int has_pclmul = 0;
bool arch;
@@ -397,7 +404,13 @@ const char *host_detect_local_cpu (int argc, const char **argv)
has_sse3 = ecx & bit_SSE3;
has_ssse3 = ecx & bit_SSSE3;
+ has_sse4_1 = ecx & bit_SSE4_1;
+ has_sse4_2 = ecx & bit_SSE4_2;
+ has_avx = ecx & bit_AVX;
has_cmpxchg16b = ecx & bit_CMPXCHG16B;
+ has_popcnt = ecx & bit_POPCNT;
+ has_aes = ecx & bit_AES;
+ has_pclmul = ecx & bit_PCLMUL;
has_cmpxchg8b = edx & bit_CMPXCHG8B;
has_cmov = edx & bit_CMOV;
@@ -433,19 +446,27 @@ const char *host_detect_local_cpu (int argc, const char **argv)
if (vendor == SIG_AMD)
{
- processor = PROCESSOR_PENTIUM;
+ unsigned int name;
- if (has_mmx)
- processor = PROCESSOR_K6;
- if (has_3dnowp)
- processor = PROCESSOR_ATHLON;
- if (has_sse2 || has_longmode)
- processor = PROCESSOR_K8;
- if (has_sse4a)
+ /* Detect geode processor by its processor signature. */
+ if (ext_level > 0x80000001)
+ __cpuid (0x80000002, name, ebx, ecx, edx);
+ else
+ name = 0;
+
+ if (name == SIG_GEODE)
+ processor = PROCESSOR_GEODE;
+ else if (has_sse4a)
processor = PROCESSOR_AMDFAM10;
+ else if (has_sse2 || has_longmode)
+ processor = PROCESSOR_K8;
+ else if (has_3dnowp)
+ processor = PROCESSOR_ATHLON;
+ else if (has_mmx)
+ processor = PROCESSOR_K6;
+ else
+ processor = PROCESSOR_PENTIUM;
}
- else if (vendor == SIG_GEODE)
- processor = PROCESSOR_GEODE;
else
{
switch (family)
@@ -576,6 +597,18 @@ const char *host_detect_local_cpu (int argc, const char **argv)
options = concat (options, "-mcx16 ", NULL);
if (has_lahf_lm)
options = concat (options, "-msahf ", NULL);
+ if (has_aes)
+ options = concat (options, "-maes ", NULL);
+ if (has_pclmul)
+ options = concat (options, "-mpclmul ", NULL);
+ if (has_popcnt)
+ options = concat (options, "-mpopcnt ", NULL);
+ if (has_avx)
+ options = concat (options, "-mavx ", NULL);
+ else if (has_sse4_2)
+ options = concat (options, "-msse4.2 ", NULL);
+ else if (has_sse4_1)
+ options = concat (options, "-msse4.1 ", NULL);
}
done:
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 12eb1dd3bcd..dda1baf1044 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -7304,10 +7304,12 @@ ix86_setup_frame_addresses (void)
cfun->machine->accesses_prev_frame = 1;
}
-#if (defined(HAVE_GAS_HIDDEN) && (SUPPORTS_ONE_ONLY - 0)) || TARGET_MACHO
-# define USE_HIDDEN_LINKONCE 1
-#else
-# define USE_HIDDEN_LINKONCE 0
+#ifndef USE_HIDDEN_LINKONCE
+# if (defined(HAVE_GAS_HIDDEN) && (SUPPORTS_ONE_ONLY - 0)) || TARGET_MACHO
+# define USE_HIDDEN_LINKONCE 1
+# else
+# define USE_HIDDEN_LINKONCE 0
+# endif
#endif
static int pic_labels_used;
diff --git a/gcc/config/i386/linux.h b/gcc/config/i386/linux.h
index 229316867fd..a2577caf5f7 100644
--- a/gcc/config/i386/linux.h
+++ b/gcc/config/i386/linux.h
@@ -153,7 +153,9 @@ along with GCC; see the file COPYING3. If not see
fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
/* Make sure that we have at least 8 byte alignment if > 8 byte \
alignment is preferred. */ \
- if ((LOG) > 3 && (1 << (LOG)) > ((MAX_SKIP) + 1)) \
+ if ((LOG) > 3 \
+ && (1 << (LOG)) > ((MAX_SKIP) + 1) \
+ && (MAX_SKIP) >= 7) \
fprintf ((FILE), "\t.p2align 3\n"); \
} \
} \
diff --git a/gcc/config/i386/sol2.h b/gcc/config/i386/sol2.h
index 1d21cd9c043..4c2dfe975cf 100644
--- a/gcc/config/i386/sol2.h
+++ b/gcc/config/i386/sol2.h
@@ -1,6 +1,6 @@
/* Target definitions for GCC for Intel 80386 running Solaris 2
Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2007, 2008 Free Software Foundation, Inc.
+ 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Fred Fish (fnf@cygnus.com).
This file is part of GCC.
@@ -112,3 +112,9 @@ along with GCC; see the file COPYING3. If not see
/* We do not need NT_VERSION notes. */
#undef X86_FILE_START_VERSION_DIRECTIVE
#define X86_FILE_START_VERSION_DIRECTIVE false
+
+/* Only recent versions of Solaris 11 ld properly support hidden .gnu.linkonce
+ sections, so don't use them. */
+#ifndef TARGET_GNU_LD
+#define USE_HIDDEN_LINKONCE 0
+#endif
diff --git a/gcc/config/i386/x86-64.h b/gcc/config/i386/x86-64.h
index 46dcad156f8..96649af7d0e 100644
--- a/gcc/config/i386/x86-64.h
+++ b/gcc/config/i386/x86-64.h
@@ -74,7 +74,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
/* Make sure that we have at least 8 byte alignment if > 8 byte \
alignment is preferred. */ \
- if ((LOG) > 3 && (1 << (LOG)) > ((MAX_SKIP) + 1)) \
+ if ((LOG) > 3 \
+ && (1 << (LOG)) > ((MAX_SKIP) + 1) \
+ && (MAX_SKIP) >= 7) \
fprintf ((FILE), "\t.p2align 3\n"); \
} \
} \
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index 3aa17143b67..3cae1c69588 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -91,6 +91,7 @@ static GTY(()) tree __pixel_keyword;
static GTY(()) tree pixel_keyword;
static GTY(()) tree __bool_keyword;
static GTY(()) tree bool_keyword;
+static GTY(()) tree _Bool_keyword;
/* Preserved across calls. */
static tree expand_bool_pixel;
@@ -111,6 +112,9 @@ altivec_categorize_keyword (const cpp_token *tok)
if (ident == C_CPP_HASHNODE (bool_keyword))
return C_CPP_HASHNODE (__bool_keyword);
+ if (ident == C_CPP_HASHNODE (_Bool_keyword))
+ return C_CPP_HASHNODE (__bool_keyword);
+
return ident;
}
@@ -141,6 +145,9 @@ init_vector_keywords (void)
bool_keyword = get_identifier ("bool");
C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
+
+ _Bool_keyword = get_identifier ("_Bool");
+ C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
}
/* Called to decide whether a conditional macro should be expanded.
@@ -295,6 +302,7 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
builtin_define ("vector=vector");
builtin_define ("pixel=pixel");
builtin_define ("bool=bool");
+ builtin_define ("_Bool=_Bool");
init_vector_keywords ();
/* Enable context-sensitive macros. */
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 7ecc3ccb353..80d334bd276 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -8750,7 +8750,7 @@
(define_insn "bswap<mode>2"
[(set (match_operand:GPR 0 "register_operand" "=d, d")
(bswap:GPR (match_operand:GPR 1 "nonimmediate_operand" " d,RT")))]
- ""
+ "TARGET_CPU_ZARCH"
"@
lrv<g>r\t%0,%1
lrv<g>\t%0,%1"
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index c8f4c85ee75..686b15fc66c 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -6908,6 +6908,8 @@ sh_set_return_address (rtx ra, rtx tmp)
tmp = gen_frame_mem (Pmode, tmp);
emit_insn (GEN_MOV (tmp, ra));
+ /* Tell this store isn't dead. */
+ emit_use (tmp);
}
/* Clear variables at function end. */
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index f494493fd63..2dcaed6fb64 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -3999,6 +3999,34 @@ label:
[(set_attr "length" "4")
(set_attr "type" "arith")])
+;; Expander for DImode shift left with SImode operations.
+
+(define_expand "ashldi3_std"
+ [(set (match_operand:DI 0 "arith_reg_dest" "=r")
+ (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
+ (match_operand:DI 2 "const_int_operand" "n")))]
+ "TARGET_SH1 && INTVAL (operands[2]) < 32"
+ "
+{
+ int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
+ int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
+ rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
+ rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
+ rtx dst = gen_reg_rtx (DImode);
+ rtx low_dst = operand_subword (dst, low_word, 1, DImode);
+ rtx high_dst = operand_subword (dst, high_word, 1, DImode);
+ rtx tmp0, tmp1;
+
+ tmp0 = gen_reg_rtx (SImode);
+ tmp1 = gen_reg_rtx (SImode);
+ emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
+ emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));
+ emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));
+ emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
+ emit_move_insn (operands[0], dst);
+ DONE;
+}")
+
(define_insn "ashldi3_media"
[(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
@@ -4031,8 +4059,19 @@ label:
emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
DONE;
}
- if (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) != 1)
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 1)
+ {
+ emit_insn (gen_ashldi3_k (operands[0], operands[1]));
+ DONE;
+ }
+ else if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) < 32)
+ {
+ emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ else
FAIL;
}")
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index eae2d190b85..3a800d2d9ef 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -122,7 +122,7 @@ vax_output_function_prologue (FILE * file, HOST_WIDE_INT size)
if (dwarf2out_do_frame ())
{
- const char *label = dwarf2out_cfi_label ();
+ const char *label = dwarf2out_cfi_label (false);
int offset = 0;
for (regno = FIRST_PSEUDO_REGISTER-1; regno >= 0; --regno)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0312fcc5de7..307d8831e8b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,62 @@
+2009-06-09 Jason Merrill <jason@redhat.com>
+
+ PR c++/40381
+ * decl2.c (mark_used): Return after complaining about deleted fn.
+
+2009-06-08 Jason Merrill <jason@redhat.com>
+
+ * parser.c (cp_parser_type_id_1): 'auto' type is ok with a
+ late-specified return type.
+
+2009-06-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/40373
+ * call.c (check_dtor_name): Return false even if
+ get_type_value (name) is error_mark_node.
+
+ PR c++/40370
+ PR c++/40372
+ * parser.c (cp_parser_direct_declarator): Don't set TREE_SIDE_EFFECTS
+ on error_mark_node. Check for VLAs outside of function context
+ before check whether to wrap bounds into a NOP_EXPR with
+ TREE_SIDE_EFFECTS.
+
+2009-06-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/40308
+ PR c++/40311
+ * typeck.c (cp_build_modify_expr): Always pass init-lists to the
+ conversion code.
+ * call.c (implicit_conversion): Allow init-list conversion to scalar
+ during direct-initialization, too. Mark the conversion bad if it
+ has too many levels of braces.
+ (convert_like_real): And give a helpful error.
+
+ PR c++/40306
+ PR c++/40307
+ * decl.c (cp_finish_decl): Handle auto deduction from ().
+ * typeck.c (build_x_indirect_ref): Handle dereferencing an operand
+ with dependent type that is known to be a pointer.
+
+2009-05-27 Jason Merrill <jason@redhat.com>
+
+ * call.c (implicit_conversion): Handle conversion from
+ initializer-list to scalar.
+ (convert_like_real): Likewise. Avoid crashing on list
+ initialization with bad conversions.
+
+2009-05-22 Jason Merrill <jason@redhat.com>
+
+ PR c++/38064
+ * typeck.c (cp_build_binary_op): Allow ENUMERAL_TYPE in
+ arithmetic comparisons.
+ (cp_common_type): Handle scoped enums.
+
+2009-05-16 Jason Merrill <jason@redhat.com>
+
+ PR c++/40139
+ * semantics.c (finish_id_expression): Fix logic.
+
2009-05-06 Dodji Seketeli <dodji@redhat.com>
PR c++/17395
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 04103b3dc5b..c18ea6808e6 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -240,7 +240,7 @@ check_dtor_name (tree basetype, tree name)
return false;
}
- if (!name)
+ if (!name || name == error_mark_node)
return false;
return same_type_p (TYPE_MAIN_VARIANT (basetype), TYPE_MAIN_VARIANT (name));
}
@@ -1384,9 +1384,37 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
if (conv)
return conv;
- if (is_std_init_list (to) && expr
- && BRACE_ENCLOSED_INITIALIZER_P (expr))
- return build_list_conv (to, expr, flags);
+ if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
+ {
+ if (is_std_init_list (to))
+ return build_list_conv (to, expr, flags);
+
+ /* Allow conversion from an initializer-list with one element to a
+ scalar type. */
+ if (SCALAR_TYPE_P (to))
+ {
+ int nelts = CONSTRUCTOR_NELTS (expr);
+ tree elt;
+
+ if (nelts == 0)
+ elt = integer_zero_node;
+ else if (nelts == 1)
+ elt = CONSTRUCTOR_ELT (expr, 0)->value;
+ else
+ elt = error_mark_node;
+
+ conv = implicit_conversion (to, TREE_TYPE (elt), elt,
+ c_cast_p, flags);
+ if (conv)
+ {
+ conv->check_narrowing = true;
+ if (BRACE_ENCLOSED_INITIALIZER_P (elt))
+ /* Too many levels of braces, i.e. '{{1}}'. */
+ conv->bad_p = true;
+ return conv;
+ }
+ }
+ }
if (expr != NULL_TREE
&& (MAYBE_CLASS_TYPE_P (from)
@@ -4529,12 +4557,21 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (convs->bad_p
&& convs->kind != ck_user
+ && convs->kind != ck_list
&& convs->kind != ck_ambig
&& convs->kind != ck_ref_bind
&& convs->kind != ck_rvalue
&& convs->kind != ck_base)
{
conversion *t = convs;
+
+ /* Give a helpful error if this is bad because of excess braces. */
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr)
+ && SCALAR_TYPE_P (totype)
+ && CONSTRUCTOR_NELTS (expr) > 0
+ && BRACE_ENCLOSED_INITIALIZER_P (CONSTRUCTOR_ELT (expr, 0)->value))
+ permerror (input_location, "too many braces around initializer for %qT", totype);
+
for (; t; t = convs->u.next)
{
if (t->kind == ck_user || !t->bad_p)
@@ -4608,6 +4645,17 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
return expr;
}
case ck_identity:
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+ {
+ int nelts = CONSTRUCTOR_NELTS (expr);
+ if (nelts == 0)
+ expr = integer_zero_node;
+ else if (nelts == 1)
+ expr = CONSTRUCTOR_ELT (expr, 0)->value;
+ else
+ gcc_unreachable ();
+ }
+
if (type_unknown_p (expr))
expr = instantiate_type (totype, expr, complain);
/* Convert a constant to its underlying value, unless we are
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6537c50409f..01d4f121320 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5533,7 +5533,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
TREE_TYPE (decl) = error_mark_node;
return;
}
- else if (describable_type (init))
+ if (TREE_CODE (init) == TREE_LIST)
+ init = build_x_compound_expr_from_list (init, "initializer");
+ if (describable_type (init))
{
type = TREE_TYPE (decl) = do_auto_deduction (type, init, auto_node);
if (type == error_mark_node)
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 2be621da7c5..147a46ffce7 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3809,6 +3809,7 @@ mark_used (tree decl)
{
error ("deleted function %q+D", decl);
error ("used here");
+ return;
}
/* If we don't need a value, then we don't need to synthesize DECL. */
if (skip_evaluation)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 34c3ed57fa0..26748624ca8 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13296,13 +13296,6 @@ cp_parser_direct_declarator (cp_parser* parser,
&non_constant_p);
if (!non_constant_p)
bounds = fold_non_dependent_expr (bounds);
- else if (processing_template_decl)
- {
- /* Remember this wasn't a constant-expression. */
- bounds = build_nop (TREE_TYPE (bounds), bounds);
- TREE_SIDE_EFFECTS (bounds) = 1;
- }
-
/* Normally, the array bound must be an integral constant
expression. However, as an extension, we allow VLAs
in function scopes. */
@@ -13312,6 +13305,12 @@ cp_parser_direct_declarator (cp_parser* parser,
&token->location);
bounds = error_mark_node;
}
+ else if (processing_template_decl && !error_operand_p (bounds))
+ {
+ /* Remember this wasn't a constant-expression. */
+ bounds = build_nop (TREE_TYPE (bounds), bounds);
+ TREE_SIDE_EFFECTS (bounds) = 1;
+ }
}
else
bounds = NULL_TREE;
@@ -13809,8 +13808,17 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg)
if (type_specifier_seq.type
&& type_uses_auto (type_specifier_seq.type))
{
- error ("invalid use of %<auto%>");
- return error_mark_node;
+ /* A type-id with type 'auto' is only ok if the abstract declarator
+ is a function declarator with a late-specified return type. */
+ if (abstract_declarator
+ && abstract_declarator->kind == cdk_function
+ && abstract_declarator->u.function.late_return_type)
+ /* OK */;
+ else
+ {
+ error ("invalid use of %<auto%>");
+ return error_mark_node;
+ }
}
return groktypename (&type_specifier_seq, abstract_declarator,
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 365e5ca3a00..4455f861734 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2838,16 +2838,16 @@ finish_id_expression (tree id_expression,
done, address_p,
template_p,
template_arg_p);
- else if (dependent_scope_p (scope))
- decl = build_qualified_name (/*type=*/NULL_TREE,
- scope,
- id_expression,
- template_p);
- else if (DECL_P (decl))
- decl = build_qualified_name (TREE_TYPE (decl),
- scope,
- id_expression,
- template_p);
+ else
+ {
+ tree type = NULL_TREE;
+ if (DECL_P (decl) && !dependent_scope_p (scope))
+ type = TREE_TYPE (decl);
+ decl = build_qualified_name (type,
+ scope,
+ id_expression,
+ template_p);
+ }
}
if (TREE_TYPE (decl))
decl = convert_from_reference (decl);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 25d87a6d87b..452331fc494 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -260,6 +260,19 @@ cp_common_type (tree t1, tree t2)
enum tree_code code2 = TREE_CODE (t2);
tree attributes;
+ /* In what follows, we slightly generalize the rules given in [expr] so
+ as to deal with `long long' and `complex'. First, merge the
+ attributes. */
+ attributes = (*targetm.merge_type_attributes) (t1, t2);
+
+ if (SCOPED_ENUM_P (t1) || SCOPED_ENUM_P (t2))
+ {
+ if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+ return build_type_attribute_variant (t1, attributes);
+ else
+ return NULL_TREE;
+ }
+
/* FIXME: Attributes. */
gcc_assert (ARITHMETIC_TYPE_P (t1)
|| TREE_CODE (t1) == VECTOR_TYPE
@@ -268,11 +281,6 @@ cp_common_type (tree t1, tree t2)
|| TREE_CODE (t2) == VECTOR_TYPE
|| UNSCOPED_ENUM_P (t2));
- /* In what follows, we slightly generalize the rules given in [expr] so
- as to deal with `long long' and `complex'. First, merge the
- attributes. */
- attributes = (*targetm.merge_type_attributes) (t1, t2);
-
/* If one type is complex, form the common type of the non-complex
components, then make that complex. Use T1 or T2 if it is the
required type. */
@@ -2437,6 +2445,10 @@ build_x_indirect_ref (tree expr, const char *errorstring,
if (processing_template_decl)
{
+ /* Retain the type if we know the operand is a pointer so that
+ describable_type doesn't make auto deduction break. */
+ if (TREE_TYPE (expr) && POINTER_TYPE_P (TREE_TYPE (expr)))
+ return build_min (INDIRECT_REF, TREE_TYPE (TREE_TYPE (expr)), expr);
if (type_dependent_expression_p (expr))
return build_min_nt (INDIRECT_REF, expr);
expr = build_non_dependent_expr (expr);
@@ -3589,9 +3601,9 @@ cp_build_binary_op (location_t location,
build_type = boolean_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
- || code0 == COMPLEX_TYPE)
+ || code0 == COMPLEX_TYPE || code0 == ENUMERAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE))
+ || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE))
short_compare = 1;
else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE)
|| (TYPE_PTRMEM_P (type0) && TYPE_PTRMEM_P (type1)))
@@ -3863,9 +3875,10 @@ cp_build_binary_op (location_t location,
break;
}
- if (((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+ if (((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
+ || code0 == ENUMERAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE)))
+ || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE)))
arithmetic_types_p = 1;
else
{
@@ -5967,8 +5980,11 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
if (modifycode == INIT_EXPR)
{
- if (TREE_CODE (rhs) == CONSTRUCTOR)
+ if (BRACE_ENCLOSED_INITIALIZER_P (rhs))
+ /* Do the default thing. */;
+ else if (TREE_CODE (rhs) == CONSTRUCTOR)
{
+ /* Compound literal. */
if (! same_type_p (TREE_TYPE (rhs), lhstype))
/* Call convert to generate an error; see PR 11063. */
rhs = convert (lhstype, rhs);
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index ad17a378d98..fcbc9036a9c 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -8304,6 +8304,7 @@ Generates the @code{crc32w} machine instruction.
@item unsigned int __builtin_ia32_crc32si (unsigned int, unsigned int)
Generates the @code{crc32l} machine instruction.
@item unsigned long long __builtin_ia32_crc32di (unsigned long long, unsigned long long)
+Generates the @code{crc32q} machine instruction.
@end table
The following built-in functions are changed to generate new SSE4.2
diff --git a/gcc/doc/gccint.texi b/gcc/doc/gccint.texi
index b4b559ec418..bb7a8af92f4 100644
--- a/gcc/doc/gccint.texi
+++ b/gcc/doc/gccint.texi
@@ -109,10 +109,10 @@ Additional tutorial information is linked to from
* Options:: Option specification files.
* Passes:: Order of passes, what they do, and what each file is for.
* Trees:: The source representation used by the C and C++ front ends.
-* RTL:: The intermediate representation that most passes work on.
* GENERIC:: Language-independent representation generated by Front Ends
* GIMPLE:: Tuple representation used by Tree SSA optimizers
* Tree SSA:: Analysis and optimization of GIMPLE
+* RTL:: Machine-dependent low-level intermediate representation.
* Control Flow:: Maintaining and manipulating the control flow graph.
* Loop Analysis and Representation:: Analysis and representation of loops
* Machine Desc:: How to write machine description instruction patterns.
diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi
index 51dcc410143..c7ae5da8e2d 100644
--- a/gcc/doc/passes.texi
+++ b/gcc/doc/passes.texi
@@ -21,7 +21,7 @@ where near complete.
* Parsing pass:: The language front end turns text into bits.
* Gimplification pass:: The bits are turned into something we can optimize.
* Pass manager:: Sequencing the optimization passes.
-* Tree-SSA passes:: Optimizations on a high-level representation.
+* Tree SSA passes:: Optimizations on a high-level representation.
* RTL passes:: Optimizations on a low-level representation.
@end menu
@@ -94,8 +94,8 @@ be passed to @code{rest_of_type_compilation}. Each function definition
should be passed to @code{cgraph_finalize_function}.
TODO: I know rest_of_compilation currently has all sorts of
-rtl-generation semantics. I plan to move all code generation
-bits (both tree and rtl) to compile_function. Should we hide
+RTL generation semantics. I plan to move all code generation
+bits (both Tree and RTL) to compile_function. Should we hide
cgraph from the front ends and move back to rest_of_compilation
as the official interface? Possibly we should rename all three
interfaces such that the names match in some meaningful way and
@@ -172,12 +172,12 @@ dump anything.
TODO: describe the global variables set up by the pass manager,
and a brief description of how a new pass should use it.
-I need to look at what info rtl passes use first@enddots{}
+I need to look at what info RTL passes use first@enddots{}
-@node Tree-SSA passes
-@section Tree-SSA passes
+@node Tree SSA passes
+@section Tree SSA passes
-The following briefly describes the tree optimization passes that are
+The following briefly describes the Tree optimization passes that are
run after gimplification and what source files they are located in.
@itemize @bullet
@@ -401,7 +401,7 @@ and described by @code{pass_loop}.
The optimizations performed by this pass are:
Loop invariant motion. This pass moves only invariants that
-would be hard to handle on rtl level (function calls, operations that expand to
+would be hard to handle on RTL level (function calls, operations that expand to
nontrivial sequences of insns). With @option{-funswitch-loops} it also moves
operands of conditions that are invariant out of the loop, so that we can use
just trivial invariantness analysis in loop unswitching. The pass also includes
@@ -422,8 +422,8 @@ Loop unswitching. This pass moves the conditional jumps that are invariant
out of the loops. To achieve this, a duplicate of the loop is created for
each possible outcome of conditional jump(s). The pass is implemented in
@file{tree-ssa-loop-unswitch.c}. This pass should eventually replace the
-rtl-level loop unswitching in @file{loop-unswitch.c}, but currently
-the rtl-level pass is not completely redundant yet due to deficiencies
+RTL level loop unswitching in @file{loop-unswitch.c}, but currently
+the RTL level pass is not completely redundant yet due to deficiencies
in tree level alias analysis.
The optimizations also use various utility functions contained in
@@ -651,8 +651,8 @@ registers don't need to be saved. This pass is located in
@node RTL passes
@section RTL passes
-The following briefly describes the rtl generation and optimization
-passes that are run after tree optimization.
+The following briefly describes the RTL generation and optimization
+passes that are run after the Tree optimization passes.
@itemize @bullet
@item RTL generation
@@ -679,15 +679,15 @@ generated from the machine description by the programs @code{genflags}
and @code{gencodes}, tell this pass which standard names are available
for use and which patterns correspond to them.
-@item Generate exception handling landing pads
+@item Generation of exception landing pads
This pass generates the glue that handles communication between the
exception handling library routines and the exception handlers within
the function. Entry points in the function that are invoked by the
exception handling library are called @dfn{landing pads}. The code
-for this pass is located within @file{except.c}.
+for this pass is located in @file{except.c}.
-@item Cleanup control flow graph
+@item Control flow graph cleanup
This pass removes unreachable code, simplifies jumps to next, jumps to
jump, jumps across jumps, etc. The pass is run multiple times.
@@ -702,16 +702,16 @@ This pass attempts to remove redundant computation by substituting
variables that come from a single definition, and
seeing if the result can be simplified. It performs copy propagation
and addressing mode selection. The pass is run twice, with values
-being propagated into loops only on the second run. It is located in
-@file{fwprop.c}.
+being propagated into loops only on the second run. The code is
+located in @file{fwprop.c}.
@item Common subexpression elimination
This pass removes redundant computation within basic blocks, and
optimizes addressing modes based on cost. The pass is run twice.
-The source is located in @file{cse.c}.
+The code for this pass is located in @file{cse.c}.
-@item Global common subexpression elimination.
+@item Global common subexpression elimination
This pass performs two
different types of GCSE depending on whether you are optimizing for
@@ -755,22 +755,13 @@ This pass attempts to replace conditional branches and surrounding
assignments with arithmetic, boolean value producing comparison
instructions, and conditional move instructions. In the very last
invocation after reload, it will generate predicated instructions
-when supported by the target. The pass is located in @file{ifcvt.c}.
+when supported by the target. The code is located in @file{ifcvt.c}.
@item Web construction
This pass splits independent uses of each pseudo-register. This can
improve effect of the other transformation, such as CSE or register
-allocation. Its source files are @file{web.c}.
-
-@item Life analysis
-
-This pass computes which pseudo-registers are live at each point in
-the program, and makes the first instruction that uses a value point
-at the instruction that computed the value. It then deletes
-computations whose results are never used, and combines memory
-references with add or subtract instructions to make autoincrement or
-autodecrement addressing. The pass is located in @file{flow.c}.
+allocation. The code for this pass is located in @file{web.c}.
@item Instruction combination
@@ -778,23 +769,23 @@ This pass attempts to combine groups of two or three instructions that
are related by data flow into single instructions. It combines the
RTL expressions for the instructions by substitution, simplifies the
result using algebra, and then attempts to match the result against
-the machine description. The pass is located in @file{combine.c}.
+the machine description. The code is located in @file{combine.c}.
@item Register movement
This pass looks for cases where matching constraints would force an
instruction to need a reload, and this reload would be a
register-to-register move. It then attempts to change the registers
-used by the instruction to avoid the move instruction.
-The pass is located in @file{regmove.c}.
+used by the instruction to avoid the move instruction. The code is
+located in @file{regmove.c}.
-@item Optimize mode switching
+@item Mode switching optimization
This pass looks for instructions that require the processor to be in a
specific ``mode'' and minimizes the number of mode changes required to
satisfy all users. What these modes are, and what they apply to are
-completely target-specific.
-The source is located in @file{mode-switching.c}.
+completely target-specific. The code for this pass is located in
+@file{mode-switching.c}.
@cindex modulo scheduling
@cindex sms, swing, software pipelining
@@ -802,8 +793,8 @@ The source is located in @file{mode-switching.c}.
This pass looks at innermost loops and reorders their instructions
by overlapping different iterations. Modulo scheduling is performed
-immediately before instruction scheduling.
-The pass is located in (@file{modulo-sched.c}).
+immediately before instruction scheduling. The code for this pass is
+located in @file{modulo-sched.c}.
@item Instruction scheduling
@@ -813,7 +804,7 @@ floating point instructions often have this behavior on RISC machines.
It re-orders instructions within a basic block to try to separate the
definition and use of items that otherwise would cause pipeline
stalls. This pass is performed twice, before and after register
-allocation. The pass is located in @file{haifa-sched.c},
+allocation. The code for this pass is located in @file{haifa-sched.c},
@file{sched-deps.c}, @file{sched-ebb.c}, @file{sched-rgn.c} and
@file{sched-vis.c}.
@@ -884,13 +875,13 @@ This pass computes where the variables are stored at each
position in code and generates notes describing the variable locations
to RTL code. The location lists are then generated according to these
notes to debug information if the debugging information format supports
-location lists.
+location lists. The code is located in @file{var-tracking.c}.
@item Delayed branch scheduling
This optional pass attempts to find instructions that can go into the
-delay slots of other instructions, usually jumps and calls. The
-source file name is @file{reorg.c}.
+delay slots of other instructions, usually jumps and calls. The code
+for this pass is located in @file{reorg.c}.
@item Branch shortening
@@ -899,13 +890,14 @@ Thus, longer sequences of instructions must be used for long branches.
In this pass, the compiler figures out what how far each instruction
will be from each other instruction, and therefore whether the usual
instructions, or the longer sequences, must be used for each branch.
+The code for this pass is located in @file{final.c}.
@item Register-to-stack conversion
Conversion from usage of some hard registers to usage of a register
stack may be done at this point. Currently, this is supported only
-for the floating-point registers of the Intel 80387 coprocessor. The
-source file name is @file{reg-stack.c}.
+for the floating-point registers of the Intel 80387 coprocessor. The
+code for this pass is located in @file{reg-stack.c}.
@item Final
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index 1411f24e5d9..9e019b55d29 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -10,10 +10,10 @@
@cindex representation of RTL
@cindex Register Transfer Language (RTL)
-Most of the work of the compiler is done on an intermediate representation
-called register transfer language. In this language, the instructions to be
-output are described, pretty much one by one, in an algebraic form that
-describes what the instruction does.
+The last part of the compiler work is done on a low-level intermediate
+representation called Register Transfer Language. In this language, the
+instructions to be output are described, pretty much one by one, in an
+algebraic form that describes what the instruction does.
RTL is inspired by Lisp lists. It has both an internal form, made up of
structures that point at other structures, and a textual form that is used
diff --git a/gcc/dse.c b/gcc/dse.c
index 1ea2a86faa0..38858647e49 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -2245,6 +2245,7 @@ check_mem_read_rtx (rtx *loc, void *data)
if (store_info->rhs
&& store_info->group_id == -1
&& store_info->cse_base == base
+ && width != -1
&& offset >= store_info->begin
&& offset + width <= store_info->end
&& all_positions_needed_p (store_info,
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 75a09a10831..b273c5dd623 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -700,14 +700,15 @@ add_cfi (dw_cfi_ref *list_head, dw_cfi_ref cfi)
*p = cfi;
}
-/* Generate a new label for the CFI info to refer to. */
+/* Generate a new label for the CFI info to refer to. FORCE is true
+ if a label needs to be output even when using .cfi_* directives. */
char *
-dwarf2out_cfi_label (void)
+dwarf2out_cfi_label (bool force)
{
static char label[20];
- if (dwarf2out_do_cfi_asm ())
+ if (!force && dwarf2out_do_cfi_asm ())
{
/* In this case, we will be emitting the asm directive instead of
the label, so just return a placeholder to keep the rest of the
@@ -735,11 +736,59 @@ add_fde_cfi (const char *label, dw_cfi_ref cfi)
{
if (label)
{
- output_cfi_directive (cfi);
+ dw_fde_ref fde = current_fde ();
+
+ gcc_assert (fde != NULL);
/* We still have to add the cfi to the list so that
- lookup_cfa works later on. */
- list_head = &current_fde ()->dw_fde_cfi;
+ lookup_cfa works later on. When -g2 and above we
+ even need to force emitting of CFI labels and
+ add to list a DW_CFA_set_loc for convert_cfa_to_fb_loc_list
+ purposes. */
+ switch (cfi->dw_cfi_opc)
+ {
+ case DW_CFA_def_cfa_offset:
+ case DW_CFA_def_cfa_offset_sf:
+ case DW_CFA_def_cfa_register:
+ case DW_CFA_def_cfa:
+ case DW_CFA_def_cfa_sf:
+ case DW_CFA_def_cfa_expression:
+ case DW_CFA_restore_state:
+ if (write_symbols != DWARF2_DEBUG
+ && write_symbols != VMS_AND_DWARF2_DEBUG)
+ break;
+ if (debug_info_level <= DINFO_LEVEL_TERSE)
+ break;
+
+ if (*label == 0 || strcmp (label, "<do not output>") == 0)
+ label = dwarf2out_cfi_label (true);
+
+ if (fde->dw_fde_current_label == NULL
+ || strcmp (label, fde->dw_fde_current_label) != 0)
+ {
+ dw_cfi_ref xcfi;
+
+ label = xstrdup (label);
+
+ /* Set the location counter to the new label. */
+ xcfi = new_cfi ();
+ /* It doesn't metter whether DW_CFA_set_loc
+ or DW_CFA_advance_loc4 is added here, those aren't
+ emitted into assembly, only looked up by
+ convert_cfa_to_fb_loc_list. */
+ xcfi->dw_cfi_opc = DW_CFA_set_loc;
+ xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
+ add_cfi (&fde->dw_fde_cfi, xcfi);
+ fde->dw_fde_current_label = label;
+ }
+ break;
+ default:
+ break;
+ }
+
+ output_cfi_directive (cfi);
+
+ list_head = &fde->dw_fde_cfi;
}
/* ??? If this is a CFI for the CIE, we don't emit. This
assumes that the standard CIE contents that the assembler
@@ -754,7 +803,7 @@ add_fde_cfi (const char *label, dw_cfi_ref cfi)
gcc_assert (fde != NULL);
if (*label == 0)
- label = dwarf2out_cfi_label ();
+ label = dwarf2out_cfi_label (false);
if (fde->dw_fde_current_label == NULL
|| strcmp (label, fde->dw_fde_current_label) != 0)
@@ -1470,7 +1519,7 @@ dwarf2out_stack_adjust (rtx insn, bool after_p)
if (offset == 0)
return;
- label = dwarf2out_cfi_label ();
+ label = dwarf2out_cfi_label (false);
dwarf2out_args_size_adjust (offset, label);
}
@@ -2423,7 +2472,7 @@ dwarf2out_frame_debug (rtx insn, bool after_p)
return;
}
- label = dwarf2out_cfi_label ();
+ label = dwarf2out_cfi_label (false);
src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
if (src)
insn = XEXP (src, 0);
@@ -2737,42 +2786,42 @@ output_cfi_directive (dw_cfi_ref cfi)
case DW_CFA_offset:
case DW_CFA_offset_extended:
case DW_CFA_offset_extended_sf:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
+ r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
fprintf (asm_out_file, "\t.cfi_offset %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
break;
case DW_CFA_restore:
case DW_CFA_restore_extended:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
+ r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
fprintf (asm_out_file, "\t.cfi_restore %lu\n", r);
break;
case DW_CFA_undefined:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
+ r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
fprintf (asm_out_file, "\t.cfi_undefined %lu\n", r);
break;
case DW_CFA_same_value:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
+ r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
fprintf (asm_out_file, "\t.cfi_same_value %lu\n", r);
break;
case DW_CFA_def_cfa:
case DW_CFA_def_cfa_sf:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
+ r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
fprintf (asm_out_file, "\t.cfi_def_cfa %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
break;
case DW_CFA_def_cfa_register:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
+ r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
fprintf (asm_out_file, "\t.cfi_def_cfa_register %lu\n", r);
break;
case DW_CFA_register:
- r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 0);
- r2 = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, 0);
+ r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
+ r2 = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, 1);
fprintf (asm_out_file, "\t.cfi_register %lu, %lu\n", r, r2);
break;
@@ -15136,6 +15185,12 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
/* Prevent broken recursion; we can't hand off to the same type. */
gcc_assert (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) != type);
+ /* Use the DIE of the containing namespace as the parent DIE of
+ the type description DIE we want to generate. */
+ if (DECL_CONTEXT (TYPE_NAME (type))
+ && TREE_CODE (DECL_CONTEXT (TYPE_NAME (type))) == NAMESPACE_DECL)
+ context_die = lookup_decl_die (DECL_CONTEXT (TYPE_NAME (type)));
+
TREE_ASM_WRITTEN (type) = 1;
gen_decl_die (TYPE_NAME (type), NULL, context_die);
return;
diff --git a/gcc/expr.c b/gcc/expr.c
index 8ab306b89f5..3aceb39f1ea 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8258,7 +8258,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
/* If neither mode is BLKmode, and both modes are the same size
then we can use gen_lowpart. */
else if (mode != BLKmode && GET_MODE (op0) != BLKmode
- && GET_MODE_SIZE (mode) == GET_MODE_SIZE (GET_MODE (op0)))
+ && GET_MODE_SIZE (mode) == GET_MODE_SIZE (GET_MODE (op0))
+ && !COMPLEX_MODE_P (GET_MODE (op0)))
{
if (GET_CODE (op0) == SUBREG)
op0 = force_reg (GET_MODE (op0), op0);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index f7b9c455c31..3c5a5c6b4dc 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -11363,6 +11363,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
if (prec < HOST_BITS_PER_WIDE_INT
|| newmask == ~(unsigned HOST_WIDE_INT) 0)
{
+ tree newmaskt;
+
if (shift_type != TREE_TYPE (arg0))
{
tem = fold_build2 (TREE_CODE (arg0), shift_type,
@@ -11373,9 +11375,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
}
else
tem = op0;
- return fold_build2 (BIT_AND_EXPR, type, tem,
- build_int_cst_type (TREE_TYPE (op1),
- newmask));
+ newmaskt = build_int_cst_type (TREE_TYPE (op1), newmask);
+ if (!tree_int_cst_equal (newmaskt, arg1))
+ return fold_build2 (BIT_AND_EXPR, type, tem, newmaskt);
}
}
}
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 48a9b209c16..20b31ecf118 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,73 @@
+2009-06-14 Richard Guenther <rguenther@suse.de>
+
+ Backport from mainline
+ 2009-05-18 Richard Guenther <rguenther@suse.de>
+
+ PR fortran/40168
+ * trans-expr.c (gfc_trans_zero_assign): For local array
+ destinations use an assignment from an empty constructor.
+
+2009-06-04 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/39893
+ fortran/data.c (gfc_assign_data_value): If the lvalue is an
+ assumed character length entity in a data statement, then
+ return FAILURE to prevent segmentation fault.
+
+2009-06-03 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/40019
+ * trans-types.c (gfc_build_uint_type): Make nonstatic.
+ * trans.h (gfor_fndecl_clz128, gfor_fndecl_ctz128): New prototypes.
+ * trans-types.h (gfc_build_uint_type): Add prototype.
+ * trans-decl.c (gfc_build_intrinsic_function_decls): Build
+ gfor_fndecl_clz128 and gfor_fndecl_ctz128.
+ * trans-intrinsic.c (gfc_conv_intrinsic_leadz,
+ gfc_conv_intrinsic_trailz): Call the right builtins or library
+ functions, and cast arguments to unsigned types first.
+ * simplify.c (gfc_simplify_leadz): Deal with negative arguments.
+
+2009-05-22 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/40195
+ * module.c (read_md5_from_module_file): Close file before returning.
+
+2009-05-10 Paul Thomas <pault@gcc.gnu.org>
+
+ Backport from mainline:
+ PR fortran/40018
+ * trans-array.c (gfc_trans_array_constructor_value): Fold
+ convert numeric constants.
+ (gfc_build_constant_array_constructor): The same.
+
+2009-05-10 Paul Thomas <pault@gcc.gnu.org>
+
+ Backport from mainline:
+ PR fortran/38863
+ * trans-expr.c (gfc_conv_operator_assign): Remove function.
+ * trans.h : Remove prototype for gfc_conv_operator_assign.
+ * trans-stmt.c (gfc_conv_elemental_dependencies): Initialize
+ derivde types with intent(out).
+ (gfc_trans_call): Add mask, count1 and invert arguments. Add
+ code to use mask for WHERE assignments.
+ (gfc_trans_forall_1): Use new arguments for gfc_trans_call.
+ (gfc_trans_where_assign): The gfc_symbol argument is replaced
+ by the corresponding code. If this has a resolved_sym, then
+ gfc_trans_call is called. The call to gfc_conv_operator_assign
+ is removed.
+ (gfc_trans_where_2): Change the last argument in the call to
+ gfc_trans_where_assign.
+ * trans-stmt.h : Modify prototype for gfc_trans_call.
+ * trans.c (gfc_trans_code): Use new args for gfc_trans_call.
+
+2009-05-10 Paul Thomas <pault@gcc.gnu.org>
+
+ Backport from mainline:
+ PR fortran/39879
+ * trans_expr.c (gfc_conv_procedure_call): Deep copy a derived
+ type parentheses argument if it is a variable with allocatable
+ components.
+
2009-04-22 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Backport from mainline:
diff --git a/gcc/fortran/data.c b/gcc/fortran/data.c
index 09dde150b22..5829c7f9c67 100644
--- a/gcc/fortran/data.c
+++ b/gcc/fortran/data.c
@@ -416,7 +416,11 @@ gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index)
}
if (ref || last_ts->type == BT_CHARACTER)
- expr = create_character_intializer (init, last_ts, ref, rvalue);
+ {
+ if (lvalue->ts.cl->length == NULL && !(ref && ref->u.ss.length != NULL))
+ return FAILURE;
+ expr = create_character_intializer (init, last_ts, ref, rvalue);
+ }
else
{
/* Overwriting an existing initializer is non-standard but usually only
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index d5a9f54a76a..bb4b3738554 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -4738,7 +4738,7 @@ read_md5_from_module_file (const char * filename, unsigned char md5[16])
if ((file = fopen (filename, "r")) == NULL)
return -1;
- /* Read two lines. */
+ /* Read the first line. */
if (fgets (buf, sizeof (buf) - 1, file) == NULL)
{
fclose (file);
@@ -4748,8 +4748,12 @@ read_md5_from_module_file (const char * filename, unsigned char md5[16])
/* The file also needs to be overwritten if the version number changed. */
n = strlen ("GFORTRAN module version '" MOD_VERSION "' created");
if (strncmp (buf, "GFORTRAN module version '" MOD_VERSION "' created", n) != 0)
- return -1;
+ {
+ fclose (file);
+ return -1;
+ }
+ /* Read a second line. */
if (fgets (buf, sizeof (buf) - 1, file) == NULL)
{
fclose (file);
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 7be4671acfb..8b84d65f8e8 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -2410,10 +2410,13 @@ gfc_simplify_leadz (gfc_expr *e)
bs = gfc_integer_kinds[i].bit_size;
if (mpz_cmp_si (e->value.integer, 0) == 0)
lz = bs;
+ else if (mpz_cmp_si (e->value.integer, 0) < 0)
+ lz = 0;
else
lz = bs - mpz_sizeinbase (e->value.integer, 2);
- result = gfc_constant_result (BT_INTEGER, gfc_default_integer_kind, &e->where);
+ result = gfc_constant_result (BT_INTEGER, gfc_default_integer_kind,
+ &e->where);
mpz_set_ui (result->value.integer, lz);
return result;
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 6c623504af8..8edfd685542 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -1246,10 +1246,11 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
gfc_init_se (&se, NULL);
gfc_conv_constant (&se, p->expr);
+ if (c->expr->ts.type != BT_CHARACTER)
+ se.expr = fold_convert (type, se.expr);
/* For constant character array constructors we build
an array of pointers. */
- if (p->expr->ts.type == BT_CHARACTER
- && POINTER_TYPE_P (type))
+ else if (POINTER_TYPE_P (type))
se.expr = gfc_build_addr_expr
(gfc_get_pchar_type (p->expr->ts.kind),
se.expr);
@@ -1618,7 +1619,9 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
{
gfc_init_se (&se, NULL);
gfc_conv_constant (&se, c->expr);
- if (c->expr->ts.type == BT_CHARACTER && POINTER_TYPE_P (type))
+ if (c->expr->ts.type != BT_CHARACTER)
+ se.expr = fold_convert (type, se.expr);
+ else if (POINTER_TYPE_P (type))
se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
se.expr);
list = tree_cons (build_int_cst (gfc_array_index_type, nelem),
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index d6539356679..8e67e8fd3d6 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -141,6 +141,8 @@ tree gfor_fndecl_convert_char4_to_char1;
tree gfor_fndecl_size0;
tree gfor_fndecl_size1;
tree gfor_fndecl_iargc;
+tree gfor_fndecl_clz128;
+tree gfor_fndecl_ctz128;
/* Intrinsic functions implemented in Fortran. */
tree gfor_fndecl_sc_kind;
@@ -2485,6 +2487,19 @@ gfc_build_intrinsic_function_decls (void)
gfc_build_library_function_decl (get_identifier (PREFIX ("iargc")),
gfc_int4_type_node,
0);
+
+ if (gfc_type_for_size (128, true))
+ {
+ tree uint128 = gfc_type_for_size (128, true);
+
+ gfor_fndecl_clz128 =
+ gfc_build_library_function_decl (get_identifier (PREFIX ("clz128")),
+ integer_type_node, 1, uint128);
+
+ gfor_fndecl_ctz128 =
+ gfc_build_library_function_decl (get_identifier (PREFIX ("ctz128")),
+ integer_type_node, 1, uint128);
+ }
}
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 8c869f977ca..f8d09c713f3 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -1526,48 +1526,6 @@ gfc_conv_function_val (gfc_se * se, gfc_symbol * sym)
}
-/* Translate the call for an elemental subroutine call used in an operator
- assignment. This is a simplified version of gfc_conv_function_call. */
-
-tree
-gfc_conv_operator_assign (gfc_se *lse, gfc_se *rse, gfc_symbol *sym)
-{
- tree args;
- tree tmp;
- gfc_se se;
- stmtblock_t block;
-
- /* Only elemental subroutines with two arguments. */
- gcc_assert (sym->attr.elemental && sym->attr.subroutine);
- gcc_assert (sym->formal->next->next == NULL);
-
- gfc_init_block (&block);
-
- gfc_add_block_to_block (&block, &lse->pre);
- gfc_add_block_to_block (&block, &rse->pre);
-
- /* Build the argument list for the call, including hidden string lengths. */
- args = gfc_chainon_list (NULL_TREE, build_fold_addr_expr (lse->expr));
- args = gfc_chainon_list (args, build_fold_addr_expr (rse->expr));
- if (lse->string_length != NULL_TREE)
- args = gfc_chainon_list (args, lse->string_length);
- if (rse->string_length != NULL_TREE)
- args = gfc_chainon_list (args, rse->string_length);
-
- /* Build the function call. */
- gfc_init_se (&se, NULL);
- gfc_conv_function_val (&se, sym);
- tmp = TREE_TYPE (TREE_TYPE (TREE_TYPE (se.expr)));
- tmp = build_call_list (tmp, se.expr, args);
- gfc_add_expr_to_block (&block, tmp);
-
- gfc_add_block_to_block (&block, &lse->post);
- gfc_add_block_to_block (&block, &rse->post);
-
- return gfc_finish_block (&block);
-}
-
-
/* Initialize MAPPING. */
void
@@ -2782,7 +2740,18 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym,
break;
}
+ if (e->expr_type == EXPR_OP
+ && e->value.op.op == INTRINSIC_PARENTHESES
+ && e->value.op.op1->expr_type == EXPR_VARIABLE)
+ {
+ tree local_tmp;
+ local_tmp = gfc_evaluate_now (tmp, &se->pre);
+ local_tmp = gfc_copy_alloc_comp (e->ts.derived, local_tmp, tmp, parm_rank);
+ gfc_add_expr_to_block (&se->post, local_tmp);
+ }
+
tmp = gfc_deallocate_alloc_comp (e->ts.derived, tmp, parm_rank);
+
gfc_add_expr_to_block (&se->post, tmp);
}
@@ -4430,11 +4399,14 @@ gfc_trans_zero_assign (gfc_expr * expr)
len = fold_build2 (MULT_EXPR, gfc_array_index_type, len,
fold_convert (gfc_array_index_type, tmp));
- /* Convert arguments to the correct types. */
+ /* If we are zeroing a local array avoid taking its address by emitting
+ a = {} instead. */
if (!POINTER_TYPE_P (TREE_TYPE (dest)))
- dest = gfc_build_addr_expr (pvoid_type_node, dest);
- else
- dest = fold_convert (pvoid_type_node, dest);
+ return build2 (MODIFY_EXPR, void_type_node,
+ dest, build_constructor (TREE_TYPE (dest), NULL));
+
+ /* Convert arguments to the correct types. */
+ dest = fold_convert (pvoid_type_node, dest);
len = fold_convert (size_type_node, len);
/* Construct call to __builtin_memset. */
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 563ec94a355..bf5d51086ee 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -2707,53 +2707,51 @@ gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
tree leadz;
tree bit_size;
tree tmp;
- int arg_kind;
- int i, n, s;
+ tree func;
+ int s, argsize;
gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
+ argsize = TYPE_PRECISION (TREE_TYPE (arg));
/* Which variant of __builtin_clz* should we call? */
- arg_kind = expr->value.function.actual->expr->ts.kind;
- i = gfc_validate_kind (BT_INTEGER, arg_kind, false);
- switch (arg_kind)
+ if (argsize <= INT_TYPE_SIZE)
{
- case 1:
- case 2:
- case 4:
- arg_type = unsigned_type_node;
- n = BUILT_IN_CLZ;
- break;
-
- case 8:
- arg_type = long_unsigned_type_node;
- n = BUILT_IN_CLZL;
- break;
-
- case 16:
- arg_type = long_long_unsigned_type_node;
- n = BUILT_IN_CLZLL;
- break;
-
- default:
- gcc_unreachable ();
+ arg_type = unsigned_type_node;
+ func = built_in_decls[BUILT_IN_CLZ];
+ }
+ else if (argsize <= LONG_TYPE_SIZE)
+ {
+ arg_type = long_unsigned_type_node;
+ func = built_in_decls[BUILT_IN_CLZL];
+ }
+ else if (argsize <= LONG_LONG_TYPE_SIZE)
+ {
+ arg_type = long_long_unsigned_type_node;
+ func = built_in_decls[BUILT_IN_CLZLL];
+ }
+ else
+ {
+ gcc_assert (argsize == 128);
+ arg_type = gfc_build_uint_type (argsize);
+ func = gfor_fndecl_clz128;
}
- /* Convert the actual argument to the proper argument type for the built-in
+ /* Convert the actual argument twice: first, to the unsigned type of the
+ same size; then, to the proper argument type for the built-in
function. But the return type is of the default INTEGER kind. */
+ arg = fold_convert (gfc_build_uint_type (argsize), arg);
arg = fold_convert (arg_type, arg);
result_type = gfc_get_int_type (gfc_default_integer_kind);
/* Compute LEADZ for the case i .ne. 0. */
- s = TYPE_PRECISION (arg_type) - gfc_integer_kinds[i].bit_size;
- tmp = fold_convert (result_type, build_call_expr (built_in_decls[n], 1, arg));
+ s = TYPE_PRECISION (arg_type) - argsize;
+ tmp = fold_convert (result_type, build_call_expr (func, 1, arg));
leadz = fold_build2 (MINUS_EXPR, result_type,
tmp, build_int_cst (result_type, s));
/* Build BIT_SIZE. */
- bit_size = build_int_cst (result_type, gfc_integer_kinds[i].bit_size);
+ bit_size = build_int_cst (result_type, argsize);
- /* ??? For some combinations of targets and integer kinds, the condition
- can be avoided if CLZ_DEFINED_VALUE_AT_ZERO is used. Later. */
cond = fold_build2 (EQ_EXPR, boolean_type_node,
arg, build_int_cst (arg_type, 0));
se->expr = fold_build3 (COND_EXPR, result_type, cond, bit_size, leadz);
@@ -2774,50 +2772,48 @@ gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
tree result_type;
tree trailz;
tree bit_size;
- int arg_kind;
- int i, n;
+ tree func;
+ int argsize;
gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
+ argsize = TYPE_PRECISION (TREE_TYPE (arg));
- /* Which variant of __builtin_clz* should we call? */
- arg_kind = expr->value.function.actual->expr->ts.kind;
- i = gfc_validate_kind (BT_INTEGER, arg_kind, false);
- switch (expr->ts.kind)
+ /* Which variant of __builtin_ctz* should we call? */
+ if (argsize <= INT_TYPE_SIZE)
{
- case 1:
- case 2:
- case 4:
- arg_type = unsigned_type_node;
- n = BUILT_IN_CTZ;
- break;
-
- case 8:
- arg_type = long_unsigned_type_node;
- n = BUILT_IN_CTZL;
- break;
-
- case 16:
- arg_type = long_long_unsigned_type_node;
- n = BUILT_IN_CTZLL;
- break;
-
- default:
- gcc_unreachable ();
+ arg_type = unsigned_type_node;
+ func = built_in_decls[BUILT_IN_CTZ];
+ }
+ else if (argsize <= LONG_TYPE_SIZE)
+ {
+ arg_type = long_unsigned_type_node;
+ func = built_in_decls[BUILT_IN_CTZL];
+ }
+ else if (argsize <= LONG_LONG_TYPE_SIZE)
+ {
+ arg_type = long_long_unsigned_type_node;
+ func = built_in_decls[BUILT_IN_CTZLL];
+ }
+ else
+ {
+ gcc_assert (argsize == 128);
+ arg_type = gfc_build_uint_type (argsize);
+ func = gfor_fndecl_ctz128;
}
- /* Convert the actual argument to the proper argument type for the built-in
+ /* Convert the actual argument twice: first, to the unsigned type of the
+ same size; then, to the proper argument type for the built-in
function. But the return type is of the default INTEGER kind. */
+ arg = fold_convert (gfc_build_uint_type (argsize), arg);
arg = fold_convert (arg_type, arg);
result_type = gfc_get_int_type (gfc_default_integer_kind);
/* Compute TRAILZ for the case i .ne. 0. */
- trailz = fold_convert (result_type, build_call_expr (built_in_decls[n], 1, arg));
+ trailz = fold_convert (result_type, build_call_expr (func, 1, arg));
/* Build BIT_SIZE. */
- bit_size = build_int_cst (result_type, gfc_integer_kinds[i].bit_size);
+ bit_size = build_int_cst (result_type, argsize);
- /* ??? For some combinations of targets and integer kinds, the condition
- can be avoided if CTZ_DEFINED_VALUE_AT_ZERO is used. Later. */
cond = fold_build2 (EQ_EXPR, boolean_type_node,
arg, build_int_cst (arg_type, 0));
se->expr = fold_build3 (COND_EXPR, result_type, cond, bit_size, trailz);
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 42f0ac438ab..ec001f3fd90 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -270,9 +270,11 @@ gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
gfc_conv_expr_descriptor (&parmse, e, gfc_walk_expr (e));
gfc_add_block_to_block (&se->pre, &parmse.pre);
- /* If we've got INTENT(INOUT), initialize the array temporary with
- a copy of the values. */
- if (fsym->attr.intent == INTENT_INOUT)
+ /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
+ initialize the array temporary with a copy of the values. */
+ if (fsym->attr.intent == INTENT_INOUT
+ || (fsym->ts.type ==BT_DERIVED
+ && fsym->attr.intent == INTENT_OUT))
initial = parmse.expr;
else
initial = NULL_TREE;
@@ -332,12 +334,16 @@ gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
/* Translate the CALL statement. Builds a call to an F95 subroutine. */
tree
-gfc_trans_call (gfc_code * code, bool dependency_check)
+gfc_trans_call (gfc_code * code, bool dependency_check,
+ tree mask, tree count1, bool invert)
{
gfc_se se;
gfc_ss * ss;
int has_alternate_specifier;
gfc_dep_check check_variable;
+ tree index = NULL_TREE;
+ tree maskexpr = NULL_TREE;
+ tree tmp;
/* A CALL starts a new block because the actual arguments may have to
be evaluated first. */
@@ -429,10 +435,31 @@ gfc_trans_call (gfc_code * code, bool dependency_check)
gfc_start_scalarized_body (&loop, &body);
gfc_init_block (&block);
+ if (mask && count1)
+ {
+ /* Form the mask expression according to the mask. */
+ index = count1;
+ maskexpr = gfc_build_array_ref (mask, index, NULL);
+ if (invert)
+ maskexpr = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (maskexpr),
+ maskexpr);
+ }
+
/* Add the subroutine call to the block. */
- gfc_conv_function_call (&loopse, code->resolved_sym, code->ext.actual,
- NULL_TREE);
- gfc_add_expr_to_block (&loopse.pre, loopse.expr);
+ gfc_conv_function_call (&loopse, code->resolved_sym,
+ code->ext.actual, NULL_TREE);
+
+ if (mask && count1)
+ {
+ tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
+ build_empty_stmt ());
+ gfc_add_expr_to_block (&loopse.pre, tmp);
+ tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
+ count1, gfc_index_one_node);
+ gfc_add_modify (&loopse.pre, count1, tmp);
+ }
+ else
+ gfc_add_expr_to_block (&loopse.pre, loopse.expr);
gfc_add_block_to_block (&block, &loopse.pre);
gfc_add_block_to_block (&block, &loopse.post);
@@ -2981,7 +3008,7 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
/* Explicit subroutine calls are prevented by the frontend but interface
assignments can legitimately produce them. */
case EXEC_ASSIGN_CALL:
- assign = gfc_trans_call (c, true);
+ assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
gfc_add_expr_to_block (&block, tmp);
break;
@@ -3176,7 +3203,7 @@ static tree
gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
tree mask, bool invert,
tree count1, tree count2,
- gfc_symbol *sym)
+ gfc_code *cnext)
{
gfc_se lse;
gfc_se rse;
@@ -3190,6 +3217,10 @@ gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
stmtblock_t body;
tree index, maskexpr;
+ /* A defined assignment. */
+ if (cnext && cnext->resolved_sym)
+ return gfc_trans_call (cnext, true, mask, count1, invert);
+
#if 0
/* TODO: handle this special case.
Special case a single function returning an array. */
@@ -3291,11 +3322,8 @@ gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
maskexpr = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (maskexpr), maskexpr);
/* Use the scalar assignment as is. */
- if (sym == NULL)
- tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
- loop.temp_ss != NULL, false);
- else
- tmp = gfc_conv_operator_assign (&lse, &rse, sym);
+ tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
+ loop.temp_ss != NULL, false);
tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
@@ -3562,7 +3590,7 @@ gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
tmp = gfc_trans_where_assign (expr1, expr2,
cmask, invert,
count1, count2,
- cnext->resolved_sym);
+ cnext);
tmp = gfc_trans_nested_forall_loop (nested_forall_info,
tmp, 1);
@@ -3580,7 +3608,7 @@ gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
tmp = gfc_trans_where_assign (expr1, expr2,
cmask, invert,
count1, count2,
- cnext->resolved_sym);
+ cnext);
gfc_add_expr_to_block (block, tmp);
}
diff --git a/gcc/fortran/trans-stmt.h b/gcc/fortran/trans-stmt.h
index 5d92a9c756f..d7307df2a82 100644
--- a/gcc/fortran/trans-stmt.h
+++ b/gcc/fortran/trans-stmt.h
@@ -39,7 +39,7 @@ tree gfc_trans_goto (gfc_code *);
tree gfc_trans_entry (gfc_code *);
tree gfc_trans_pause (gfc_code *);
tree gfc_trans_stop (gfc_code *);
-tree gfc_trans_call (gfc_code *, bool);
+tree gfc_trans_call (gfc_code *, bool, tree, tree, bool);
tree gfc_trans_return (gfc_code *);
tree gfc_trans_if (gfc_code *);
tree gfc_trans_arithmetic_if (gfc_code *);
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index fa91578b8f9..ca040e42405 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -595,7 +595,7 @@ gfc_build_int_type (gfc_integer_info *info)
return make_signed_type (mode_precision);
}
-static tree
+tree
gfc_build_uint_type (int size)
{
if (size == CHAR_TYPE_SIZE)
diff --git a/gcc/fortran/trans-types.h b/gcc/fortran/trans-types.h
index 7074913d4ef..1eadbc0e75b 100644
--- a/gcc/fortran/trans-types.h
+++ b/gcc/fortran/trans-types.h
@@ -68,6 +68,7 @@ tree gfc_get_function_type (gfc_symbol *);
tree gfc_type_for_size (unsigned, int);
tree gfc_type_for_mode (enum machine_mode, int);
+tree gfc_build_uint_type (int);
tree gfc_get_element_type (tree);
tree gfc_get_array_type_bounds (tree, int, tree *, tree *, int,
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 628c2a08346..8f046d3d6b1 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -1109,12 +1109,14 @@ gfc_trans_code (gfc_code * code)
if (code->resolved_isym
&& code->resolved_isym->id == GFC_ISYM_MVBITS)
is_mvbits = true;
- res = gfc_trans_call (code, is_mvbits);
+ res = gfc_trans_call (code, is_mvbits, NULL_TREE,
+ NULL_TREE, false);
}
break;
case EXEC_ASSIGN_CALL:
- res = gfc_trans_call (code, true);
+ res = gfc_trans_call (code, true, NULL_TREE,
+ NULL_TREE, false);
break;
case EXEC_RETURN:
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index f5fa658b8d9..3a931da4b79 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -310,9 +310,6 @@ void gfc_conv_intrinsic_function (gfc_se *, gfc_expr *);
/* Does an intrinsic map directly to an external library call. */
int gfc_is_intrinsic_libcall (gfc_expr *);
-/* Used to call the elemental subroutines used in operator assignments. */
-tree gfc_conv_operator_assign (gfc_se *, gfc_se *, gfc_symbol *);
-
/* Also used to CALL subroutines. */
int gfc_conv_function_call (gfc_se *, gfc_symbol *, gfc_actual_arglist *,
tree);
@@ -594,6 +591,8 @@ extern GTY(()) tree gfor_fndecl_convert_char4_to_char1;
extern GTY(()) tree gfor_fndecl_size0;
extern GTY(()) tree gfor_fndecl_size1;
extern GTY(()) tree gfor_fndecl_iargc;
+extern GTY(()) tree gfor_fndecl_clz128;
+extern GTY(()) tree gfor_fndecl_ctz128;
/* Implemented in Fortran. */
extern GTY(()) tree gfor_fndecl_sc_kind;
diff --git a/gcc/gimple.h b/gcc/gimple.h
index ddcdc4a8952..b4ab9d6dfd0 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1398,35 +1398,6 @@ gimple_modified_p (const_gimple g)
return (gimple_has_ops (g)) ? (bool) g->gsbase.modified : false;
}
-/* Return the type of the main expression computed by STMT. Return
- void_type_node if the statement computes nothing. */
-
-static inline tree
-gimple_expr_type (const_gimple stmt)
-{
- enum gimple_code code = gimple_code (stmt);
-
- if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL)
- {
- tree type = TREE_TYPE (gimple_get_lhs (stmt));
- /* Integral sub-types are never the type of the expression,
- but they still can be the type of the result as the base
- type (in which expressions are computed) is trivially
- convertible to one of its sub-types. So always return
- the base type here. */
- if (INTEGRAL_TYPE_P (type)
- && TREE_TYPE (type)
- /* But only if they are trivially convertible. */
- && useless_type_conversion_p (type, TREE_TYPE (type)))
- type = TREE_TYPE (type);
- return type;
- }
- else if (code == GIMPLE_COND)
- return boolean_type_node;
- else
- return void_type_node;
-}
-
/* Return the tree code for the expression computed by STMT. This is
only valid for GIMPLE_COND, GIMPLE_CALL and GIMPLE_ASSIGN. For
@@ -4360,6 +4331,55 @@ gimple_predict_set_outcome (gimple gs, enum prediction outcome)
}
+/* Return the type of the main expression computed by STMT. Return
+ void_type_node if the statement computes nothing. */
+
+static inline tree
+gimple_expr_type (const_gimple stmt)
+{
+ enum gimple_code code = gimple_code (stmt);
+
+ if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL)
+ {
+ tree type;
+ /* In general we want to pass out a type that can be substituted
+ for both the RHS and the LHS types if there is a possibly
+ useless conversion involved. That means returning the
+ original RHS type as far as we can reconstruct it. */
+ if (code == GIMPLE_CALL)
+ type = gimple_call_return_type (stmt);
+ else
+ switch (gimple_assign_rhs_code (stmt))
+ {
+ case POINTER_PLUS_EXPR:
+ type = TREE_TYPE (gimple_assign_rhs1 (stmt));
+ break;
+
+ default:
+ /* As fallback use the type of the LHS. */
+ type = TREE_TYPE (gimple_get_lhs (stmt));
+ break;
+ }
+
+ /* Integral sub-types are never the type of the expression,
+ but they still can be the type of the result as the base
+ type (in which expressions are computed) is trivially
+ convertible to one of its sub-types. So always return
+ the base type here. */
+ if (INTEGRAL_TYPE_P (type)
+ && TREE_TYPE (type)
+ /* But only if they are trivially convertible. */
+ && useless_type_conversion_p (type, TREE_TYPE (type)))
+ type = TREE_TYPE (type);
+ return type;
+ }
+ else if (code == GIMPLE_COND)
+ return boolean_type_node;
+ else
+ return void_type_node;
+}
+
+
/* Return a new iterator pointing to GIMPLE_SEQ's first statement. */
static inline gimple_stmt_iterator
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 8ed42636642..b9ae0845976 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1628,20 +1628,63 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
}
len = i;
+ if (!VEC_empty (tree, labels))
+ sort_case_labels (labels);
+
if (!default_case)
{
- gimple new_default;
+ tree type = TREE_TYPE (switch_expr);
/* If the switch has no default label, add one, so that we jump
- around the switch body. */
- default_case = build3 (CASE_LABEL_EXPR, void_type_node, NULL_TREE,
- NULL_TREE, create_artificial_label ());
- new_default = gimple_build_label (CASE_LABEL (default_case));
- gimplify_seq_add_stmt (&switch_body_seq, new_default);
- }
+ around the switch body. If the labels already cover the whole
+ range of type, add the default label pointing to one of the
+ existing labels. */
+ if (type == void_type_node)
+ type = TREE_TYPE (SWITCH_COND (switch_expr));
+ if (len
+ && INTEGRAL_TYPE_P (type)
+ && TYPE_MIN_VALUE (type)
+ && TYPE_MAX_VALUE (type)
+ && tree_int_cst_equal (CASE_LOW (VEC_index (tree, labels, 0)),
+ TYPE_MIN_VALUE (type)))
+ {
+ tree low, high = CASE_HIGH (VEC_index (tree, labels, len - 1));
+ if (!high)
+ high = CASE_LOW (VEC_index (tree, labels, len - 1));
+ if (tree_int_cst_equal (high, TYPE_MAX_VALUE (type)))
+ {
+ for (i = 1; i < len; i++)
+ {
+ high = CASE_LOW (VEC_index (tree, labels, i));
+ low = CASE_HIGH (VEC_index (tree, labels, i - 1));
+ if (!low)
+ low = CASE_LOW (VEC_index (tree, labels, i - 1));
+ if ((TREE_INT_CST_LOW (low) + 1
+ != TREE_INT_CST_LOW (high))
+ || (TREE_INT_CST_HIGH (low)
+ + (TREE_INT_CST_LOW (high) == 0)
+ != TREE_INT_CST_HIGH (high)))
+ break;
+ }
+ if (i == len)
+ default_case = build3 (CASE_LABEL_EXPR, void_type_node,
+ NULL_TREE, NULL_TREE,
+ CASE_LABEL (VEC_index (tree,
+ labels, 0)));
+ }
+ }
- if (!VEC_empty (tree, labels))
- sort_case_labels (labels);
+ if (!default_case)
+ {
+ gimple new_default;
+
+ default_case = build3 (CASE_LABEL_EXPR, void_type_node,
+ NULL_TREE, NULL_TREE,
+ create_artificial_label ());
+ new_default = gimple_build_label (CASE_LABEL (default_case));
+ gimplify_seq_add_stmt (&switch_body_seq, new_default);
+ }
+ }
gimple_switch = gimple_build_switch_vec (SWITCH_COND (switch_expr),
default_case, labels);
diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h
index 3ccdbafe909..ee6417dfcdd 100644
--- a/gcc/ipa-utils.h
+++ b/gcc/ipa-utils.h
@@ -23,9 +23,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "cgraph.h"
-/* Used for parsing attributes of asm code. */
-extern tree memory_identifier_string;
-
struct ipa_dfs_info {
int dfn_number;
int low_link;
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 55577eca23e..540047ce72e 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -1398,21 +1398,23 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
if (pat != PATTERN (insn))
{
- /* The fix_truncdi_1 pattern wants to be able to allocate
- its own scratch register. It does this by clobbering
- an fp reg so that it is assured of an empty reg-stack
- register. If the register is live, kill it now.
- Remove the DEAD/UNUSED note so we don't try to kill it
- later too. */
+ /* The fix_truncdi_1 pattern wants to be able to
+ allocate its own scratch register. It does this by
+ clobbering an fp reg so that it is assured of an
+ empty reg-stack register. If the register is live,
+ kill it now. Remove the DEAD/UNUSED note so we
+ don't try to kill it later too.
+
+ In reality the UNUSED note can be absent in some
+ complicated cases when the register is reused for
+ partially set variable. */
if (note)
emit_pop_insn (insn, regstack, *dest, EMIT_BEFORE);
else
- {
- note = find_reg_note (insn, REG_UNUSED, *dest);
- gcc_assert (note);
- }
- remove_note (insn, note);
+ note = find_reg_note (insn, REG_UNUSED, *dest);
+ if (note)
+ remove_note (insn, note);
replace_reg (dest, FIRST_STACK_REG + 1);
}
else
diff --git a/gcc/resource.c b/gcc/resource.c
index 419e7706e5f..66ff2085071 100644
--- a/gcc/resource.c
+++ b/gcc/resource.c
@@ -135,8 +135,6 @@ update_live_status (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
static int
find_basic_block (rtx insn, int search_limit)
{
- basic_block bb;
-
/* Scan backwards to the previous BARRIER. Then see if we can find a
label that starts a basic block. Return the basic block number. */
for (insn = prev_nonnote_insn (insn);
@@ -157,11 +155,8 @@ find_basic_block (rtx insn, int search_limit)
for (insn = next_nonnote_insn (insn);
insn && LABEL_P (insn);
insn = next_nonnote_insn (insn))
- {
- FOR_EACH_BB (bb)
- if (insn == BB_HEAD (bb))
- return bb->index;
- }
+ if (BLOCK_FOR_INSN (insn))
+ return BLOCK_FOR_INSN (insn)->index;
return -1;
}
@@ -848,13 +843,12 @@ return_insn_p (const_rtx insn)
(with no intervening active insns) to see if any of them start a basic
block. If we hit the start of the function first, we use block 0.
- Once we have found a basic block and a corresponding first insns, we can
- accurately compute the live status from basic_block_live_regs and
- reg_renumber. (By starting at a label following a BARRIER, we are immune
- to actions taken by reload and jump.) Then we scan all insns between
- that point and our target. For each CLOBBER (or for call-clobbered regs
- when we pass a CALL_INSN), mark the appropriate registers are dead. For
- a SET, mark them as live.
+ Once we have found a basic block and a corresponding first insn, we can
+ accurately compute the live status (by starting at a label following a
+ BARRIER, we are immune to actions taken by reload and jump.) Then we
+ scan all insns between that point and our target. For each CLOBBER (or
+ for call-clobbered regs when we pass a CALL_INSN), mark the appropriate
+ registers are dead. For a SET, mark them as live.
We have to be careful when using REG_DEAD notes because they are not
updated by such things as find_equiv_reg. So keep track of registers
@@ -954,13 +948,10 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
TARGET. Otherwise, we must assume everything is live. */
if (b != -1)
{
- regset regs_live = DF_LR_IN (BASIC_BLOCK (b));
+ regset regs_live = df_get_live_in (BASIC_BLOCK (b));
rtx start_insn, stop_insn;
- /* Compute hard regs live at start of block -- this is the real hard regs
- marked live, plus live pseudo regs that have been renumbered to
- hard regs. */
-
+ /* Compute hard regs live at start of block. */
REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
/* Get starting and ending insn, handling the case where each might
@@ -1049,10 +1040,24 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
else if (LABEL_P (real_insn))
{
+ basic_block bb;
+
/* A label clobbers the pending dead registers since neither
reload nor jump will propagate a value across a label. */
AND_COMPL_HARD_REG_SET (current_live_regs, pending_dead_regs);
CLEAR_HARD_REG_SET (pending_dead_regs);
+
+ /* We must conservatively assume that all registers that used
+ to be live here still are. The fallthrough edge may have
+ left a live register uninitialized. */
+ bb = BLOCK_FOR_INSN (real_insn);
+ if (bb)
+ {
+ HARD_REG_SET extra_live;
+
+ REG_SET_TO_HARD_REG_SET (extra_live, df_get_live_in (bb));
+ IOR_HARD_REG_SET (current_live_regs, extra_live);
+ }
}
/* The beginning of the epilogue corresponds to the end of the
@@ -1124,6 +1129,7 @@ void
init_resource_info (rtx epilogue_insn)
{
int i;
+ basic_block bb;
/* Indicate what resources are required to be valid at the end of the current
function. The condition code never is and memory always is. If the
@@ -1192,6 +1198,11 @@ init_resource_info (rtx epilogue_insn)
/* Allocate and initialize the tables used by mark_target_live_regs. */
target_hash_table = XCNEWVEC (struct target_info *, TARGET_HASH_PRIME);
bb_ticks = XCNEWVEC (int, last_basic_block);
+
+ /* Set the BLOCK_FOR_INSN of each label that starts a basic block. */
+ FOR_EACH_BB (bb)
+ if (LABEL_P (BB_HEAD (bb)))
+ BLOCK_FOR_INSN (BB_HEAD (bb)) = bb;
}
/* Free up the resources allocated to mark_target_live_regs (). This
@@ -1200,6 +1211,8 @@ init_resource_info (rtx epilogue_insn)
void
free_resource_info (void)
{
+ basic_block bb;
+
if (target_hash_table != NULL)
{
int i;
@@ -1225,6 +1238,10 @@ free_resource_info (void)
free (bb_ticks);
bb_ticks = NULL;
}
+
+ FOR_EACH_BB (bb)
+ if (LABEL_P (BB_HEAD (bb)))
+ BLOCK_FOR_INSN (BB_HEAD (bb)) = NULL;
}
/* Clear any hashed information that we have stored for INSN. */
diff --git a/gcc/rtl.def b/gcc/rtl.def
index 9c6f235caa1..5a4eb4f24dc 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -2,7 +2,7 @@
Register Transfer Expressions (rtx's) that make up the
Register Transfer Language (rtl) used in the Back End of the GNU compiler.
Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2004,
- 2005, 2006, 2007, 2008
+ 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
@@ -81,6 +81,13 @@ along with GCC; see the file COPYING3. If not see
value zero. */
DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", RTX_EXTRA)
+/* Used in the cselib routines to describe a value. Objects of this
+ kind are only allocated in cselib.c, in an alloc pool instead of in
+ GC memory. The only operand of a VALUE is a cselib_val_struct.
+ var-tracking requires this to have a distinct integral value from
+ DECL codes in trees. */
+DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
+
/* ---------------------------------------------------------------------
Expressions used in constructing lists.
--------------------------------------------------------------------- */
@@ -328,11 +335,6 @@ DEF_RTL_EXPR(CONST, "const", "e", RTX_CONST_OBJ)
by a SET whose first operand is (PC). */
DEF_RTL_EXPR(PC, "pc", "", RTX_OBJ)
-/* Used in the cselib routines to describe a value. Objects of this
- kind are only allocated in cselib.c, in an alloc pool instead of
- in GC memory. The only operand of a VALUE is a cselib_val_struct. */
-DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
-
/* A register. The "operand" is the register number, accessed with
the REGNO macro. If this number is less than FIRST_PSEUDO_REGISTER
than a hardware register is being referred to. The second operand
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c7e34c6143c..2ec1d112a26 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,342 @@
+2009-06-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40446
+ * g++.dg/other/pr40446.C: New test.
+
+2009-06-14 Richard Guenther <rguenther@suse.de>
+
+ Backport from mainline
+ 2009-05-18 Richard Guenther <rguenther@suse.de>
+
+ PR fortran/40168
+ * gfortran.dg/array_memset_2.f90: Adjust.
+
+2009-06-09 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/defaulted10.C: New.
+
+2009-06-08 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/auto15.C: New.
+
+2009-06-08 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libfortran/40334
+ * gfortran.dg/backspace_11.f90: New test.
+
+2009-06-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/40373
+ * g++.dg/template/dtor7.C: New test.
+
+ PR c++/40370
+ PR c++/40372
+ * g++.dg/template/error41.C: New test.
+ * g++.dg/template/error42.C: New test.
+
+2009-06-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-06-03 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/40328
+ * gcc.dg/torture/pr40328.c: New testcase.
+
+2009-06-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-06-07 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR middle-end/32950
+ * g++.dg/torture/pr32950.C: New.
+
+2009-06-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40340
+ * gcc.dg/pr40340-1.c: New test.
+ * gcc.dg/pr40340-2.c: New test.
+ * gcc.dg/pr40340-3.c: New test.
+ * gcc.dg/pr40340-4.c: New test.
+ * gcc.dg/pr40340-5.c: New test.
+ * gcc.dg/pr40340.h: New file.
+
+2009-06-04 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/39893
+ * gfortran.dg/assumed_charlen_dummy.f90: New Test.
+
+2009-06-04 Richard Guenther <rguenther@suse.de>
+
+ PR c++/39371
+ * g++.dg/torture/pr40335.C: New testcase.
+
+2009-06-03 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/40019
+ * gfortran.dg/leadz_trailz_1.f90: New test.
+ * gfortran.dg/leadz_trailz_2.f90: New test.
+
+2009-06-02 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/initlist13.C: Remove expected error.
+ * g++.dg/cpp0x/initlist18.C: New.
+ * g++.dg/cpp0x/initlist19.C: New.
+
+ * g++.dg/cpp0x/auto14.C: New.
+
+2009-05-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * g++.dg/template/typedef19.C: XFAIL.
+ * g++.dg/template/typedef20.C: Likewise.
+
+2009-05-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+
+ 2009-05-28 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/39754
+ * g++.dg/template/canon-type-1.C: New test.
+ * g++.dg/template/canon-type-2.C: Likewise.
+ * g++.dg/template/canon-type-3.C: Likewise.
+ * g++.dg/template/canon-type-4.C: Likewise.
+ * g++.dg/template/canon-type-5.C: Likewise.
+ * g++.dg/template/canon-type-6.C: Likewise.
+ * g++.dg/template/canon-type-7.C: Likewise.
+
+ 2009-05-28 Ira Rosen <irar@il.ibm.com>
+
+ PR tree-optimization/40254
+ * gcc.dg/vect/pr40254.c: New test.
+
+ 2009-05-26 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/40252
+ * gcc.c-torture/compile/pr40252.c: New testcase.
+
+ 2009-05-26 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/40007
+ * g++.dg/template/typedef18.C: New test.
+ * g++.dg/template/typedef19.C: Likewise.
+ * g++.dg/template/typedef20.C: Likewise.
+
+ 2009-05-25 Ira Rosen <irar@il.ibm.com>
+
+ PR tree-optimization/40238
+ * gcc.dg/vect/pr40238.c: New test.
+
+ 2009-05-24 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/40233
+ * gcc.c-torture/compile/pr40233.c: New testcase.
+
+2009-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40291
+ * gcc.c-torture/compile/pr40291.c: New test.
+
+ PR target/40017
+ * gcc.target/powerpc/altivec-types-1.c: Don't expect error for
+ __vector _Bool.
+ * gcc.target/powerpc/altivec-30.c: New test.
+ * gcc.target/powerpc/altivec-31.c: New test.
+
+2009-05-27 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/initlist15.C: New.
+ * g++.dg/cpp0x/initlist16.C: New.
+ * g++.dg/cpp0x/initlist17.C: New.
+
+2009-05-28 Kai Tietz <kai.tietz@onevision.com>
+
+ * g++.dg/ext/packed6.C (size_t): Use __extension__ and
+ __SIZE_TYPE__.
+ * g++.dg/opt/memcpy1.C (size_t): Likewise.
+ * g++.dg/pr37742.C (size_t): Likewise.
+ * g++.dg/torture/pr34850.C (size_t): Likewise.
+ * g++.dg/torture/20070621-1.C (ptrdiff_t): Use __extension__ and
+ _PTRDIFF_TYPE__.
+ * g++.dg/torture/pr34222.C (ptrdiff_t): Likewise.
+ * g++.dg/tree-ssa/pr22444.C (ptrdiff_t): Likewise.
+ (size_t): Use __extension__ and __SIZE_TYPE__.
+ * gcc.c-torture/compile/20000211-1.c (size_t): Typedef size_t via
+ __SIZE_TYPE__.
+ * gcc.c-torture/compile/20010328-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/20030320-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/20030405-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/20030902-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/20060202-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/20080613-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/920428-2.c (size_t): Likewise,
+ * gcc.c-torture/compile/980329-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/980816-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/pr32584.c (size_t): Likewise,
+ * (__ssize_t): Likewise.
+ * gcc.c-torture/compile/pr33173.c (size_t): Likewise,
+ * gcc.c-torture/compile/pr33382.c (size_t): Likewise,
+ * gcc.c-torture/compile/pr34334.c (size_t): Likewise,
+ * gcc.c-torture/compile/pr34688.c (size_t): Likewise,
+ * gcc.c-torture/compile/pr35043.c (size_t): Likewise,
+ * gcc.c-torture/compile/pr37669.c (size_t): Likewise,
+ * gcc.dg/20050629-1.c (size_t): Typedef size_t via __SIZE_TYPE__.
+ * gcc.dg/pr33667.c (size_t): Likewise.
+ * gcc.dg/prefetch-loop-arrays-1.c (size_t): Likewise.
+ * gcc.dg/torture/pr39204.c (size_t): Likewise.
+ * gcc.dg/tree-ssa/20041122-1.c (size_t): Likewise.
+ * gcc.dg/tree-ssa/pr36908.c (size_t): Likewise.
+ * gcc.dg/tree-ssa/pr38250.c (size_t): Likewise.
+ * gcc.dg/tree-ssa/ssa-dse-10.c (size_t): Likewise.
+
+2009-05-27 Kai TIetz <kai.tietz@onevision.com>
+
+ * g++.old-deja/g++.brendan/array1.C (array): Use __SIZE_TYPE__
+ cast instead of assuming 0ul.
+ * g++.old-deja/g++.brendan/crash64.C (size_t): Define it via
+ __SIZE_TYPE__.
+ (_type_desc): Make first argument const.
+ * g++.old-deja/g++.jason/new3.C (dg-options): Add -Wno-long-long.
+
+2009-05-25 Jason Merrill <jason@redhat.com>
+
+ PR c++/38064
+ * g++.dg/cpp0x/enum3.C: New test.
+
+2009-05-22 Zdenek Dvorak <ook@ucw.cz>
+
+ PR tree-optimization/40087
+ * gcc.dg/tree-ssa/pr40087.c: New test.
+
+2009-05-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40204
+ * gcc.c-torture/compile/pr40204.c: New test.
+
+2009-05-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-05-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR c/40172
+ * gcc.dg/pr40172-1.c: New.
+ * gcc.dg/pr40172-2.c: Likewise.
+ * gcc.dg/pr40172-3.c: Likewise.
+
+2009-05-19 Richard Guenther <rguenther@suse.de>
+
+ * gcc.c-torture/compile/20090519-1.c: New testcase.
+
+2009-05-18 Dodji Seketeli <dodji@redhat.com>
+
+ PR debug/40109
+ * g++.dg/debug/dwarf2/nested-1.C: New test.
+
+2009-05-18 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-05-18 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR testsuite/39907
+ * gcc.target/x86_64/abi/asm-support.S (snapshot_ret): Preserve
+ stack alignment.
+
+2009-05-18 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/39999
+ * gcc.c-torture/compile/pr39999.c: New testcase.
+
+2009-05-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/40139
+ * g++.dg/template/dtor6.C: New.
+
+2009-05-16 David Billinghurst <billingd@gcc.gnu.org>
+
+ * gfortran.dg/default_format_denormal_1.f90: XFAIL on cygwin.
+ * gfortran.dg/default_format_1.f90: Revert change of 2009-05-12
+
+2009-05-14 Ben Elliston <bje@au.ibm.com>
+
+ Backport from mainline:
+ 2009-05-14 Ben Elliston <bje@au.ibm.com>
+
+ PR middle-end/40035
+ * gcc.c-torture/compile/pr40035.c: New test.
+
+2009-05-13 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * gcc.target/i386/pr39543-2.c: Skip if ilp32 && pic.
+
+2009-05-12 Jakub Jelinek <jakub@redhat.com>
+
+ Backport from mainline:
+ 2009-05-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/39666
+ * gcc.dg/pr39666-1.c: New test.
+ * gcc.dg/pr39666-2.c: Likewise.
+ * g++.dg/warn/Wuninitialized-4.C: Likewise.
+ * g++.dg/warn/Wuninitialized-5.C: Likewise.
+ * gfortran.dg/pr39666-1.f90: Likewise.
+ * gfortran.dg/pr39666-2.f90: Likewise.
+
+2009-05-12 David Billinghurst <billingd@gcc.gnu.org>
+
+ * gfortran.dg/default_format_1.f90: XFAIL on cygwin.
+
+2009-05-12 David Billinghurst <billingd@gcc.gnu.org>
+
+ * lib/target-supports.exp (check_profiling_available): Return
+ false for -p on *-*-cygwin* targets.
+
+2009-05-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ 2009-05-11 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR middle-end/40080
+ * gcc.c-torture/compile/pr40080.c: New.
+
+ 2009-05-11 Paolo Bonzini <bonzini@gnu.org>
+
+ * gcc.c-torture/compile/pr40026.c: New testcase.
+
+ 2009-05-09 Jan Hubicka <jh@suse.cz>
+
+ PR middle-end/40043
+ * g++.dg/eh/nested-try.C: New test.
+
+2009-05-11 Ira Rosen <irar@il.ibm.com>
+
+ PR tree-optimization/40074
+ * gcc.dg/vect/pr40074.c: New test.
+
+2009-05-10 Paul Thomas <pault@gcc.gnu.org>
+
+ Backport from mainline:
+ PR fortran/40018
+ * gfortran.dg/array_constructor_31.f90: New test.
+
+2009-05-10 Paul Thomas <pault@gcc.gnu.org>
+
+ Backport from mainline:
+ PR fortran/38863
+ * gfortran.dg/dependency_24.f90: New test.
+
+2009-05-10 Paul Thomas <pault@gcc.gnu.org>
+
+ Backport from mainline:
+ PR fortran/39879
+ * gfortran.dg/alloc_comp_assign_10.f90: New test.
+
+2009-04-10 David Billinghurst <billingd@gcc.gnu.org>
+
+ PR fortran/38956
+ * gfortran.dg/chmod_1.f90: Don't run on *-*-cygwin*.
+ * gfortran.dg/chmod_2.f90: Likewise.
+ * gfortran.dg/chmod_3.f90: Likewise.
+ * gfortran.dg/open_errors.f90: Likewise.
+
2009-05-07 Jakub Jelinek <jakub@redhat.com>
PR middle-end/40057
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto14.C b/gcc/testsuite/g++.dg/cpp0x/auto14.C
new file mode 100644
index 00000000000..cb2c4e0351a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto14.C
@@ -0,0 +1,29 @@
+// PR c++/40306, c++/40307
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+
+template< typename T >
+struct test {
+ test run() {
+ auto tmp = *this;
+ return tmp;
+ }
+ test run_pass() {
+ test tmp( *this );
+ return tmp;
+ }
+
+ test run_fail() {
+ auto tmp( *this );
+ return tmp;
+ }
+};
+
+int main()
+{
+ test<int> x;
+ x.run();
+ x.run_pass();
+ x.run_fail();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto15.C b/gcc/testsuite/g++.dg/cpp0x/auto15.C
new file mode 100644
index 00000000000..b23e1e2fd6f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto15.C
@@ -0,0 +1,13 @@
+// { dg-options "-std=c++0x" }
+
+template< typename Fn > struct function;
+
+template< typename Result, typename ... ArgTypes >
+struct function< auto (ArgTypes...)->Result > {
+};
+
+int main()
+{
+ function< auto(double)->int > y;
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted10.C b/gcc/testsuite/g++.dg/cpp0x/defaulted10.C
new file mode 100644
index 00000000000..d169e0c6007
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted10.C
@@ -0,0 +1,14 @@
+// PR c++/40381
+// { dg-options "-std=gnu++0x" }
+
+struct A
+{
+ template<typename T> void foo(T) = delete; // { dg-error "previously|deleted" }
+};
+
+template<typename T> void A::foo(T) {} // { dg-error "redefinition" }
+
+void bar()
+{
+ A().foo(0); // { dg-error "used" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum3.C b/gcc/testsuite/g++.dg/cpp0x/enum3.C
new file mode 100644
index 00000000000..5555ab2aac8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum3.C
@@ -0,0 +1,17 @@
+// PR c++/38064
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+
+enum class E { elem };
+
+template <class T>
+void f (T t);
+
+bool f (bool b) { return b; }
+
+int main()
+{
+ E e = E::elem;
+ if (!f (e == E::elem))
+ return 1;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist13.C b/gcc/testsuite/g++.dg/cpp0x/initlist13.C
index 98af92bca53..9ed6c74419f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist13.C
@@ -2,4 +2,7 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
-__complex__ int i ({0}); // { dg-error "cannot convert" }
+#include <complex>
+
+__complex__ int i ({0});
+std::complex<int> i2 ({0});
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist15.C b/gcc/testsuite/g++.dg/cpp0x/initlist15.C
new file mode 100644
index 00000000000..d59e5af640b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist15.C
@@ -0,0 +1,17 @@
+// { dg-options "-std=c++0x" }
+
+#include <vector>
+#include <typeinfo>
+
+using namespace std;
+
+template< typename ... ArgTypes >
+void test( ArgTypes ... args ) {
+ vector<type_info*> x = { &typeid(ArgTypes)... }; // { dg-error "" }
+}
+
+int main()
+{
+ test( 1, 3.14f, 2.78 );
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist16.C b/gcc/testsuite/g++.dg/cpp0x/initlist16.C
new file mode 100644
index 00000000000..86a00396051
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist16.C
@@ -0,0 +1,12 @@
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+
+extern "C" void abort();
+
+void f(int i) { if (i != 42) abort(); }
+
+int main()
+{
+ f({42});
+ return {0};
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist17.C b/gcc/testsuite/g++.dg/cpp0x/initlist17.C
new file mode 100644
index 00000000000..86371e81969
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist17.C
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+
+void f(int i);
+
+int main()
+{
+ f({42.0}); // { dg-error "narrowing" }
+ return {1.0}; // { dg-error "narrowing" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist18.C b/gcc/testsuite/g++.dg/cpp0x/initlist18.C
new file mode 100644
index 00000000000..c9a9bcd9415
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist18.C
@@ -0,0 +1,19 @@
+// PR c++/40308, 40311
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+template< typename T >
+struct test {
+ test() : data{} {}
+
+ T data;
+};
+
+int main()
+{
+ test<int> x;
+ test<int*> y;
+ int * a = new int{};
+ int * b = new int{5};
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist19.C b/gcc/testsuite/g++.dg/cpp0x/initlist19.C
new file mode 100644
index 00000000000..418cddc618a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist19.C
@@ -0,0 +1,8 @@
+// { dg-options "-std=c++0x" }
+
+void f(double);
+int main()
+{
+ f({{1}}); // { dg-error "too many braces" }
+ // { dg-error "" "" { target *-*-* } 6 } allow other errors, too
+}
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/nested-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/nested-1.C
new file mode 100644
index 00000000000..336582c112a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/nested-1.C
@@ -0,0 +1,29 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR debug/40109
+// { dg-do compile }
+// { dg-options "-g -dA -O0" }
+
+namespace A
+{
+
+ class B
+ {
+ };
+ typedef A::B AB;
+};
+
+int
+main()
+{
+ A::AB ab;
+ return 0;
+}
+
+// { dg-final { scan-assembler "DW_TAG_typedef" } }
+//
+// What we want to do here is to be sure that the DIE of A::AB is generated
+// as a child of the DIE of the namespace A declaration.
+// So this test won't catch a regression on this fix yet. To write a proper
+// test for this fix, we would need a dwarf reader written in tcl,
+// or something along those lines.
+
diff --git a/gcc/testsuite/g++.dg/eh/nested-try.C b/gcc/testsuite/g++.dg/eh/nested-try.C
new file mode 100644
index 00000000000..5796f9a2806
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/nested-try.C
@@ -0,0 +1,25 @@
+// { dg-do compile }
+// Nested try statements shadowing each other was crashing in EH edge redirection.
+// PR middle-end/40043
+struct A
+{
+ ~A();
+ void foo();
+};
+
+void bar()
+{
+ A a;
+
+ try
+ {
+ A b;
+
+ try
+ {
+ b.foo();
+ }
+ catch (int) {}
+ }
+ catch (int) {}
+}
diff --git a/gcc/testsuite/g++.dg/ext/packed6.C b/gcc/testsuite/g++.dg/ext/packed6.C
index f89aafec163..6a176b62442 100644
--- a/gcc/testsuite/g++.dg/ext/packed6.C
+++ b/gcc/testsuite/g++.dg/ext/packed6.C
@@ -1,7 +1,7 @@
// PR c++/15209
// { dg-options "-w" }
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
diff --git a/gcc/testsuite/g++.dg/opt/memcpy1.C b/gcc/testsuite/g++.dg/opt/memcpy1.C
index f9887ee2314..f2913459973 100644
--- a/gcc/testsuite/g++.dg/opt/memcpy1.C
+++ b/gcc/testsuite/g++.dg/opt/memcpy1.C
@@ -6,7 +6,7 @@
typedef unsigned char uint8_t;
typedef uint8_t uint8;
-typedef long unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
class csVector2
{
public:float x;
diff --git a/gcc/testsuite/g++.dg/other/pr40446.C b/gcc/testsuite/g++.dg/other/pr40446.C
new file mode 100644
index 00000000000..33dbcec7159
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/pr40446.C
@@ -0,0 +1,46 @@
+// PR middle-end/40446
+// { dg-do run { target i?86-*-* x86_64-*-* } }
+// { dg-options "-O1 -msse2" }
+
+#include <emmintrin.h>
+#include "cpuid.h"
+
+extern "C" void abort ();
+
+struct S
+{
+ S (double r, double i) { __real__ s = r; __imag__ s = i; }
+ __complex__ double s;
+};
+
+__m128d
+foo ()
+{
+ S c (0, 1);
+ return _mm_load_pd ((double *) &c);
+}
+
+static void
+__attribute__((noinline))
+sse2_test ()
+{
+ union { __m128d vec; double val[2]; } u;
+ u.vec = foo ();
+ if (u.val[0] != 0 || u.val[1] != 1)
+ abort ();
+}
+
+int
+main ()
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+ return 0;
+
+ /* Run SSE2 test only if host has SSE2 support. */
+ if (edx & bit_SSE2)
+ sse2_test ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/pr37742.C b/gcc/testsuite/g++.dg/pr37742.C
index 784eb498487..2bbb01723fb 100644
--- a/gcc/testsuite/g++.dg/pr37742.C
+++ b/gcc/testsuite/g++.dg/pr37742.C
@@ -1,6 +1,6 @@
/* { dg-do compile } */
-typedef long unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
void* __valarray_get_memory(size_t __n);
int*__restrict__
__valarray_get_storage(size_t __n)
diff --git a/gcc/testsuite/g++.dg/template/canon-type-1.C b/gcc/testsuite/g++.dg/template/canon-type-1.C
new file mode 100644
index 00000000000..2a36dc09951
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-1.C
@@ -0,0 +1,18 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+template < typename > struct A ;
+template < typename T , typename = A < T > > struct B { } ;
+template < class W , class > struct D
+{
+ typedef W X ;
+ A<X*> a ;
+};
+
+template < class Y > struct E
+{
+ B<Y*> b ;
+} ;
+E<int> e ;
+
diff --git a/gcc/testsuite/g++.dg/template/canon-type-2.C b/gcc/testsuite/g++.dg/template/canon-type-2.C
new file mode 100644
index 00000000000..dd23ec5ea6d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-2.C
@@ -0,0 +1,18 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+template < typename > struct A ;
+template < typename T , typename = A < T > > struct B { } ;
+template < class W , class > struct D
+{
+ typedef W X ;
+ A< X()> a ;
+};
+
+template < class Y > struct E
+{
+ B< Y()> b ;
+};
+E<int> e ;
+
diff --git a/gcc/testsuite/g++.dg/template/canon-type-3.C b/gcc/testsuite/g++.dg/template/canon-type-3.C
new file mode 100644
index 00000000000..a43169addc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-3.C
@@ -0,0 +1,20 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+template<typename> struct A ;
+template<typename T , typename = A<T> > struct B { } ;
+template<class W , class > struct D
+{
+ typedef W X ;
+ typedef X (FP) ();
+ A<FP&> a ;
+} ;
+
+template < class Y > struct E
+{
+ typedef Y (FP) ();
+ B<FP&> b ;
+} ;
+E < int > e ;
+
diff --git a/gcc/testsuite/g++.dg/template/canon-type-4.C b/gcc/testsuite/g++.dg/template/canon-type-4.C
new file mode 100644
index 00000000000..ec5e1e6a200
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-4.C
@@ -0,0 +1,22 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+template<typename> struct A ;
+template<typename T ,typename = A<T> > struct B { } ;
+
+template<class W, class>
+struct D
+{
+ typedef W X;
+ A<X[2]> a;
+} ;
+
+template<class Y>
+struct E
+{
+ B<Y[2]> b;
+};
+
+E < int > e;
+
diff --git a/gcc/testsuite/g++.dg/template/canon-type-5.C b/gcc/testsuite/g++.dg/template/canon-type-5.C
new file mode 100644
index 00000000000..7331c3086fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-5.C
@@ -0,0 +1,22 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+struct Foo {};
+template<typename> struct A ;
+template<typename T ,typename = A<T> > struct B { } ;
+
+template<class W, class>
+struct D
+{
+ typedef W X ;
+ A<X Foo::*> a ;
+} ;
+
+template<class Y>
+struct E
+{
+ B<Y Foo::*> b ;
+} ;
+E < int > e ;
+
diff --git a/gcc/testsuite/g++.dg/template/canon-type-6.C b/gcc/testsuite/g++.dg/template/canon-type-6.C
new file mode 100644
index 00000000000..5065c395dc4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-6.C
@@ -0,0 +1,22 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+struct Foo {};
+template<typename> struct A ;
+template<typename T ,typename = A<T> > struct B { } ;
+
+template<class W, class>
+struct D
+{
+ typedef W X;
+ A<void (Foo::*) (X)> a;
+} ;
+
+template<class Y>
+struct E
+{
+ B<void (Foo::*) (Y)> b;
+};
+E < int > e ;
+
diff --git a/gcc/testsuite/g++.dg/template/canon-type-7.C b/gcc/testsuite/g++.dg/template/canon-type-7.C
new file mode 100644
index 00000000000..80e8f87e834
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-7.C
@@ -0,0 +1,21 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+struct Foo {};
+template<typename> struct A ;
+template<typename T ,typename = A<T> > struct B { } ;
+
+template<class W, class>
+struct D
+{
+ typedef W X;
+ A<X (Foo::*) (X)> a ;
+};
+
+template<class Y>
+struct E
+{
+ B<Y (Foo::*) (Y)> b ;
+};
+E<int> e ;
diff --git a/gcc/testsuite/g++.dg/template/dtor6.C b/gcc/testsuite/g++.dg/template/dtor6.C
new file mode 100644
index 00000000000..83bcf51b7c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dtor6.C
@@ -0,0 +1,10 @@
+// PR c++/40139
+
+template<int> struct A
+{
+ static int i;
+};
+
+template<int N> int A<N>::i = { A::~A }; // { dg-error "" }
+
+template class A<0>;
diff --git a/gcc/testsuite/g++.dg/template/dtor7.C b/gcc/testsuite/g++.dg/template/dtor7.C
new file mode 100644
index 00000000000..0dac69e8948
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dtor7.C
@@ -0,0 +1,24 @@
+// PR c++/40373
+// { dg-compile }
+
+struct A; // { dg-bogus "candidates are" "" { xfail *-*-* } }
+namespace
+{
+ struct A; // { dg-bogus "struct" "" { xfail *-*-* } }
+}
+
+struct B {};
+
+template <typename T> void
+foo (T t)
+{
+ t.~A (); // { dg-error "does not match destructor name" }
+}
+
+void
+bar ()
+{
+ foo (B ()); // { dg-bogus "instantiated from here" "" { xfail *-*-* } }
+}
+
+// { dg-bogus "is ambiguous" "" { xfail *-*-* } 15 }
diff --git a/gcc/testsuite/g++.dg/template/error41.C b/gcc/testsuite/g++.dg/template/error41.C
new file mode 100644
index 00000000000..c92b8497aff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/error41.C
@@ -0,0 +1,12 @@
+// PR c++/40370
+// { dg-do compile }
+
+struct A
+{
+ static int i;
+};
+
+template <int> struct B
+{
+ int x[A::i]; // { dg-error "array bound is not an integer constant" }
+};
diff --git a/gcc/testsuite/g++.dg/template/error42.C b/gcc/testsuite/g++.dg/template/error42.C
new file mode 100644
index 00000000000..0d651e31620
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/error42.C
@@ -0,0 +1,20 @@
+// PR c++/40372
+// { dg-do compile }
+
+template <int> struct A
+{
+ int i; // { dg-error "invalid use of non-static data member" }
+ friend void foo ()
+ {
+ int x[i]; // { dg-error "from this location" }
+ }
+};
+
+struct B
+{
+ int j; // { dg-error "invalid use of non-static data member" }
+ friend int bar ()
+ {
+ return j; // { dg-error "from this location" }
+ }
+};
diff --git a/gcc/testsuite/g++.dg/template/typedef18.C b/gcc/testsuite/g++.dg/template/typedef18.C
new file mode 100644
index 00000000000..8ea3c736a0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef18.C
@@ -0,0 +1,24 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/40007
+// { dg-do compile }
+
+template<typename T>
+struct x
+{
+ protected:
+ typedef int type;
+};
+
+template<typename T>
+struct y : public x<T>
+{
+ typename x<T>::type z;
+};
+
+template<>
+struct y<void> : public x<void>
+{
+ typedef x<void>::type z;
+};
+
+template class y<int>;
diff --git a/gcc/testsuite/g++.dg/template/typedef19.C b/gcc/testsuite/g++.dg/template/typedef19.C
new file mode 100644
index 00000000000..76dca68825e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef19.C
@@ -0,0 +1,21 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/40007
+// { dg-do compile }
+
+class A
+{
+ typedef int mytype; // { dg-error "'typedef int A::mytype' is private" "" { xfail *-*-* } }
+};
+
+template <class T>
+class B : public A
+{
+};
+
+template<class T>
+class B<T*> : public A
+{ // { dg-error "within this context" "" { xfail *-*-* } }
+ mytype mem;
+};
+
+B<int*> b;
diff --git a/gcc/testsuite/g++.dg/template/typedef20.C b/gcc/testsuite/g++.dg/template/typedef20.C
new file mode 100644
index 00000000000..689c1d21705
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef20.C
@@ -0,0 +1,27 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/40007
+// { dg-do compile }
+
+class x
+{
+ typedef int privtype; // { dg-error "is private" "" { xfail *-*-* } }
+
+protected:
+ typedef int type;
+};
+
+template<typename T>
+struct y : public x
+{
+ typename x::type z;
+};
+
+template<typename T>
+struct y<T*> : public x
+{ // { dg-error "within this context" "" { xfail *-*-* } }
+ typedef x::type good;
+ typedef x::privtype bad;
+};
+
+template class y<int>;
+template class y<int*>;
diff --git a/gcc/testsuite/g++.dg/torture/20070621-1.C b/gcc/testsuite/g++.dg/torture/20070621-1.C
index d17db9763ae..185314a47ca 100644
--- a/gcc/testsuite/g++.dg/torture/20070621-1.C
+++ b/gcc/testsuite/g++.dg/torture/20070621-1.C
@@ -6,7 +6,7 @@
*/
-typedef long int ptrdiff_t;
+__extension__ typedef __PTRDIFF_TYPE__ ptrdiff_t;
namespace std __attribute__ ((__visibility__ ("default"))) {
template<typename, typename> struct __are_same {
enum {
diff --git a/gcc/testsuite/g++.dg/torture/pr32950.C b/gcc/testsuite/g++.dg/torture/pr32950.C
new file mode 100644
index 00000000000..8d64296e40b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr32950.C
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+
+struct A
+{
+ __complex__ double c;
+};
+
+struct B
+{
+ A a;
+ B(A x) : a(x) {}
+ void foo();
+};
+
+void bar()
+{
+ B b = A();
+ B(b).foo();
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr34222.C b/gcc/testsuite/g++.dg/torture/pr34222.C
index 1939b5015b1..130896dc9da 100644
--- a/gcc/testsuite/g++.dg/torture/pr34222.C
+++ b/gcc/testsuite/g++.dg/torture/pr34222.C
@@ -3,7 +3,7 @@
namespace std __attribute__ ((__visibility__ ("default"))) {
template<class _CharT> struct char_traits;
}
-typedef long int ptrdiff_t;
+__extension__ typedef __PTRDIFF_TYPE__ ptrdiff_t;
namespace std __attribute__ ((__visibility__ ("default"))) {
typedef ptrdiff_t streamsize;
template<typename _CharT, typename _Traits = char_traits<_CharT> > class basic_ifstream;
diff --git a/gcc/testsuite/g++.dg/torture/pr34850.C b/gcc/testsuite/g++.dg/torture/pr34850.C
index e7caa7b6638..88df5a3382b 100644
--- a/gcc/testsuite/g++.dg/torture/pr34850.C
+++ b/gcc/testsuite/g++.dg/torture/pr34850.C
@@ -5,7 +5,7 @@ typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef uint8_t byte;
typedef uint32_t u32bit;
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
extern "C" {
extern void __warn_memset_zero_len (void) __attribute__((__warning__ ("")));
extern __inline __attribute__ ((__always_inline__)) __attribute__ ((__gnu_inline__, __artificial__))
diff --git a/gcc/testsuite/g++.dg/torture/pr40335.C b/gcc/testsuite/g++.dg/torture/pr40335.C
new file mode 100644
index 00000000000..14ea95d4086
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr40335.C
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+
+extern "C" void abort (void);
+int
+main (void)
+{
+ int i = -1;
+ switch ((signed char) i)
+ {
+ case 255: /* { dg-bogus "exceeds maximum value" "" { xfail *-*-* } } */
+ abort ();
+ default:
+ break;
+ }
+}
+
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr22444.C b/gcc/testsuite/g++.dg/tree-ssa/pr22444.C
index 2cc84bb9d1e..7df4b9cce15 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr22444.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr22444.C
@@ -4,8 +4,8 @@
// with the subvars leading to the subvars not being renamed when they should
// { dg-do compile }
// { dg-options "-O2" }
-typedef int ptrdiff_t;
-typedef unsigned int size_t;
+__extension__ typedef __PTRDIFF_TYPE__ ptrdiff_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
namespace std
{
template<class _T1, class _T2> struct pair
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-4.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-4.C
new file mode 100644
index 00000000000..3d2543fb175
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-4.C
@@ -0,0 +1,22 @@
+// PR middle-end/39666
+// { dg-do compile }
+// { dg-options "-O2 -Wuninitialized" }
+
+int
+foo (int i)
+{
+ int j;
+ switch (i)
+ {
+ case -__INT_MAX__ - 1 ... -1:
+ j = 6;
+ break;
+ case 0:
+ j = 5;
+ break;
+ case 1 ... __INT_MAX__:
+ j = 4;
+ break;
+ }
+ return j;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-5.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-5.C
new file mode 100644
index 00000000000..26add34945f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-5.C
@@ -0,0 +1,22 @@
+// PR middle-end/39666
+// { dg-do compile }
+// { dg-options "-O2 -Wuninitialized" }
+
+int
+foo (int i)
+{
+ int j; // { dg-warning "may be used uninitialized" }
+ switch (i)
+ {
+ case -__INT_MAX__ - 1 ... -1:
+ j = 6;
+ break;
+ case 0:
+ j = 5;
+ break;
+ case 2 ... __INT_MAX__:
+ j = 4;
+ break;
+ }
+ return j;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/array1.C b/gcc/testsuite/g++.old-deja/g++.brendan/array1.C
index df132ea9024..a58d3363bcd 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/array1.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/array1.C
@@ -3,5 +3,5 @@
// GROUPS passed array-bindings
extern "C" int printf (const char *, ...);
-char array[~(~0ul>>1)|~(0ul>>3)]; // { dg-error "" } overflow in array dimension.*
+char array[~(~((__SIZE_TYPE__)0ul)>>1)|~(((__SIZE_TYPE__)0ul)>>3)]; // { dg-error "" } overflow in array dimension.*
int main () { printf ("PASS\n"); return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C
index b3717a5d999..6046cb1c9ee 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C
@@ -1,6 +1,6 @@
// { dg-do assemble }
// GROUPS passed old-abort
-typedef long unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef void (*RF_Ptr)(void *);
struct _im_pers_mem_spec {
@@ -9,7 +9,7 @@ struct _im_pers_mem_spec {
};
struct _type_desc {
- _type_desc(char *, int , RF_Ptr , int , int ,...);
+ _type_desc(const char *, int , RF_Ptr , int , int ,...);
};
struct metatype { int base_list; };
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/new3.C b/gcc/testsuite/g++.old-deja/g++.jason/new3.C
index 62e9b7dd1b6..d950259e72a 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/new3.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/new3.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-fcheck-new -pedantic" }
+// { dg-options "-fcheck-new -pedantic -Wno-long-long" }
// PRMS Id: 6037
extern "C" void * malloc (__SIZE_TYPE__);
diff --git a/gcc/testsuite/gcc.c-torture/compile/20000211-1.c b/gcc/testsuite/gcc.c-torture/compile/20000211-1.c
index 8d8a4074e0f..7a7c8c0cb20 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20000211-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20000211-1.c
@@ -1,4 +1,4 @@
-typedef long unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef unsigned char Bufbyte;
typedef int Bytecount;
typedef int Charcount;
diff --git a/gcc/testsuite/gcc.c-torture/compile/20010328-1.c b/gcc/testsuite/gcc.c-torture/compile/20010328-1.c
index d92c6dae113..951ae78b950 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20010328-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20010328-1.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef unsigned int __u_int;
typedef unsigned long __u_long;
diff --git a/gcc/testsuite/gcc.c-torture/compile/20030320-1.c b/gcc/testsuite/gcc.c-torture/compile/20030320-1.c
index 40243f28f93..72d0d0966c6 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20030320-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20030320-1.c
@@ -2,7 +2,7 @@
conditional returns without updating dominance info.
Extracted from glibc's dl-load.c. */
-typedef unsigned long size_t;
+typedef __SIZE_TYPE__ size_t;
static size_t
is_dst (const char *start, const char *name, const char *str,
diff --git a/gcc/testsuite/gcc.c-torture/compile/20030405-1.c b/gcc/testsuite/gcc.c-torture/compile/20030405-1.c
index f84e606c045..0bdafb9239f 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20030405-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20030405-1.c
@@ -6,7 +6,7 @@
and when the PHI node at the end of the while() is visited the first
time, CCP will try to assign it a value of UNDEFINED, but the default
value for *str is a constant. */
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
size_t strlength (const char * const);
char foo();
diff --git a/gcc/testsuite/gcc.c-torture/compile/20030902-1.c b/gcc/testsuite/gcc.c-torture/compile/20030902-1.c
index 443b43921b8..56c2650b86b 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20030902-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20030902-1.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef unsigned long int reg_syntax_t;
struct re_pattern_buffer
{
diff --git a/gcc/testsuite/gcc.c-torture/compile/20060202-1.c b/gcc/testsuite/gcc.c-torture/compile/20060202-1.c
index 9d440741c6b..d16e7b7c5ad 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20060202-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20060202-1.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef const struct objc_selector
{
void *sel_id;
diff --git a/gcc/testsuite/gcc.c-torture/compile/20080613-1.c b/gcc/testsuite/gcc.c-torture/compile/20080613-1.c
index f64964e7740..20e3878420e 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20080613-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20080613-1.c
@@ -1,7 +1,7 @@
/* PR middle-end/36520 */
/* Testcase by Richard Guenther <rguenth@gcc.gnu.org> */
-typedef long unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef unsigned short int sa_family_t;
struct cmsghdr {
size_t cmsg_len;
diff --git a/gcc/testsuite/gcc.c-torture/compile/20090519-1.c b/gcc/testsuite/gcc.c-torture/compile/20090519-1.c
new file mode 100644
index 00000000000..54add6b2e1a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20090519-1.c
@@ -0,0 +1,11 @@
+typedef struct { int licensed; } __pmPDUInfo;
+void __pmDecodeXtendError (int *);
+void do_handshake(void)
+{
+ __pmPDUInfo *pduinfo;
+ int challenge;
+ __pmDecodeXtendError(&challenge);
+ pduinfo = (__pmPDUInfo *)&challenge;
+ *pduinfo = *pduinfo;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/compile/920428-2.c b/gcc/testsuite/gcc.c-torture/compile/920428-2.c
index 23f32a83a9d..f313b32986b 100644
--- a/gcc/testsuite/gcc.c-torture/compile/920428-2.c
+++ b/gcc/testsuite/gcc.c-torture/compile/920428-2.c
@@ -41,7 +41,7 @@ extern struct _iobuf {
short _flag;
char _file;
} _iob[];
-typedef unsigned long size_t;
+typedef __SIZE_TYPE__ size_t;
typedef char *va_list;
struct _iobuf *fopen(const char *filename, const char *type);
struct _iobuf *freopen(const char *filename, const char *type, struct _iobuf *stream);
diff --git a/gcc/testsuite/gcc.c-torture/compile/980329-1.c b/gcc/testsuite/gcc.c-torture/compile/980329-1.c
index d11b49b01c7..3b3fe27cf71 100644
--- a/gcc/testsuite/gcc.c-torture/compile/980329-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/980329-1.c
@@ -1,4 +1,4 @@
-typedef unsigned long int size_t;
+typedef __SIZE_TYPE__ size_t;
struct re_pattern_buffer
{
unsigned char *buffer;
diff --git a/gcc/testsuite/gcc.c-torture/compile/980816-1.c b/gcc/testsuite/gcc.c-torture/compile/980816-1.c
index c56b6c9b92c..a79100fab57 100644
--- a/gcc/testsuite/gcc.c-torture/compile/980816-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/980816-1.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef void *XtPointer;
typedef struct _WidgetRec *Widget;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr32584.c b/gcc/testsuite/gcc.c-torture/compile/pr32584.c
index 02799fc7449..403ea9b12fa 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr32584.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr32584.c
@@ -1,5 +1,8 @@
-typedef long unsigned int size_t;
-typedef long int __ssize_t;
+typedef __SIZE_TYPE__ size_t;
+/* Kludge */
+#define unsigned
+typedef __SIZE_TYPE__ __ssize_t;
+#undef unsigned
typedef struct
{
} __mbstate_t;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr33173.c b/gcc/testsuite/gcc.c-torture/compile/pr33173.c
index 503c7afbdac..f599297e79a 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr33173.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr33173.c
@@ -1,4 +1,4 @@
-typedef long unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef struct
{
}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr33382.c b/gcc/testsuite/gcc.c-torture/compile/pr33382.c
index d83f74e42cc..c939cf7b772 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr33382.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr33382.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef struct {
int disable;
char *searchconfig[];
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr34334.c b/gcc/testsuite/gcc.c-torture/compile/pr34334.c
index 15f895f1cba..30bb782626f 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr34334.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr34334.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
__extension__ typedef long long int __quad_t;
__extension__ typedef unsigned int __mode_t;
__extension__ typedef __quad_t __off64_t;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr34688.c b/gcc/testsuite/gcc.c-torture/compile/pr34688.c
index 9891c72d93d..60e0f3c9f15 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr34688.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr34688.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef struct {
}
HashTable;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr35043.c b/gcc/testsuite/gcc.c-torture/compile/pr35043.c
index 29c685207b9..a14379dc148 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr35043.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr35043.c
@@ -1,4 +1,4 @@
-typedef long unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef struct {
long double dat[2];
} gsl_complex_long_double;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr37669.c b/gcc/testsuite/gcc.c-torture/compile/pr37669.c
index 9b003cdf099..68e96c621cf 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr37669.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr37669.c
@@ -1,6 +1,6 @@
/* This testcase used to fail because a miscompiled execute_fold_all_builtins. */
-typedef long unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
extern __inline __attribute__ ((__always_inline__)) int __attribute__
((__nothrow__)) snprintf (char *__restrict __s, size_t __n, __const char
*__restrict __fmt, ...) {
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr39999.c b/gcc/testsuite/gcc.c-torture/compile/pr39999.c
new file mode 100644
index 00000000000..c46a651a18a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr39999.c
@@ -0,0 +1,18 @@
+void foo(void *);
+void
+MMAPGCD (int *A1, int *A2)
+{
+ int *t;
+
+ do
+ {
+ t = A1;
+ A1 = A2;
+ A2 = t;
+ }
+ while (A2[-1]);
+
+ foo (A1-1);
+ foo (A2-1);
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr40026.c b/gcc/testsuite/gcc.c-torture/compile/pr40026.c
new file mode 100644
index 00000000000..0d08f0dc8ac
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr40026.c
@@ -0,0 +1,15 @@
+typedef struct {
+ unsigned long bits;
+} S;
+struct T {
+ S span;
+ int flags;
+};
+
+struct T f(int x)
+{
+ return (struct T) {
+ .span = (S) { 0UL },
+ .flags = (x ? 256 : 0),
+ };
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr40035.c b/gcc/testsuite/gcc.c-torture/compile/pr40035.c
new file mode 100644
index 00000000000..1bf1a7c4c41
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr40035.c
@@ -0,0 +1,20 @@
+typedef __SIZE_TYPE__ size_t;
+void *memmove (void *dest, const void *src, size_t count);
+size_t strlen (const char *s);
+
+int
+foo (char *param, char *val)
+{
+ if (val)
+ {
+ if (val == param + strlen (param) + 1)
+ val[-1] = '=';
+ else if (val == param + strlen (param) + 2)
+ {
+ val[-2] = '=';
+ memmove (val - 1, val, strlen (val) + 1);
+ val--;
+ }
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr40080.c b/gcc/testsuite/gcc.c-torture/compile/pr40080.c
new file mode 100644
index 00000000000..e36f14273e8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr40080.c
@@ -0,0 +1,44 @@
+extern void *ff(void*,int);
+
+struct lpgl { struct lpgl *next; };
+struct lpgd { struct lpgl *first; };
+
+typedef int (*xfn)( );
+static void xDP_IF_EnumGroupsInGroup ( void *a, int b, xfn fn)
+{
+ struct lpgd *lpGData;
+ struct lpgl *lpGList;
+
+ if( ( lpGData = ff( a, b ) ) == ((void *)0) )
+ return;
+
+ if( lpGData->first == ((void *)0) )
+ return;
+ lpGList = lpGData->first;
+
+ for( ;; ) {
+ if( !(*fn)( ) )
+ return;
+ if( lpGList->next == ((void *)0) )
+ break;
+ lpGList = lpGList->next;
+ }
+ return;
+}
+
+
+static int
+xcbDeletePlayerFromAllGroups() {
+ xDP_IF_EnumGroupsInGroup(0, 0, 0);
+ return 1;
+}
+
+void xDP_IF_EnumGroups( xfn fn) {
+ xDP_IF_EnumGroupsInGroup( 0, 0, fn);
+}
+
+static void xDP_IF_DestroyPlayer () {
+ xDP_IF_EnumGroups( xcbDeletePlayerFromAllGroups);
+}
+
+void* foo=xDP_IF_DestroyPlayer;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr40204.c b/gcc/testsuite/gcc.c-torture/compile/pr40204.c
new file mode 100644
index 00000000000..3193284ff7a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr40204.c
@@ -0,0 +1,14 @@
+/* PR middle-end/40204 */
+
+struct S
+{
+ unsigned int a : 4;
+ unsigned int b : 28;
+} s;
+char c;
+
+void
+f (void)
+{
+ s.a = (c >> 4) & ~(1 << 4);
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr40233.c b/gcc/testsuite/gcc.c-torture/compile/pr40233.c
new file mode 100644
index 00000000000..b3487edde74
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr40233.c
@@ -0,0 +1,10 @@
+typedef int aligned __attribute__((aligned(64)));
+struct Frame {
+ aligned i;
+};
+
+void foo(struct Frame *p)
+{
+ aligned *q = &p->i;
+ *q = 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr40252.c b/gcc/testsuite/gcc.c-torture/compile/pr40252.c
new file mode 100644
index 00000000000..f58e799b01f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr40252.c
@@ -0,0 +1,6 @@
+typedef unsigned int uint32_t;
+static void IP(uint32_t v[2])
+{
+ v[0] = ((v[0] << 1) | ((v[0] >> 31) & 1L)) & 0xffffffffL;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr40291.c b/gcc/testsuite/gcc.c-torture/compile/pr40291.c
new file mode 100644
index 00000000000..d50bbee6608
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr40291.c
@@ -0,0 +1,7 @@
+/* PR middle-end/40291 */
+
+int
+foo (void *x, char *y, unsigned long long z)
+{
+ return memcmp (x, y, z);
+}
diff --git a/gcc/testsuite/gcc.dg/20050629-1.c b/gcc/testsuite/gcc.dg/20050629-1.c
index 67d73f0eb66..0dd47f7024b 100644
--- a/gcc/testsuite/gcc.dg/20050629-1.c
+++ b/gcc/testsuite/gcc.dg/20050629-1.c
@@ -5,7 +5,7 @@
contains many warnings, but it exposes a copy propagation bug that
is somewhat difficult to reproduce otherwise. */
-typedef long unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
extern void fancy_abort (const char *, int, const char *) __attribute__ ((__noreturn__));
typedef union tree_node *tree;
enum tree_code {
diff --git a/gcc/testsuite/gcc.dg/pr33667.c b/gcc/testsuite/gcc.dg/pr33667.c
index d3c039b51df..676c4a46dac 100644
--- a/gcc/testsuite/gcc.dg/pr33667.c
+++ b/gcc/testsuite/gcc.dg/pr33667.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned long long int uint64_t;
diff --git a/gcc/testsuite/gcc.dg/pr39666-1.c b/gcc/testsuite/gcc.dg/pr39666-1.c
new file mode 100644
index 00000000000..f1ba499c331
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr39666-1.c
@@ -0,0 +1,22 @@
+/* PR middle-end/39666 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized" } */
+
+int
+foo (int i)
+{
+ int j;
+ switch (i)
+ {
+ case -__INT_MAX__ - 1 ... -1:
+ j = 6;
+ break;
+ case 0:
+ j = 5;
+ break;
+ case 1 ... __INT_MAX__:
+ j = 4;
+ break;
+ }
+ return j;
+}
diff --git a/gcc/testsuite/gcc.dg/pr39666-2.c b/gcc/testsuite/gcc.dg/pr39666-2.c
new file mode 100644
index 00000000000..e4ef1d5d2b7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr39666-2.c
@@ -0,0 +1,22 @@
+/* PR middle-end/39666 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wuninitialized" } */
+
+int
+foo (int i)
+{
+ int j; /* { dg-warning "may be used uninitialized" } */
+ switch (i)
+ {
+ case -__INT_MAX__ - 1 ... -1:
+ j = 6;
+ break;
+ case 0:
+ j = 5;
+ break;
+ case 2 ... __INT_MAX__:
+ j = 4;
+ break;
+ }
+ return j;
+}
diff --git a/gcc/testsuite/gcc.dg/pr40172-1.c b/gcc/testsuite/gcc.dg/pr40172-1.c
new file mode 100644
index 00000000000..a834a8a998e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr40172-1.c
@@ -0,0 +1,31 @@
+/* PR middle-end/40172 */
+/* { dg-do compile } */
+/* { dg-options "-Wall -W -Werror -Wlogical-op" } */
+
+struct rtx_def;
+typedef struct rtx_def *rtx;
+
+extern int foo;
+extern int bar;
+extern int xxx;
+
+int
+test (void)
+{
+ if (((rtx) 0 != (rtx) 0) && xxx ? foo : bar)
+ return 1;
+ else if ((foo & 0) && xxx)
+ return 2;
+ else if (foo & 0)
+ return 3;
+ else if (0 && xxx)
+ return 4;
+ else if (0)
+ return 5;
+ if (((int) 0 != (int) 0) && bar ? foo : xxx)
+ return 6;
+ else if (0 != 0 && foo ? xxx : bar)
+ return 7;
+ else
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr40172-2.c b/gcc/testsuite/gcc.dg/pr40172-2.c
new file mode 100644
index 00000000000..17aabb8b5f3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr40172-2.c
@@ -0,0 +1,16 @@
+/* PR middle-end/40172 */
+/* { dg-do compile } */
+/* { dg-options "-Wall -W -Werror" } */
+
+extern int xxx;
+
+#define XXX xxx
+
+int
+test (void)
+{
+ if (!XXX && xxx)
+ return 4;
+ else
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr40172-3.c b/gcc/testsuite/gcc.dg/pr40172-3.c
new file mode 100644
index 00000000000..a16e22e3749
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr40172-3.c
@@ -0,0 +1,16 @@
+/* PR middle-end/40172 */
+/* { dg-do compile */
+/* { dg-options "-Wall -W -Werror -Wlogical-op" } */
+
+extern int xxx;
+
+#define XXX xxx
+
+int
+test (void)
+{
+ if (!XXX && xxx)
+ return 4;
+ else
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr40340-1.c b/gcc/testsuite/gcc.dg/pr40340-1.c
new file mode 100644
index 00000000000..aae84c63781
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr40340-1.c
@@ -0,0 +1,24 @@
+/* PR middle-end/40340 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall -Wno-system-headers" } */
+
+#include "pr40340.h"
+
+static inline
+__attribute__ ((always_inline))
+void
+test (char *p)
+{
+ memset (p, 0, 6);
+}
+
+int
+main (void)
+{
+ char buf[4];
+ test (buf);
+ return 0;
+}
+
+/* { dg-warning "will always overflow destination buffer" "" { target *-*-* } 10 } */
+/* { dg-message "file included" "In file included" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/pr40340-2.c b/gcc/testsuite/gcc.dg/pr40340-2.c
new file mode 100644
index 00000000000..a0d6e084e73
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr40340-2.c
@@ -0,0 +1,16 @@
+/* PR middle-end/40340 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall -Wno-system-headers" } */
+
+#include "pr40340.h"
+
+int
+main (void)
+{
+ char buf[4];
+ memset (buf, 0, 6);
+ return 0;
+}
+
+/* { dg-warning "will always overflow destination buffer" "" { target *-*-* } 10 } */
+/* { dg-message "file included" "In file included" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/pr40340-3.c b/gcc/testsuite/gcc.dg/pr40340-3.c
new file mode 100644
index 00000000000..5ef09e073d8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr40340-3.c
@@ -0,0 +1,15 @@
+/* PR middle-end/40340 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall -Wno-system-headers" } */
+
+#define TEST2
+#include "pr40340.h"
+
+int
+main (void)
+{
+ test2 ();
+ return 0;
+}
+
+/* { dg-bogus "will always overflow destination buffer" "" { target *-*-* } 10 } */
diff --git a/gcc/testsuite/gcc.dg/pr40340-4.c b/gcc/testsuite/gcc.dg/pr40340-4.c
new file mode 100644
index 00000000000..d3f020cada8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr40340-4.c
@@ -0,0 +1,16 @@
+/* PR middle-end/40340 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall -Wno-system-headers -g" } */
+
+#define TEST3
+#include "pr40340.h"
+
+int
+main (void)
+{
+ char buf[4];
+ test3 (buf);
+ return 0;
+}
+
+/* { dg-bogus "will always overflow destination buffer" "" { target *-*-* } 10 } */
diff --git a/gcc/testsuite/gcc.dg/pr40340-5.c b/gcc/testsuite/gcc.dg/pr40340-5.c
new file mode 100644
index 00000000000..f50514c3ac9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr40340-5.c
@@ -0,0 +1,17 @@
+/* PR middle-end/40340 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall -Wsystem-headers -g" } */
+
+#define TEST3
+#include "pr40340.h"
+
+int
+main (void)
+{
+ char buf[4];
+ test3 (buf);
+ return 0;
+}
+
+/* { dg-warning "will always overflow destination buffer" "" { target *-*-* } 10 } */
+/* { dg-message "file included" "In file included" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/pr40340.h b/gcc/testsuite/gcc.dg/pr40340.h
new file mode 100644
index 00000000000..174e076b943
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr40340.h
@@ -0,0 +1,31 @@
+#pragma GCC system_header
+typedef __SIZE_TYPE__ size_t;
+extern void *memset (void *s, int c, size_t n)
+ __attribute__ ((nothrow, nonnull (1)));
+extern inline
+__attribute__ ((always_inline, artificial, gnu_inline, nothrow))
+void *
+memset (void *dest, int ch, size_t len)
+{
+ return __builtin___memset_chk (dest, ch, len,
+ __builtin_object_size (dest, 0));
+}
+
+#ifdef TEST2
+static void
+__attribute__ ((noinline))
+test2 (void)
+{
+ char buf[4];
+ memset (buf, 0, 6);
+}
+#endif
+
+#ifdef TEST3
+static inline void
+__attribute__ ((always_inline))
+test3 (char *p)
+{
+ memset (p, 0, 6);
+}
+#endif
diff --git a/gcc/testsuite/gcc.dg/prefetch-loop-arrays-1.c b/gcc/testsuite/gcc.dg/prefetch-loop-arrays-1.c
index ba91d69650d..59cebc52e96 100644
--- a/gcc/testsuite/gcc.dg/prefetch-loop-arrays-1.c
+++ b/gcc/testsuite/gcc.dg/prefetch-loop-arrays-1.c
@@ -3,7 +3,7 @@
/* { dg-options "-O2 -fprefetch-loop-arrays -w" } */
/* { dg-options "-O2 -fprefetch-loop-arrays -march=i686 -msse -w" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
-typedef unsigned long size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
struct re_pattern_buffer
{
diff --git a/gcc/testsuite/gcc.dg/torture/pr39204.c b/gcc/testsuite/gcc.dg/torture/pr39204.c
index 4604b7079d1..1389a52ec58 100644
--- a/gcc/testsuite/gcc.dg/torture/pr39204.c
+++ b/gcc/testsuite/gcc.dg/torture/pr39204.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-w" } */
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
diff --git a/gcc/testsuite/gcc.dg/torture/pr40328.c b/gcc/testsuite/gcc.dg/torture/pr40328.c
new file mode 100644
index 00000000000..e378e63c00a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr40328.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-tree-sra" } */
+
+_Complex float foo(void)
+{
+ _Complex float a[64] = {};
+ _Complex float x;
+ x = a[1];
+ return x;
+}
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c
index d5cabb0bd37..d72d133e154 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c
@@ -2,7 +2,7 @@
/* { dg-options "-O1 -fdump-tree-dom2" } */
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
extern void *xmalloc (size_t) __attribute__ ((__malloc__));
struct edge_def
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr36908.c b/gcc/testsuite/gcc.dg/tree-ssa/pr36908.c
index a135bcff238..8fa2ed2ca1f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr36908.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr36908.c
@@ -2,7 +2,7 @@
/* { dg-options "-O2 -ftree-loop-distribution" } */
#define NULL ((void *)0)
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
extern void *foo(size_t nelem, size_t elsize);
extern void bar (char*, ...);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr38250.c b/gcc/testsuite/gcc.dg/tree-ssa/pr38250.c
index 79039066808..fac6cd3b806 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr38250.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr38250.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O2 -ftree-loop-distribution" } */
-typedef long unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
typedef struct {
long dat[2];
} gsl_complex_long_double;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr40087.c b/gcc/testsuite/gcc.dg/tree-ssa/pr40087.c
new file mode 100644
index 00000000000..22e2b629ed7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr40087.c
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-options "-O1 " } */
+
+extern void abort (void);
+
+static void __attribute__((always_inline))
+reverse(int *first, int *last)
+{
+ if (first == last--)
+ return;
+ while (first != last)
+ {
+ int t = *first;
+ *first = *last;
+ *last = t;
+ if (++first == last--)
+ break;
+ }
+}
+
+int main()
+{
+ int seq[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+
+ reverse(seq, seq + 8);
+ if (seq[3] != 5 || seq[4] != 4)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c
index dd0da7913dc..bce2c315a66 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O -w -fdump-tree-dse-vops" } */
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
typedef struct _IO_FILE FILE;
typedef struct
{
diff --git a/gcc/testsuite/gcc.dg/vect/pr40074.c b/gcc/testsuite/gcc.dg/vect/pr40074.c
new file mode 100644
index 00000000000..6459f1b552e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr40074.c
@@ -0,0 +1,54 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 16
+
+typedef struct {
+ int a;
+ int b;
+ int c;
+ int d;
+} s;
+
+
+s arr[N] = {{7,0,1,5}, {7,2,3,5}, {7,4,5,5}, {7,6,7,5}, {7,8,9,5}, {7,10,11,5}, {7,12,13,5}, {7,14,15,5}, {7,16,17,5}, {7,18,19,5}, {7,20,21,5}, {7,22,23,5}, {7,24,25,5}, {7,26,27,5}, {7,28,29,5}, {7,30,31,5}};
+
+__attribute__ ((noinline)) int
+main1 ()
+{
+ s *p = arr, *q = arr + 1;
+ int res[N];
+ int i;
+
+ for (i = 0; i < N-1; i++)
+ {
+ res[i] = p->b + p->d + q->b;
+ p++;
+ q++;
+ }
+
+ /* check results: */
+ for (i = 0; i < N-1; i++)
+ {
+ if (res[i] != arr[i].b + arr[i].d + arr[i+1].b)
+ abort ();
+ }
+
+ return 0;
+}
+
+int main (void)
+{
+ int i;
+
+ check_vect ();
+
+ main1 ();
+
+ return 0;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/pr40238.c b/gcc/testsuite/gcc.dg/vect/pr40238.c
new file mode 100644
index 00000000000..91cf0982439
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr40238.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+
+extern int xdo_rb_ctr_row( int *pos_code);
+
+int xgp_ahd_interpolate (int tile)
+{
+ int p[4];
+
+ switch (tile) {
+ default:
+ case 0:
+ case 1:
+ p[0] = 0; p[1] = 1; p[2] = 2; p[3] = 3;
+ break;
+ case 2:
+ case 3:
+ p[0] = 1; p[1] = 0; p[2] = 3; p[3] = 2;
+ break;
+ case 4:
+ case 5:
+ p[0] = 3; p[1] = 2; p[2] = 1; p[3] = 0;
+ break;
+ case 6:
+ case 7:
+ p[0] = 2; p[1] = 3; p[2] = 0; p[3] = 1;
+ break;
+ }
+
+ xdo_rb_ctr_row(p);
+ xdo_rb_ctr_row(p);
+ return 0;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/pr40254.c b/gcc/testsuite/gcc.dg/vect/pr40254.c
new file mode 100644
index 00000000000..b890a449312
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr40254.c
@@ -0,0 +1,39 @@
+#include <stdlib.h>
+#include <stdarg.h>
+#include "tree-vect.h"
+
+struct s
+{
+ int *x;
+ int x1;
+ int x2;
+ int x3;
+ int *y;
+};
+
+struct s arr[64] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
+
+__attribute__ ((noinline)) void
+foo (int i, int *in_x, int *in_y)
+{
+ arr[i].x = in_x;
+ arr[i].y = in_y;
+}
+
+int
+main (void)
+{
+ int a, b;
+
+ check_vect ();
+
+ foo (5, &a, &b);
+
+ if (arr[5].x != &a || arr[5].y != &b)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr39543-2.c b/gcc/testsuite/gcc.target/i386/pr39543-2.c
index c292041a700..04e980efa7a 100644
--- a/gcc/testsuite/gcc.target/i386/pr39543-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr39543-2.c
@@ -1,6 +1,7 @@
/* PR inline-asm/39543 */
/* { dg-do compile } */
/* { dg-options "-O3" } */
+/* { dg-skip-if "" { ilp32 && { ! nonpic } } { "*" } { "" } } */
float __attribute__ ((aligned (16))) s0[128];
const float s1 = 0.707;
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-30.c b/gcc/testsuite/gcc.target/powerpc/altivec-30.c
new file mode 100644
index 00000000000..99783191db9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-30.c
@@ -0,0 +1,32 @@
+/* { dg-do compile { target powerpc*-*-* } } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec" } */
+
+#include <stdbool.h>
+#include <altivec.h>
+
+#define f0(type) void x0##type (vector bool type x) { }
+f0 (int)
+
+#define f1(v, type) void x1##type (v bool type x) { }
+f1 (vector, int)
+
+#define f2(b, type) void x2##type (vector b type x) { }
+f2 (bool, int)
+
+#define f3(v, b, type) void x3##type (v b type x) { }
+f3 (vector, bool, int)
+
+#define f4(v, b, type) void x4##type (v type b x) { }
+f4 (vector, bool, int)
+
+#define B bool
+#define I int
+#define BI bool int
+#define VBI vector bool int
+
+vector bool int a;
+vector B int b;
+vector B I c;
+vector BI d;
+VBI e;
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-31.c b/gcc/testsuite/gcc.target/powerpc/altivec-31.c
new file mode 100644
index 00000000000..233efe1bebb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-31.c
@@ -0,0 +1,29 @@
+/* { dg-do compile { target powerpc*-*-* } } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec" } */
+
+#define f0(type) void x0##type (vector _Bool type x) { }
+f0 (int)
+
+#define f1(v, type) void x1##type (v _Bool type x) { }
+f1 (vector, int)
+
+#define f2(b, type) void x2##type (vector b type x) { }
+f2 (_Bool, int)
+
+#define f3(v, b, type) void x3##type (v b type x) { }
+f3 (vector, _Bool, int)
+
+#define f4(v, b, type) void x4##type (v type b x) { }
+f4 (vector, _Bool, int)
+
+#define B _Bool
+#define I int
+#define BI _Bool int
+#define VBI vector _Bool int
+
+vector _Bool int a;
+vector B int b;
+vector B I c;
+vector BI d;
+VBI e;
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-types-1.c b/gcc/testsuite/gcc.target/powerpc/altivec-types-1.c
index d293042d64f..41de95225b3 100644
--- a/gcc/testsuite/gcc.target/powerpc/altivec-types-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-types-1.c
@@ -24,6 +24,7 @@ __vector unsigned vuj;
__vector signed vsj;
__vector __bool vbj;
__vector float vf;
+__vector _Bool vb;
/* These should be rejected as invalid AltiVec types. */
@@ -37,7 +38,6 @@ __vector signed long long int vslli; /* { dg-error "AltiVec types" "" } */
__vector __bool long long int vblli; /* { dg-error "AltiVec types" "" } */
__vector double vd1; /* { dg-error "AltiVec types" "" } */
__vector long double vld; /* { dg-error "AltiVec types" "" } */
-__vector _Bool vb; /* { dg-error "AltiVec types" "" } */
__vector _Complex float vcf; /* { dg-error "AltiVec types" "" } */
__vector _Complex double vcd; /* { dg-error "AltiVec types" "" } */
__vector _Complex long double vcld; /* { dg-error "AltiVec types" "" } */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/asm-support.S b/gcc/testsuite/gcc.target/x86_64/abi/asm-support.S
index 61b66e1490a..cb1e31ea785 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/asm-support.S
+++ b/gcc/testsuite/gcc.target/x86_64/abi/asm-support.S
@@ -49,7 +49,9 @@ snapshot:
.type snapshot_ret, @function
snapshot_ret:
movq %rdi, rdi(%rip)
+ subq $8, %rsp
call *callthis(%rip)
+ addq $8, %rsp
movq %rax, rax(%rip)
movq %rdx, rdx(%rip)
movdqu %xmm0, xmm_regs+0(%rip)
diff --git a/gcc/testsuite/gfortran.dg/alloc_comp_assign_10.f90 b/gcc/testsuite/gfortran.dg/alloc_comp_assign_10.f90
new file mode 100644
index 00000000000..c85edea62fc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/alloc_comp_assign_10.f90
@@ -0,0 +1,61 @@
+! { dg-do run }
+!
+! Test the fix for PR39879, in which gfc gagged on the double
+! defined assignment where the rhs had a default initialiser.
+!
+! Contributed by David Sagan <david.sagan@gmail.com>
+!
+module test_struct
+ interface assignment (=)
+ module procedure tao_lat_equal_tao_lat
+ end interface
+ type bunch_params_struct
+ integer n_live_particle
+ end type
+ type tao_lattice_struct
+ type (bunch_params_struct), allocatable :: bunch_params(:)
+ type (bunch_params_struct), allocatable :: bunch_params2(:)
+ end type
+ type tao_universe_struct
+ type (tao_lattice_struct), pointer :: model, design
+ character(200), pointer :: descrip => NULL()
+ end type
+ type tao_super_universe_struct
+ type (tao_universe_struct), allocatable :: u(:)
+ end type
+ type (tao_super_universe_struct), save, target :: s
+ contains
+ subroutine tao_lat_equal_tao_lat (lat1, lat2)
+ implicit none
+ type (tao_lattice_struct), intent(inout) :: lat1
+ type (tao_lattice_struct), intent(in) :: lat2
+ if (allocated(lat2%bunch_params)) then
+ lat1%bunch_params = lat2%bunch_params
+ end if
+ if (allocated(lat2%bunch_params2)) then
+ lat1%bunch_params2 = lat2%bunch_params2
+ end if
+ end subroutine
+end module
+
+program tao_program
+ use test_struct
+ implicit none
+ type (tao_universe_struct), pointer :: u
+ integer n, i
+ allocate (s%u(1))
+ u => s%u(1)
+ allocate (u%design, u%model)
+ n = 112
+ allocate (u%model%bunch_params(0:n), u%design%bunch_params(0:n))
+ u%design%bunch_params%n_live_particle = [(i, i = 0, n)]
+ u%model = u%design
+ u%model = u%design ! The double assignment was the cause of the ICE
+ if (.not. allocated (u%model%bunch_params)) call abort
+ if (any (u%model%bunch_params%n_live_particle .ne. [(i, i = 0, n)])) call abort
+ Deallocate (u%model%bunch_params, u%design%bunch_params)
+ deallocate (u%design, u%model)
+ deallocate (s%u)
+end program
+
+! { dg-final { cleanup-modules "test_struct" } }
diff --git a/gcc/testsuite/gfortran.dg/array_constructor_31.f90 b/gcc/testsuite/gfortran.dg/array_constructor_31.f90
new file mode 100644
index 00000000000..02936340ffc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/array_constructor_31.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+! Test the fix for pr40018 in which the elements in the array
+! constructor would be of default type and this would cause an
+! ICE in the backend because of the type mistmatch with 'i'.
+!
+! Contributed by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+!
+ integer(kind=8) :: i
+ write(*,*) [(i, i = 1, 10)]
+ end
diff --git a/gcc/testsuite/gfortran.dg/array_memset_2.f90 b/gcc/testsuite/gfortran.dg/array_memset_2.f90
index 58ce8fe6442..7805f7b9420 100644
--- a/gcc/testsuite/gfortran.dg/array_memset_2.f90
+++ b/gcc/testsuite/gfortran.dg/array_memset_2.f90
@@ -20,8 +20,8 @@ program test
data c /2*1.0/
a(1,:) = 0. ! This can't be optimized to a memset.
- b(1,:) = 0. ! This is optimized to memset.
- c = 0. ! This is optimized to memset.
+ b(1,:) = 0. ! This is optimized to = {}.
+ c = 0. ! This is optimized to = {}.
d(:,1) = 0. ! This can't be otimized to a memset.
call bar(e)
@@ -33,6 +33,6 @@ program test
end program
-! { dg-final { scan-tree-dump-times "memset" 2 "original" } }
+! { dg-final { scan-tree-dump-times "= {}" 2 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
! { dg-final { cleanup-modules "foo" } }
diff --git a/gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f90 b/gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f90
new file mode 100644
index 00000000000..04f0b9faade
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_charlen_dummy.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+! Test the fix for PR fortran/39893.
+! Original testcase provided by Deji Akingunola.
+! Reduced testcase provided by Dominique d'Humieres.
+!
+ SUBROUTINE XAUTOGET()
+ CHARACTER*(*) DICBA ! { dg-error "Entity with assumed character" }
+ DATA DICBA /"CLIP" /
+ RETURN
+ END
diff --git a/gcc/testsuite/gfortran.dg/backspace_11.f90 b/gcc/testsuite/gfortran.dg/backspace_11.f90
new file mode 100644
index 00000000000..7ee40828b2c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/backspace_11.f90
@@ -0,0 +1,24 @@
+! { dg-do run }
+! PR 40334 backspace regression
+program backspace_11
+ implicit none
+ character(len=5) :: str
+ open(10, access='sequential', status='scratch')
+ write(10,'(A)')'HELLO'
+ rewind(10)
+
+ do
+ read(10,'(A)',end=1) str
+ enddo
+1 backspace 10
+ !the file pointer is now at EOF
+
+ read(10,*,end=2) str
+ call abort
+2 backspace 10
+ !the file pointer is now at EOF
+
+ read(10,'(A)',end=3) str
+ call abort
+3 continue
+end program backspace_11
diff --git a/gcc/testsuite/gfortran.dg/chmod_1.f90 b/gcc/testsuite/gfortran.dg/chmod_1.f90
index 1c7907e8f35..07760cf1245 100644
--- a/gcc/testsuite/gfortran.dg/chmod_1.f90
+++ b/gcc/testsuite/gfortran.dg/chmod_1.f90
@@ -1,5 +1,6 @@
-! { dg-do run { target { ! { *-*-mingw* spu-*-* } } } }
+! { dg-do run { target { ! { *-*-mingw* *-*-cygwin* spu-*-* } } } }
! { dg-options "-std=gnu" }
+! See PR38956. Test fails on cygwin when user has Administrator rights
implicit none
character(len=*), parameter :: n = "foobar_file"
integer :: i
diff --git a/gcc/testsuite/gfortran.dg/chmod_2.f90 b/gcc/testsuite/gfortran.dg/chmod_2.f90
index b43c60f9b92..3e5ed617be4 100644
--- a/gcc/testsuite/gfortran.dg/chmod_2.f90
+++ b/gcc/testsuite/gfortran.dg/chmod_2.f90
@@ -1,5 +1,6 @@
-! { dg-do run { target { ! { *-*-mingw* spu-*-* } } } }
+! { dg-do run { target { ! { *-*-mingw* *-*-cygwin* spu-*-* } } } }
! { dg-options "-std=gnu" }
+! See PR38956. Test fails on cygwin when user has Administrator rights
implicit none
character(len=*), parameter :: n = "foobar_file"
integer :: i
diff --git a/gcc/testsuite/gfortran.dg/chmod_3.f90 b/gcc/testsuite/gfortran.dg/chmod_3.f90
index c97af6d4692..9e92ecabccd 100644
--- a/gcc/testsuite/gfortran.dg/chmod_3.f90
+++ b/gcc/testsuite/gfortran.dg/chmod_3.f90
@@ -1,5 +1,6 @@
-! { dg-do run { target { ! { *-*-mingw* spu-*-* } } } }
+! { dg-do run { target { ! { *-*-mingw* *-*-cygwin* spu-*-* } } } }
! { dg-options "-std=gnu -fdefault-integer-8" }
+! See PR38956. Test fails on cygwin when user has Administrator rights
implicit none
character(len=*), parameter :: n = "foobar_file"
integer :: i
diff --git a/gcc/testsuite/gfortran.dg/default_format_1.f90 b/gcc/testsuite/gfortran.dg/default_format_1.f90
index 1c6e71ebc71..e374f1b895d 100644
--- a/gcc/testsuite/gfortran.dg/default_format_1.f90
+++ b/gcc/testsuite/gfortran.dg/default_format_1.f90
@@ -1,4 +1,4 @@
-! { dg-do run { xfail spu-*-* } }
+! { dg-do run { xfail spu-*-* } }
! Test XFAILed on Darwin because the system's printf() lacks
! proper support for denormals.
!
diff --git a/gcc/testsuite/gfortran.dg/default_format_denormal_1.f90 b/gcc/testsuite/gfortran.dg/default_format_denormal_1.f90
index adecd50c4d0..debc113ffc1 100644
--- a/gcc/testsuite/gfortran.dg/default_format_denormal_1.f90
+++ b/gcc/testsuite/gfortran.dg/default_format_denormal_1.f90
@@ -1,4 +1,4 @@
-! { dg-do run { xfail alpha*-*-* *-*-darwin[89]* *-*-freebsd* *-*-mingw* spu-*-* } }
+! { dg-do run { xfail alpha*-*-* *-*-darwin[89]* *-*-freebsd* *-*-mingw* *-*-cygwin* spu-*-* } }
! Test XFAILed on these platforms because the system's printf() lacks
! proper support for denormals.
!
diff --git a/gcc/testsuite/gfortran.dg/dependency_24.f90 b/gcc/testsuite/gfortran.dg/dependency_24.f90
new file mode 100644
index 00000000000..d73479137a8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dependency_24.f90
@@ -0,0 +1,82 @@
+! { dg-do run }
+! Check the fix for PR38863 comment #1, where defined assignment
+! to derived types was not treating components correctly that were
+! not set explicitly.
+!
+! Contributed by Mikael Morin <mikael@gcc.gnu.org>
+!
+module m
+ type t
+ integer :: i,j
+ end type t
+ type ti
+ integer :: i,j = 99
+ end type ti
+ interface assignment (=)
+ module procedure i_to_t, i_to_ti
+ end interface
+contains
+ elemental subroutine i_to_ti (p, q)
+ type(ti), intent(out) :: p
+ integer, intent(in) :: q
+ p%i = q
+ end subroutine
+ elemental subroutine i_to_t (p, q)
+ type(t), intent(out) :: p
+ integer, intent(in) :: q
+ p%i = q
+ end subroutine
+end module
+
+ use m
+ call test_t ! Check original problem
+ call test_ti ! Default initializers were treated wrongly
+contains
+ subroutine test_t
+ type(t), target :: a(3)
+ type(t), target :: b(3)
+ type(t), dimension(:), pointer :: p
+ logical :: l(3)
+
+ a%i = 1
+ a%j = [101, 102, 103]
+ b%i = 3
+ b%j = 4
+
+ p => b
+ l = .true.
+
+ where (l)
+ a = p%i ! Comment #1 of PR38863 concerned WHERE assignment
+ end where
+ if (any (a%j .ne. [101, 102, 103])) call abort
+
+ a = p%i ! Ordinary assignment was wrong too.
+ if (any (a%j .ne. [101, 102, 103])) call abort
+ end subroutine
+
+ subroutine test_ti
+ type(ti), target :: a(3)
+ type(ti), target :: b(3)
+ type(ti), dimension(:), pointer :: p
+ logical :: l(3)
+
+ a%i = 1
+ a%j = [101, 102, 103]
+ b%i = 3
+ b%j = 4
+
+ p => b
+ l = .true.
+
+ where (l)
+ a = p%i
+ end where
+ if (any (a%j .ne. 99)) call abort
+
+ a = p%i
+ if (any (a%j .ne. 99)) call abort
+ end subroutine
+end
+! { dg-final { cleanup-modules "m" } }
+
diff --git a/gcc/testsuite/gfortran.dg/leadz_trailz_1.f90 b/gcc/testsuite/gfortran.dg/leadz_trailz_1.f90
new file mode 100644
index 00000000000..a0cd1979225
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/leadz_trailz_1.f90
@@ -0,0 +1,133 @@
+! { dg-do run }
+
+ integer(kind=1) :: i1
+ integer(kind=2) :: i2
+ integer(kind=4) :: i4
+ integer(kind=8) :: i8
+
+ i1 = -1
+ i2 = -1
+ i4 = -1
+ i8 = -1
+
+ if (leadz(i1) /= 0) call abort
+ if (leadz(i2) /= 0) call abort
+ if (leadz(i4) /= 0) call abort
+ if (leadz(i8) /= 0) call abort
+
+ if (trailz(i1) /= 0) call abort
+ if (trailz(i2) /= 0) call abort
+ if (trailz(i4) /= 0) call abort
+ if (trailz(i8) /= 0) call abort
+
+ if (leadz(-1_1) /= 0) call abort
+ if (leadz(-1_2) /= 0) call abort
+ if (leadz(-1_4) /= 0) call abort
+ if (leadz(-1_8) /= 0) call abort
+
+ if (trailz(-1_1) /= 0) call abort
+ if (trailz(-1_2) /= 0) call abort
+ if (trailz(-1_4) /= 0) call abort
+ if (trailz(-1_8) /= 0) call abort
+
+ i1 = -64
+ i2 = -64
+ i4 = -64
+ i8 = -64
+
+ if (leadz(i1) /= 0) call abort
+ if (leadz(i2) /= 0) call abort
+ if (leadz(i4) /= 0) call abort
+ if (leadz(i8) /= 0) call abort
+
+ if (trailz(i1) /= 6) call abort
+ if (trailz(i2) /= 6) call abort
+ if (trailz(i4) /= 6) call abort
+ if (trailz(i8) /= 6) call abort
+
+ if (leadz(-64_1) /= 0) call abort
+ if (leadz(-64_2) /= 0) call abort
+ if (leadz(-64_4) /= 0) call abort
+ if (leadz(-64_8) /= 0) call abort
+
+ if (trailz(-64_1) /= 6) call abort
+ if (trailz(-64_2) /= 6) call abort
+ if (trailz(-64_4) /= 6) call abort
+ if (trailz(-64_8) /= 6) call abort
+
+ i1 = -108
+ i2 = -108
+ i4 = -108
+ i8 = -108
+
+ if (leadz(i1) /= 0) call abort
+ if (leadz(i2) /= 0) call abort
+ if (leadz(i4) /= 0) call abort
+ if (leadz(i8) /= 0) call abort
+
+ if (trailz(i1) /= 2) call abort
+ if (trailz(i2) /= 2) call abort
+ if (trailz(i4) /= 2) call abort
+ if (trailz(i8) /= 2) call abort
+
+ if (leadz(-108_1) /= 0) call abort
+ if (leadz(-108_2) /= 0) call abort
+ if (leadz(-108_4) /= 0) call abort
+ if (leadz(-108_8) /= 0) call abort
+
+ if (trailz(-108_1) /= 2) call abort
+ if (trailz(-108_2) /= 2) call abort
+ if (trailz(-108_4) /= 2) call abort
+ if (trailz(-108_8) /= 2) call abort
+
+ i1 = 1
+ i2 = 1
+ i4 = 1
+ i8 = 1
+
+ if (leadz(i1) /= bit_size(i1) - 1) call abort
+ if (leadz(i2) /= bit_size(i2) - 1) call abort
+ if (leadz(i4) /= bit_size(i4) - 1) call abort
+ if (leadz(i8) /= bit_size(i8) - 1) call abort
+
+ if (trailz(i1) /= 0) call abort
+ if (trailz(i2) /= 0) call abort
+ if (trailz(i4) /= 0) call abort
+ if (trailz(i8) /= 0) call abort
+
+ if (leadz(1_1) /= bit_size(1_1) - 1) call abort
+ if (leadz(1_2) /= bit_size(1_2) - 1) call abort
+ if (leadz(1_4) /= bit_size(1_4) - 1) call abort
+ if (leadz(1_8) /= bit_size(1_8) - 1) call abort
+
+ if (trailz(1_1) /= 0) call abort
+ if (trailz(1_2) /= 0) call abort
+ if (trailz(1_4) /= 0) call abort
+ if (trailz(1_8) /= 0) call abort
+
+ i1 = 64
+ i2 = 64
+ i4 = 64
+ i8 = 64
+
+ if (leadz(i1) /= 1) call abort
+ if (leadz(i2) /= 9) call abort
+ if (leadz(i4) /= 25) call abort
+ if (leadz(i8) /= 57) call abort
+
+ if (trailz(i1) /= 6) call abort
+ if (trailz(i2) /= 6) call abort
+ if (trailz(i4) /= 6) call abort
+ if (trailz(i8) /= 6) call abort
+
+ if (leadz(64_1) /= 1) call abort
+ if (leadz(64_2) /= 9) call abort
+ if (leadz(64_4) /= 25) call abort
+ if (leadz(64_8) /= 57) call abort
+
+ if (trailz(64_1) /= 6) call abort
+ if (trailz(64_2) /= 6) call abort
+ if (trailz(64_4) /= 6) call abort
+ if (trailz(64_8) /= 6) call abort
+
+end
diff --git a/gcc/testsuite/gfortran.dg/leadz_trailz_2.f90 b/gcc/testsuite/gfortran.dg/leadz_trailz_2.f90
new file mode 100644
index 00000000000..08701d8a537
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/leadz_trailz_2.f90
@@ -0,0 +1,36 @@
+! { dg-do run }
+! { dg-require-effective-target fortran_large_int }
+
+ integer(kind=16) :: i16
+
+ i16 = -1
+ if (leadz(i16) /= 0) call abort
+ if (trailz(i16) /= 0) call abort
+ if (leadz(-1_16) /= 0) call abort
+ if (trailz(-1_16) /= 0) call abort
+
+ i16 = -64
+ if (leadz(i16) /= 0) call abort
+ if (trailz(i16) /= 6) call abort
+ if (leadz(-64_16) /= 0) call abort
+ if (trailz(-64_16) /= 6) call abort
+
+ i16 = -108
+ if (leadz(i16) /= 0) call abort
+ if (trailz(i16) /= 2) call abort
+ if (leadz(-108_16) /= 0) call abort
+ if (trailz(-108_16) /= 2) call abort
+
+ i16 = 1
+ if (leadz(i16) /= bit_size(i16) - 1) call abort
+ if (trailz(i16) /= 0) call abort
+ if (leadz(1_16) /= bit_size(1_16) - 1) call abort
+ if (trailz(1_16) /= 0) call abort
+
+ i16 = 64
+ if (leadz(i16) /= 121) call abort
+ if (trailz(i16) /= 6) call abort
+ if (leadz(64_16) /= 121) call abort
+ if (trailz(64_16) /= 6) call abort
+
+end
diff --git a/gcc/testsuite/gfortran.dg/open_errors.f90 b/gcc/testsuite/gfortran.dg/open_errors.f90
index 729cc6a4fef..d6f1e430526 100644
--- a/gcc/testsuite/gfortran.dg/open_errors.f90
+++ b/gcc/testsuite/gfortran.dg/open_errors.f90
@@ -1,6 +1,7 @@
-! { dg-do run { target { ! { *-*-mingw* spu-*-* } } } }
+! { dg-do run { target { ! { *-*-mingw* *-*-cygwin* spu-*-* } } } }
! PR30005 Enhanced error messages for OPEN
! Submitted by Jerry DeLisle <jvdelisle@gcc.gnu.org>
+! See PR38956. Test fails on cygwin when user has Administrator rights
character(60) :: msg
character(25) :: n = "temptestfile"
logical :: there
diff --git a/gcc/testsuite/gfortran.dg/pr39666-1.f90 b/gcc/testsuite/gfortran.dg/pr39666-1.f90
new file mode 100644
index 00000000000..31840ec1df8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr39666-1.f90
@@ -0,0 +1,14 @@
+! PR middle-end/39666
+! { dg-do compile }
+! { dg-options "-O2 -Wuninitialized" }
+
+FUNCTION f(n)
+ INTEGER, INTENT(in) :: n
+ REAL :: f
+
+ SELECT CASE (n)
+ CASE (:-1); f = -1.0
+ CASE (0); f = 0.0
+ CASE (1:); f = 1.0
+ END SELECT
+END FUNCTION
diff --git a/gcc/testsuite/gfortran.dg/pr39666-2.f90 b/gcc/testsuite/gfortran.dg/pr39666-2.f90
new file mode 100644
index 00000000000..720a716ae31
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr39666-2.f90
@@ -0,0 +1,14 @@
+! PR middle-end/39666
+! { dg-do compile }
+! { dg-options "-O2 -Wuninitialized" }
+
+FUNCTION f(n) ! { dg-warning "may be used uninitialized" }
+ INTEGER, INTENT(in) :: n
+ REAL :: f
+
+ SELECT CASE (n)
+ CASE (:-1); f = -1.0
+ CASE (0); f = 0.0
+ CASE (2:); f = 1.0
+ END SELECT
+END FUNCTION
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index eace2bb7948..632cdbb0061 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -466,6 +466,11 @@ proc check_profiling_available { test_what } {
return 0
}
+ # cygwin does not support -p.
+ if { [istarget *-*-cygwin*] && [lindex $test_what 1] == "-p" } {
+ return 0
+ }
+
# uClibc does not have gcrt1.o.
if { [check_effective_target_uclibc]
&& ([lindex $test_what 1] == "-p"
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index c10c41177a8..447361f73ba 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -683,6 +683,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
tree *rhsp, *lhsp;
gimple use_stmt = gsi_stmt (*use_stmt_gsi);
enum tree_code rhs_code;
+ bool res = true;
gcc_assert (TREE_CODE (def_rhs) == ADDR_EXPR);
@@ -726,19 +727,26 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
/* Now see if the LHS node is an INDIRECT_REF using NAME. If so,
propagate the ADDR_EXPR into the use of NAME and fold the result. */
if (TREE_CODE (lhs) == INDIRECT_REF
- && TREE_OPERAND (lhs, 0) == name
- && may_propagate_address_into_dereference (def_rhs, lhs)
- && (lhsp != gimple_assign_lhs_ptr (use_stmt)
- || useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (def_rhs, 0)),
- TREE_TYPE (rhs))))
+ && TREE_OPERAND (lhs, 0) == name)
{
- *lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
- fold_stmt_inplace (use_stmt);
- tidy_after_forward_propagate_addr (use_stmt);
+ if (may_propagate_address_into_dereference (def_rhs, lhs)
+ && (lhsp != gimple_assign_lhs_ptr (use_stmt)
+ || useless_type_conversion_p
+ (TREE_TYPE (TREE_OPERAND (def_rhs, 0)), TREE_TYPE (rhs))))
+ {
+ *lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
+ fold_stmt_inplace (use_stmt);
+ tidy_after_forward_propagate_addr (use_stmt);
- /* Continue propagating into the RHS if this was not the only use. */
- if (single_use_p)
- return true;
+ /* Continue propagating into the RHS if this was not the only use. */
+ if (single_use_p)
+ return true;
+ }
+ else
+ /* We can have a struct assignment dereferencing our name twice.
+ Note that we didn't propagate into the lhs to not falsely
+ claim we did when propagating into the rhs. */
+ res = false;
}
/* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR
@@ -758,7 +766,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
*rhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
fold_stmt_inplace (use_stmt);
tidy_after_forward_propagate_addr (use_stmt);
- return true;
+ return res;
}
/* Now see if the RHS node is an INDIRECT_REF using NAME. If so,
@@ -789,7 +797,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
true, GSI_NEW_STMT);
gimple_assign_set_rhs1 (use_stmt, new_rhs);
tidy_after_forward_propagate_addr (use_stmt);
- return true;
+ return res;
}
/* If the defining rhs comes from an indirect reference, then do not
convert into a VIEW_CONVERT_EXPR. */
@@ -803,7 +811,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
*rhsp = new_rhs;
fold_stmt_inplace (use_stmt);
tidy_after_forward_propagate_addr (use_stmt);
- return true;
+ return res;
}
}
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index 1e22bcb62da..0a04fdef551 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -592,7 +592,25 @@ remove_unused_scope_block_p (tree scope)
/* For terse debug info we can eliminate info on unused variables. */
else if (debug_info_level == DINFO_LEVEL_NONE
|| debug_info_level == DINFO_LEVEL_TERSE)
- ;
+ {
+ /* Even for -g0/-g1 don't prune outer scopes from artificial
+ functions, otherwise diagnostics using tree_nonartificial_location
+ will not be emitted properly. */
+ if (inlined_function_outer_scope_p (scope))
+ {
+ tree ao = scope;
+
+ while (ao
+ && TREE_CODE (ao) == BLOCK
+ && BLOCK_ABSTRACT_ORIGIN (ao) != ao)
+ ao = BLOCK_ABSTRACT_ORIGIN (ao);
+ if (ao
+ && TREE_CODE (ao) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (ao)
+ && lookup_attribute ("artificial", DECL_ATTRIBUTES (ao)))
+ unused = false;
+ }
+ }
else if (BLOCK_VARS (scope) || BLOCK_NUM_NONLOCALIZED_VARS (scope))
unused = false;
/* See if this block is important for representation of inlined function.
@@ -690,6 +708,9 @@ remove_unused_locals (void)
var_ann_t ann;
bitmap global_unused_vars = NULL;
+ /* Removing declarations from lexical blocks when not optimizing is
+ not only a waste of time, it actually causes differences in stack
+ layout. */
if (!optimize)
return;
@@ -758,8 +779,7 @@ remove_unused_locals (void)
if (TREE_CODE (var) != FUNCTION_DECL
&& (!(ann = var_ann (var))
- || !ann->used)
- && (optimize || DECL_ARTIFICIAL (var)))
+ || !ann->used))
{
if (is_global_var (var))
{
@@ -820,8 +840,7 @@ remove_unused_locals (void)
&& TREE_CODE (t) != RESULT_DECL
&& !(ann = var_ann (t))->used
&& !ann->symbol_mem_tag
- && !TREE_ADDRESSABLE (t)
- && (optimize || DECL_ARTIFICIAL (t)))
+ && !TREE_ADDRESSABLE (t))
remove_referenced_var (t);
remove_unused_scope_block_p (DECL_INITIAL (current_function_decl));
if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index d657e1ae78f..fad714724a6 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -534,7 +534,7 @@ inverse (tree x, tree mask)
}
/* Derives the upper bound BND on the number of executions of loop with exit
- condition S * i <> C, assuming that the loop is not infinite. If
+ condition S * i <> C, assuming that this exit is taken. If
NO_OVERFLOW is true, then the control variable of the loop does not
overflow. If NO_OVERFLOW is true or BNDS.below >= 0, then BNDS.up
contains the upper bound on the value of C. */
@@ -574,7 +574,7 @@ number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
/* Determines number of iterations of loop whose ending condition
is IV <> FINAL. TYPE is the type of the iv. The number of
- iterations is stored to NITER. NEVER_INFINITE is true if
+ iterations is stored to NITER. EXIT_MUST_BE_TAKEN is true if
we know that the exit must be taken eventually, i.e., that the IV
ever reaches the value FINAL (we derived this earlier, and possibly set
NITER->assumptions to make sure this is the case). BNDS contains the
@@ -582,7 +582,7 @@ number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
static bool
number_of_iterations_ne (tree type, affine_iv *iv, tree final,
- struct tree_niter_desc *niter, bool never_infinite,
+ struct tree_niter_desc *niter, bool exit_must_be_taken,
bounds *bnds)
{
tree niter_type = unsigned_type_for (type);
@@ -639,9 +639,9 @@ number_of_iterations_ne (tree type, affine_iv *iv, tree final,
build_int_cst (niter_type, 1), bits);
s = fold_binary_to_constant (RSHIFT_EXPR, niter_type, s, bits);
- if (!never_infinite)
+ if (!exit_must_be_taken)
{
- /* If we cannot assume that the loop is not infinite, record the
+ /* If we cannot assume that the exit is taken eventually, record the
assumptions for divisibility of c. */
assumption = fold_build2 (FLOOR_MOD_EXPR, niter_type, c, d);
assumption = fold_build2 (EQ_EXPR, boolean_type_node,
@@ -664,20 +664,21 @@ number_of_iterations_ne (tree type, affine_iv *iv, tree final,
of the final value does not overflow are recorded in NITER. If we
find the final value, we adjust DELTA and return TRUE. Otherwise
we return false. BNDS bounds the value of IV1->base - IV0->base,
- and will be updated by the same amount as DELTA. */
+ and will be updated by the same amount as DELTA. EXIT_MUST_BE_TAKEN is
+ true if we know that the exit must be taken eventually. */
static bool
number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
struct tree_niter_desc *niter,
tree *delta, tree step,
- bounds *bnds)
+ bool exit_must_be_taken, bounds *bnds)
{
tree niter_type = TREE_TYPE (step);
tree mod = fold_build2 (FLOOR_MOD_EXPR, niter_type, *delta, step);
tree tmod;
mpz_t mmod;
tree assumption = boolean_true_node, bound, noloop;
- bool ret = false;
+ bool ret = false, fv_comp_no_overflow;
tree type1 = type;
if (POINTER_TYPE_P (type))
type1 = sizetype;
@@ -692,17 +693,31 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
mpz_set_double_int (mmod, tree_to_double_int (mod), true);
mpz_neg (mmod, mmod);
+ /* If the induction variable does not overflow and the exit is taken,
+ then the computation of the final value does not overflow. This is
+ also obviously the case if the new final value is equal to the
+ current one. Finally, we postulate this for pointer type variables,
+ as the code cannot rely on the object to that the pointer points being
+ placed at the end of the address space (and more pragmatically,
+ TYPE_{MIN,MAX}_VALUE is not defined for pointers). */
+ if (integer_zerop (mod) || POINTER_TYPE_P (type))
+ fv_comp_no_overflow = true;
+ else if (!exit_must_be_taken)
+ fv_comp_no_overflow = false;
+ else
+ fv_comp_no_overflow =
+ (iv0->no_overflow && integer_nonzerop (iv0->step))
+ || (iv1->no_overflow && integer_nonzerop (iv1->step));
+
if (integer_nonzerop (iv0->step))
{
/* The final value of the iv is iv1->base + MOD, assuming that this
computation does not overflow, and that
iv0->base <= iv1->base + MOD. */
- if (!iv0->no_overflow && !integer_zerop (mod))
+ if (!fv_comp_no_overflow)
{
bound = fold_build2 (MINUS_EXPR, type1,
TYPE_MAX_VALUE (type1), tmod);
- if (POINTER_TYPE_P (type))
- bound = fold_convert (type, bound);
assumption = fold_build2 (LE_EXPR, boolean_type_node,
iv1->base, bound);
if (integer_zerop (assumption))
@@ -726,12 +741,10 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
/* The final value of the iv is iv0->base - MOD, assuming that this
computation does not overflow, and that
iv0->base - MOD <= iv1->base. */
- if (!iv1->no_overflow && !integer_zerop (mod))
+ if (!fv_comp_no_overflow)
{
bound = fold_build2 (PLUS_EXPR, type1,
TYPE_MIN_VALUE (type1), tmod);
- if (POINTER_TYPE_P (type))
- bound = fold_convert (type, bound);
assumption = fold_build2 (GE_EXPR, boolean_type_node,
iv0->base, bound);
if (integer_zerop (assumption))
@@ -969,13 +982,13 @@ assert_loop_rolls_lt (tree type, affine_iv *iv0, affine_iv *iv1,
/* Determines number of iterations of loop whose ending condition
is IV0 < IV1. TYPE is the type of the iv. The number of
iterations is stored to NITER. BNDS bounds the difference
- IV1->base - IV0->base. */
+ IV1->base - IV0->base. EXIT_MUST_BE_TAKEN is true if we know
+ that the exit must be taken eventually. */
static bool
number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
struct tree_niter_desc *niter,
- bool never_infinite ATTRIBUTE_UNUSED,
- bounds *bnds)
+ bool exit_must_be_taken, bounds *bnds)
{
tree niter_type = unsigned_type_for (type);
tree delta, step, s;
@@ -1034,7 +1047,7 @@ number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
transform the condition to != comparison. In particular, this will be
the case if DELTA is constant. */
if (number_of_iterations_lt_to_ne (type, iv0, iv1, niter, &delta, step,
- bnds))
+ exit_must_be_taken, bnds))
{
affine_iv zps;
@@ -1076,14 +1089,14 @@ number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
/* Determines number of iterations of loop whose ending condition
is IV0 <= IV1. TYPE is the type of the iv. The number of
- iterations is stored to NITER. NEVER_INFINITE is true if
+ iterations is stored to NITER. EXIT_MUST_BE_TAKEN is true if
we know that this condition must eventually become false (we derived this
earlier, and possibly set NITER->assumptions to make sure this
is the case). BNDS bounds the difference IV1->base - IV0->base. */
static bool
number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
- struct tree_niter_desc *niter, bool never_infinite,
+ struct tree_niter_desc *niter, bool exit_must_be_taken,
bounds *bnds)
{
tree assumption;
@@ -1094,9 +1107,13 @@ number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
/* Say that IV0 is the control variable. Then IV0 <= IV1 iff
IV0 < IV1 + 1, assuming that IV1 is not equal to the greatest
value of the type. This we must know anyway, since if it is
- equal to this value, the loop rolls forever. */
+ equal to this value, the loop rolls forever. We do not check
+ this condition for pointer type ivs, as the code cannot rely on
+ the object to that the pointer points being placed at the end of
+ the address space (and more pragmatically, TYPE_{MIN,MAX}_VALUE is
+ not defined for pointers). */
- if (!never_infinite)
+ if (!exit_must_be_taken && !POINTER_TYPE_P (type))
{
if (integer_nonzerop (iv0->step))
assumption = fold_build2 (NE_EXPR, boolean_type_node,
@@ -1131,7 +1148,8 @@ number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
bounds_add (bnds, double_int_one, type1);
- return number_of_iterations_lt (type, iv0, iv1, niter, never_infinite, bnds);
+ return number_of_iterations_lt (type, iv0, iv1, niter, exit_must_be_taken,
+ bnds);
}
/* Dumps description of affine induction variable IV to FILE. */
@@ -1177,7 +1195,7 @@ number_of_iterations_cond (struct loop *loop,
affine_iv *iv1, struct tree_niter_desc *niter,
bool only_exit)
{
- bool never_infinite, ret;
+ bool exit_must_be_taken = false, ret;
bounds bnds;
/* The meaning of these assumptions is this:
@@ -1202,42 +1220,27 @@ number_of_iterations_cond (struct loop *loop,
code = swap_tree_comparison (code);
}
- if (!only_exit)
- {
- /* If this is not the only possible exit from the loop, the information
- that the induction variables cannot overflow as derived from
- signedness analysis cannot be relied upon. We use them e.g. in the
- following way: given loop for (i = 0; i <= n; i++), if i is
- signed, it cannot overflow, thus this loop is equivalent to
- for (i = 0; i < n + 1; i++); however, if n == MAX, but the loop
- is exited in some other way before i overflows, this transformation
- is incorrect (the new loop exits immediately). */
- iv0->no_overflow = false;
- iv1->no_overflow = false;
- }
-
if (POINTER_TYPE_P (type))
{
/* Comparison of pointers is undefined unless both iv0 and iv1 point
to the same object. If they do, the control variable cannot wrap
(as wrap around the bounds of memory will never return a pointer
that would be guaranteed to point to the same object, even if we
- avoid undefined behavior by casting to size_t and back). The
- restrictions on pointer arithmetics and comparisons of pointers
- ensure that using the no-overflow assumptions is correct in this
- case even if ONLY_EXIT is false. */
+ avoid undefined behavior by casting to size_t and back). */
iv0->no_overflow = true;
iv1->no_overflow = true;
}
- /* If the control induction variable does not overflow, the loop obviously
- cannot be infinite. */
- if (!integer_zerop (iv0->step) && iv0->no_overflow)
- never_infinite = true;
- else if (!integer_zerop (iv1->step) && iv1->no_overflow)
- never_infinite = true;
- else
- never_infinite = false;
+ /* If the control induction variable does not overflow and the only exit
+ from the loop is the one that we analyze, we know it must be taken
+ eventually. */
+ if (only_exit)
+ {
+ if (!integer_zerop (iv0->step) && iv0->no_overflow)
+ exit_must_be_taken = true;
+ else if (!integer_zerop (iv1->step) && iv1->no_overflow)
+ exit_must_be_taken = true;
+ }
/* We can handle the case when neither of the sides of the comparison is
invariant, provided that the test is NE_EXPR. This rarely occurs in
@@ -1308,16 +1311,16 @@ number_of_iterations_cond (struct loop *loop,
case NE_EXPR:
gcc_assert (integer_zerop (iv1->step));
ret = number_of_iterations_ne (type, iv0, iv1->base, niter,
- never_infinite, &bnds);
+ exit_must_be_taken, &bnds);
break;
case LT_EXPR:
- ret = number_of_iterations_lt (type, iv0, iv1, niter, never_infinite,
+ ret = number_of_iterations_lt (type, iv0, iv1, niter, exit_must_be_taken,
&bnds);
break;
case LE_EXPR:
- ret = number_of_iterations_le (type, iv0, iv1, niter, never_infinite,
+ ret = number_of_iterations_le (type, iv0, iv1, niter, exit_must_be_taken,
&bnds);
break;
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 7d7236e2966..539abf6a3f4 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1293,7 +1293,7 @@ vn_nary_op_lookup_stmt (gimple stmt, vn_nary_op_t *vnresult)
*vnresult = NULL;
vno1.opcode = gimple_assign_rhs_code (stmt);
vno1.length = gimple_num_ops (stmt) - 1;
- vno1.type = TREE_TYPE (gimple_assign_lhs (stmt));
+ vno1.type = gimple_expr_type (stmt);
for (i = 0; i < vno1.length; ++i)
vno1.op[i] = gimple_op (stmt, i + 1);
if (vno1.opcode == REALPART_EXPR
@@ -1401,7 +1401,7 @@ vn_nary_op_insert_stmt (gimple stmt, tree result)
vno1->value_id = VN_INFO (result)->value_id;
vno1->opcode = gimple_assign_rhs_code (stmt);
vno1->length = length;
- vno1->type = TREE_TYPE (gimple_assign_lhs (stmt));
+ vno1->type = gimple_expr_type (stmt);
for (i = 0; i < vno1->length; ++i)
vno1->op[i] = gimple_op (stmt, i + 1);
if (vno1->opcode == REALPART_EXPR
@@ -2142,7 +2142,7 @@ simplify_binary_expression (gimple stmt)
fold_defer_overflow_warnings ();
result = fold_binary (gimple_assign_rhs_code (stmt),
- TREE_TYPE (gimple_get_lhs (stmt)), op0, op1);
+ gimple_expr_type (stmt), op0, op1);
if (result)
STRIP_USELESS_TYPE_CONVERSION (result);
diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c
index e753ccbabf4..f88af5dc9b0 100644
--- a/gcc/tree-vect-analyze.c
+++ b/gcc/tree-vect-analyze.c
@@ -2187,7 +2187,7 @@ vect_analyze_group_access (struct data_reference *dr)
tree next_step;
tree prev_init = DR_INIT (data_ref);
gimple prev = stmt;
- HOST_WIDE_INT diff, count_in_bytes;
+ HOST_WIDE_INT diff, count_in_bytes, gaps = 0;
while (next)
{
@@ -2249,6 +2249,8 @@ vect_analyze_group_access (struct data_reference *dr)
fprintf (vect_dump, "interleaved store with gaps");
return false;
}
+
+ gaps += diff - 1;
}
/* Store the gap from the previous member of the group. If there is no
@@ -2265,8 +2267,9 @@ vect_analyze_group_access (struct data_reference *dr)
the type to get COUNT_IN_BYTES. */
count_in_bytes = type_size * count;
- /* Check that the size of the interleaving is not greater than STEP. */
- if (dr_step < count_in_bytes)
+ /* Check that the size of the interleaving (including gaps) is not greater
+ than STEP. */
+ if (dr_step && dr_step < count_in_bytes + gaps * type_size)
{
if (vect_print_dump_info (REPORT_DETAILS))
{
diff --git a/gcc/tree.c b/gcc/tree.c
index 5395e99909c..c9618f7d517 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -9060,32 +9060,12 @@ block_nonartificial_location (tree block)
location_t
tree_nonartificial_location (tree exp)
{
- tree block = TREE_BLOCK (exp);
+ location_t *loc = block_nonartificial_location (TREE_BLOCK (exp));
- while (block
- && TREE_CODE (block) == BLOCK
- && BLOCK_ABSTRACT_ORIGIN (block))
- {
- tree ao = BLOCK_ABSTRACT_ORIGIN (block);
-
- do
- {
- if (TREE_CODE (ao) == FUNCTION_DECL
- && DECL_DECLARED_INLINE_P (ao)
- && lookup_attribute ("artificial", DECL_ATTRIBUTES (ao)))
- return BLOCK_SOURCE_LOCATION (block);
- else if (TREE_CODE (ao) == BLOCK
- && BLOCK_SUPERCONTEXT (ao) != ao)
- ao = BLOCK_SUPERCONTEXT (ao);
- else
- break;
- }
- while (ao);
-
- block = BLOCK_SUPERCONTEXT (block);
- }
-
- return EXPR_LOCATION (exp);
+ if (loc)
+ return *loc;
+ else
+ return EXPR_LOCATION (exp);
}
diff --git a/gcc/tree.h b/gcc/tree.h
index 8274b5961c8..92d8c476c3b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5102,7 +5102,7 @@ extern tree tree_overlaps_hard_reg_set (tree, HARD_REG_SET *);
/* Generate a new label for the CFI info to refer to. */
-extern char *dwarf2out_cfi_label (void);
+extern char *dwarf2out_cfi_label (bool);
/* Entry point to update the canonical frame address (CFA). */
@@ -5270,6 +5270,9 @@ extern unsigned HOST_WIDE_INT highest_pow2_factor (const_tree);
void init_inline_once (void);
+/* In ipa-reference.c. Used for parsing attributes of asm code. */
+extern GTY(()) tree memory_identifier_string;
+
/* Compute the number of operands in an expression node NODE. For
tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself,
otherwise it is looked up from the node's code. */
diff --git a/gnattools/ChangeLog b/gnattools/ChangeLog
index 47412230fdf..4fc4c0e733d 100644
--- a/gnattools/ChangeLog
+++ b/gnattools/ChangeLog
@@ -1,3 +1,9 @@
+2009-05-18 Bechir Zalila <bechir.zalila@gmail.com>
+
+ PR ada/40166
+ * Makefile.in (TOOLS_TARGET_PAIRS): Use the correct path to the
+ target specific sources.
+
2009-04-21 Release Manager
* GCC 4.4.0 released.
diff --git a/gnattools/Makefile.in b/gnattools/Makefile.in
index 1c8535f93e9..b7dc497b75d 100644
--- a/gnattools/Makefile.in
+++ b/gnattools/Makefile.in
@@ -164,7 +164,7 @@ $(GCC_DIR)/stamp-tools:
-(cd $(GCC_DIR)/ada/tools; $(LN_S) ../sdefault.adb .)
-$(foreach PAIR,$(TOOLS_TARGET_PAIRS), \
rm -f $(GCC_DIR)/ada/tools/$(word 1,$(subst <, ,$(PAIR)));\
- $(LN_S) $(fsrcdir)/$(word 2,$(subst <, ,$(PAIR))) \
+ $(LN_S) $(fsrcdir)/ada/$(word 2,$(subst <, ,$(PAIR))) \
$(GCC_DIR)/ada/tools/$(word 1,$(subst <, ,$(PAIR)));)
touch $(GCC_DIR)/stamp-tools
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 9980e049b89..ad129b822b1 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,359 @@
+2009-06-11 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libfortran/40330
+ * io/io.h: Revert format caching.
+ * io/unit.c: Likewise.
+ * io/transfer.c: Likewise.
+ * io/format.c: Likewise.
+
+2009-06-09 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR libfortran/40330
+ * io/format.c (free_format_hash_table): Also free and nullify hash
+ key.
+ (save_parsed_format): Copy string rather than pointer copy.
+
+2009-06-08 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libfortran/40334
+ * io/list_read.c (list_formatted_read_scalar): Set the end file
+ conditions after a return from EOF error.
+
+2009-06-03 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/40019
+ * intrinsics/bit_intrinsics.c: New file.
+ * gfortran.map (GFORTRAN_1.2): New list.
+ * Makefile.am: Add intrinsics/bit_intrinsics.c.
+ * Makefile.in: Regenerate.
+
+2009-05-23 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ Backport from mainline:
+ PR libfortran/37754
+ * io/write_float.def: Simplify format calculation.
+
+2009-05-23 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ Backport from mainline:
+ PR fortran/22423
+ * io/transfer.c (read_block_direct): Avoid warning.
+
+2009-05-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ Backport from mainline:
+ PR libfortran/39667
+ * io/file_pos.c (st_rewind): Don't truncate or flush.
+ * io/intrinsics.c (fgetc): Flush if switching mode.
+ (fputc): Likewise.
+
+2009-05-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ Backport from mainline:
+ PR libfortran/39782
+ * io/transfer.c (data_transfer_init): Don't flush before seek.
+
+2009-05-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ Backport from mainline:
+ * io/io.h (is_preconnected): Remove prototype.
+ * io/unix.c (is_preconnected): Remove function.
+
+2009-05-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ Backport from mainline:
+ PR libfortran/38668
+ * io/transfer.c (finalize_transfer): Don't flush for advance='no'.
+
+2009-05-23 Danny Smith <dannysmith@clear.net.nz>
+
+ Backport from mainline:
+ * io/write.c (itoa) : Rename back to gfc_itoa.
+ (write_i): Adjust call to write_decimal.
+ (write_integer): Use gfc_itoa.
+
+2009-05-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ Backport from mainline:
+ * io/io.h (move_pos_offset): Remove prototype.
+ * io/transfer.c (formatted_transfer_scalar_read): Use sseek
+ instead of move_pos_offset.
+ * io/unix.c (move_pos_offset): Remove.
+
+2009-05-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ Backport from mainline:
+ PR libfortran/39665 libfortran/39702 libfortran/39709
+ * io/io.h (st_parameter_dt): Revert aligned attribute from u.p.value.
+ * io/list_read.c (read_complex): Read directly into user pointer.
+ (read_real): Likewise.
+ (list_formatted_read_scalar): Update read_complex and read_real calls.
+ (nml_read_obj): Read directly into user pointer.
+
+2009-05-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ Backport from mainline:
+ PR libfortran/39665
+ * io/io.h (st_parameter_dt): Add aligned attribute to u.p.value.
+ * io/read.c (convert_real): Add note about alignment requirements.
+
+2009-05-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ Backport from mainline:
+ * io/open.c (already_open): Test for POSIX close return value.
+ * io/unit.c (close_unit_1): Likewise.
+ * io/unix.c (raw_close): Return 0 for success for preconnected units.
+
+2009-05-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ Backport from mainline:
+ * runtime/error.c (gfc_itoa): Move to io/write.c
+ (xtoa): Rename to gfc_xtoa.
+ * runtime/backtrace.c (show_backtrace): Call gfc_xtoa.
+ * libgfortran.h (gfc_itoa): Remove prototype.
+ (xtoa): Rename prototype to gfc_xtoa.
+ * io/list_read.c (nml_read_obj): Use size_t for string length.
+ * io/transfer.c (read_block_direct): Change nbytes arg from
+ pointer to value.
+ (unformatted_read): Minor cleanup, call read_block_directly properly.
+ (skip_record): Use ssize_t.
+ (next_record_w_unf): Avoid stell() call by calling sseek with SEEK_CUR.
+ (iolength_transfer): Make sure to multiply before cast.
+ * io/intrinsics.c (fgetc): Remove unnecessary variable.
+ * io/format.c (format_hash): Use gfc_charlen_type.
+ * io/write.c (itoa): Move from runtime/error.c:gfc_itoa, rename,
+ make static.
+ (write_i): Call with pointer to itoa.
+ (write_z): Call with pointer to gfc_xtoa.
+ (write_integer): Pointer to itoa.
+ (nml_write_obj): Type cleanup, don't call strlen in loop.
+
+2009-05-23 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from mainline:
+ PR libgfortran/39664
+ * io/unix.c (raw_close): Don't close STDOUT_FILENO,
+ STDERR_FILENO nor STDIN_FILENO.
+
+2009-05-23 David Edelsohn <edelsohn@gnu.org>
+
+ Backport from mainline:
+ * io/io.h (struct stream): Rename truncate to trunc.
+ (struncate): Same.
+ * io/unix.c (raw_init): Rename truncate to trunc.
+ (buf_init): Same.
+ (open_internal): Same.
+
+2009-05-23 Daniel Kraft <d@domob.eu>
+
+ Backport from mainline:
+ PR fortran/38654
+ * io/read.c (read_f): Reworked to speed up floating point parsing.
+ (convert_real): Use pointer-casting instead of memcpy and temporaries.
+
+2009-05-23 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ Backport from mainline:
+ PR libfortran/37754
+ * io/io.h (format_hash_entry): New structure for hash table.
+ (format_hash_table): The hash table itself.
+ (free_format_data): Revise function prototype.
+ (free_format_hash_table, init_format_hash,
+ free_format_hash): New function prototypes.
+ * io/unit.c (close_unit_1): Use free_format_hash_table.
+ * io/transfer.c (st_read_done, st_write_done): Free format data if
+ internal unit.
+ * io/format.c (free_format_hash_table): New function that frees any
+ memory allocated previously for cached format data.
+ (reset_node): New static helper function to reset the format counters
+ for a format node.
+ (reset_fnode_counters): New static function recursively calls reset_node
+ to traverse the fnode tree.
+ (format_hash): New simple hash function based on XOR, probabalistic,
+ tosses collisions.
+ (save_parsed_format): New static function to save the parsed format
+ data to use again.
+ (find_parsed_format): New static function searches the hash table
+ looking for a match.
+ (free_format_data): Revised to accept pointer to format data rather than
+ the dtp pointer so that the function can be used in more places.
+ (format_lex): Editorial.
+ (parse_format_list): Set flag used to determine of format data hashing
+ is to be used. Internal units are not persistent enough for this.
+ (revert): Move to ne location in file.
+ (parse_format): Use new functions to look for previously parsed
+ format strings and use them rather than re-parse. If not found, saves
+ the parsed format data for later use.
+
+2009-05-23 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ Backport from mainline:
+ PR libfortran/37754
+ * io/transfer.c (formatted_transfer_scalar): Remove this function by
+ factoring it into two new functions, one for read and one for write,
+ eliminating all the conditionals for read or write mode.
+ (formatted transfer_scalar_read): New function.
+ (formatted transfer_scalar_write): New function.
+ (formatted_transfer): Use new functions.
+
+2009-05-23 Janne Blomqvist <jb@gcc.gnu.org>
+
+ Backport from mainline:
+ PR libfortran/25561 libfortran/37754
+ * io/io.h (struct stream): Define new stream interface function
+ pointers, and inline functions for accessing it.
+ (struct fbuf): Use int instead of size_t, remove flushed element.
+ (mem_alloc_w): New prototype.
+ (mem_alloc_r): New prototype.
+ (stream_at_bof): Remove prototype.
+ (stream_at_eof): Remove prototype.
+ (file_position): Remove prototype.
+ (flush): Remove prototype.
+ (stream_offset): Remove prototype.
+ (unit_truncate): New prototype.
+ (read_block_form): Change to return pointer, int* argument.
+ (hit_eof): New prototype.
+ (fbuf_init): Change prototype.
+ (fbuf_reset): Change prototype.
+ (fbuf_alloc): Change prototype.
+ (fbuf_flush): Change prototype.
+ (fbuf_seek): Change prototype.
+ (fbuf_read): New prototype.
+ (fbuf_getc_refill): New prototype.
+ (fbuf_getc): New inline function.
+ * io/fbuf.c (fbuf_init): Use int, get rid of flushed.
+ (fbuf_debug): New function.
+ (fbuf_reset): Flush, and return position offset.
+ (fbuf_alloc): Simplify, don't flush, just realloc.
+ (fbuf_flush): Make usable for read mode, salvage remaining bytes.
+ (fbuf_seek): New whence argument.
+ (fbuf_read): New function.
+ (fbuf_getc_refill): New function.
+ * io/file_pos.c (formatted_backspace): Use new stream interface.
+ (unformatted_backspace): Likewise.
+ (st_backspace): Make sure format buffer is reset, use new stream
+ interface, use unit_truncate.
+ (st_endfile): Likewise.
+ (st_rewind): Likewise.
+ * io/intrinsics.c: Use new stream interface.
+ * io/list_read.c (push_char): Don't use u.p.scratch, use realloc
+ to resize.
+ (free_saved): Don't check u.p.scratch.
+ (next_char): Use new stream interface, use fbuf_getc() for external files.
+ (finish_list_read): flush format buffer.
+ (nml_query): Update to use modified interface:s
+ * io/open.c (test_endfile): Use new stream interface.
+ (edit_modes): Likewise.
+ (new_unit): Likewise, set bytes_left to 1 for stream files.
+ * io/read.c (read_l): Use new read_block_form interface.
+ (read_utf8): Likewise.
+ (read_utf8_char1): Likewise.
+ (read_default_char1): Likewise.
+ (read_utf8_char4): Likewise.
+ (read_default_char4): Likewise.
+ (read_a): Likewise.
+ (read_a_char4): Likewise.
+ (read_decimal): Likewise.
+ (read_radix): Likewise.
+ (read_f): Likewise.
+ * io/transfer.c (read_sf): Use fbuf_read and mem_alloc_r, remove
+ usage of u.p.line_buffer.
+ (read_block_form): Update interface to return pointer, use
+ fbuf_read for direct access.
+ (read_block_direct): Update to new stream interface.
+ (write_block): Use mem_alloc_w for internal I/O.
+ (write_buf): Update to new stream interface.
+ (formatted_transfer_scalar): Don't use u.p.line_buffer, use
+ fbuf_seek for external files.
+ (us_read): Update to new stream interface.
+ (us_write): Likewise.
+ (data_transfer_init): Always check if we switch modes and flush.
+ (skip_record): Use new stream interface, fix comparison.
+ (next_record_r): Check for and reset u.p.at_eof, use new stream
+ interface, use fbuf_getc for spacing.
+ (write_us_marker): Update to new stream interface, don't inline.
+ (next_record_w_unf): Likewise.
+ (sset): New function.
+ (next_record_w): Use new stream interface, use fbuf for printing
+ newline.
+ (next_record): Use new stream interface.
+ (finalize_transfer): Remove sfree call, use new stream interface.
+ (st_iolength_done): Don't use u.p.scratch.
+ (st_read): Don't check for end of file.
+ (st_read_done): Don't use u.p.scratch, use unit_truncate.
+ (hit_eof): New function.
+ * io/unit.c (init_units): Always init fbuf for formatted units.
+ (update_position): Use new stream interface.
+ (unit_truncate): New function.
+ (finish_last_advance_record): Use fbuf to print newline.
+ * io/unix.c: Remove unused SSIZE_MAX macro.
+ (BUFFER_SIZE): Make static const variable rather than macro.
+ (struct unix_stream): Remove dirty_offset, len, method,
+ small_buffer. Order elements by decreasing size.
+ (struct int_stream): Remove.
+ (move_pos_offset): Remove usage of dirty_offset.
+ (reset_stream): Remove.
+ (do_read): Rename to raw_read, update to match new stream
+ interface.
+ (do_write): Rename to raw_write, update to new stream interface.
+ (raw_seek): New function.
+ (raw_tell): New function.
+ (raw_truncate): New function.
+ (raw_close): New function.
+ (raw_flush): New function.
+ (raw_init): New function.
+ (fd_alloc): Remove.
+ (fd_alloc_r_at): Remove.
+ (fd_alloc_w_at): Remove.
+ (fd_sfree): Remove.
+ (fd_seek): Remove.
+ (fd_truncate): Remove.
+ (fd_sset): Remove.
+ (fd_read): Remove.
+ (fd_write): Remove.
+ (fd_close): Remove.
+ (fd_open): Remove.
+ (fd_flush): Rename to buf_flush, update to new stream interface
+ and unix_stream.
+ (buf_read): New function.
+ (buf_write): New function.
+ (buf_seek): New function.
+ (buf_tell): New function.
+ (buf_truncate): New function.
+ (buf_close): New function.
+ (buf_init): New function.
+ (mem_alloc_r_at): Rename to mem_alloc_r, change prototype.
+ (mem_alloc_w_at): Rename to mem_alloc_w, change prototype.
+ (mem_read): Change to match new stream interface.
+ (mem_write): Likewise.
+ (mem_seek): Likewise.
+ (mem_tell): Likewise.
+ (mem_truncate): Likewise.
+ (mem_close): Likewise.
+ (mem_flush): New function.
+ (mem_sfree): Remove.
+ (empty_internal_buffer): Cast to correct type.
+ (open_internal): Use correct type, init function pointers.
+ (fd_to_stream): Test whether to open file as buffered or raw.
+ (output_stream): Remove mode set.
+ (error_stream): Likewise.
+ (flush_all_units_1): Use new stream interface.
+ (flush_all_units): Likewise.
+ (stream_at_bof): Remove.
+ (stream_at_eof): Remove.
+ (file_position): Remove.
+ (file_length): Update logic to use stream interface.
+ (flush): Remove.
+ (stream_offset): Remove.
+ * io/write.c (write_utf8_char4): Use int instead of size_t.
+ (write_x): Extra safety check.
+ (namelist_write_newline): Use new stream interface.
+
+2009-05-16 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR libfortran/39782
+ * io/transfer.c (finalize_transfer): Remove extra flush.
+
2009-04-21 Release Manager
* GCC 4.4.0 released.
diff --git a/libgfortran/Makefile.am b/libgfortran/Makefile.am
index 2223d61fcf2..b3b2e81f473 100644
--- a/libgfortran/Makefile.am
+++ b/libgfortran/Makefile.am
@@ -58,6 +58,7 @@ intrinsics/associated.c \
intrinsics/abort.c \
intrinsics/access.c \
intrinsics/args.c \
+intrinsics/bit_intrinsics.c \
intrinsics/c99_functions.c \
intrinsics/chdir.c \
intrinsics/chmod.c \
diff --git a/libgfortran/Makefile.in b/libgfortran/Makefile.in
index eb3a12ef252..ac01a2d3bfd 100644
--- a/libgfortran/Makefile.in
+++ b/libgfortran/Makefile.in
@@ -416,9 +416,9 @@ am__libgfortran_la_SOURCES_DIST = runtime/backtrace.c \
io/size_from_kind.c io/transfer.c io/unit.c io/unix.c \
io/write.c io/fbuf.c intrinsics/associated.c \
intrinsics/abort.c intrinsics/access.c intrinsics/args.c \
- intrinsics/c99_functions.c intrinsics/chdir.c \
- intrinsics/chmod.c intrinsics/clock.c intrinsics/cpu_time.c \
- intrinsics/cshift0.c intrinsics/ctime.c \
+ intrinsics/bit_intrinsics.c intrinsics/c99_functions.c \
+ intrinsics/chdir.c intrinsics/chmod.c intrinsics/clock.c \
+ intrinsics/cpu_time.c intrinsics/cshift0.c intrinsics/ctime.c \
intrinsics/date_and_time.c intrinsics/dtime.c intrinsics/env.c \
intrinsics/eoshift0.c intrinsics/eoshift2.c \
intrinsics/erfc_scaled.c intrinsics/etime.c intrinsics/exit.c \
@@ -711,9 +711,9 @@ am__objects_35 = close.lo file_pos.lo format.lo inquire.lo \
intrinsics.lo list_read.lo lock.lo open.lo read.lo \
size_from_kind.lo transfer.lo unit.lo unix.lo write.lo fbuf.lo
am__objects_36 = associated.lo abort.lo access.lo args.lo \
- c99_functions.lo chdir.lo chmod.lo clock.lo cpu_time.lo \
- cshift0.lo ctime.lo date_and_time.lo dtime.lo env.lo \
- eoshift0.lo eoshift2.lo erfc_scaled.lo etime.lo exit.lo \
+ bit_intrinsics.lo c99_functions.lo chdir.lo chmod.lo clock.lo \
+ cpu_time.lo cshift0.lo ctime.lo date_and_time.lo dtime.lo \
+ env.lo eoshift0.lo eoshift2.lo erfc_scaled.lo etime.lo exit.lo \
fnum.lo gerror.lo getcwd.lo getlog.lo getXid.lo hostnm.lo \
ierrno.lo ishftc.lo iso_c_generated_procs.lo iso_c_binding.lo \
kill.lo link.lo malloc.lo mvbits.lo move_alloc.lo \
@@ -987,6 +987,7 @@ intrinsics/associated.c \
intrinsics/abort.c \
intrinsics/access.c \
intrinsics/args.c \
+intrinsics/bit_intrinsics.c \
intrinsics/c99_functions.c \
intrinsics/chdir.c \
intrinsics/chmod.c \
@@ -1801,6 +1802,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/args.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/associated.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bit_intrinsics.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/c99_functions.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chdir.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chmod.Plo@am__quote@
@@ -5319,6 +5321,13 @@ args.lo: intrinsics/args.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o args.lo `test -f 'intrinsics/args.c' || echo '$(srcdir)/'`intrinsics/args.c
+bit_intrinsics.lo: intrinsics/bit_intrinsics.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT bit_intrinsics.lo -MD -MP -MF "$(DEPDIR)/bit_intrinsics.Tpo" -c -o bit_intrinsics.lo `test -f 'intrinsics/bit_intrinsics.c' || echo '$(srcdir)/'`intrinsics/bit_intrinsics.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/bit_intrinsics.Tpo" "$(DEPDIR)/bit_intrinsics.Plo"; else rm -f "$(DEPDIR)/bit_intrinsics.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='intrinsics/bit_intrinsics.c' object='bit_intrinsics.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o bit_intrinsics.lo `test -f 'intrinsics/bit_intrinsics.c' || echo '$(srcdir)/'`intrinsics/bit_intrinsics.c
+
c99_functions.lo: intrinsics/c99_functions.c
@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT c99_functions.lo -MD -MP -MF "$(DEPDIR)/c99_functions.Tpo" -c -o c99_functions.lo `test -f 'intrinsics/c99_functions.c' || echo '$(srcdir)/'`intrinsics/c99_functions.c; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/c99_functions.Tpo" "$(DEPDIR)/c99_functions.Plo"; else rm -f "$(DEPDIR)/c99_functions.Tpo"; exit 1; fi
diff --git a/libgfortran/gfortran.map b/libgfortran/gfortran.map
index 93973d5b338..c8de09cf055 100644
--- a/libgfortran/gfortran.map
+++ b/libgfortran/gfortran.map
@@ -1090,6 +1090,13 @@ GFORTRAN_1.1 {
_gfortran_unpack1_char4;
} GFORTRAN_1.0;
+
+GFORTRAN_1.2 {
+ global:
+ _gfortran_clz128;
+ _gfortran_ctz128;
+} GFORTRAN_1.1;
+
F2C_1.0 {
global:
_gfortran_f2c_specific__abs_c4;
diff --git a/libgfortran/intrinsics/bit_intrinsics.c b/libgfortran/intrinsics/bit_intrinsics.c
new file mode 100644
index 00000000000..92f5f039be6
--- /dev/null
+++ b/libgfortran/intrinsics/bit_intrinsics.c
@@ -0,0 +1,138 @@
+/* Implementation of the bit intrinsics not implemented as GCC builtins.
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran 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 3 of the License, or (at your option) any later version.
+
+Libgfortran 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include "libgfortran.h"
+
+
+#ifdef HAVE_GFC_INTEGER_16
+extern int clz128 (GFC_INTEGER_16);
+export_proto(clz128);
+
+int
+clz128 (GFC_INTEGER_16 x)
+{
+ int res = 127;
+
+ // We can't write 0xFFFFFFFFFFFFFFFF0000000000000000, so we work around it
+ if (x & ((__uint128_t) 0xFFFFFFFFFFFFFFFF << 64))
+ {
+ res -= 64;
+ x >>= 64;
+ }
+
+ if (x & 0xFFFFFFFF00000000)
+ {
+ res -= 32;
+ x >>= 32;
+ }
+
+ if (x & 0xFFFF0000)
+ {
+ res -= 16;
+ x >>= 16;
+ }
+
+ if (x & 0xFF00)
+ {
+ res -= 8;
+ x >>= 8;
+ }
+
+ if (x & 0xF0)
+ {
+ res -= 4;
+ x >>= 4;
+ }
+
+ if (x & 0xC)
+ {
+ res -= 2;
+ x >>= 2;
+ }
+
+ if (x & 0x2)
+ {
+ res -= 1;
+ x >>= 1;
+ }
+
+ return res;
+}
+#endif
+
+
+#ifdef HAVE_GFC_INTEGER_16
+extern int ctz128 (GFC_INTEGER_16);
+export_proto(ctz128);
+
+int
+ctz128 (GFC_INTEGER_16 x)
+{
+ int res = 0;
+
+ if ((x & 0xFFFFFFFFFFFFFFFF) == 0)
+ {
+ res += 64;
+ x >>= 64;
+ }
+
+ if ((x & 0xFFFFFFFF) == 0)
+ {
+ res += 32;
+ x >>= 32;
+ }
+
+ if ((x & 0xFFFF) == 0)
+ {
+ res += 16;
+ x >>= 16;
+ }
+
+ if ((x & 0xFF) == 0)
+ {
+ res += 8;
+ x >>= 8;
+ }
+
+ if ((x & 0xF) == 0)
+ {
+ res += 4;
+ x >>= 4;
+ }
+
+ if ((x & 0x3) == 0)
+ {
+ res += 2;
+ x >>= 2;
+ }
+
+ if ((x & 0x1) == 0)
+ {
+ res += 1;
+ x >>= 1;
+ }
+
+ return res;
+}
+#endif
diff --git a/libgfortran/io/fbuf.c b/libgfortran/io/fbuf.c
index a9171751bb0..e1daa0d32d6 100644
--- a/libgfortran/io/fbuf.c
+++ b/libgfortran/io/fbuf.c
@@ -28,8 +28,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <stdlib.h>
+//#define FBUF_DEBUG
+
+
void
-fbuf_init (gfc_unit * u, size_t len)
+fbuf_init (gfc_unit * u, int len)
{
if (len == 0)
len = 512; /* Default size. */
@@ -37,14 +40,7 @@ fbuf_init (gfc_unit * u, size_t len)
u->fbuf = get_mem (sizeof (fbuf));
u->fbuf->buf = get_mem (len);
u->fbuf->len = len;
- u->fbuf->act = u->fbuf->flushed = u->fbuf->pos = 0;
-}
-
-
-void
-fbuf_reset (gfc_unit * u)
-{
- u->fbuf->act = u->fbuf->flushed = u->fbuf->pos = 0;
+ u->fbuf->act = u->fbuf->pos = 0;
}
@@ -56,58 +52,79 @@ fbuf_destroy (gfc_unit * u)
if (u->fbuf->buf)
free_mem (u->fbuf->buf);
free_mem (u->fbuf);
+ u->fbuf = NULL;
+}
+
+
+static void
+#ifdef FBUF_DEBUG
+fbuf_debug (gfc_unit * u, const char * format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf (stderr, "fbuf_debug pos: %d, act: %d, buf: ''",
+ u->fbuf->pos, u->fbuf->act);
+ for (int ii = 0; ii < u->fbuf->act; ii++)
+ {
+ putc (u->fbuf->buf[ii], stderr);
+ }
+ fprintf (stderr, "''\n");
+}
+#else
+fbuf_debug (gfc_unit * u __attribute__ ((unused)),
+ const char * format __attribute__ ((unused)),
+ ...) {}
+#endif
+
+
+
+/* You should probably call this before doing a physical seek on the
+ underlying device. Returns how much the physical position was
+ modified. */
+
+int
+fbuf_reset (gfc_unit * u)
+{
+ int seekval = 0;
+
+ if (!u->fbuf)
+ return 0;
+
+ fbuf_debug (u, "fbuf_reset: ");
+ fbuf_flush (u, u->mode);
+ /* If we read past the current position, seek the underlying device
+ back. */
+ if (u->mode == READING && u->fbuf->act > u->fbuf->pos)
+ {
+ seekval = - (u->fbuf->act - u->fbuf->pos);
+ fbuf_debug (u, "fbuf_reset seekval %d, ", seekval);
+ }
+ u->fbuf->act = u->fbuf->pos = 0;
+ return seekval;
}
/* Return a pointer to the current position in the buffer, and increase
the pointer by len. Makes sure that the buffer is big enough,
- reallocating if necessary. If the buffer is not big enough, there are
- three cases to consider:
- 1. If we haven't flushed anything, realloc
- 2. If we have flushed enough that by discarding the flushed bytes
- the request fits into the buffer, do that.
- 3. Else allocate a new buffer, memcpy unflushed active bytes from old
- buffer. */
+ reallocating if necessary. */
char *
-fbuf_alloc (gfc_unit * u, size_t len)
+fbuf_alloc (gfc_unit * u, int len)
{
- size_t newlen;
+ int newlen;
char *dest;
+ fbuf_debug (u, "fbuf_alloc len %d, ", len);
if (u->fbuf->pos + len > u->fbuf->len)
{
- if (u->fbuf->flushed == 0)
- {
- /* Round up to nearest multiple of the current buffer length. */
- newlen = ((u->fbuf->pos + len) / u->fbuf->len + 1) * u->fbuf->len;
- dest = realloc (u->fbuf->buf, newlen);
- if (dest == NULL)
- return NULL;
- u->fbuf->buf = dest;
- u->fbuf->len = newlen;
- }
- else if (u->fbuf->act - u->fbuf->flushed + len < u->fbuf->len)
- {
- memmove (u->fbuf->buf, u->fbuf->buf + u->fbuf->flushed,
- u->fbuf->act - u->fbuf->flushed);
- u->fbuf->act -= u->fbuf->flushed;
- u->fbuf->pos -= u->fbuf->flushed;
- u->fbuf->flushed = 0;
- }
- else
- {
- /* Most general case, flushed != 0, request doesn't fit. */
- newlen = ((u->fbuf->pos - u->fbuf->flushed + len)
- / u->fbuf->len + 1) * u->fbuf->len;
- dest = get_mem (newlen);
- memcpy (dest, u->fbuf->buf + u->fbuf->flushed,
- u->fbuf->act - u->fbuf->flushed);
- u->fbuf->act -= u->fbuf->flushed;
- u->fbuf->pos -= u->fbuf->flushed;
- u->fbuf->flushed = 0;
- u->fbuf->buf = dest;
- u->fbuf->len = newlen;
- }
+ /* Round up to nearest multiple of the current buffer length. */
+ newlen = ((u->fbuf->pos + len) / u->fbuf->len + 1) * u->fbuf->len;
+ dest = realloc (u->fbuf->buf, newlen);
+ if (dest == NULL)
+ return NULL;
+ u->fbuf->buf = dest;
+ u->fbuf->len = newlen;
}
dest = u->fbuf->buf + u->fbuf->pos;
@@ -118,42 +135,134 @@ fbuf_alloc (gfc_unit * u, size_t len)
}
-
+/* mode argument is WRITING for write mode and READING for read
+ mode. Return value is 0 for success, -1 on failure. */
int
-fbuf_flush (gfc_unit * u, int record_done)
+fbuf_flush (gfc_unit * u, unit_mode mode)
{
- int status;
- size_t nbytes;
+ int nwritten;
if (!u->fbuf)
return 0;
- if (u->fbuf->act - u->fbuf->flushed != 0)
+
+ fbuf_debug (u, "fbuf_flush with mode %d: ", mode);
+
+ if (mode == WRITING)
{
- if (record_done)
- nbytes = u->fbuf->act - u->fbuf->flushed;
- else
- nbytes = u->fbuf->pos - u->fbuf->flushed;
- status = swrite (u->s, u->fbuf->buf + u->fbuf->flushed, &nbytes);
- u->fbuf->flushed += nbytes;
+ if (u->fbuf->pos > 0)
+ {
+ nwritten = swrite (u->s, u->fbuf->buf, u->fbuf->pos);
+ if (nwritten < 0)
+ return -1;
+ }
}
- else
- status = 0;
- if (record_done)
- fbuf_reset (u);
- return status;
+ /* Salvage remaining bytes for both reading and writing. This
+ happens with the combination of advance='no' and T edit
+ descriptors leaving the final position somewhere not at the end
+ of the record. For reading, this also happens if we sread() past
+ the record boundary. */
+ if (u->fbuf->act > u->fbuf->pos && u->fbuf->pos > 0)
+ memmove (u->fbuf->buf, u->fbuf->buf + u->fbuf->pos,
+ u->fbuf->act - u->fbuf->pos);
+
+ u->fbuf->act -= u->fbuf->pos;
+ u->fbuf->pos = 0;
+
+ return 0;
}
int
-fbuf_seek (gfc_unit * u, gfc_offset off)
+fbuf_seek (gfc_unit * u, int off, int whence)
{
- gfc_offset pos = u->fbuf->pos + off;
- /* Moving to the left past the flushed marked would imply moving past
- the left tab limit, which is never allowed. So return error if
- that is attempted. */
- if (pos < (gfc_offset) u->fbuf->flushed)
+ if (!u->fbuf)
return -1;
- u->fbuf->pos = pos;
- return 0;
+
+ switch (whence)
+ {
+ case SEEK_SET:
+ break;
+ case SEEK_CUR:
+ off += u->fbuf->pos;
+ break;
+ case SEEK_END:
+ off += u->fbuf->act;
+ break;
+ default:
+ return -1;
+ }
+
+ fbuf_debug (u, "fbuf_seek, off %d ", off);
+ /* The start of the buffer is always equal to the left tab
+ limit. Moving to the left past the buffer is illegal in C and
+ would also imply moving past the left tab limit, which is never
+ allowed in Fortran. Similarly, seeking past the end of the buffer
+ is not possible, in that case the user must make sure to allocate
+ space with fbuf_alloc(). So return error if that is
+ attempted. */
+ if (off < 0 || off > u->fbuf->act)
+ return -1;
+ u->fbuf->pos = off;
+ return off;
+}
+
+
+/* Fill the buffer with bytes for reading. Returns a pointer to start
+ reading from. If we hit EOF, returns a short read count. If any
+ other error occurs, return NULL. After reading, the caller is
+ expected to call fbuf_seek to update the position with the number
+ of bytes actually processed. */
+
+char *
+fbuf_read (gfc_unit * u, int * len)
+{
+ char *ptr;
+ int oldact, oldpos;
+ int readlen = 0;
+
+ fbuf_debug (u, "fbuf_read, len %d: ", *len);
+ oldact = u->fbuf->act;
+ oldpos = u->fbuf->pos;
+ ptr = fbuf_alloc (u, *len);
+ u->fbuf->pos = oldpos;
+ if (oldpos + *len > oldact)
+ {
+ fbuf_debug (u, "reading %d bytes starting at %d ",
+ oldpos + *len - oldact, oldact);
+ readlen = sread (u->s, u->fbuf->buf + oldact, oldpos + *len - oldact);
+ if (readlen < 0)
+ return NULL;
+ *len = oldact - oldpos + readlen;
+ }
+ u->fbuf->act = oldact + readlen;
+ fbuf_debug (u, "fbuf_read done: ");
+ return ptr;
+}
+
+
+/* When the fbuf_getc() inline function runs out of buffer space, it
+ calls this function to fill the buffer with bytes for
+ reading. Never call this function directly. */
+
+int
+fbuf_getc_refill (gfc_unit * u)
+{
+ int nread;
+ char *p;
+
+ fbuf_debug (u, "fbuf_getc_refill ");
+
+ /* Read 80 bytes (average line length?). This is a compromise
+ between not needing to call the read() syscall all the time and
+ not having to memmove unnecessary stuff when switching to the
+ next record. */
+ nread = 80;
+
+ p = fbuf_read (u, &nread);
+
+ if (p && nread > 0)
+ return (unsigned char) u->fbuf->buf[u->fbuf->pos++];
+ else
+ return EOF;
}
diff --git a/libgfortran/io/file_pos.c b/libgfortran/io/file_pos.c
index 5573c34da8b..c1690173658 100644
--- a/libgfortran/io/file_pos.c
+++ b/libgfortran/io/file_pos.c
@@ -41,17 +41,17 @@ formatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
{
gfc_offset base;
char p[READ_CHUNK];
- size_t n;
+ ssize_t n;
- base = file_position (u->s) - 1;
+ base = stell (u->s) - 1;
do
{
n = (base < READ_CHUNK) ? base : READ_CHUNK;
base -= n;
- if (sseek (u->s, base) == FAILURE)
+ if (sseek (u->s, base, SEEK_SET) < 0)
goto io_error;
- if (sread (u->s, p, &n) != 0)
+ if (sread (u->s, p, n) != n)
goto io_error;
/* We have moved backwards from the current position, it should
@@ -76,7 +76,7 @@ formatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
/* base is the new pointer. Seek to it exactly. */
done:
- if (sseek (u->s, base) == FAILURE)
+ if (sseek (u->s, base, SEEK_SET) < 0)
goto io_error;
u->last_record--;
u->endfile = NO_ENDFILE;
@@ -95,10 +95,10 @@ formatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
static void
unformatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
{
- gfc_offset m, new;
+ gfc_offset m, slen;
GFC_INTEGER_4 m4;
GFC_INTEGER_8 m8;
- size_t length;
+ ssize_t length;
int continued;
char p[sizeof (GFC_INTEGER_8)];
@@ -109,9 +109,10 @@ unformatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
do
{
- if (sseek (u->s, file_position (u->s) - length) == FAILURE)
+ slen = - (gfc_offset) length;
+ if (sseek (u->s, slen, SEEK_CUR) < 0)
goto io_error;
- if (sread (u->s, p, &length) != 0)
+ if (sread (u->s, p, length) != length)
goto io_error;
/* Only GFC_CONVERT_NATIVE and GFC_CONVERT_SWAP are valid here. */
@@ -159,10 +160,7 @@ unformatted_backspace (st_parameter_filepos *fpp, gfc_unit *u)
if (continued)
m = -m;
- if ((new = file_position (u->s) - m - 2*length) < 0)
- new = 0;
-
- if (sseek (u->s, new) == FAILURE)
+ if (sseek (u->s, -m -2 * length, SEEK_CUR) < 0)
goto io_error;
} while (continued);
@@ -201,15 +199,21 @@ st_backspace (st_parameter_filepos *fpp)
goto done;
}
- if (u->flags.access == ACCESS_STREAM && u->flags.form == FORM_UNFORMATTED)
- {
- generate_error (&fpp->common, LIBERROR_OPTION_CONFLICT,
- "Cannot BACKSPACE an unformatted stream file");
- goto done;
- }
+ if (u->flags.access == ACCESS_STREAM && u->flags.form == FORM_UNFORMATTED)
+ {
+ generate_error (&fpp->common, LIBERROR_OPTION_CONFLICT,
+ "Cannot BACKSPACE an unformatted stream file");
+ goto done;
+ }
+
+ /* Make sure format buffer is flushed and reset. */
+ if (u->flags.form == FORM_FORMATTED)
+ {
+ int pos = fbuf_reset (u);
+ if (pos != 0)
+ sseek (u->s, pos, SEEK_CUR);
+ }
- /* Make sure format buffer is flushed. */
- fbuf_flush (u, 1);
/* Check for special cases involving the ENDFILE record first. */
@@ -217,11 +221,11 @@ st_backspace (st_parameter_filepos *fpp)
{
u->endfile = AT_ENDFILE;
u->flags.position = POSITION_APPEND;
- flush (u->s);
+ sflush (u->s);
}
else
{
- if (file_position (u->s) == 0)
+ if (stell (u->s) == 0)
{
u->flags.position = POSITION_REWIND;
goto done; /* Common special case */
@@ -238,8 +242,7 @@ st_backspace (st_parameter_filepos *fpp)
u->previous_nonadvancing_write = 0;
- flush (u->s);
- struncate (u->s);
+ unit_truncate (u, stell (u->s), &fpp->common);
u->mode = READING;
}
@@ -248,7 +251,7 @@ st_backspace (st_parameter_filepos *fpp)
else
unformatted_backspace (fpp, u);
- update_position (u);
+ u->flags.position = POSITION_UNSPECIFIED;
u->endfile = NO_ENDFILE;
u->current_record = 0;
u->bytes_left = 0;
@@ -300,10 +303,10 @@ st_endfile (st_parameter_filepos *fpp)
next_record (&dtp, 1);
}
- flush (u->s);
- struncate (u->s);
+ unit_truncate (u, stell (u->s), &fpp->common);
u->endfile = AFTER_ENDFILE;
- update_position (u);
+ if (0 == stell (u->s))
+ u->flags.position = POSITION_REWIND;
done:
unlock_unit (u);
}
@@ -338,18 +341,11 @@ st_rewind (st_parameter_filepos *fpp)
u->previous_nonadvancing_write = 0;
- /* Flush the buffers. If we have been writing to the file, the last
- written record is the last record in the file, so truncate the
- file now. Reset to read mode so two consecutive rewind
- statements do not delete the file contents. */
- flush (u->s);
- if (u->mode == WRITING && u->flags.access != ACCESS_STREAM)
- struncate (u->s);
+ fbuf_reset (u);
- u->mode = READING;
u->last_record = 0;
- if (file_position (u->s) != 0 && sseek (u->s, 0) == FAILURE)
+ if (sseek (u->s, 0, SEEK_SET) < 0)
generate_error (&fpp->common, LIBERROR_OS, NULL);
/* Handle special files like /dev/null differently. */
@@ -361,7 +357,7 @@ st_rewind (st_parameter_filepos *fpp)
else
{
/* Set this for compatibilty with g77 for /dev/null. */
- if (file_length (u->s) == 0 && file_position (u->s) == 0)
+ if (file_length (u->s) == 0 && stell (u->s) == 0)
u->endfile = AT_ENDFILE;
/* Future refinements on special files can go here. */
}
@@ -392,7 +388,11 @@ st_flush (st_parameter_filepos *fpp)
u = find_unit (fpp->common.unit);
if (u != NULL)
{
- flush (u->s);
+ /* Make sure format buffer is flushed. */
+ if (u->flags.form == FORM_FORMATTED)
+ fbuf_flush (u, u->mode);
+
+ sflush (u->s);
unlock_unit (u);
}
else
diff --git a/libgfortran/io/format.c b/libgfortran/io/format.c
index 086ab678ecb..4c6f17c5cbf 100644
--- a/libgfortran/io/format.c
+++ b/libgfortran/io/format.c
@@ -58,7 +58,7 @@ format_data;
static const fnode colon_node = { FMT_COLON, 0, NULL, NULL, {{ 0, 0, 0 }}, 0,
NULL };
-/* Error messages */
+/* Error messages. */
static const char posint_required[] = "Positive width required in format",
period_required[] = "Period required in format",
@@ -85,7 +85,8 @@ next_char (format_data *fmt, int literal)
return -1;
fmt->format_string_len--;
- fmt->error_element = c = toupper (*fmt->format_string++);
+ c = toupper (*fmt->format_string++);
+ fmt->error_element = c;
}
while ((c == ' ' || c == '\t') && !literal);
@@ -179,6 +180,14 @@ format_lex (format_data *fmt)
switch (c)
{
+ case '(':
+ token = FMT_LPAREN;
+ break;
+
+ case ')':
+ token = FMT_RPAREN;
+ break;
+
case '-':
negative_flag = 1;
/* Fall Through */
@@ -271,14 +280,6 @@ format_lex (format_data *fmt)
break;
- case '(':
- token = FMT_LPAREN;
- break;
-
- case ')':
- token = FMT_RPAREN;
- break;
-
case 'X':
token = FMT_X;
break;
@@ -994,6 +995,33 @@ format_error (st_parameter_dt *dtp, const fnode *f, const char *message)
}
+/* revert()-- Do reversion of the format. Control reverts to the left
+ * parenthesis that matches the rightmost right parenthesis. From our
+ * tree structure, we are looking for the rightmost parenthesis node
+ * at the second level, the first level always being a single
+ * parenthesis node. If this node doesn't exit, we use the top
+ * level. */
+
+static void
+revert (st_parameter_dt *dtp)
+{
+ fnode *f, *r;
+ format_data *fmt = dtp->u.p.fmt;
+
+ dtp->u.p.reversion_flag = 1;
+
+ r = NULL;
+
+ for (f = fmt->array.array[0].u.child; f; f = f->next)
+ if (f->format == FMT_LPAREN)
+ r = f;
+
+ /* If r is NULL because no node was found, the whole tree will be used */
+
+ fmt->array.array[0].current = r;
+ fmt->array.array[0].count = 0;
+}
+
/* parse_format()-- Parse a format string. */
void
@@ -1036,34 +1064,6 @@ parse_format (st_parameter_dt *dtp)
}
-/* revert()-- Do reversion of the format. Control reverts to the left
- * parenthesis that matches the rightmost right parenthesis. From our
- * tree structure, we are looking for the rightmost parenthesis node
- * at the second level, the first level always being a single
- * parenthesis node. If this node doesn't exit, we use the top
- * level. */
-
-static void
-revert (st_parameter_dt *dtp)
-{
- fnode *f, *r;
- format_data *fmt = dtp->u.p.fmt;
-
- dtp->u.p.reversion_flag = 1;
-
- r = NULL;
-
- for (f = fmt->array.array[0].u.child; f; f = f->next)
- if (f->format == FMT_LPAREN)
- r = f;
-
- /* If r is NULL because no node was found, the whole tree will be used */
-
- fmt->array.array[0].current = r;
- fmt->array.array[0].count = 0;
-}
-
-
/* next_format0()-- Get the next format node without worrying about
* reversion. Returns NULL when we hit the end of the list.
* Parenthesis nodes are incremented after the list has been
diff --git a/libgfortran/io/intrinsics.c b/libgfortran/io/intrinsics.c
index e460ad04aea..0e33e8490da 100644
--- a/libgfortran/io/intrinsics.c
+++ b/libgfortran/io/intrinsics.c
@@ -41,21 +41,26 @@ int
PREFIX(fgetc) (const int * unit, char * c, gfc_charlen_type c_len)
{
int ret;
- size_t s;
gfc_unit * u = find_unit (*unit);
if (u == NULL)
return -1;
- s = 1;
+ fbuf_reset (u);
+ if (u->mode == WRITING)
+ {
+ sflush (u->s);
+ u->mode = READING;
+ }
+
memset (c, ' ', c_len);
- ret = sread (u->s, c, &s);
+ ret = sread (u->s, c, 1);
unlock_unit (u);
- if (ret != 0)
+ if (ret < 0)
return ret;
- if (s != 1)
+ if (ret != 1)
return -1;
else
return 0;
@@ -114,17 +119,24 @@ int
PREFIX(fputc) (const int * unit, char * c,
gfc_charlen_type c_len __attribute__((unused)))
{
- size_t s;
- int ret;
+ ssize_t s;
gfc_unit * u = find_unit (*unit);
if (u == NULL)
return -1;
- s = 1;
- ret = swrite (u->s, c, &s);
+ fbuf_reset (u);
+ if (u->mode == READING)
+ {
+ sflush (u->s);
+ u->mode = WRITING;
+ }
+
+ s = swrite (u->s, c, 1);
unlock_unit (u);
- return ret;
+ if (s < 0)
+ return -1;
+ return 0;
}
@@ -191,7 +203,7 @@ flush_i4 (GFC_INTEGER_4 *unit)
us = find_unit (*unit);
if (us != NULL)
{
- flush (us->s);
+ sflush (us->s);
unlock_unit (us);
}
}
@@ -214,7 +226,7 @@ flush_i8 (GFC_INTEGER_8 *unit)
us = find_unit (*unit);
if (us != NULL)
{
- flush (us->s);
+ sflush (us->s);
unlock_unit (us);
}
}
@@ -229,22 +241,17 @@ void
fseek_sub (int * unit, GFC_IO_INT * offset, int * whence, int * status)
{
gfc_unit * u = find_unit (*unit);
- try result = FAILURE;
+ ssize_t result = -1;
if (u != NULL && is_seekable(u->s))
{
- if (*whence == 0)
- result = sseek(u->s, *offset); /* SEEK_SET */
- else if (*whence == 1)
- result = sseek(u->s, file_position(u->s) + *offset); /* SEEK_CUR */
- else if (*whence == 2)
- result = sseek(u->s, file_length(u->s) + *offset); /* SEEK_END */
+ result = sseek(u->s, *offset, *whence);
unlock_unit (u);
}
if (status)
- *status = (result == FAILURE ? -1 : 0);
+ *status = (result < 0 ? -1 : 0);
}
@@ -261,7 +268,7 @@ PREFIX(ftell) (int * unit)
size_t ret;
if (u == NULL)
return ((size_t) -1);
- ret = (size_t) stream_offset (u->s);
+ ret = (size_t) stell (u->s);
unlock_unit (u);
return ret;
}
@@ -277,7 +284,7 @@ PREFIX(ftell) (int * unit)
*offset = -1; \
else \
{ \
- *offset = stream_offset (u->s); \
+ *offset = stell (u->s); \
unlock_unit (u); \
} \
}
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index a0d43a166b2..d3c658901a1 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -46,34 +46,60 @@ struct st_parameter_dt;
typedef struct stream
{
- char *(*alloc_w_at) (struct stream *, int *);
- try (*sfree) (struct stream *);
- try (*close) (struct stream *);
- try (*seek) (struct stream *, gfc_offset);
- try (*trunc) (struct stream *);
- int (*read) (struct stream *, void *, size_t *);
- int (*write) (struct stream *, const void *, size_t *);
- try (*set) (struct stream *, int, size_t);
+ ssize_t (*read) (struct stream *, void *, ssize_t);
+ ssize_t (*write) (struct stream *, const void *, ssize_t);
+ off_t (*seek) (struct stream *, off_t, int);
+ off_t (*tell) (struct stream *);
+ /* Avoid keyword truncate due to AIX namespace collision. */
+ int (*trunc) (struct stream *, off_t);
+ int (*flush) (struct stream *);
+ int (*close) (struct stream *);
}
stream;
-typedef enum
-{ SYNC_BUFFERED, SYNC_UNBUFFERED, ASYNC }
-io_mode;
+/* Inline functions for doing file I/O given a stream. */
+static inline ssize_t
+sread (stream * s, void * buf, ssize_t nbyte)
+{
+ return s->read (s, buf, nbyte);
+}
+
+static inline ssize_t
+swrite (stream * s, const void * buf, ssize_t nbyte)
+{
+ return s->write (s, buf, nbyte);
+}
-/* Macros for doing file I/O given a stream. */
+static inline off_t
+sseek (stream * s, off_t offset, int whence)
+{
+ return s->seek (s, offset, whence);
+}
+
+static inline off_t
+stell (stream * s)
+{
+ return s->tell (s);
+}
-#define sfree(s) ((s)->sfree)(s)
-#define sclose(s) ((s)->close)(s)
+static inline int
+struncate (stream * s, off_t length)
+{
+ return s->trunc (s, length);
+}
-#define salloc_w(s, len) ((s)->alloc_w_at)(s, len)
+static inline int
+sflush (stream * s)
+{
+ return s->flush (s);
+}
-#define sseek(s, pos) ((s)->seek)(s, pos)
-#define struncate(s) ((s)->trunc)(s)
-#define sread(s, buf, nbytes) ((s)->read)(s, buf, nbytes)
-#define swrite(s, buf, nbytes) ((s)->write)(s, buf, nbytes)
+static inline int
+sclose (stream * s)
+{
+ return s->close (s);
+}
-#define sset(s, c, n) ((s)->set)(s, c, n)
/* Macros for testing what kinds of I/O we are doing. */
@@ -124,7 +150,6 @@ array_loop_spec;
typedef struct namelist_type
{
-
/* Object type, stored as GFC_DTYPE_xxxx. */
bt type;
@@ -461,9 +486,9 @@ typedef struct st_parameter_dt
/* A flag used to identify when a non-standard expanded namelist read
has occurred. */
int expanded_read;
- /* Storage area for values except for strings. Must be large
- enough to hold a complex value (two reals) of the largest
- kind. */
+ /* Storage area for values except for strings. Must be
+ large enough to hold a complex value (two reals) of the
+ largest kind. */
char value[32];
GFC_IO_INT size_used;
} p;
@@ -535,10 +560,9 @@ unit_flags;
typedef struct fbuf
{
char *buf; /* Start of buffer. */
- size_t len; /* Length of buffer. */
- size_t act; /* Active bytes in buffer. */
- size_t flushed; /* Flushed bytes from beginning of buffer. */
- size_t pos; /* Current position in buffer. */
+ int len; /* Length of buffer. */
+ int act; /* Active bytes in buffer. */
+ int pos; /* Current position in buffer. */
}
fbuf;
@@ -596,7 +620,7 @@ typedef struct gfc_unit
int file_len;
char *file;
-
+
/* Formatting buffer. */
struct fbuf *fbuf;
}
@@ -668,9 +692,6 @@ fnode;
/* unix.c */
-extern int move_pos_offset (stream *, int);
-internal_proto(move_pos_offset);
-
extern int compare_files (stream *, stream *);
internal_proto(compare_files);
@@ -680,6 +701,12 @@ internal_proto(open_external);
extern stream *open_internal (char *, int, gfc_offset);
internal_proto(open_internal);
+extern char * mem_alloc_w (stream *, int *);
+internal_proto(mem_alloc_w);
+
+extern char * mem_alloc_r (stream *, int *);
+internal_proto(mem_alloc_w);
+
extern stream *input_stream (void);
internal_proto(input_stream);
@@ -695,12 +722,6 @@ internal_proto(compare_file_filename);
extern gfc_unit *find_file (const char *file, gfc_charlen_type file_len);
internal_proto(find_file);
-extern int stream_at_bof (stream *);
-internal_proto(stream_at_bof);
-
-extern int stream_at_eof (stream *);
-internal_proto(stream_at_eof);
-
extern int delete_file (gfc_unit *);
internal_proto(delete_file);
@@ -731,36 +752,24 @@ internal_proto(inquire_readwrite);
extern gfc_offset file_length (stream *);
internal_proto(file_length);
-extern gfc_offset file_position (stream *);
-internal_proto(file_position);
-
extern int is_seekable (stream *);
internal_proto(is_seekable);
extern int is_special (stream *);
internal_proto(is_special);
-extern int is_preconnected (stream *);
-internal_proto(is_preconnected);
-
extern void flush_if_preconnected (stream *);
internal_proto(flush_if_preconnected);
extern void empty_internal_buffer(stream *);
internal_proto(empty_internal_buffer);
-extern try flush (stream *);
-internal_proto(flush);
-
extern int stream_isatty (stream *);
internal_proto(stream_isatty);
extern char * stream_ttyname (stream *);
internal_proto(stream_ttyname);
-extern gfc_offset stream_offset (stream *s);
-internal_proto(stream_offset);
-
extern int unpack_filename (char *, const char *, int);
internal_proto(unpack_filename);
@@ -804,6 +813,9 @@ internal_proto(update_position);
extern void finish_last_advance_record (gfc_unit *u);
internal_proto (finish_last_advance_record);
+extern int unit_truncate (gfc_unit *, gfc_offset, st_parameter_common *);
+internal_proto (unit_truncate);
+
/* open.c */
extern gfc_unit *new_unit (st_parameter_open *, gfc_unit *, unit_flags *);
@@ -833,7 +845,7 @@ internal_proto(free_format_data);
extern const char *type_name (bt);
internal_proto(type_name);
-extern try read_block_form (st_parameter_dt *, void *, size_t *);
+extern void * read_block_form (st_parameter_dt *, int *);
internal_proto(read_block_form);
extern char *read_sf (st_parameter_dt *, int *, int);
@@ -859,6 +871,9 @@ internal_proto (reverse_memcpy);
extern void st_wait (st_parameter_wait *);
export_proto(st_wait);
+extern void hit_eof (st_parameter_dt *);
+internal_proto(hit_eof);
+
/* read.c */
extern void set_integer (void *, GFC_INTEGER_LARGEST, int);
@@ -965,24 +980,39 @@ extern size_t size_from_complex_kind (int);
internal_proto(size_from_complex_kind);
/* fbuf.c */
-extern void fbuf_init (gfc_unit *, size_t);
+extern void fbuf_init (gfc_unit *, int);
internal_proto(fbuf_init);
extern void fbuf_destroy (gfc_unit *);
internal_proto(fbuf_destroy);
-extern void fbuf_reset (gfc_unit *);
+extern int fbuf_reset (gfc_unit *);
internal_proto(fbuf_reset);
-extern char * fbuf_alloc (gfc_unit *, size_t);
+extern char * fbuf_alloc (gfc_unit *, int);
internal_proto(fbuf_alloc);
-extern int fbuf_flush (gfc_unit *, int);
+extern int fbuf_flush (gfc_unit *, unit_mode);
internal_proto(fbuf_flush);
-extern int fbuf_seek (gfc_unit *, gfc_offset);
+extern int fbuf_seek (gfc_unit *, int, int);
internal_proto(fbuf_seek);
+extern char * fbuf_read (gfc_unit *, int *);
+internal_proto(fbuf_read);
+
+/* Never call this function, only use fbuf_getc(). */
+extern int fbuf_getc_refill (gfc_unit *);
+internal_proto(fbuf_getc_refill);
+
+static inline int
+fbuf_getc (gfc_unit * u)
+{
+ if (u->fbuf->pos < u->fbuf->act)
+ return (unsigned char) u->fbuf->buf[u->fbuf->pos++];
+ return fbuf_getc_refill (u);
+}
+
/* lock.c */
extern void free_ionml (st_parameter_dt *);
internal_proto(free_ionml);
diff --git a/libgfortran/io/list_read.c b/libgfortran/io/list_read.c
index 0b07759e6fd..3ca63de82e9 100644
--- a/libgfortran/io/list_read.c
+++ b/libgfortran/io/list_read.c
@@ -28,6 +28,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "io.h"
#include <string.h>
+#include <stdlib.h>
#include <ctype.h>
@@ -74,9 +75,8 @@ push_char (st_parameter_dt *dtp, char c)
if (dtp->u.p.saved_string == NULL)
{
- if (dtp->u.p.scratch == NULL)
- dtp->u.p.scratch = get_mem (SCRATCH_SIZE);
- dtp->u.p.saved_string = dtp->u.p.scratch;
+ dtp->u.p.saved_string = get_mem (SCRATCH_SIZE);
+ // memset below should be commented out.
memset (dtp->u.p.saved_string, 0, SCRATCH_SIZE);
dtp->u.p.saved_length = SCRATCH_SIZE;
dtp->u.p.saved_used = 0;
@@ -85,15 +85,15 @@ push_char (st_parameter_dt *dtp, char c)
if (dtp->u.p.saved_used >= dtp->u.p.saved_length)
{
dtp->u.p.saved_length = 2 * dtp->u.p.saved_length;
- new = get_mem (2 * dtp->u.p.saved_length);
-
- memset (new, 0, 2 * dtp->u.p.saved_length);
-
- memcpy (new, dtp->u.p.saved_string, dtp->u.p.saved_used);
- if (dtp->u.p.saved_string != dtp->u.p.scratch)
- free_mem (dtp->u.p.saved_string);
-
+ new = realloc (dtp->u.p.saved_string, dtp->u.p.saved_length);
+ if (new == NULL)
+ generate_error (&dtp->common, LIBERROR_OS, NULL);
dtp->u.p.saved_string = new;
+
+ // Also this should not be necessary.
+ memset (new + dtp->u.p.saved_used, 0,
+ dtp->u.p.saved_length - dtp->u.p.saved_used);
+
}
dtp->u.p.saved_string[dtp->u.p.saved_used++] = c;
@@ -108,8 +108,7 @@ free_saved (st_parameter_dt *dtp)
if (dtp->u.p.saved_string == NULL)
return;
- if (dtp->u.p.saved_string != dtp->u.p.scratch)
- free_mem (dtp->u.p.saved_string);
+ free_mem (dtp->u.p.saved_string);
dtp->u.p.saved_string = NULL;
dtp->u.p.saved_used = 0;
@@ -135,9 +134,10 @@ free_line (st_parameter_dt *dtp)
static char
next_char (st_parameter_dt *dtp)
{
- size_t length;
+ ssize_t length;
gfc_offset record;
char c;
+ int cc;
if (dtp->u.p.last_char != '\0')
{
@@ -189,7 +189,7 @@ next_char (st_parameter_dt *dtp)
}
record *= dtp->u.p.current_unit->recl;
- if (sseek (dtp->u.p.current_unit->s, record) == FAILURE)
+ if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
longjmp (*dtp->u.p.eof_jump, 1);
dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
@@ -199,19 +199,15 @@ next_char (st_parameter_dt *dtp)
/* Get the next character and handle end-of-record conditions. */
- length = 1;
-
- if (sread (dtp->u.p.current_unit->s, &c, &length) != 0)
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return '\0';
- }
-
- if (is_stream_io (dtp) && length == 1)
- dtp->u.p.current_unit->strm_pos++;
-
if (is_internal_unit (dtp))
{
+ length = sread (dtp->u.p.current_unit->s, &c, 1);
+ if (length < 0)
+ {
+ generate_error (&dtp->common, LIBERROR_OS, NULL);
+ return '\0';
+ }
+
if (is_array_io (dtp))
{
/* Check whether we hit EOF. */
@@ -235,13 +231,20 @@ next_char (st_parameter_dt *dtp)
}
else
{
- if (length == 0)
+ cc = fbuf_getc (dtp->u.p.current_unit);
+
+ if (cc == EOF)
{
if (dtp->u.p.current_unit->endfile == AT_ENDFILE)
longjmp (*dtp->u.p.eof_jump, 1);
dtp->u.p.current_unit->endfile = AT_ENDFILE;
c = '\n';
}
+ else
+ c = (char) cc;
+ if (is_stream_io (dtp) && cc != EOF)
+ dtp->u.p.current_unit->strm_pos++;
+
}
done:
dtp->u.p.at_eol = (c == '\n' || c == '\r');
@@ -1216,7 +1219,7 @@ parse_real (st_parameter_dt *dtp, void *buffer, int length)
what it is right away. */
static void
-read_complex (st_parameter_dt *dtp, int kind, size_t size)
+read_complex (st_parameter_dt *dtp, void * dest, int kind, size_t size)
{
char message[100];
char c;
@@ -1240,7 +1243,7 @@ read_complex (st_parameter_dt *dtp, int kind, size_t size)
}
eat_spaces (dtp);
- if (parse_real (dtp, dtp->u.p.value, kind))
+ if (parse_real (dtp, dest, kind))
return;
eol_1:
@@ -1263,7 +1266,7 @@ eol_2:
else
unget_char (dtp, c);
- if (parse_real (dtp, dtp->u.p.value + size / 2, kind))
+ if (parse_real (dtp, dest + size / 2, kind))
return;
eat_spaces (dtp);
@@ -1297,7 +1300,7 @@ eol_2:
/* Parse a real number with a possible repeat count. */
static void
-read_real (st_parameter_dt *dtp, int length)
+read_real (st_parameter_dt *dtp, void * dest, int length)
{
char c, message[100];
int seen_dp;
@@ -1510,7 +1513,7 @@ read_real (st_parameter_dt *dtp, int length)
unget_char (dtp, c);
eat_separator (dtp);
push_char (dtp, '\0');
- if (convert_real (dtp, dtp->u.p.value, dtp->u.p.saved_string, length))
+ if (convert_real (dtp, dest, dtp->u.p.saved_string, length))
return;
free_saved (dtp);
@@ -1684,6 +1687,11 @@ list_formatted_read_scalar (st_parameter_dt *dtp, volatile bt type, void *p,
if (setjmp (eof_jump))
{
generate_error (&dtp->common, LIBERROR_END, NULL);
+ if (!is_internal_unit (dtp))
+ {
+ dtp->u.p.current_unit->endfile = AFTER_ENDFILE;
+ dtp->u.p.current_unit->current_record = 0;
+ }
goto cleanup;
}
@@ -1693,7 +1701,7 @@ list_formatted_read_scalar (st_parameter_dt *dtp, volatile bt type, void *p,
dtp->u.p.input_complete = 0;
dtp->u.p.repeat_count = 1;
dtp->u.p.at_eol = 0;
-
+
c = eat_spaces (dtp);
if (is_separator (c))
{
@@ -1721,6 +1729,9 @@ list_formatted_read_scalar (st_parameter_dt *dtp, volatile bt type, void *p,
return;
goto set_value;
}
+
+ if (dtp->u.p.input_complete)
+ goto cleanup;
if (dtp->u.p.input_complete)
goto cleanup;
@@ -1751,10 +1762,16 @@ list_formatted_read_scalar (st_parameter_dt *dtp, volatile bt type, void *p,
read_character (dtp, kind);
break;
case BT_REAL:
- read_real (dtp, kind);
+ read_real (dtp, p, kind);
+ /* Copy value back to temporary if needed. */
+ if (dtp->u.p.repeat_count > 0)
+ memcpy (dtp->u.p.value, p, kind);
break;
case BT_COMPLEX:
- read_complex (dtp, kind, size);
+ read_complex (dtp, p, kind, size);
+ /* Copy value back to temporary if needed. */
+ if (dtp->u.p.repeat_count > 0)
+ memcpy (dtp->u.p.value, p, size);
break;
default:
internal_error (&dtp->common, "Bad type for list read");
@@ -1770,8 +1787,12 @@ list_formatted_read_scalar (st_parameter_dt *dtp, volatile bt type, void *p,
switch (dtp->u.p.saved_type)
{
case BT_COMPLEX:
- case BT_INTEGER:
case BT_REAL:
+ if (dtp->u.p.repeat_count > 0)
+ memcpy (p, dtp->u.p.value, size);
+ break;
+
+ case BT_INTEGER:
case BT_LOGICAL:
memcpy (p, dtp->u.p.value, size);
break;
@@ -1848,6 +1869,8 @@ finish_list_read (st_parameter_dt *dtp)
free_saved (dtp);
+ fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
+
if (dtp->u.p.at_eol)
{
dtp->u.p.at_eol = 0;
@@ -2256,8 +2279,8 @@ nml_query (st_parameter_dt *dtp, char c)
/* Flush the stream to force immediate output. */
- fbuf_flush (dtp->u.p.current_unit, 1);
- flush (dtp->u.p.current_unit->s);
+ fbuf_flush (dtp->u.p.current_unit, WRITING);
+ sflush (dtp->u.p.current_unit->s);
unlock_unit (dtp->u.p.current_unit);
}
@@ -2292,7 +2315,7 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info * nl, index_type offset,
int dim;
index_type dlen;
index_type m;
- index_type obj_name_len;
+ size_t obj_name_len;
void * pdata;
/* This object not touched in name parsing. */
@@ -2371,12 +2394,17 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info * nl, index_type offset,
break;
case GFC_DTYPE_REAL:
- read_real (dtp, len);
- break;
+ /* Need to copy data back from the real location to the temp in order
+ to handle nml reads into arrays. */
+ read_real (dtp, pdata, len);
+ memcpy (dtp->u.p.value, pdata, dlen);
+ break;
case GFC_DTYPE_COMPLEX:
- read_complex (dtp, len, dlen);
- break;
+ /* Same as for REAL, copy back to temp. */
+ read_complex (dtp, pdata, len, dlen);
+ memcpy (dtp->u.p.value, pdata, dlen);
+ break;
case GFC_DTYPE_DERIVED:
obj_name_len = strlen (nl->var_name) + 1;
@@ -2898,7 +2926,7 @@ find_nml_name:
st_printf ("%s\n", nml_err_msg);
if (u != NULL)
{
- flush (u->s);
+ sflush (u->s);
unlock_unit (u);
}
}
diff --git a/libgfortran/io/open.c b/libgfortran/io/open.c
index edc9ca217ca..ba6e9d8804a 100644
--- a/libgfortran/io/open.c
+++ b/libgfortran/io/open.c
@@ -150,7 +150,7 @@ static const st_option async_opt[] =
static void
test_endfile (gfc_unit * u)
{
- if (u->endfile == NO_ENDFILE && file_length (u->s) == file_position (u->s))
+ if (u->endfile == NO_ENDFILE && file_length (u->s) == stell (u->s))
u->endfile = AT_ENDFILE;
}
@@ -266,7 +266,7 @@ edit_modes (st_parameter_open *opp, gfc_unit * u, unit_flags * flags)
break;
case POSITION_REWIND:
- if (sseek (u->s, 0) == FAILURE)
+ if (sseek (u->s, 0, SEEK_SET) != 0)
goto seek_error;
u->current_record = 0;
@@ -276,7 +276,7 @@ edit_modes (st_parameter_open *opp, gfc_unit * u, unit_flags * flags)
break;
case POSITION_APPEND:
- if (sseek (u->s, file_length (u->s)) == FAILURE)
+ if (sseek (u->s, 0, SEEK_END) < 0)
goto seek_error;
if (flags->access != ACCESS_STREAM)
@@ -552,7 +552,7 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags)
if (flags->position == POSITION_APPEND)
{
- if (sseek (u->s, file_length (u->s)) == FAILURE)
+ if (sseek (u->s, 0, SEEK_END) < 0)
generate_error (&opp->common, LIBERROR_OS, NULL);
u->endfile = AT_ENDFILE;
}
@@ -606,7 +606,8 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags)
{
u->maxrec = max_offset;
u->recl = 1;
- u->strm_pos = file_position (u->s) + 1;
+ u->bytes_left = 1;
+ u->strm_pos = stell (u->s) + 1;
}
memmove (u->file, opp->file, opp->file_len);
@@ -622,7 +623,7 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags)
if (flags->status == STATUS_SCRATCH && opp->file != NULL)
free_mem (opp->file);
- if (flags->form == FORM_FORMATTED && (flags->action != ACTION_READ))
+ if (flags->form == FORM_FORMATTED)
{
if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN))
fbuf_init (u, u->recl);
@@ -676,7 +677,7 @@ already_open (st_parameter_open *opp, gfc_unit * u, unit_flags * flags)
}
#endif
- if (sclose (u->s) == FAILURE)
+ if (sclose (u->s) == -1)
{
unlock_unit (u);
generate_error (&opp->common, LIBERROR_OS,
diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c
index 267f62735cc..23a8fa3019d 100644
--- a/libgfortran/io/read.c
+++ b/libgfortran/io/read.c
@@ -28,6 +28,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <errno.h>
#include <ctype.h>
#include <stdlib.h>
+#include <assert.h>
typedef unsigned char uchar;
@@ -125,8 +126,10 @@ max_value (int length, int signed_flag)
/* convert_real()-- Convert a character representation of a floating
* point number to the machine number. Returns nonzero if there is a
- * range problem during conversion. TODO: handle not-a-numbers and
- * infinities. */
+ * range problem during conversion. Note: many architectures
+ * (e.g. IA-64, HP-PA) require that the storage pointed to by the dest
+ * argument is properly aligned for the type in question. TODO:
+ * handle not-a-numbers and infinities. */
int
convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
@@ -136,38 +139,30 @@ convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
switch (length)
{
case 4:
- {
- GFC_REAL_4 tmp =
+ *((GFC_REAL_4*) dest) =
#if defined(HAVE_STRTOF)
- strtof (buffer, NULL);
+ strtof (buffer, NULL);
#else
- (GFC_REAL_4) strtod (buffer, NULL);
+ (GFC_REAL_4) strtod (buffer, NULL);
#endif
- memcpy (dest, (void *) &tmp, length);
- }
break;
+
case 8:
- {
- GFC_REAL_8 tmp = strtod (buffer, NULL);
- memcpy (dest, (void *) &tmp, length);
- }
+ *((GFC_REAL_8*) dest) = strtod (buffer, NULL);
break;
+
#if defined(HAVE_GFC_REAL_10) && defined (HAVE_STRTOLD)
case 10:
- {
- GFC_REAL_10 tmp = strtold (buffer, NULL);
- memcpy (dest, (void *) &tmp, length);
- }
+ *((GFC_REAL_10*) dest) = strtold (buffer, NULL);
break;
#endif
+
#if defined(HAVE_GFC_REAL_16) && defined (HAVE_STRTOLD)
case 16:
- {
- GFC_REAL_16 tmp = strtold (buffer, NULL);
- memcpy (dest, (void *) &tmp, length);
- }
+ *((GFC_REAL_16*) dest) = strtold (buffer, NULL);
break;
#endif
+
default:
internal_error (&dtp->common, "Unsupported real kind during IO");
}
@@ -190,13 +185,13 @@ void
read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
{
char *p;
- size_t w;
+ int w;
w = f->u.w;
- p = gfc_alloca (w);
+ p = read_block_form (dtp, &w);
- if (read_block_form (dtp, p, &w) == FAILURE)
+ if (p == NULL)
return;
while (*p == ' ')
@@ -233,28 +228,26 @@ read_l (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
}
-static inline gfc_char4_t
-read_utf8 (st_parameter_dt *dtp, size_t *nbytes)
+static gfc_char4_t
+read_utf8 (st_parameter_dt *dtp, int *nbytes)
{
static const uchar masks[6] = { 0x7F, 0x1F, 0x0F, 0x07, 0x02, 0x01 };
static const uchar patns[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
- static uchar buffer[6];
- size_t i, nb, nread;
+ int i, nb, nread;
gfc_char4_t c;
- int status;
char *s;
*nbytes = 1;
- s = (char *) &buffer[0];
- status = read_block_form (dtp, s, nbytes);
- if (status == FAILURE)
+
+ s = read_block_form (dtp, nbytes);
+ if (s == NULL)
return 0;
/* If this is a short read, just return. */
if (*nbytes == 0)
return 0;
- c = buffer[0];
+ c = (uchar) s[0];
if (c < 0x80)
return c;
@@ -269,9 +262,8 @@ read_utf8 (st_parameter_dt *dtp, size_t *nbytes)
c = (c & masks[nb-1]);
nread = nb - 1;
- s = (char *) &buffer[1];
- status = read_block_form (dtp, s, &nread);
- if (status == FAILURE)
+ s = read_block_form (dtp, &nread);
+ if (s == NULL)
return 0;
/* Decode the bytes read. */
for (i = 1; i < nb; i++)
@@ -304,14 +296,14 @@ read_utf8 (st_parameter_dt *dtp, size_t *nbytes)
static void
-read_utf8_char1 (st_parameter_dt *dtp, char *p, int len, size_t width)
+read_utf8_char1 (st_parameter_dt *dtp, char *p, int len, int width)
{
gfc_char4_t c;
char *dest;
- size_t nbytes;
+ int nbytes;
int i, j;
- len = ((int) width < len) ? len : (int) width;
+ len = (width < len) ? len : width;
dest = (char *) p;
@@ -334,21 +326,19 @@ read_utf8_char1 (st_parameter_dt *dtp, char *p, int len, size_t width)
}
static void
-read_default_char1 (st_parameter_dt *dtp, char *p, int len, size_t width)
+read_default_char1 (st_parameter_dt *dtp, char *p, int len, int width)
{
char *s;
- int m, n, status;
+ int m, n;
- s = gfc_alloca (width);
-
- status = read_block_form (dtp, s, &width);
+ s = read_block_form (dtp, &width);
- if (status == FAILURE)
+ if (s == NULL)
return;
- if (width > (size_t) len)
+ if (width > len)
s += (width - len);
- m = ((int) width > len) ? len : (int) width;
+ m = (width > len) ? len : width;
memcpy (p, s, m);
n = len - width;
@@ -358,13 +348,13 @@ read_default_char1 (st_parameter_dt *dtp, char *p, int len, size_t width)
static void
-read_utf8_char4 (st_parameter_dt *dtp, void *p, int len, size_t width)
+read_utf8_char4 (st_parameter_dt *dtp, void *p, int len, int width)
{
gfc_char4_t *dest;
- size_t nbytes;
+ int nbytes;
int i, j;
- len = ((int) width < len) ? len : (int) width;
+ len = (width < len) ? len : width;
dest = (gfc_char4_t *) p;
@@ -386,19 +376,17 @@ read_utf8_char4 (st_parameter_dt *dtp, void *p, int len, size_t width)
static void
-read_default_char4 (st_parameter_dt *dtp, char *p, int len, size_t width)
+read_default_char4 (st_parameter_dt *dtp, char *p, int len, int width)
{
char *s;
gfc_char4_t *dest;
- int m, n, status;
-
- s = gfc_alloca (width);
+ int m, n;
- status = read_block_form (dtp, s, &width);
+ s = read_block_form (dtp, &width);
- if (status == FAILURE)
+ if (s == NULL)
return;
- if (width > (size_t) len)
+ if (width > len)
s += (width - len);
m = ((int) width > len) ? len : (int) width;
@@ -420,7 +408,7 @@ void
read_a (st_parameter_dt *dtp, const fnode *f, char *p, int length)
{
int wi;
- size_t w;
+ int w;
wi = f->u.w;
if (wi == -1) /* '(A)' edit descriptor */
@@ -446,13 +434,11 @@ read_a (st_parameter_dt *dtp, const fnode *f, char *p, int length)
void
read_a_char4 (st_parameter_dt *dtp, const fnode *f, char *p, int length)
{
- int wi;
- size_t w;
+ int w;
- wi = f->u.w;
- if (wi == -1) /* '(A)' edit descriptor */
- wi = length;
- w = wi;
+ w = f->u.w;
+ if (w == -1) /* '(A)' edit descriptor */
+ w = length;
/* Read in w characters, treating comma as not a separator. */
dtp->u.p.sf_read_comma = 0;
@@ -527,18 +513,15 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
GFC_UINTEGER_LARGEST value, maxv, maxv_10;
GFC_INTEGER_LARGEST v;
int w, negative;
- size_t wu;
char c, *p;
- wu = f->u.w;
+ w = f->u.w;
- p = gfc_alloca (wu);
+ p = read_block_form (dtp, &w);
- if (read_block_form (dtp, p, &wu) == FAILURE)
+ if (p == NULL)
return;
- w = wu;
-
p = eat_leading_spaces (&w, p);
if (w == 0)
{
@@ -631,17 +614,14 @@ read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
GFC_INTEGER_LARGEST v;
int w, negative;
char c, *p;
- size_t wu;
- wu = f->u.w;
+ w = f->u.w;
- p = gfc_alloca (wu);
+ p = read_block_form (dtp, &w);
- if (read_block_form (dtp, p, &wu) == FAILURE)
+ if (p == NULL)
return;
- w = wu;
-
p = eat_leading_spaces (&w, p);
if (w == 0)
{
@@ -778,75 +758,83 @@ read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
void
read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
{
- size_t wu;
int w, seen_dp, exponent;
- int exponent_sign, val_sign;
- int ndigits;
- int edigits;
- int i;
- char *p, *buffer;
- char *digits;
- char scratch[SCRATCH_SIZE];
-
- val_sign = 1;
- seen_dp = 0;
- wu = f->u.w;
+ int exponent_sign;
+ const char *p;
+ char *buffer;
+ char *out;
+ int seen_int_digit; /* Seen a digit before the decimal point? */
+ int seen_dec_digit; /* Seen a digit after the decimal point? */
- p = gfc_alloca (wu);
+ seen_dp = 0;
+ seen_int_digit = 0;
+ seen_dec_digit = 0;
+ exponent_sign = 1;
+ exponent = 0;
+ w = f->u.w;
- if (read_block_form (dtp, p, &wu) == FAILURE)
+ /* Read in the next block. */
+ p = read_block_form (dtp, &w);
+ if (p == NULL)
return;
-
- w = wu;
-
- p = eat_leading_spaces (&w, p);
+ p = eat_leading_spaces (&w, (char*) p);
if (w == 0)
goto zero;
- /* Optional sign */
+ /* In this buffer we're going to re-format the number cleanly to be parsed
+ by convert_real in the end; this assures we're using strtod from the
+ C library for parsing and thus probably get the best accuracy possible.
+ This process may add a '+0.0' in front of the number as well as change the
+ exponent because of an implicit decimal point or the like. Thus allocating
+ strlen ("+0.0e-1000") == 10 characters plus one for NUL more than the
+ original buffer had should be enough. */
+ buffer = gfc_alloca (w + 11);
+ out = buffer;
+ /* Optional sign */
if (*p == '-' || *p == '+')
{
if (*p == '-')
- val_sign = -1;
- p++;
- w--;
+ *(out++) = '-';
+ ++p;
+ --w;
}
- exponent_sign = 1;
- p = eat_leading_spaces (&w, p);
+ p = eat_leading_spaces (&w, (char*) p);
if (w == 0)
goto zero;
- /* A digit, a '.' or a exponent character ('e', 'E', 'd' or 'D')
- is required at this point */
-
- if (!isdigit (*p) && *p != '.' && *p != ',' && *p != 'd' && *p != 'D'
- && *p != 'e' && *p != 'E')
- goto bad_float;
-
- /* Remember the position of the first digit. */
- digits = p;
- ndigits = 0;
-
- /* Scan through the string to find the exponent. */
+ /* Process the mantissa string. */
while (w > 0)
{
switch (*p)
{
case ',':
- if (dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA
- && *p == ',')
- *p = '.';
- else
+ if (dtp->u.p.current_unit->decimal_status != DECIMAL_COMMA)
goto bad_float;
- /* Fall through */
+ /* Fall through. */
case '.':
if (seen_dp)
goto bad_float;
+ if (!seen_int_digit)
+ *(out++) = '0';
+ *(out++) = '.';
seen_dp = 1;
- /* Fall through */
+ break;
+ case ' ':
+ if (dtp->u.p.blank_status == BLANK_ZERO)
+ {
+ *(out++) = '0';
+ goto found_digit;
+ }
+ else if (dtp->u.p.blank_status == BLANK_NULL)
+ break;
+ else
+ /* TODO: Should we check instead that there are only trailing
+ blanks here, as is done below for exponents? */
+ goto done;
+ /* Fall through. */
case '0':
case '1':
case '2':
@@ -857,207 +845,173 @@ read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
case '7':
case '8':
case '9':
- case ' ':
- ndigits++;
- p++;
- w--;
+ *(out++) = *p;
+found_digit:
+ if (!seen_dp)
+ seen_int_digit = 1;
+ else
+ seen_dec_digit = 1;
break;
case '-':
- exponent_sign = -1;
- /* Fall through */
-
case '+':
- p++;
- w--;
- goto exp2;
+ goto exponent;
- case 'd':
case 'e':
- case 'D':
case 'E':
- p++;
- w--;
- goto exp1;
+ case 'd':
+ case 'D':
+ ++p;
+ --w;
+ goto exponent;
default:
goto bad_float;
}
- }
- /* No exponent has been seen, so we use the current scale factor */
- exponent = -dtp->u.p.scale_factor;
- goto done;
-
- bad_float:
- generate_error (&dtp->common, LIBERROR_READ_VALUE,
- "Bad value during floating point read");
- next_record (dtp, 1);
- return;
-
- /* The value read is zero */
- zero:
- switch (length)
- {
- case 4:
- *((GFC_REAL_4 *) dest) = 0;
- break;
-
- case 8:
- *((GFC_REAL_8 *) dest) = 0;
- break;
-
-#ifdef HAVE_GFC_REAL_10
- case 10:
- *((GFC_REAL_10 *) dest) = 0;
- break;
-#endif
-
-#ifdef HAVE_GFC_REAL_16
- case 16:
- *((GFC_REAL_16 *) dest) = 0;
- break;
-#endif
-
- default:
- internal_error (&dtp->common, "Unsupported real kind during IO");
+ ++p;
+ --w;
}
- return;
+
+ /* No exponent has been seen, so we use the current scale factor. */
+ exponent = - dtp->u.p.scale_factor;
+ goto done;
- /* At this point the start of an exponent has been found */
- exp1:
- while (w > 0 && *p == ' ')
+ /* At this point the start of an exponent has been found. */
+exponent:
+ p = eat_leading_spaces (&w, (char*) p);
+ if (*p == '-' || *p == '+')
{
- w--;
- p++;
+ if (*p == '-')
+ exponent_sign = -1;
+ ++p;
+ --w;
}
- switch (*p)
- {
- case '-':
- exponent_sign = -1;
- /* Fall through */
-
- case '+':
- p++;
- w--;
- break;
- }
+ /* At this point a digit string is required. We calculate the value
+ of the exponent in order to take account of the scale factor and
+ the d parameter before explict conversion takes place. */
if (w == 0)
goto bad_float;
- /* At this point a digit string is required. We calculate the value
- of the exponent in order to take account of the scale factor and
- the d parameter before explict conversion takes place. */
- exp2:
- /* Normal processing of exponent */
- exponent = 0;
if (dtp->u.p.blank_status == BLANK_UNSPECIFIED)
{
while (w > 0 && isdigit (*p))
- {
- exponent = 10 * exponent + *p - '0';
- p++;
- w--;
- }
-
- /* Only allow trailing blanks */
-
+ {
+ exponent *= 10;
+ exponent += *p - '0';
+ ++p;
+ --w;
+ }
+
+ /* Only allow trailing blanks. */
while (w > 0)
- {
- if (*p != ' ')
+ {
+ if (*p != ' ')
goto bad_float;
- p++;
- w--;
- }
+ ++p;
+ --w;
+ }
}
- else /* BZ or BN status is enabled */
+ else /* BZ or BN status is enabled. */
{
while (w > 0)
- {
- if (*p == ' ')
- {
- if (dtp->u.p.blank_status == BLANK_ZERO) *p = '0';
- if (dtp->u.p.blank_status == BLANK_NULL)
- {
- p++;
- w--;
- continue;
- }
- }
- else if (!isdigit (*p))
- goto bad_float;
-
- exponent = 10 * exponent + *p - '0';
- p++;
- w--;
- }
+ {
+ if (*p == ' ')
+ {
+ if (dtp->u.p.blank_status == BLANK_ZERO)
+ exponent *= 10;
+ else
+ assert (dtp->u.p.blank_status == BLANK_NULL);
+ }
+ else if (!isdigit (*p))
+ goto bad_float;
+ else
+ {
+ exponent *= 10;
+ exponent += *p - '0';
+ }
+
+ ++p;
+ --w;
+ }
}
- exponent = exponent * exponent_sign;
+ exponent *= exponent_sign;
- done:
+done:
/* Use the precision specified in the format if no decimal point has been
seen. */
if (!seen_dp)
exponent -= f->u.real.d;
- if (exponent > 0)
- {
- edigits = 2;
- i = exponent;
- }
- else
- {
- edigits = 3;
- i = -exponent;
- }
+ /* Output a trailing '0' after decimal point if not yet found. */
+ if (seen_dp && !seen_dec_digit)
+ *(out++) = '0';
- while (i >= 10)
+ /* Print out the exponent to finish the reformatted number. Maximum 4
+ digits for the exponent. */
+ if (exponent != 0)
{
- i /= 10;
- edigits++;
- }
+ int dig;
- i = ndigits + edigits + 1;
- if (val_sign < 0)
- i++;
+ *(out++) = 'e';
+ if (exponent < 0)
+ {
+ *(out++) = '-';
+ exponent = - exponent;
+ }
- if (i < SCRATCH_SIZE)
- buffer = scratch;
- else
- buffer = get_mem (i);
-
- /* Reformat the string into a temporary buffer. As we're using atof it's
- easiest to just leave the decimal point in place. */
- p = buffer;
- if (val_sign < 0)
- *(p++) = '-';
- for (; ndigits > 0; ndigits--)
- {
- if (*digits == ' ')
- {
- if (dtp->u.p.blank_status == BLANK_ZERO) *digits = '0';
- if (dtp->u.p.blank_status == BLANK_NULL)
- {
- digits++;
- continue;
- }
- }
- *p = *digits;
- p++;
- digits++;
+ assert (exponent < 10000);
+ for (dig = 3; dig >= 0; --dig)
+ {
+ out[dig] = (char) ('0' + exponent % 10);
+ exponent /= 10;
+ }
+ out += 4;
}
- *(p++) = 'e';
- sprintf (p, "%d", exponent);
+ *(out++) = '\0';
/* Do the actual conversion. */
convert_real (dtp, dest, buffer, length);
- if (buffer != scratch)
- free_mem (buffer);
+ return;
+ /* The value read is zero. */
+zero:
+ switch (length)
+ {
+ case 4:
+ *((GFC_REAL_4 *) dest) = 0.0;
+ break;
+
+ case 8:
+ *((GFC_REAL_8 *) dest) = 0.0;
+ break;
+
+#ifdef HAVE_GFC_REAL_10
+ case 10:
+ *((GFC_REAL_10 *) dest) = 0.0;
+ break;
+#endif
+
+#ifdef HAVE_GFC_REAL_16
+ case 16:
+ *((GFC_REAL_16 *) dest) = 0.0;
+ break;
+#endif
+
+ default:
+ internal_error (&dtp->common, "Unsupported real kind during IO");
+ }
+ return;
+
+bad_float:
+ generate_error (&dtp->common, LIBERROR_READ_VALUE,
+ "Bad value during floating point read");
+ next_record (dtp, 1);
+ return;
}
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index 4d314c5939d..cf25a89fff6 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -32,6 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <string.h>
#include <assert.h>
#include <stdlib.h>
+#include <errno.h>
/* Calling conventions: Data transfer statements are unlike other
@@ -178,60 +179,58 @@ current_mode (st_parameter_dt *dtp)
heap. Hopefully this won't happen very often. */
char *
-read_sf (st_parameter_dt *dtp, int *length, int no_error)
+read_sf (st_parameter_dt *dtp, int * length, int no_error)
{
+ static char *empty_string[0];
char *base, *p, q;
- int n, crlf;
- gfc_offset pos;
- size_t readlen;
+ int n, lorig, memread, seen_comma;
- if (*length > SCRATCH_SIZE)
- dtp->u.p.line_buffer = get_mem (*length);
- p = base = dtp->u.p.line_buffer;
+ /* If we hit EOF previously with the no_error flag set (i.e. X, T,
+ TR edit descriptors), and we now try to read again, this time
+ without setting no_error. */
+ if (!no_error && dtp->u.p.at_eof)
+ {
+ *length = 0;
+ hit_eof (dtp);
+ return NULL;
+ }
/* If we have seen an eor previously, return a length of 0. The
caller is responsible for correctly padding the input field. */
if (dtp->u.p.sf_seen_eor)
{
*length = 0;
- return base;
+ /* Just return something that isn't a NULL pointer, otherwise the
+ caller thinks an error occured. */
+ return (char*) empty_string;
}
if (is_internal_unit (dtp))
{
- readlen = *length;
- if (unlikely (sread (dtp->u.p.current_unit->s, p, &readlen) != 0
- || readlen < (size_t) *length))
+ memread = *length;
+ base = mem_alloc_r (dtp->u.p.current_unit->s, length);
+ if (unlikely (memread > *length))
{
- generate_error (&dtp->common, LIBERROR_END, NULL);
+ hit_eof (dtp);
return NULL;
}
-
+ n = *length;
goto done;
}
- readlen = 1;
- n = 0;
+ n = seen_comma = 0;
- do
- {
- if (unlikely (sread (dtp->u.p.current_unit->s, &q, &readlen) != 0))
- {
- generate_error (&dtp->common, LIBERROR_END, NULL);
- return NULL;
- }
+ /* Read data into format buffer and scan through it. */
+ lorig = *length;
+ base = p = fbuf_read (dtp->u.p.current_unit, length);
+ if (base == NULL)
+ return NULL;
- /* If we have a line without a terminating \n, drop through to
- EOR below. */
- if (readlen < 1 && n == 0)
- {
- if (likely (no_error))
- break;
- generate_error (&dtp->common, LIBERROR_END, NULL);
- return NULL;
- }
+ while (n < *length)
+ {
+ q = *p;
- if (readlen < 1 || q == '\n' || q == '\r')
+ if (q == '\n' || q == '\r')
{
/* Unexpected end of line. */
@@ -240,23 +239,14 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error)
if (dtp->u.p.advance_status == ADVANCE_NO || dtp->u.p.seen_dollar)
dtp->u.p.eor_condition = 1;
- crlf = 0;
/* If we encounter a CR, it might be a CRLF. */
if (q == '\r') /* Probably a CRLF */
{
- readlen = 1;
- pos = stream_offset (dtp->u.p.current_unit->s);
- if (unlikely (sread (dtp->u.p.current_unit->s, &q, &readlen)
- != 0))
- {
- generate_error (&dtp->common, LIBERROR_END, NULL);
- return NULL;
- }
- if (q != '\n' && readlen == 1) /* Not a CRLF after all. */
- sseek (dtp->u.p.current_unit->s, pos);
- else
- crlf = 1;
+ if (n < *length && *(p + 1) == '\n')
+ dtp->u.p.sf_seen_eor = 2;
}
+ else
+ dtp->u.p.sf_seen_eor = 1;
/* Without padding, terminate the I/O statement without assigning
the value. With padding, the value still needs to be assigned,
@@ -270,7 +260,6 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error)
}
*length = n;
- dtp->u.p.sf_seen_eor = (crlf ? 2 : 1);
break;
}
/* Short circuit the read if a comma is found during numeric input.
@@ -279,6 +268,7 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error)
if (q == ',')
if (dtp->u.p.sf_read_comma == 1)
{
+ seen_comma = 1;
notify_std (&dtp->common, GFC_STD_GNU,
"Comma in formatted numeric read.");
*length = n;
@@ -286,16 +276,31 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error)
}
n++;
- *p++ = q;
- dtp->u.p.sf_seen_eor = 0;
+ p++;
+ }
+
+ fbuf_seek (dtp->u.p.current_unit, n + dtp->u.p.sf_seen_eor + seen_comma,
+ SEEK_CUR);
+
+ /* A short read implies we hit EOF, unless we hit EOR, a comma, or
+ some other stuff. Set the relevant flags. */
+ if (lorig > *length && !dtp->u.p.sf_seen_eor && !seen_comma)
+ {
+ if (no_error)
+ dtp->u.p.at_eof = 1;
+ else
+ {
+ hit_eof (dtp);
+ return NULL;
+ }
}
- while (n < *length);
done:
- dtp->u.p.current_unit->bytes_left -= *length;
+
+ dtp->u.p.current_unit->bytes_left -= n;
if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
- dtp->u.p.size_used += (GFC_IO_INT) *length;
+ dtp->u.p.size_used += (GFC_IO_INT) n;
return base;
}
@@ -311,12 +316,11 @@ read_sf (st_parameter_dt *dtp, int *length, int no_error)
opened with PAD=YES. The caller must assume tailing spaces for
short reads. */
-try
-read_block_form (st_parameter_dt *dtp, void *buf, size_t *nbytes)
+void *
+read_block_form (st_parameter_dt *dtp, int * nbytes)
{
char *source;
- size_t nread;
- int nb;
+ int norig;
if (!is_stream_io (dtp))
{
@@ -333,15 +337,14 @@ read_block_form (st_parameter_dt *dtp, void *buf, size_t *nbytes)
{
/* Not enough data left. */
generate_error (&dtp->common, LIBERROR_EOR, NULL);
- return FAILURE;
+ return NULL;
}
}
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);
- return FAILURE;
+ hit_eof (dtp);
+ return NULL;
}
*nbytes = dtp->u.p.current_unit->bytes_left;
@@ -352,42 +355,36 @@ read_block_form (st_parameter_dt *dtp, void *buf, size_t *nbytes)
(dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL ||
dtp->u.p.current_unit->flags.access == ACCESS_STREAM))
{
- nb = *nbytes;
- source = read_sf (dtp, &nb, 0);
- *nbytes = nb;
+ source = read_sf (dtp, nbytes, 0);
dtp->u.p.current_unit->strm_pos +=
(gfc_offset) (*nbytes + dtp->u.p.sf_seen_eor);
- if (source == NULL)
- return FAILURE;
- memcpy (buf, source, *nbytes);
- return SUCCESS;
+ return source;
}
+
+ /* If we reach here, we can assume it's direct access. */
+
dtp->u.p.current_unit->bytes_left -= (gfc_offset) *nbytes;
- nread = *nbytes;
- if (unlikely (sread (dtp->u.p.current_unit->s, buf, &nread) != 0))
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return FAILURE;
- }
+ norig = *nbytes;
+ source = fbuf_read (dtp->u.p.current_unit, nbytes);
+ fbuf_seek (dtp->u.p.current_unit, *nbytes, SEEK_CUR);
if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
- dtp->u.p.size_used += (GFC_IO_INT) nread;
+ dtp->u.p.size_used += (GFC_IO_INT) *nbytes;
- if (nread != *nbytes)
- { /* Short read, this shouldn't happen. */
- if (likely (dtp->u.p.current_unit->pad_status == PAD_YES))
- *nbytes = nread;
- else
+ if (norig != *nbytes)
+ {
+ /* Short read, this shouldn't happen. */
+ if (!dtp->u.p.current_unit->pad_status == PAD_YES)
{
generate_error (&dtp->common, LIBERROR_EOR, NULL);
source = NULL;
}
}
- dtp->u.p.current_unit->strm_pos += (gfc_offset) nread;
+ dtp->u.p.current_unit->strm_pos += (gfc_offset) *nbytes;
- return SUCCESS;
+ return source;
}
@@ -395,20 +392,19 @@ read_block_form (st_parameter_dt *dtp, void *buf, size_t *nbytes)
unformatted files. */
static void
-read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
+read_block_direct (st_parameter_dt *dtp, void *buf, size_t nbytes)
{
- size_t to_read_record;
- size_t have_read_record;
- size_t to_read_subrecord;
- size_t have_read_subrecord;
+ ssize_t to_read_record;
+ ssize_t have_read_record;
+ ssize_t to_read_subrecord;
+ ssize_t have_read_subrecord;
int short_record;
if (is_stream_io (dtp))
{
- to_read_record = *nbytes;
- have_read_record = to_read_record;
- if (unlikely (sread (dtp->u.p.current_unit->s, buf, &have_read_record)
- != 0))
+ have_read_record = sread (dtp->u.p.current_unit->s, buf,
+ nbytes);
+ if (unlikely (have_read_record < 0))
{
generate_error (&dtp->common, LIBERROR_OS, NULL);
return;
@@ -416,52 +412,48 @@ 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 (unlikely (to_read_record != have_read_record))
+ if (unlikely ((ssize_t) nbytes != have_read_record))
{
/* Short read, e.g. if we hit EOF. For stream files,
we have to set the end-of-file condition. */
- generate_error (&dtp->common, LIBERROR_END, NULL);
- return;
+ hit_eof (dtp);
}
return;
}
if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
{
- if (dtp->u.p.current_unit->bytes_left < (gfc_offset) *nbytes)
+ if (dtp->u.p.current_unit->bytes_left < (gfc_offset) nbytes)
{
short_record = 1;
- to_read_record = (size_t) dtp->u.p.current_unit->bytes_left;
- *nbytes = to_read_record;
+ to_read_record = dtp->u.p.current_unit->bytes_left;
+ nbytes = to_read_record;
}
-
else
{
short_record = 0;
- to_read_record = *nbytes;
+ to_read_record = nbytes;
}
dtp->u.p.current_unit->bytes_left -= to_read_record;
- if (unlikely (sread (dtp->u.p.current_unit->s, buf, &to_read_record)
- != 0))
+ to_read_record = sread (dtp->u.p.current_unit->s, buf, to_read_record);
+ if (unlikely (to_read_record < 0))
{
generate_error (&dtp->common, LIBERROR_OS, NULL);
return;
}
- if (to_read_record != *nbytes)
+ if (to_read_record != (ssize_t) nbytes)
{
/* Short read, e.g. if we hit EOF. Apparently, we read
more than was written to the last record. */
- *nbytes = to_read_record;
return;
}
if (unlikely (short_record))
{
generate_error (&dtp->common, LIBERROR_SHORT_RECORD, NULL);
- return;
}
return;
}
@@ -470,23 +462,17 @@ 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 (unlikely (dtp->u.p.current_unit->endfile == AT_ENDFILE))
- {
- generate_error (&dtp->common, LIBERROR_END, NULL);
- return;
- }
-
/* Check whether we exceed the total record length. */
if (dtp->u.p.current_unit->flags.has_recl
- && (*nbytes > (size_t) dtp->u.p.current_unit->bytes_left))
+ && ((gfc_offset) nbytes > dtp->u.p.current_unit->bytes_left))
{
- to_read_record = (size_t) dtp->u.p.current_unit->bytes_left;
+ to_read_record = dtp->u.p.current_unit->bytes_left;
short_record = 1;
}
else
{
- to_read_record = *nbytes;
+ to_read_record = nbytes;
short_record = 0;
}
have_read_record = 0;
@@ -496,7 +482,7 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
if (dtp->u.p.current_unit->bytes_left_subrecord
< (gfc_offset) to_read_record)
{
- to_read_subrecord = (size_t) dtp->u.p.current_unit->bytes_left_subrecord;
+ to_read_subrecord = dtp->u.p.current_unit->bytes_left_subrecord;
to_read_record -= to_read_subrecord;
}
else
@@ -507,9 +493,9 @@ 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 (unlikely (sread (dtp->u.p.current_unit->s, buf + have_read_record,
- &have_read_subrecord) != 0))
+ have_read_subrecord = sread (dtp->u.p.current_unit->s,
+ buf + have_read_record, to_read_subrecord);
+ if (unlikely (have_read_subrecord) < 0)
{
generate_error (&dtp->common, LIBERROR_OS, NULL);
return;
@@ -524,7 +510,6 @@ read_block_direct (st_parameter_dt *dtp, void *buf, size_t *nbytes)
structure has been corrupted, or the trailing record
marker would still be present. */
- *nbytes = have_read_record;
generate_error (&dtp->common, LIBERROR_CORRUPT_FILE, NULL);
return;
}
@@ -598,7 +583,7 @@ write_block (st_parameter_dt *dtp, int length)
if (is_internal_unit (dtp))
{
- dest = salloc_w (dtp->u.p.current_unit->s, &length);
+ dest = mem_alloc_w (dtp->u.p.current_unit->s, &length);
if (dest == NULL)
{
@@ -636,20 +621,22 @@ static try
write_buf (st_parameter_dt *dtp, void *buf, size_t nbytes)
{
- size_t have_written, to_write_subrecord;
+ ssize_t have_written;
+ ssize_t to_write_subrecord;
int short_record;
/* Stream I/O. */
if (is_stream_io (dtp))
{
- if (unlikely (swrite (dtp->u.p.current_unit->s, buf, &nbytes) != 0))
+ have_written = swrite (dtp->u.p.current_unit->s, buf, nbytes);
+ if (unlikely (have_written < 0))
{
generate_error (&dtp->common, LIBERROR_OS, NULL);
return FAILURE;
}
- dtp->u.p.current_unit->strm_pos += (gfc_offset) nbytes;
+ dtp->u.p.current_unit->strm_pos += (gfc_offset) have_written;
return SUCCESS;
}
@@ -667,14 +654,15 @@ write_buf (st_parameter_dt *dtp, void *buf, size_t nbytes)
if (buf == NULL && nbytes == 0)
return SUCCESS;
- if (unlikely (swrite (dtp->u.p.current_unit->s, buf, &nbytes) != 0))
+ have_written = swrite (dtp->u.p.current_unit->s, buf, nbytes);
+ if (unlikely (have_written < 0))
{
generate_error (&dtp->common, LIBERROR_OS, NULL);
return FAILURE;
}
- dtp->u.p.current_unit->strm_pos += (gfc_offset) nbytes;
- dtp->u.p.current_unit->bytes_left -= (gfc_offset) nbytes;
+ dtp->u.p.current_unit->strm_pos += (gfc_offset) have_written;
+ dtp->u.p.current_unit->bytes_left -= (gfc_offset) have_written;
return SUCCESS;
}
@@ -704,8 +692,9 @@ 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 (unlikely (swrite (dtp->u.p.current_unit->s, buf + have_written,
- &to_write_subrecord) != 0))
+ to_write_subrecord = swrite (dtp->u.p.current_unit->s,
+ buf + have_written, to_write_subrecord);
+ if (unlikely (to_write_subrecord < 0))
{
generate_error (&dtp->common, LIBERROR_OS, NULL);
return FAILURE;
@@ -737,20 +726,18 @@ static void
unformatted_read (st_parameter_dt *dtp, bt type,
void *dest, int kind, size_t size, size_t nelems)
{
- size_t i, sz;
-
if (likely (dtp->u.p.current_unit->flags.convert == GFC_CONVERT_NATIVE)
|| kind == 1)
{
- sz = size * nelems;
if (type == BT_CHARACTER)
- sz *= GFC_SIZE_OF_CHAR_KIND(kind);
- read_block_direct (dtp, dest, &sz);
+ size *= GFC_SIZE_OF_CHAR_KIND(kind);
+ read_block_direct (dtp, dest, size * nelems);
}
else
{
char buffer[16];
char *p;
+ size_t i;
p = dest;
@@ -773,7 +760,7 @@ unformatted_read (st_parameter_dt *dtp, bt type,
for (i = 0; i < nelems; i++)
{
- read_block_direct (dtp, buffer, &size);
+ read_block_direct (dtp, buffer, size);
reverse_memcpy (p, buffer, size);
p += size;
}
@@ -915,19 +902,18 @@ require_type (st_parameter_dt *dtp, bt expected, bt actual, const fnode *f)
}
-/* This subroutine is the main loop for a formatted data transfer
+/* This function is in the main loop for a formatted data transfer
statement. It would be natural to implement this as a coroutine
with the user program, but C makes that awkward. We loop,
processing format elements. When we actually have to transfer
data instead of just setting flags, we return control to the user
- program which calls a subroutine that supplies the address and type
+ program which calls a function that supplies the address and type
of the next element, then comes back here to process it. */
static void
-formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
- size_t size)
+formatted_transfer_scalar_read (st_parameter_dt *dtp, bt type, void *p, int kind,
+ size_t size)
{
- char scratch[SCRATCH_SIZE];
int pos, bytes_used;
const fnode *f;
format_token t;
@@ -954,7 +940,347 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
dtp->u.p.sf_read_comma =
dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
- dtp->u.p.line_buffer = scratch;
+ for (;;)
+ {
+ /* If reversion has occurred and there is another real data item,
+ then we have to move to the next record. */
+ if (dtp->u.p.reversion_flag && n > 0)
+ {
+ dtp->u.p.reversion_flag = 0;
+ next_record (dtp, 0);
+ }
+
+ consume_data_flag = 1;
+ if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
+ break;
+
+ f = next_format (dtp);
+ if (f == NULL)
+ {
+ /* No data descriptors left. */
+ if (unlikely (n > 0))
+ generate_error (&dtp->common, LIBERROR_FORMAT,
+ "Insufficient data descriptors in format after reversion");
+ return;
+ }
+
+ t = f->format;
+
+ bytes_used = (int)(dtp->u.p.current_unit->recl
+ - dtp->u.p.current_unit->bytes_left);
+
+ if (is_stream_io(dtp))
+ bytes_used = 0;
+
+ switch (t)
+ {
+ case FMT_I:
+ if (n == 0)
+ goto need_read_data;
+ if (require_type (dtp, BT_INTEGER, type, f))
+ return;
+ read_decimal (dtp, f, p, kind);
+ break;
+
+ case FMT_B:
+ if (n == 0)
+ goto need_read_data;
+ if (compile_options.allow_std < GFC_STD_GNU
+ && require_type (dtp, BT_INTEGER, type, f))
+ return;
+ read_radix (dtp, f, p, kind, 2);
+ break;
+
+ case FMT_O:
+ if (n == 0)
+ goto need_read_data;
+ if (compile_options.allow_std < GFC_STD_GNU
+ && require_type (dtp, BT_INTEGER, type, f))
+ return;
+ read_radix (dtp, f, p, kind, 8);
+ break;
+
+ case FMT_Z:
+ if (n == 0)
+ goto need_read_data;
+ if (compile_options.allow_std < GFC_STD_GNU
+ && require_type (dtp, BT_INTEGER, type, f))
+ return;
+ read_radix (dtp, f, p, kind, 16);
+ break;
+
+ case FMT_A:
+ if (n == 0)
+ goto need_read_data;
+
+ /* It is possible to have FMT_A with something not BT_CHARACTER such
+ as when writing out hollerith strings, so check both type
+ and kind before calling wide character routines. */
+ if (type == BT_CHARACTER && kind == 4)
+ read_a_char4 (dtp, f, p, size);
+ else
+ read_a (dtp, f, p, size);
+ break;
+
+ case FMT_L:
+ if (n == 0)
+ goto need_read_data;
+ read_l (dtp, f, p, kind);
+ break;
+
+ case FMT_D:
+ if (n == 0)
+ goto need_read_data;
+ if (require_type (dtp, BT_REAL, type, f))
+ return;
+ read_f (dtp, f, p, kind);
+ break;
+
+ case FMT_E:
+ if (n == 0)
+ goto need_read_data;
+ if (require_type (dtp, BT_REAL, type, f))
+ return;
+ read_f (dtp, f, p, kind);
+ break;
+
+ case FMT_EN:
+ if (n == 0)
+ goto need_read_data;
+ if (require_type (dtp, BT_REAL, type, f))
+ return;
+ read_f (dtp, f, p, kind);
+ break;
+
+ case FMT_ES:
+ if (n == 0)
+ goto need_read_data;
+ if (require_type (dtp, BT_REAL, type, f))
+ return;
+ read_f (dtp, f, p, kind);
+ break;
+
+ case FMT_F:
+ if (n == 0)
+ goto need_read_data;
+ if (require_type (dtp, BT_REAL, type, f))
+ return;
+ read_f (dtp, f, p, kind);
+ break;
+
+ case FMT_G:
+ if (n == 0)
+ goto need_read_data;
+ switch (type)
+ {
+ case BT_INTEGER:
+ read_decimal (dtp, f, p, kind);
+ break;
+ case BT_LOGICAL:
+ read_l (dtp, f, p, kind);
+ break;
+ case BT_CHARACTER:
+ if (kind == 4)
+ read_a_char4 (dtp, f, p, size);
+ else
+ read_a (dtp, f, p, size);
+ break;
+ case BT_REAL:
+ read_f (dtp, f, p, kind);
+ break;
+ default:
+ internal_error (&dtp->common, "formatted_transfer(): Bad type");
+ }
+ break;
+
+ case FMT_STRING:
+ consume_data_flag = 0;
+ format_error (dtp, f, "Constant string in input format");
+ return;
+
+ /* Format codes that don't transfer data. */
+ case FMT_X:
+ case FMT_TR:
+ consume_data_flag = 0;
+ dtp->u.p.skips += f->u.n;
+ pos = bytes_used + dtp->u.p.skips - 1;
+ dtp->u.p.pending_spaces = pos - dtp->u.p.max_pos + 1;
+ read_x (dtp, f->u.n);
+ break;
+
+ case FMT_TL:
+ case FMT_T:
+ consume_data_flag = 0;
+
+ if (f->format == FMT_TL)
+ {
+ /* Handle the special case when no bytes have been used yet.
+ Cannot go below zero. */
+ if (bytes_used == 0)
+ {
+ dtp->u.p.pending_spaces -= f->u.n;
+ dtp->u.p.skips -= f->u.n;
+ dtp->u.p.skips = dtp->u.p.skips < 0 ? 0 : dtp->u.p.skips;
+ }
+
+ pos = bytes_used - f->u.n;
+ }
+ else /* FMT_T */
+ pos = f->u.n - 1;
+
+ /* Standard 10.6.1.1: excessive left tabbing is reset to the
+ left tab limit. We do not check if the position has gone
+ beyond the end of record because a subsequent tab could
+ bring us back again. */
+ pos = pos < 0 ? 0 : pos;
+
+ dtp->u.p.skips = dtp->u.p.skips + pos - bytes_used;
+ dtp->u.p.pending_spaces = dtp->u.p.pending_spaces
+ + pos - dtp->u.p.max_pos;
+ dtp->u.p.pending_spaces = dtp->u.p.pending_spaces < 0
+ ? 0 : dtp->u.p.pending_spaces;
+ if (dtp->u.p.skips == 0)
+ break;
+
+ /* Adjust everything for end-of-record condition */
+ if (dtp->u.p.sf_seen_eor && !is_internal_unit (dtp))
+ {
+ dtp->u.p.current_unit->bytes_left -= dtp->u.p.sf_seen_eor;
+ dtp->u.p.skips -= dtp->u.p.sf_seen_eor;
+ bytes_used = pos;
+ dtp->u.p.sf_seen_eor = 0;
+ }
+ if (dtp->u.p.skips < 0)
+ {
+ if (is_internal_unit (dtp))
+ sseek (dtp->u.p.current_unit->s, dtp->u.p.skips, SEEK_CUR);
+ else
+ fbuf_seek (dtp->u.p.current_unit, dtp->u.p.skips, SEEK_CUR);
+ dtp->u.p.current_unit->bytes_left -= (gfc_offset) dtp->u.p.skips;
+ dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
+ }
+ else
+ read_x (dtp, dtp->u.p.skips);
+ break;
+
+ case FMT_S:
+ consume_data_flag = 0;
+ dtp->u.p.sign_status = SIGN_S;
+ break;
+
+ case FMT_SS:
+ consume_data_flag = 0;
+ dtp->u.p.sign_status = SIGN_SS;
+ break;
+
+ case FMT_SP:
+ consume_data_flag = 0;
+ dtp->u.p.sign_status = SIGN_SP;
+ break;
+
+ case FMT_BN:
+ consume_data_flag = 0 ;
+ dtp->u.p.blank_status = BLANK_NULL;
+ break;
+
+ case FMT_BZ:
+ consume_data_flag = 0;
+ dtp->u.p.blank_status = BLANK_ZERO;
+ break;
+
+ case FMT_DC:
+ consume_data_flag = 0;
+ dtp->u.p.current_unit->decimal_status = DECIMAL_COMMA;
+ break;
+
+ case FMT_DP:
+ consume_data_flag = 0;
+ dtp->u.p.current_unit->decimal_status = DECIMAL_POINT;
+ break;
+
+ case FMT_P:
+ consume_data_flag = 0;
+ dtp->u.p.scale_factor = f->u.k;
+ break;
+
+ case FMT_DOLLAR:
+ consume_data_flag = 0;
+ dtp->u.p.seen_dollar = 1;
+ break;
+
+ case FMT_SLASH:
+ consume_data_flag = 0;
+ dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
+ next_record (dtp, 0);
+ break;
+
+ case FMT_COLON:
+ /* A colon descriptor causes us to exit this loop (in
+ particular preventing another / descriptor from being
+ processed) unless there is another data item to be
+ transferred. */
+ consume_data_flag = 0;
+ if (n == 0)
+ return;
+ break;
+
+ default:
+ internal_error (&dtp->common, "Bad format node");
+ }
+
+ /* Adjust the item count and data pointer. */
+
+ if ((consume_data_flag > 0) && (n > 0))
+ {
+ n--;
+ p = ((char *) p) + size;
+ }
+
+ dtp->u.p.skips = 0;
+
+ pos = (int)(dtp->u.p.current_unit->recl - dtp->u.p.current_unit->bytes_left);
+ dtp->u.p.max_pos = (dtp->u.p.max_pos > pos) ? dtp->u.p.max_pos : pos;
+ }
+
+ return;
+
+ /* Come here when we need a data descriptor but don't have one. We
+ push the current format node back onto the input, then return and
+ let the user program call us back with the data. */
+ need_read_data:
+ unget_format (dtp, f);
+}
+
+
+static void
+formatted_transfer_scalar_write (st_parameter_dt *dtp, bt type, void *p, int kind,
+ size_t size)
+{
+ int pos, bytes_used;
+ const fnode *f;
+ format_token t;
+ int n;
+ int consume_data_flag;
+
+ /* Change a complex data item into a pair of reals. */
+
+ n = (p == NULL) ? 0 : ((type != BT_COMPLEX) ? 1 : 2);
+ if (type == BT_COMPLEX)
+ {
+ type = BT_REAL;
+ size /= 2;
+ }
+
+ /* If there's an EOR condition, we simulate finalizing the transfer
+ by doing nothing. */
+ if (dtp->u.p.eor_condition)
+ return;
+
+ /* Set this flag so that commas in reads cause the read to complete before
+ the entire field has been read. The next read field will start right after
+ the comma in the stream. (Set to 0 for character reads). */
+ dtp->u.p.sf_read_comma =
+ dtp->u.p.current_unit->decimal_status == DECIMAL_COMMA ? 0 : 1;
for (;;)
{
@@ -1003,9 +1329,9 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
if (dtp->u.p.skips < 0)
{
if (is_internal_unit (dtp))
- move_pos_offset (dtp->u.p.current_unit->s, dtp->u.p.skips);
+ sseek (dtp->u.p.current_unit->s, dtp->u.p.skips, SEEK_CUR);
else
- fbuf_seek (dtp->u.p.current_unit, dtp->u.p.skips);
+ fbuf_seek (dtp->u.p.current_unit, dtp->u.p.skips, SEEK_CUR);
dtp->u.p.current_unit->bytes_left -= (gfc_offset) dtp->u.p.skips;
}
dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
@@ -1024,57 +1350,34 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
goto need_data;
if (require_type (dtp, BT_INTEGER, type, f))
return;
-
- if (dtp->u.p.mode == READING)
- read_decimal (dtp, f, p, kind);
- else
- write_i (dtp, f, p, kind);
-
+ write_i (dtp, f, p, kind);
break;
case FMT_B:
if (n == 0)
goto need_data;
-
if (compile_options.allow_std < GFC_STD_GNU
&& require_type (dtp, BT_INTEGER, type, f))
return;
-
- if (dtp->u.p.mode == READING)
- read_radix (dtp, f, p, kind, 2);
- else
- write_b (dtp, f, p, kind);
-
+ write_b (dtp, f, p, kind);
break;
case FMT_O:
if (n == 0)
goto need_data;
-
if (compile_options.allow_std < GFC_STD_GNU
&& require_type (dtp, BT_INTEGER, type, f))
return;
-
- if (dtp->u.p.mode == READING)
- read_radix (dtp, f, p, kind, 8);
- else
- write_o (dtp, f, p, kind);
-
+ write_o (dtp, f, p, kind);
break;
case FMT_Z:
if (n == 0)
goto need_data;
-
if (compile_options.allow_std < GFC_STD_GNU
&& require_type (dtp, BT_INTEGER, type, f))
return;
-
- if (dtp->u.p.mode == READING)
- read_radix (dtp, f, p, kind, 16);
- else
- write_z (dtp, f, p, kind);
-
+ write_z (dtp, f, p, kind);
break;
case FMT_A:
@@ -1084,31 +1387,16 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
/* It is possible to have FMT_A with something not BT_CHARACTER such
as when writing out hollerith strings, so check both type
and kind before calling wide character routines. */
- if (dtp->u.p.mode == READING)
- {
- if (type == BT_CHARACTER && kind == 4)
- read_a_char4 (dtp, f, p, size);
- else
- read_a (dtp, f, p, size);
- }
+ if (type == BT_CHARACTER && kind == 4)
+ write_a_char4 (dtp, f, p, size);
else
- {
- if (type == BT_CHARACTER && kind == 4)
- write_a_char4 (dtp, f, p, size);
- else
- write_a (dtp, f, p, size);
- }
+ write_a (dtp, f, p, size);
break;
case FMT_L:
if (n == 0)
goto need_data;
-
- if (dtp->u.p.mode == READING)
- read_l (dtp, f, p, kind);
- else
- write_l (dtp, f, p, kind);
-
+ write_l (dtp, f, p, kind);
break;
case FMT_D:
@@ -1116,12 +1404,7 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
goto need_data;
if (require_type (dtp, BT_REAL, type, f))
return;
-
- if (dtp->u.p.mode == READING)
- read_f (dtp, f, p, kind);
- else
- write_d (dtp, f, p, kind);
-
+ write_d (dtp, f, p, kind);
break;
case FMT_E:
@@ -1129,11 +1412,7 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
goto need_data;
if (require_type (dtp, BT_REAL, type, f))
return;
-
- if (dtp->u.p.mode == READING)
- read_f (dtp, f, p, kind);
- else
- write_e (dtp, f, p, kind);
+ write_e (dtp, f, p, kind);
break;
case FMT_EN:
@@ -1141,12 +1420,7 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
goto need_data;
if (require_type (dtp, BT_REAL, type, f))
return;
-
- if (dtp->u.p.mode == READING)
- read_f (dtp, f, p, kind);
- else
- write_en (dtp, f, p, kind);
-
+ write_en (dtp, f, p, kind);
break;
case FMT_ES:
@@ -1154,12 +1428,7 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
goto need_data;
if (require_type (dtp, BT_REAL, type, f))
return;
-
- if (dtp->u.p.mode == READING)
- read_f (dtp, f, p, kind);
- else
- write_es (dtp, f, p, kind);
-
+ write_es (dtp, f, p, kind);
break;
case FMT_F:
@@ -1167,41 +1436,14 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
goto need_data;
if (require_type (dtp, BT_REAL, type, f))
return;
-
- if (dtp->u.p.mode == READING)
- read_f (dtp, f, p, kind);
- else
- write_f (dtp, f, p, kind);
-
+ write_f (dtp, f, p, kind);
break;
case FMT_G:
if (n == 0)
goto need_data;
- if (dtp->u.p.mode == READING)
- switch (type)
- {
- case BT_INTEGER:
- read_decimal (dtp, f, p, kind);
- break;
- case BT_LOGICAL:
- read_l (dtp, f, p, kind);
- break;
- case BT_CHARACTER:
- if (kind == 4)
- read_a_char4 (dtp, f, p, size);
- else
- read_a (dtp, f, p, size);
- break;
- case BT_REAL:
- read_f (dtp, f, p, kind);
- break;
- default:
- goto bad_type;
- }
- else
- switch (type)
- {
+ switch (type)
+ {
case BT_INTEGER:
write_i (dtp, f, p, kind);
break;
@@ -1216,25 +1458,18 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
break;
case BT_REAL:
if (f->u.real.w == 0)
- write_real_g0 (dtp, p, kind, f->u.real.d);
+ write_real_g0 (dtp, p, kind, f->u.real.d);
else
write_d (dtp, f, p, kind);
break;
default:
- bad_type:
internal_error (&dtp->common,
"formatted_transfer(): Bad type");
- }
-
+ }
break;
case FMT_STRING:
consume_data_flag = 0;
- if (dtp->u.p.mode == READING)
- {
- format_error (dtp, f, "Constant string in input format");
- return;
- }
write_constant_string (dtp, f);
break;
@@ -1246,21 +1481,15 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
dtp->u.p.skips += f->u.n;
pos = bytes_used + dtp->u.p.skips - 1;
dtp->u.p.pending_spaces = pos - dtp->u.p.max_pos + 1;
-
/* Writes occur just before the switch on f->format, above, so
that trailing blanks are suppressed, unless we are doing a
non-advancing write in which case we want to output the blanks
now. */
- if (dtp->u.p.mode == WRITING
- && dtp->u.p.advance_status == ADVANCE_NO)
+ if (dtp->u.p.advance_status == ADVANCE_NO)
{
write_x (dtp, dtp->u.p.skips, dtp->u.p.pending_spaces);
dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
}
-
- if (dtp->u.p.mode == READING)
- read_x (dtp, f->u.n);
-
break;
case FMT_TL:
@@ -1282,12 +1511,7 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
pos = bytes_used - f->u.n;
}
else /* FMT_T */
- {
- if (dtp->u.p.mode == READING)
- pos = f->u.n - 1;
- else
- pos = f->u.n - dtp->u.p.pending_spaces - 1;
- }
+ pos = f->u.n - dtp->u.p.pending_spaces - 1;
/* Standard 10.6.1.1: excessive left tabbing is reset to the
left tab limit. We do not check if the position has gone
@@ -1300,43 +1524,6 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
+ pos - dtp->u.p.max_pos;
dtp->u.p.pending_spaces = dtp->u.p.pending_spaces < 0
? 0 : dtp->u.p.pending_spaces;
-
- if (dtp->u.p.skips == 0)
- break;
-
- /* Writes occur just before the switch on f->format, above, so that
- trailing blanks are suppressed. */
- if (dtp->u.p.mode == READING)
- {
- /* Adjust everything for end-of-record condition */
- if (dtp->u.p.sf_seen_eor && !is_internal_unit (dtp))
- {
- if (dtp->u.p.sf_seen_eor == 2)
- {
- /* The EOR was a CRLF (two bytes wide). */
- dtp->u.p.current_unit->bytes_left -= 2;
- dtp->u.p.skips -= 2;
- }
- else
- {
- /* The EOR marker was only one byte wide. */
- dtp->u.p.current_unit->bytes_left--;
- dtp->u.p.skips--;
- }
- bytes_used = pos;
- dtp->u.p.sf_seen_eor = 0;
- }
- if (dtp->u.p.skips < 0)
- {
- move_pos_offset (dtp->u.p.current_unit->s, dtp->u.p.skips);
- dtp->u.p.current_unit->bytes_left
- -= (gfc_offset) dtp->u.p.skips;
- dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
- }
- else
- read_x (dtp, dtp->u.p.skips);
- }
-
break;
case FMT_S:
@@ -1404,30 +1591,16 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
internal_error (&dtp->common, "Bad format node");
}
- /* Free a buffer that we had to allocate during a sequential
- formatted read of a block that was larger than the static
- buffer. */
-
- if (dtp->u.p.line_buffer != scratch)
- {
- free_mem (dtp->u.p.line_buffer);
- dtp->u.p.line_buffer = scratch;
- }
-
/* Adjust the item count and data pointer. */
if ((consume_data_flag > 0) && (n > 0))
- {
- n--;
- p = ((char *) p) + size;
- }
-
- if (dtp->u.p.mode == READING)
- dtp->u.p.skips = 0;
+ {
+ n--;
+ p = ((char *) p) + size;
+ }
pos = (int)(dtp->u.p.current_unit->recl - dtp->u.p.current_unit->bytes_left);
dtp->u.p.max_pos = (dtp->u.p.max_pos > pos) ? dtp->u.p.max_pos : pos;
-
}
return;
@@ -1439,6 +1612,7 @@ formatted_transfer_scalar (st_parameter_dt *dtp, bt type, void *p, int kind,
unget_format (dtp, f);
}
+
static void
formatted_transfer (st_parameter_dt *dtp, bt type, void *p, int kind,
size_t size, size_t nelems)
@@ -1449,16 +1623,27 @@ formatted_transfer (st_parameter_dt *dtp, bt type, void *p, int kind,
tmp = (char *) p;
size_t stride = type == BT_CHARACTER ?
size * GFC_SIZE_OF_CHAR_KIND(kind) : size;
- /* Big loop over all the elements. */
- for (elem = 0; elem < nelems; elem++)
+ if (dtp->u.p.mode == READING)
{
- dtp->u.p.item_count++;
- formatted_transfer_scalar (dtp, type, tmp + stride*elem, kind, size);
+ /* Big loop over all the elements. */
+ for (elem = 0; elem < nelems; elem++)
+ {
+ dtp->u.p.item_count++;
+ formatted_transfer_scalar_read (dtp, type, tmp + stride*elem, kind, size);
+ }
+ }
+ else
+ {
+ /* Big loop over all the elements. */
+ for (elem = 0; elem < nelems; elem++)
+ {
+ dtp->u.p.item_count++;
+ formatted_transfer_scalar_write (dtp, type, tmp + stride*elem, kind, size);
+ }
}
}
-
/* Data transfer entry points. The type of the data entity is
implicit in the subroutine call. This prevents us from having to
share a common enum with the compiler. */
@@ -1652,34 +1837,28 @@ transfer_array (st_parameter_dt *dtp, gfc_array_char *desc, int kind,
static void
us_read (st_parameter_dt *dtp, int continued)
{
- size_t n, nr;
+ ssize_t n, nr;
GFC_INTEGER_4 i4;
GFC_INTEGER_8 i8;
gfc_offset i;
- if (dtp->u.p.current_unit->endfile == AT_ENDFILE)
- return;
-
if (compile_options.record_marker == 0)
n = sizeof (GFC_INTEGER_4);
else
n = compile_options.record_marker;
- nr = n;
-
- if (unlikely (sread (dtp->u.p.current_unit->s, &i, &n) != 0))
+ nr = sread (dtp->u.p.current_unit->s, &i, n);
+ if (unlikely (nr < 0))
{
generate_error (&dtp->common, LIBERROR_BAD_US, NULL);
return;
}
-
- if (n == 0)
+ else if (nr == 0)
{
- dtp->u.p.current_unit->endfile = AT_ENDFILE;
+ hit_eof (dtp);
return; /* end of file */
}
-
- if (unlikely (n != nr))
+ else if (unlikely (n != nr))
{
generate_error (&dtp->common, LIBERROR_BAD_US, NULL);
return;
@@ -1745,7 +1924,7 @@ us_read (st_parameter_dt *dtp, int continued)
static void
us_write (st_parameter_dt *dtp, int continued)
{
- size_t nbytes;
+ ssize_t nbytes;
gfc_offset dummy;
dummy = 0;
@@ -1755,7 +1934,7 @@ us_write (st_parameter_dt *dtp, int continued)
else
nbytes = compile_options.record_marker ;
- if (swrite (dtp->u.p.current_unit->s, &dummy, &nbytes) != 0)
+ if (swrite (dtp->u.p.current_unit->s, &dummy, nbytes) != nbytes)
generate_error (&dtp->common, LIBERROR_OS, NULL);
/* For sequential unformatted, if RECL= was not specified in the OPEN
@@ -1957,7 +2136,7 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
return;
}
- /* Check the record number. */
+ /* Check the record or position number. */
if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT
&& (cf & IOPARM_DT_HAS_REC) == 0)
@@ -2106,65 +2285,70 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
if (dtp->u.p.current_unit->pad_status == PAD_UNSPECIFIED)
dtp->u.p.current_unit->pad_status = dtp->u.p.current_unit->flags.pad;
-
+
+ /* Check to see if we might be reading what we wrote before */
+
+ if (dtp->u.p.mode != dtp->u.p.current_unit->mode
+ && !is_internal_unit (dtp))
+ {
+ int pos = fbuf_reset (dtp->u.p.current_unit);
+ if (pos != 0)
+ sseek (dtp->u.p.current_unit->s, pos, SEEK_CUR);
+ sflush(dtp->u.p.current_unit->s);
+ }
+
/* Check the POS= specifier: that it is in range and that it is used with a
unit that has been connected for STREAM access. F2003 9.5.1.10. */
if (((cf & IOPARM_DT_HAS_POS) != 0))
{
if (is_stream_io (dtp))
- {
-
- if (dtp->pos <= 0)
- {
- generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "POS=specifier must be positive");
- return;
- }
-
- if (dtp->pos >= dtp->u.p.current_unit->maxrec)
- {
- generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "POS=specifier too large");
- return;
- }
-
- dtp->rec = dtp->pos;
-
- if (dtp->u.p.mode == READING)
- {
- /* Required for compatibility between 4.3 and 4.4 runtime. Check
- to see if we might be reading what we wrote before */
- if (dtp->u.p.current_unit->mode == WRITING)
- {
- fbuf_flush (dtp->u.p.current_unit, 1);
- flush(dtp->u.p.current_unit->s);
- }
-
- if (dtp->pos < file_length (dtp->u.p.current_unit->s))
- dtp->u.p.current_unit->endfile = NO_ENDFILE;
- }
-
- if (dtp->pos != dtp->u.p.current_unit->strm_pos)
- {
- fbuf_flush (dtp->u.p.current_unit, 1);
- flush (dtp->u.p.current_unit->s);
- if (sseek (dtp->u.p.current_unit->s, dtp->pos - 1) == FAILURE)
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return;
- }
- dtp->u.p.current_unit->strm_pos = dtp->pos;
- }
- }
+ {
+
+ if (dtp->pos <= 0)
+ {
+ generate_error (&dtp->common, LIBERROR_BAD_OPTION,
+ "POS=specifier must be positive");
+ return;
+ }
+
+ if (dtp->pos >= dtp->u.p.current_unit->maxrec)
+ {
+ generate_error (&dtp->common, LIBERROR_BAD_OPTION,
+ "POS=specifier too large");
+ return;
+ }
+
+ dtp->rec = dtp->pos;
+
+ if (dtp->u.p.mode == READING)
+ {
+ /* Reset the endfile flag; if we hit EOF during reading
+ we'll set the flag and generate an error at that point
+ rather than worrying about it here. */
+ dtp->u.p.current_unit->endfile = NO_ENDFILE;
+ }
+
+ if (dtp->pos != dtp->u.p.current_unit->strm_pos)
+ {
+ fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
+ if (sseek (dtp->u.p.current_unit->s, dtp->pos - 1, SEEK_SET) < 0)
+ {
+ generate_error (&dtp->common, LIBERROR_OS, NULL);
+ return;
+ }
+ dtp->u.p.current_unit->strm_pos = dtp->pos;
+ }
+ }
else
- {
- generate_error (&dtp->common, LIBERROR_BAD_OPTION,
- "POS=specifier not allowed, "
- "Try OPEN with ACCESS='stream'");
- return;
- }
+ {
+ generate_error (&dtp->common, LIBERROR_BAD_OPTION,
+ "POS=specifier not allowed, "
+ "Try OPEN with ACCESS='stream'");
+ return;
+ }
}
+
/* Sanity checks on the record number. */
if ((cf & IOPARM_DT_HAS_REC) != 0)
@@ -2183,15 +2367,10 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
return;
}
- /* Check to see if we might be reading what we wrote before */
+ /* Make sure format buffer is reset. */
+ if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED)
+ fbuf_reset (dtp->u.p.current_unit);
- if (dtp->u.p.mode == READING
- && dtp->u.p.current_unit->mode == WRITING
- && !is_internal_unit (dtp))
- {
- fbuf_flush (dtp->u.p.current_unit, 1);
- flush(dtp->u.p.current_unit->s);
- }
/* Check whether the record exists to be read. Only
a partial record needs to exist. */
@@ -2206,37 +2385,28 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
/* Position the file. */
if (sseek (dtp->u.p.current_unit->s, (gfc_offset) (dtp->rec - 1)
- * dtp->u.p.current_unit->recl) == FAILURE)
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return;
- }
+ * dtp->u.p.current_unit->recl, SEEK_SET) < 0)
+ {
+ generate_error (&dtp->common, LIBERROR_OS, NULL);
+ return;
+ }
/* TODO: This is required to maintain compatibility between
- 4.3 and 4.4 runtime. Remove when ABI changes from 4.3 */
+ 4.3 and 4.4 runtime. Remove when ABI changes from 4.3 */
if (is_stream_io (dtp))
- dtp->u.p.current_unit->strm_pos = dtp->rec;
-
+ dtp->u.p.current_unit->strm_pos = dtp->rec;
+
/* TODO: Un-comment this code when ABI changes from 4.3.
if (dtp->u.p.current_unit->flags.access == ACCESS_STREAM)
- {
- generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
- "Record number not allowed for stream access "
- "data transfer");
- return;
- } */
-
+ {
+ generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
+ "Record number not allowed for stream access "
+ "data transfer");
+ return;
+ } */
}
- /* Overwriting an existing sequential file ?
- it is always safe to truncate the file on the first write */
- if (dtp->u.p.mode == WRITING
- && dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL
- && dtp->u.p.current_unit->last_record == 0
- && !is_preconnected(dtp->u.p.current_unit->s))
- struncate(dtp->u.p.current_unit->s);
-
/* Bugware for badly written mixed C-Fortran I/O. */
flush_if_preconnected(dtp->u.p.current_unit->s);
@@ -2387,11 +2557,10 @@ next_array_record (st_parameter_dt *dtp, array_loop_spec *ls, int *finished)
position. */
static void
-skip_record (st_parameter_dt *dtp, size_t bytes)
+skip_record (st_parameter_dt *dtp, ssize_t bytes)
{
- gfc_offset new;
- size_t rlength;
- static const size_t MAX_READ = 4096;
+ ssize_t rlength, readb;
+ static const ssize_t MAX_READ = 4096;
char p[MAX_READ];
dtp->u.p.current_unit->bytes_left_subrecord += bytes;
@@ -2400,12 +2569,10 @@ skip_record (st_parameter_dt *dtp, size_t bytes)
if (is_seekable (dtp->u.p.current_unit->s))
{
- new = file_position (dtp->u.p.current_unit->s)
- + dtp->u.p.current_unit->bytes_left_subrecord;
-
/* Direct access files do not generate END conditions,
only I/O errors. */
- if (sseek (dtp->u.p.current_unit->s, new) == FAILURE)
+ if (sseek (dtp->u.p.current_unit->s,
+ dtp->u.p.current_unit->bytes_left_subrecord, SEEK_CUR) < 0)
generate_error (&dtp->common, LIBERROR_OS, NULL);
}
else
@@ -2413,16 +2580,17 @@ skip_record (st_parameter_dt *dtp, size_t bytes)
while (dtp->u.p.current_unit->bytes_left_subrecord > 0)
{
rlength =
- (MAX_READ > (size_t) dtp->u.p.current_unit->bytes_left_subrecord) ?
- MAX_READ : (size_t) dtp->u.p.current_unit->bytes_left_subrecord;
+ (MAX_READ < dtp->u.p.current_unit->bytes_left_subrecord) ?
+ MAX_READ : dtp->u.p.current_unit->bytes_left_subrecord;
- if (sread (dtp->u.p.current_unit->s, p, &rlength) != 0)
+ readb = sread (dtp->u.p.current_unit->s, p, rlength);
+ if (readb < 0)
{
generate_error (&dtp->common, LIBERROR_OS, NULL);
return;
}
- dtp->u.p.current_unit->bytes_left_subrecord -= rlength;
+ dtp->u.p.current_unit->bytes_left_subrecord -= readb;
}
}
@@ -2470,8 +2638,8 @@ next_record_r (st_parameter_dt *dtp)
{
gfc_offset record;
int bytes_left;
- size_t length;
char p;
+ int cc;
switch (current_mode (dtp))
{
@@ -2491,11 +2659,12 @@ next_record_r (st_parameter_dt *dtp)
case FORMATTED_STREAM:
case FORMATTED_SEQUENTIAL:
- length = 1;
- /* sf_read has already terminated input because of an '\n' */
- if (dtp->u.p.sf_seen_eor)
+ /* read_sf has already terminated input because of an '\n', or
+ we have hit EOF. */
+ if (dtp->u.p.sf_seen_eor || dtp->u.p.at_eof)
{
dtp->u.p.sf_seen_eor = 0;
+ dtp->u.p.at_eof = 0;
break;
}
@@ -2510,7 +2679,7 @@ next_record_r (st_parameter_dt *dtp)
/* Now seek to this record. */
record = record * dtp->u.p.current_unit->recl;
- if (sseek (dtp->u.p.current_unit->s, record) == FAILURE)
+ if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
{
generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
break;
@@ -2522,10 +2691,9 @@ next_record_r (st_parameter_dt *dtp)
bytes_left = (int) dtp->u.p.current_unit->bytes_left;
bytes_left = min_off (bytes_left,
file_length (dtp->u.p.current_unit->s)
- - file_position (dtp->u.p.current_unit->s));
+ - stell (dtp->u.p.current_unit->s));
if (sseek (dtp->u.p.current_unit->s,
- file_position (dtp->u.p.current_unit->s)
- + bytes_left) == FAILURE)
+ bytes_left, SEEK_CUR) < 0)
{
generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
break;
@@ -2535,42 +2703,37 @@ next_record_r (st_parameter_dt *dtp)
}
break;
}
- else do
+ else
{
- if (sread (dtp->u.p.current_unit->s, &p, &length) != 0)
+ do
{
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- break;
- }
-
- if (length == 0)
- {
- dtp->u.p.current_unit->endfile = AT_ENDFILE;
- break;
+ errno = 0;
+ cc = fbuf_getc (dtp->u.p.current_unit);
+ if (cc == EOF)
+ {
+ if (errno != 0)
+ generate_error (&dtp->common, LIBERROR_OS, NULL);
+ else
+ hit_eof (dtp);
+ break;
+ }
+
+ if (is_stream_io (dtp))
+ dtp->u.p.current_unit->strm_pos++;
+
+ p = (char) cc;
}
-
- if (is_stream_io (dtp))
- dtp->u.p.current_unit->strm_pos++;
+ while (p != '\n');
}
- while (p != '\n');
-
break;
}
-
- if (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL
- && !dtp->u.p.namelist_mode
- && dtp->u.p.current_unit->endfile == NO_ENDFILE
- && (file_length (dtp->u.p.current_unit->s) ==
- file_position (dtp->u.p.current_unit->s)))
- dtp->u.p.current_unit->endfile = AT_ENDFILE;
-
}
/* Small utility function to write a record marker, taking care of
byte swapping and of choosing the correct size. */
-inline static int
+static int
write_us_marker (st_parameter_dt *dtp, const gfc_offset buf)
{
size_t len;
@@ -2590,12 +2753,12 @@ write_us_marker (st_parameter_dt *dtp, const gfc_offset buf)
{
case sizeof (GFC_INTEGER_4):
buf4 = buf;
- return swrite (dtp->u.p.current_unit->s, &buf4, &len);
+ return swrite (dtp->u.p.current_unit->s, &buf4, len);
break;
case sizeof (GFC_INTEGER_8):
buf8 = buf;
- return swrite (dtp->u.p.current_unit->s, &buf8, &len);
+ return swrite (dtp->u.p.current_unit->s, &buf8, len);
break;
default:
@@ -2610,13 +2773,13 @@ write_us_marker (st_parameter_dt *dtp, const gfc_offset buf)
case sizeof (GFC_INTEGER_4):
buf4 = buf;
reverse_memcpy (p, &buf4, sizeof (GFC_INTEGER_4));
- return swrite (dtp->u.p.current_unit->s, p, &len);
+ return swrite (dtp->u.p.current_unit->s, p, len);
break;
case sizeof (GFC_INTEGER_8):
buf8 = buf;
reverse_memcpy (p, &buf8, sizeof (GFC_INTEGER_8));
- return swrite (dtp->u.p.current_unit->s, p, &len);
+ return swrite (dtp->u.p.current_unit->s, p, len);
break;
default:
@@ -2633,13 +2796,11 @@ write_us_marker (st_parameter_dt *dtp, const gfc_offset buf)
static void
next_record_w_unf (st_parameter_dt *dtp, int next_subrecord)
{
- gfc_offset c, m, m_write;
- size_t record_marker;
+ gfc_offset m, m_write, record_marker;
/* Bytes written. */
m = dtp->u.p.current_unit->recl_subrecord
- dtp->u.p.current_unit->bytes_left_subrecord;
- c = file_position (dtp->u.p.current_unit->s);
/* Write the length tail. If we finish a record containing
subrecords, we write out the negative length. */
@@ -2649,7 +2810,7 @@ next_record_w_unf (st_parameter_dt *dtp, int next_subrecord)
else
m_write = m;
- if (unlikely (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)
@@ -2660,8 +2821,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 (unlikely (sseek (dtp->u.p.current_unit->s, c - m - record_marker)
- == FAILURE))
+ if (unlikely (sseek (dtp->u.p.current_unit->s, - m - 2 * record_marker,
+ SEEK_CUR) < 0))
goto io_error;
if (next_subrecord)
@@ -2669,13 +2830,13 @@ next_record_w_unf (st_parameter_dt *dtp, int next_subrecord)
else
m_write = m;
- if (unlikely (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 (unlikely (sseek (dtp->u.p.current_unit->s, c + record_marker)
- == FAILURE))
+ if (unlikely (sseek (dtp->u.p.current_unit->s, m + record_marker,
+ SEEK_CUR) < 0))
goto io_error;
return;
@@ -2686,6 +2847,35 @@ next_record_w_unf (st_parameter_dt *dtp, int next_subrecord)
}
+
+/* Utility function like memset() but operating on streams. Return
+ value is same as for POSIX write(). */
+
+static ssize_t
+sset (stream * s, int c, ssize_t nbyte)
+{
+ static const int WRITE_CHUNK = 256;
+ char p[WRITE_CHUNK];
+ ssize_t bytes_left, trans;
+
+ if (nbyte < WRITE_CHUNK)
+ memset (p, c, nbyte);
+ else
+ memset (p, c, WRITE_CHUNK);
+
+ bytes_left = nbyte;
+ while (bytes_left > 0)
+ {
+ trans = (bytes_left < WRITE_CHUNK) ? bytes_left : WRITE_CHUNK;
+ trans = swrite (s, p, trans);
+ if (trans < 0)
+ return trans;
+ bytes_left -= trans;
+ }
+
+ return nbyte - bytes_left;
+}
+
/* Position to the next record in write mode. */
static void
@@ -2694,9 +2884,6 @@ next_record_w (st_parameter_dt *dtp, int done)
gfc_offset m, record, max_pos;
int length;
- /* Flush and reset the format buffer. */
- fbuf_flush (dtp->u.p.current_unit, 1);
-
/* Zero counters for X- and T-editing. */
max_pos = dtp->u.p.max_pos;
dtp->u.p.max_pos = dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
@@ -2711,8 +2898,11 @@ next_record_w (st_parameter_dt *dtp, int done)
if (dtp->u.p.current_unit->bytes_left == 0)
break;
+ fbuf_seek (dtp->u.p.current_unit, 0, SEEK_END);
+ fbuf_flush (dtp->u.p.current_unit, WRITING);
if (sset (dtp->u.p.current_unit->s, ' ',
- dtp->u.p.current_unit->bytes_left) == FAILURE)
+ dtp->u.p.current_unit->bytes_left)
+ != dtp->u.p.current_unit->bytes_left)
goto io_error;
break;
@@ -2721,7 +2911,7 @@ next_record_w (st_parameter_dt *dtp, int done)
if (dtp->u.p.current_unit->bytes_left > 0)
{
length = (int) dtp->u.p.current_unit->bytes_left;
- if (sset (dtp->u.p.current_unit->s, 0, length) == FAILURE)
+ if (sset (dtp->u.p.current_unit->s, 0, length) != length)
goto io_error;
}
break;
@@ -2752,8 +2942,7 @@ next_record_w (st_parameter_dt *dtp, int done)
{
length = (int) (max_pos - m);
if (sseek (dtp->u.p.current_unit->s,
- file_position (dtp->u.p.current_unit->s)
- + length) == FAILURE)
+ length, SEEK_CUR) < 0)
{
generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
return;
@@ -2761,7 +2950,7 @@ next_record_w (st_parameter_dt *dtp, int done)
length = (int) (dtp->u.p.current_unit->recl - max_pos);
}
- if (sset (dtp->u.p.current_unit->s, ' ', length) == FAILURE)
+ if (sset (dtp->u.p.current_unit->s, ' ', length) != length)
{
generate_error (&dtp->common, LIBERROR_END, NULL);
return;
@@ -2777,7 +2966,7 @@ next_record_w (st_parameter_dt *dtp, int done)
/* Now seek to this record */
record = record * dtp->u.p.current_unit->recl;
- if (sseek (dtp->u.p.current_unit->s, record) == FAILURE)
+ if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
{
generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
return;
@@ -2800,8 +2989,7 @@ next_record_w (st_parameter_dt *dtp, int done)
{
length = (int) (max_pos - m);
if (sseek (dtp->u.p.current_unit->s,
- file_position (dtp->u.p.current_unit->s)
- + length) == FAILURE)
+ length, SEEK_CUR) < 0)
{
generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
return;
@@ -2812,7 +3000,7 @@ next_record_w (st_parameter_dt *dtp, int done)
length = (int) dtp->u.p.current_unit->bytes_left;
}
- if (sset (dtp->u.p.current_unit->s, ' ', length) == FAILURE)
+ if (sset (dtp->u.p.current_unit->s, ' ', length) != length)
{
generate_error (&dtp->common, LIBERROR_END, NULL);
return;
@@ -2821,23 +3009,27 @@ next_record_w (st_parameter_dt *dtp, int done)
}
else
{
- size_t len;
- const char crlf[] = "\r\n";
-
#ifdef HAVE_CRLF
- len = 2;
+ const int len = 2;
#else
- len = 1;
+ const int len = 1;
#endif
- if (swrite (dtp->u.p.current_unit->s, &crlf[2-len], &len) != 0)
- goto io_error;
-
+ fbuf_seek (dtp->u.p.current_unit, 0, SEEK_END);
+ char * p = fbuf_alloc (dtp->u.p.current_unit, len);
+ if (!p)
+ goto io_error;
+#ifdef HAVE_CRLF
+ *(p++) = '\r';
+#endif
+ *p = '\n';
if (is_stream_io (dtp))
{
dtp->u.p.current_unit->strm_pos += len;
if (dtp->u.p.current_unit->strm_pos
< file_length (dtp->u.p.current_unit->s))
- struncate (dtp->u.p.current_unit->s);
+ unit_truncate (dtp->u.p.current_unit,
+ dtp->u.p.current_unit->strm_pos - 1,
+ &dtp->common);
}
}
@@ -2875,7 +3067,7 @@ next_record (st_parameter_dt *dtp, int done)
dtp->u.p.current_unit->current_record = 0;
if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
{
- fp = file_position (dtp->u.p.current_unit->s);
+ fp = stell (dtp->u.p.current_unit->s);
/* Calculate next record, rounding up partial records. */
dtp->u.p.current_unit->last_record =
(fp + dtp->u.p.current_unit->recl - 1) /
@@ -2887,6 +3079,8 @@ next_record (st_parameter_dt *dtp, int done)
if (!done)
pre_position (dtp);
+
+ fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
}
@@ -2935,7 +3129,6 @@ finalize_transfer (st_parameter_dt *dtp)
if ((cf & IOPARM_DT_LIST_FORMAT) != 0 && dtp->u.p.mode == READING)
{
finish_list_read (dtp);
- sfree (dtp->u.p.current_unit->s);
return;
}
@@ -2949,12 +3142,6 @@ finalize_transfer (st_parameter_dt *dtp)
&& dtp->u.p.advance_status != ADVANCE_NO)
next_record (dtp, 1);
- if (dtp->u.p.current_unit->flags.form == FORM_UNFORMATTED
- && file_position (dtp->u.p.current_unit->s) >= dtp->rec)
- {
- flush (dtp->u.p.current_unit->s);
- sfree (dtp->u.p.current_unit->s);
- }
return;
}
@@ -2962,9 +3149,8 @@ finalize_transfer (st_parameter_dt *dtp)
if (!is_internal_unit (dtp) && dtp->u.p.seen_dollar)
{
+ fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
dtp->u.p.seen_dollar = 0;
- fbuf_flush (dtp->u.p.current_unit, 1);
- sfree (dtp->u.p.current_unit->s);
return;
}
@@ -2976,15 +3162,16 @@ finalize_transfer (st_parameter_dt *dtp)
- dtp->u.p.current_unit->bytes_left);
dtp->u.p.current_unit->saved_pos =
dtp->u.p.max_pos > 0 ? dtp->u.p.max_pos - bytes_written : 0;
- fbuf_flush (dtp->u.p.current_unit, 0);
- flush (dtp->u.p.current_unit->s);
+ fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode);
return;
}
+ else if (dtp->u.p.current_unit->flags.form == FORM_FORMATTED
+ && dtp->u.p.mode == WRITING && !is_internal_unit (dtp))
+ fbuf_seek (dtp->u.p.current_unit, 0, SEEK_END);
dtp->u.p.current_unit->saved_pos = 0;
next_record (dtp, 1);
- sfree (dtp->u.p.current_unit->s);
}
/* Transfer function for IOLENGTH. It doesn't actually do any
@@ -2997,7 +3184,7 @@ iolength_transfer (st_parameter_dt *dtp, bt type __attribute__((unused)),
size_t size, size_t nelems)
{
if ((dtp->common.flags & IOPARM_DT_HAS_IOLENGTH) != 0)
- *dtp->iolength += (GFC_IO_INT) size * nelems;
+ *dtp->iolength += (GFC_IO_INT) (size * nelems);
}
@@ -3041,8 +3228,6 @@ void
st_iolength_done (st_parameter_dt *dtp __attribute__((unused)))
{
free_ionml (dtp);
- if (dtp->u.p.scratch != NULL)
- free_mem (dtp->u.p.scratch);
library_end ();
}
@@ -3058,29 +3243,6 @@ st_read (st_parameter_dt *dtp)
library_start (&dtp->common);
data_transfer_init (dtp, 1);
-
- /* Handle complications dealing with the endfile record. */
-
- if (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
- switch (dtp->u.p.current_unit->endfile)
- {
- case NO_ENDFILE:
- break;
-
- case AT_ENDFILE:
- if (!is_internal_unit (dtp))
- {
- generate_error (&dtp->common, LIBERROR_END, NULL);
- dtp->u.p.current_unit->endfile = AFTER_ENDFILE;
- dtp->u.p.current_unit->current_record = 0;
- }
- break;
-
- case AFTER_ENDFILE:
- generate_error (&dtp->common, LIBERROR_ENDFILE, NULL);
- dtp->u.p.current_unit->current_record = 0;
- break;
- }
}
extern void st_read_done (st_parameter_dt *);
@@ -3092,8 +3254,6 @@ st_read_done (st_parameter_dt *dtp)
finalize_transfer (dtp);
free_format_data (dtp);
free_ionml (dtp);
- if (dtp->u.p.scratch != NULL)
- free_mem (dtp->u.p.scratch);
if (dtp->u.p.current_unit != NULL)
unlock_unit (dtp->u.p.current_unit);
@@ -3136,19 +3296,15 @@ st_write_done (st_parameter_dt *dtp)
case NO_ENDFILE:
/* Get rid of whatever is after this record. */
if (!is_internal_unit (dtp))
- {
- flush (dtp->u.p.current_unit->s);
- if (struncate (dtp->u.p.current_unit->s) == FAILURE)
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- }
+ unit_truncate (dtp->u.p.current_unit,
+ stell (dtp->u.p.current_unit->s),
+ &dtp->common);
dtp->u.p.current_unit->endfile = AT_ENDFILE;
break;
}
free_format_data (dtp);
free_ionml (dtp);
- if (dtp->u.p.scratch != NULL)
- free_mem (dtp->u.p.scratch);
if (dtp->u.p.current_unit != NULL)
unlock_unit (dtp->u.p.current_unit);
@@ -3262,3 +3418,46 @@ void reverse_memcpy (void *dest, const void *src, size_t n)
for (i=0; i<n; i++)
*(d++) = *(s--);
}
+
+
+/* Once upon a time, a poor innocent Fortran program was reading a
+ file, when suddenly it hit the end-of-file (EOF). Unfortunately
+ the OS doesn't tell whether we're at the EOF or whether we already
+ went past it. Luckily our hero, libgfortran, keeps track of this.
+ Call this function when you detect an EOF condition. See Section
+ 9.10.2 in F2003. */
+
+void
+hit_eof (st_parameter_dt * dtp)
+{
+ dtp->u.p.current_unit->flags.position = POSITION_APPEND;
+
+ if (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL)
+ switch (dtp->u.p.current_unit->endfile)
+ {
+ case NO_ENDFILE:
+ case AT_ENDFILE:
+ generate_error (&dtp->common, LIBERROR_END, NULL);
+ if (!is_internal_unit (dtp))
+ {
+ dtp->u.p.current_unit->endfile = AFTER_ENDFILE;
+ dtp->u.p.current_unit->current_record = 0;
+ }
+ else
+ dtp->u.p.current_unit->endfile = AT_ENDFILE;
+ break;
+
+ case AFTER_ENDFILE:
+ generate_error (&dtp->common, LIBERROR_ENDFILE, NULL);
+ dtp->u.p.current_unit->current_record = 0;
+ break;
+ }
+ else
+ {
+ /* Non-sequential files don't have an ENDFILE record, so we
+ can't be at AFTER_ENDFILE. */
+ dtp->u.p.current_unit->endfile = AT_ENDFILE;
+ generate_error (&dtp->common, LIBERROR_END, NULL);
+ dtp->u.p.current_unit->current_record = 0;
+ }
+}
diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c
index 98f525541c6..b6985378395 100644
--- a/libgfortran/io/unit.c
+++ b/libgfortran/io/unit.c
@@ -535,6 +535,8 @@ init_units (void)
u->file_len = strlen (stdin_name);
u->file = get_mem (u->file_len);
memmove (u->file, stdin_name, u->file_len);
+
+ fbuf_init (u, 0);
__gthread_mutex_unlock (&u->lock);
}
@@ -619,7 +621,7 @@ close_unit_1 (gfc_unit *u, int locked)
if (u->previous_nonadvancing_write)
finish_last_advance_record (u);
- rc = (u->s == NULL) ? 0 : sclose (u->s) == FAILURE;
+ rc = (u->s == NULL) ? 0 : sclose (u->s) == -1;
u->closed = 1;
if (!locked)
@@ -635,7 +637,7 @@ close_unit_1 (gfc_unit *u, int locked)
free_mem (u->file);
u->file = NULL;
u->file_len = 0;
-
+
fbuf_destroy (u);
if (!locked)
@@ -692,15 +694,62 @@ close_units (void)
void
update_position (gfc_unit *u)
{
- if (file_position (u->s) == 0)
+ if (stell (u->s) == 0)
u->flags.position = POSITION_REWIND;
- else if (file_length (u->s) == file_position (u->s))
+ else if (file_length (u->s) == stell (u->s))
u->flags.position = POSITION_APPEND;
else
u->flags.position = POSITION_ASIS;
}
+/* High level interface to truncate a file safely, i.e. flush format
+ buffers, check that it's a regular file, and generate error if that
+ occurs. Just like POSIX ftruncate, returns 0 on success, -1 on
+ failure. */
+
+int
+unit_truncate (gfc_unit * u, gfc_offset pos, st_parameter_common * common)
+{
+ int ret;
+
+ /* Make sure format buffer is flushed. */
+ if (u->flags.form == FORM_FORMATTED)
+ {
+ if (u->mode == READING)
+ pos += fbuf_reset (u);
+ else
+ fbuf_flush (u, u->mode);
+ }
+
+ /* Don't try to truncate a special file, just pretend that it
+ succeeds. */
+ if (is_special (u->s) || !is_seekable (u->s))
+ {
+ sflush (u->s);
+ return 0;
+ }
+
+ /* struncate() should flush the stream buffer if necessary, so don't
+ bother calling sflush() here. */
+ ret = struncate (u->s, pos);
+
+ if (ret != 0)
+ {
+ generate_error (common, LIBERROR_OS, NULL);
+ u->endfile = NO_ENDFILE;
+ u->flags.position = POSITION_ASIS;
+ }
+ else
+ {
+ u->endfile = AT_ENDFILE;
+ u->flags.position = POSITION_APPEND;
+ }
+
+ return ret;
+}
+
+
/* filename_from_unit()-- If the unit_number exists, return a pointer to the
name of the associated file, otherwise return the empty string. The caller
must free memory allocated for the filename string. */
@@ -741,23 +790,25 @@ finish_last_advance_record (gfc_unit *u)
{
if (u->saved_pos > 0)
- fbuf_seek (u, u->saved_pos);
-
- fbuf_flush (u, 1);
+ fbuf_seek (u, u->saved_pos, SEEK_CUR);
if (!(u->unit_number == options.stdout_unit
|| u->unit_number == options.stderr_unit))
{
- size_t len;
-
- const char crlf[] = "\r\n";
#ifdef HAVE_CRLF
- len = 2;
+ const int len = 2;
#else
- len = 1;
+ const int len = 1;
#endif
- if (swrite (u->s, &crlf[2-len], &len) != 0)
+ char *p = fbuf_alloc (u, len);
+ if (!p)
os_error ("Completing record after ADVANCE_NO failed");
+#ifdef HAVE_CRLF
+ *(p++) = '\r';
+#endif
+ *p = '\n';
}
+
+ fbuf_flush (u, u->mode);
}
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index b3222f22c12..a7eb4e36ae5 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -89,10 +89,6 @@ id_from_fd (const int fd)
#endif
-#ifndef SSIZE_MAX
-#define SSIZE_MAX SHRT_MAX
-#endif
-
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
@@ -124,128 +120,30 @@ id_from_fd (const int fd)
#endif
-/* Unix stream I/O module */
+/* Unix and internal stream I/O module */
-#define BUFFER_SIZE 8192
+static const int BUFFER_SIZE = 8192;
typedef struct
{
stream st;
- int fd;
gfc_offset buffer_offset; /* File offset of the start of the buffer */
gfc_offset physical_offset; /* Current physical file offset */
gfc_offset logical_offset; /* Current logical file offset */
- gfc_offset dirty_offset; /* Start of modified bytes in buffer */
gfc_offset file_length; /* Length of the file, -1 if not seekable. */
- int len; /* Physical length of the current buffer */
- int active; /* Length of valid bytes in the buffer */
-
- int prot;
- int ndirty; /* Dirty bytes starting at dirty_offset */
-
- int special_file; /* =1 if the fd refers to a special file */
-
- io_mode method; /* Method of stream I/O being used */
-
- char *buffer;
- char small_buffer[BUFFER_SIZE];
-}
-unix_stream;
-
-
-/* Stream structure for internal files. Fields must be kept in sync
- with unix_stream above, except for the buffer. For internal files
- we point the buffer pointer directly at the destination memory. */
-
-typedef struct
-{
- stream st;
+ char *buffer; /* Pointer to the buffer. */
+ int fd; /* The POSIX file descriptor. */
- int fd;
- gfc_offset buffer_offset; /* File offset of the start of the buffer */
- gfc_offset physical_offset; /* Current physical file offset */
- gfc_offset logical_offset; /* Current logical file offset */
- gfc_offset dirty_offset; /* Start of modified bytes in buffer */
- gfc_offset file_length; /* Length of the file, -1 if not seekable. */
-
- int len; /* Physical length of the current buffer */
int active; /* Length of valid bytes in the buffer */
int prot;
- int ndirty; /* Dirty bytes starting at dirty_offset */
+ int ndirty; /* Dirty bytes starting at buffer_offset */
int special_file; /* =1 if the fd refers to a special file */
-
- io_mode method; /* Method of stream I/O being used */
-
- char *buffer;
-}
-int_stream;
-
-/* This implementation of stream I/O is based on the paper:
- *
- * "Exploiting the advantages of mapped files for stream I/O",
- * O. Krieger, M. Stumm and R. Umrau, "Proceedings of the 1992 Winter
- * USENIX conference", p. 27-42.
- *
- * It differs in a number of ways from the version described in the
- * paper. First of all, threads are not an issue during I/O and we
- * also don't have to worry about having multiple regions, since
- * fortran's I/O model only allows you to be one place at a time.
- *
- * On the other hand, we have to be able to writing at the end of a
- * stream, read from the start of a stream or read and write blocks of
- * bytes from an arbitrary position. After opening a file, a pointer
- * to a stream structure is returned, which is used to handle file
- * accesses until the file is closed.
- *
- * salloc_at_r(stream, len, where)-- Given a stream pointer, return a
- * pointer to a block of memory that mirror the file at position
- * 'where' that is 'len' bytes long. The len integer is updated to
- * reflect how many bytes were actually read. The only reason for a
- * short read is end of file. The file pointer is updated. The
- * pointer is valid until the next call to salloc_*.
- *
- * salloc_at_w(stream, len, where)-- Given the stream pointer, returns
- * a pointer to a block of memory that is updated to reflect the state
- * of the file. The length of the buffer is always equal to that
- * requested. The buffer must be completely set by the caller. When
- * data has been written, the sfree() function must be called to
- * indicate that the caller is done writing data to the buffer. This
- * may or may not cause a physical write.
- *
- * Short forms of these are salloc_r() and salloc_w() which drop the
- * 'where' parameter and use the current file pointer. */
-
-
-/*move_pos_offset()-- Move the record pointer right or left
- *relative to current position */
-
-int
-move_pos_offset (stream* st, int pos_off)
-{
- unix_stream * str = (unix_stream*)st;
- if (pos_off < 0)
- {
- str->logical_offset += pos_off;
-
- if (str->dirty_offset + str->ndirty > str->logical_offset)
- {
- if (str->ndirty + pos_off > 0)
- str->ndirty += pos_off;
- else
- {
- str->dirty_offset += pos_off + pos_off;
- str->ndirty = 0;
- }
- }
-
- return pos_off;
- }
- return 0;
}
+unix_stream;
/* fix_fd()-- Given a file descriptor, make sure it is not one of the
@@ -292,17 +190,6 @@ fix_fd (int fd)
return fd;
}
-int
-is_preconnected (stream * s)
-{
- int fd;
-
- fd = ((unix_stream *) s)->fd;
- if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
- return 1;
- else
- return 0;
-}
/* If the stream corresponds to a preconnected unit, we flush the
corresponding C stream. This is bugware for mixed C-Fortran codes
@@ -322,580 +209,335 @@ flush_if_preconnected (stream * s)
}
-/* Reset a stream after reading/writing. Assumes that the buffers have
- been flushed. */
+/* get_oserror()-- Get the most recent operating system error. For
+ * unix, this is errno. */
-inline static void
-reset_stream (unix_stream * s, size_t bytes_rw)
+const char *
+get_oserror (void)
{
- s->physical_offset += bytes_rw;
- s->logical_offset = s->physical_offset;
- if (s->file_length != -1 && s->physical_offset > s->file_length)
- s->file_length = s->physical_offset;
+ return strerror (errno);
}
-/* Read bytes into a buffer, allowing for short reads. If the nbytes
- * argument is less on return than on entry, it is because we've hit
- * the end of file. */
+/********************************************************************
+Raw I/O functions (read, write, seek, tell, truncate, close).
+
+These functions wrap the basic POSIX I/O syscalls. Any deviation in
+semantics is a bug, except the following: write restarts in case
+of being interrupted by a signal, and as the first argument the
+functions take the unix_stream struct rather than an integer file
+descriptor. Also, for POSIX read() and write() a nbyte argument larger
+than SSIZE_MAX is undefined; here the type of nbyte is ssize_t rather
+than size_t as for POSIX read/write.
+*********************************************************************/
static int
-do_read (unix_stream * s, void * buf, size_t * nbytes)
+raw_flush (unix_stream * s __attribute__ ((unused)))
{
- ssize_t trans;
- size_t bytes_left;
- char *buf_st;
- int status;
-
- status = 0;
- bytes_left = *nbytes;
- buf_st = (char *) buf;
-
- /* We must read in a loop since some systems don't restart system
- calls in case of a signal. */
- while (bytes_left > 0)
- {
- /* Requests between SSIZE_MAX and SIZE_MAX are undefined by SUSv3,
- so we must read in chunks smaller than SSIZE_MAX. */
- trans = (bytes_left < SSIZE_MAX) ? bytes_left : SSIZE_MAX;
- trans = read (s->fd, buf_st, trans);
- if (trans < 0)
- {
- if (errno == EINTR)
- continue;
- else
- {
- status = errno;
- break;
- }
- }
- else if (trans == 0) /* We hit EOF. */
- break;
- buf_st += trans;
- bytes_left -= trans;
- }
-
- *nbytes -= bytes_left;
- return status;
+ return 0;
}
+static ssize_t
+raw_read (unix_stream * s, void * buf, ssize_t nbyte)
+{
+ /* For read we can't do I/O in a loop like raw_write does, because
+ that will break applications that wait for interactive I/O. */
+ return read (s->fd, buf, nbyte);
+}
-/* Write a buffer to a stream, allowing for short writes. */
-
-static int
-do_write (unix_stream * s, const void * buf, size_t * nbytes)
+static ssize_t
+raw_write (unix_stream * s, const void * buf, ssize_t nbyte)
{
- ssize_t trans;
- size_t bytes_left;
+ ssize_t trans, bytes_left;
char *buf_st;
- int status;
- status = 0;
- bytes_left = *nbytes;
+ bytes_left = nbyte;
buf_st = (char *) buf;
/* We must write in a loop since some systems don't restart system
calls in case of a signal. */
while (bytes_left > 0)
{
- /* Requests between SSIZE_MAX and SIZE_MAX are undefined by SUSv3,
- so we must write in chunks smaller than SSIZE_MAX. */
- trans = (bytes_left < SSIZE_MAX) ? bytes_left : SSIZE_MAX;
- trans = write (s->fd, buf_st, trans);
+ trans = write (s->fd, buf_st, bytes_left);
if (trans < 0)
{
if (errno == EINTR)
continue;
else
- {
- status = errno;
- break;
- }
+ return trans;
}
buf_st += trans;
bytes_left -= trans;
}
- *nbytes -= bytes_left;
- return status;
+ return nbyte - bytes_left;
}
+static off_t
+raw_seek (unix_stream * s, off_t offset, int whence)
+{
+ return lseek (s->fd, offset, whence);
+}
-/* get_oserror()-- Get the most recent operating system error. For
- * unix, this is errno. */
+static off_t
+raw_tell (unix_stream * s)
+{
+ return lseek (s->fd, 0, SEEK_CUR);
+}
-const char *
-get_oserror (void)
+static int
+raw_truncate (unix_stream * s, off_t length)
{
- return strerror (errno);
+#ifdef HAVE_FTRUNCATE
+ return ftruncate (s->fd, length);
+#elif defined HAVE_CHSIZE
+ return chsize (s->fd, length);
+#else
+ runtime_error ("required ftruncate or chsize support not present");
+ return -1;
+#endif
+}
+
+static int
+raw_close (unix_stream * s)
+{
+ int retval;
+
+ if (s->fd != STDOUT_FILENO
+ && s->fd != STDERR_FILENO
+ && s->fd != STDIN_FILENO)
+ retval = close (s->fd);
+ else
+ retval = 0;
+ free_mem (s);
+ return retval;
}
+static int
+raw_init (unix_stream * s)
+{
+ s->st.read = (void *) raw_read;
+ s->st.write = (void *) raw_write;
+ s->st.seek = (void *) raw_seek;
+ s->st.tell = (void *) raw_tell;
+ s->st.trunc = (void *) raw_truncate;
+ s->st.close = (void *) raw_close;
+ s->st.flush = (void *) raw_flush;
-/*********************************************************************
- File descriptor stream functions
-*********************************************************************/
+ s->buffer = NULL;
+ return 0;
+}
-/* fd_flush()-- Write bytes that need to be written */
+/*********************************************************************
+Buffered I/O functions. These functions have the same semantics as the
+raw I/O functions above, except that they are buffered in order to
+improve performance. The buffer must be flushed when switching from
+reading to writing and vice versa.
+*********************************************************************/
-static try
-fd_flush (unix_stream * s)
+static int
+buf_flush (unix_stream * s)
{
- size_t writelen;
+ int writelen;
+
+ /* Flushing in read mode means discarding read bytes. */
+ s->active = 0;
if (s->ndirty == 0)
- return SUCCESS;
+ return 0;
- if (s->file_length != -1 && s->physical_offset != s->dirty_offset &&
- lseek (s->fd, s->dirty_offset, SEEK_SET) < 0)
- return FAILURE;
+ if (s->file_length != -1 && s->physical_offset != s->buffer_offset
+ && lseek (s->fd, s->buffer_offset, SEEK_SET) < 0)
+ return -1;
- writelen = s->ndirty;
- if (do_write (s, s->buffer + (s->dirty_offset - s->buffer_offset),
- &writelen) != 0)
- return FAILURE;
+ writelen = raw_write (s, s->buffer, s->ndirty);
- s->physical_offset = s->dirty_offset + writelen;
+ s->physical_offset = s->buffer_offset + writelen;
- /* don't increment file_length if the file is non-seekable */
+ /* Don't increment file_length if the file is non-seekable. */
if (s->file_length != -1 && s->physical_offset > s->file_length)
- s->file_length = s->physical_offset;
+ s->file_length = s->physical_offset;
s->ndirty -= writelen;
if (s->ndirty != 0)
- return FAILURE;
+ return -1;
- return SUCCESS;
+ return 0;
}
-
-/* fd_alloc()-- Arrange a buffer such that the salloc() request can be
- * satisfied. This subroutine gets the buffer ready for whatever is
- * to come next. */
-
-static void
-fd_alloc (unix_stream * s, gfc_offset where,
- int *len __attribute__ ((unused)))
+static ssize_t
+buf_read (unix_stream * s, void * buf, ssize_t nbyte)
{
- char *new_buffer;
- int n, read_len;
+ if (s->active == 0)
+ s->buffer_offset = s->logical_offset;
- if (*len <= BUFFER_SIZE)
- {
- new_buffer = s->small_buffer;
- read_len = BUFFER_SIZE;
- }
+ /* Is the data we want in the buffer? */
+ if (s->logical_offset + nbyte <= s->buffer_offset + s->active
+ && s->buffer_offset <= s->logical_offset)
+ memcpy (buf, s->buffer + (s->logical_offset - s->buffer_offset), nbyte);
else
{
- new_buffer = get_mem (*len);
- read_len = *len;
- }
-
- /* Salvage bytes currently within the buffer. This is important for
- * devices that cannot seek. */
-
- if (s->buffer != NULL && s->buffer_offset <= where &&
- where <= s->buffer_offset + s->active)
- {
-
- n = s->active - (where - s->buffer_offset);
- memmove (new_buffer, s->buffer + (where - s->buffer_offset), n);
-
- s->active = n;
- }
- else
- { /* new buffer starts off empty */
- s->active = 0;
+ /* First copy the active bytes if applicable, then read the rest
+ either directly or filling the buffer. */
+ char *p;
+ int nread = 0;
+ ssize_t to_read, did_read;
+ gfc_offset new_logical;
+
+ p = (char *) buf;
+ if (s->logical_offset >= s->buffer_offset
+ && s->buffer_offset + s->active >= s->logical_offset)
+ {
+ nread = s->active - (s->logical_offset - s->buffer_offset);
+ memcpy (buf, s->buffer + (s->logical_offset - s->buffer_offset),
+ nread);
+ p += nread;
+ }
+ /* At this point we consider all bytes in the buffer discarded. */
+ to_read = nbyte - nread;
+ new_logical = s->logical_offset + nread;
+ if (s->file_length != -1 && s->physical_offset != new_logical
+ && lseek (s->fd, new_logical, SEEK_SET) < 0)
+ return -1;
+ s->buffer_offset = s->physical_offset = new_logical;
+ if (to_read <= BUFFER_SIZE/2)
+ {
+ did_read = raw_read (s, s->buffer, BUFFER_SIZE);
+ s->physical_offset += did_read;
+ s->active = did_read;
+ did_read = (did_read > to_read) ? to_read : did_read;
+ memcpy (p, s->buffer, did_read);
+ }
+ else
+ {
+ did_read = raw_read (s, p, to_read);
+ s->physical_offset += did_read;
+ s->active = 0;
+ }
+ nbyte = did_read + nread;
}
-
- s->buffer_offset = where;
-
- /* free the old buffer if necessary */
-
- if (s->buffer != NULL && s->buffer != s->small_buffer)
- free_mem (s->buffer);
-
- s->buffer = new_buffer;
- s->len = read_len;
+ s->logical_offset += nbyte;
+ return nbyte;
}
-
-/* fd_alloc_r_at()-- Allocate a stream buffer for reading. Either
- * we've already buffered the data or we need to load it. Returns
- * NULL on I/O error. */
-
-static char *
-fd_alloc_r_at (unix_stream * s, int *len)
+static ssize_t
+buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
{
- gfc_offset m;
- gfc_offset where = s->logical_offset;
-
- if (s->buffer != NULL && s->buffer_offset <= where &&
- where + *len <= s->buffer_offset + s->active)
- {
-
- /* Return a position within the current buffer */
-
- s->logical_offset = where + *len;
- return s->buffer + where - s->buffer_offset;
- }
-
- fd_alloc (s, where, len);
-
- m = where + s->active;
-
- if (s->physical_offset != m && lseek (s->fd, m, SEEK_SET) < 0)
- return NULL;
-
- /* do_read() hangs on read from terminals for *BSD-systems. Only
- use read() in that case. */
-
- if (s->special_file)
+ if (s->ndirty == 0)
+ s->buffer_offset = s->logical_offset;
+
+ /* Does the data fit into the buffer? As a special case, if the
+ buffer is empty and the request is bigger than BUFFER_SIZE/2,
+ write directly. This avoids the case where the buffer would have
+ to be flushed at every write. */
+ if (!(s->ndirty == 0 && nbyte > BUFFER_SIZE/2)
+ && s->logical_offset + nbyte <= s->buffer_offset + BUFFER_SIZE
+ && s->buffer_offset <= s->logical_offset
+ && s->buffer_offset + s->ndirty >= s->logical_offset)
{
- ssize_t n;
-
- n = read (s->fd, s->buffer + s->active, s->len - s->active);
- if (n < 0)
- return NULL;
-
- s->physical_offset = m + n;
- s->active += n;
+ memcpy (s->buffer + (s->logical_offset - s->buffer_offset), buf, nbyte);
+ int nd = (s->logical_offset - s->buffer_offset) + nbyte;
+ if (nd > s->ndirty)
+ s->ndirty = nd;
}
else
{
- size_t n;
-
- n = s->len - s->active;
- if (do_read (s, s->buffer + s->active, &n) != 0)
- return NULL;
-
- s->physical_offset = m + n;
- s->active += n;
- }
-
- if (s->active < *len)
- *len = s->active; /* Bytes actually available */
-
- s->logical_offset = where + *len;
-
- return s->buffer;
-}
-
-
-/* fd_alloc_w_at()-- Allocate a stream buffer for writing. Either
- * we've already buffered the data or we need to load it. */
-
-static char *
-fd_alloc_w_at (unix_stream * s, int *len)
-{
- gfc_offset n;
- gfc_offset where = s->logical_offset;
-
- if (s->buffer == NULL || s->buffer_offset > where ||
- where + *len > s->buffer_offset + s->len)
- {
-
- if (fd_flush (s) == FAILURE)
- return NULL;
- fd_alloc (s, where, len);
- }
-
- /* Return a position within the current buffer */
- if (s->ndirty == 0
- || where > s->dirty_offset + s->ndirty
- || s->dirty_offset > where + *len)
- { /* Discontiguous blocks, start with a clean buffer. */
- /* Flush the buffer. */
- if (s->ndirty != 0)
- fd_flush (s);
- s->dirty_offset = where;
- s->ndirty = *len;
- }
- else
- {
- gfc_offset start; /* Merge with the existing data. */
- if (where < s->dirty_offset)
- start = where;
- else
- start = s->dirty_offset;
- if (where + *len > s->dirty_offset + s->ndirty)
- s->ndirty = where + *len - start;
- else
- s->ndirty = s->dirty_offset + s->ndirty - start;
- s->dirty_offset = start;
+ /* Flush, and either fill the buffer with the new data, or if
+ the request is bigger than the buffer size, write directly
+ bypassing the buffer. */
+ buf_flush (s);
+ if (nbyte <= BUFFER_SIZE/2)
+ {
+ memcpy (s->buffer, buf, nbyte);
+ s->buffer_offset = s->logical_offset;
+ s->ndirty += nbyte;
+ }
+ else
+ {
+ if (s->file_length != -1 && s->physical_offset != s->logical_offset
+ && lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
+ return -1;
+ nbyte = raw_write (s, buf, nbyte);
+ s->physical_offset += nbyte;
+ }
}
-
- s->logical_offset = where + *len;
-
+ s->logical_offset += nbyte;
/* Don't increment file_length if the file is non-seekable. */
-
if (s->file_length != -1 && s->logical_offset > s->file_length)
- s->file_length = s->logical_offset;
-
- n = s->logical_offset - s->buffer_offset;
- if (n > s->active)
- s->active = n;
-
- return s->buffer + where - s->buffer_offset;
+ s->file_length = s->logical_offset;
+ return nbyte;
}
-
-static try
-fd_sfree (unix_stream * s)
+static off_t
+buf_seek (unix_stream * s, off_t offset, int whence)
{
- if (s->ndirty != 0 &&
- (s->buffer != s->small_buffer || options.all_unbuffered ||
- s->method == SYNC_UNBUFFERED))
- return fd_flush (s);
-
- return SUCCESS;
-}
-
-
-static try
-fd_seek (unix_stream * s, gfc_offset offset)
-{
-
- if (s->file_length == -1)
- return SUCCESS;
-
- if (s->physical_offset == offset) /* Are we lucky and avoid syscall? */
+ switch (whence)
{
- s->logical_offset = offset;
- return SUCCESS;
- }
-
- if (lseek (s->fd, offset, SEEK_SET) >= 0)
- {
- s->physical_offset = s->logical_offset = offset;
- s->active = 0;
- return SUCCESS;
- }
-
- return FAILURE;
-}
-
-
-/* truncate_file()-- Given a unit, truncate the file at the current
- * position. Sets the physical location to the new end of the file.
- * Returns nonzero on error. */
-
-static try
-fd_truncate (unix_stream * s)
-{
- /* Non-seekable files, like terminals and fifo's fail the lseek so just
- return success, there is nothing to truncate. If its not a pipe there
- is a real problem. */
- if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
- {
- if (errno == ESPIPE)
- return SUCCESS;
- else
- return FAILURE;
+ case SEEK_SET:
+ break;
+ case SEEK_CUR:
+ offset += s->logical_offset;
+ break;
+ case SEEK_END:
+ offset += s->file_length;
+ break;
+ default:
+ return -1;
}
-
- /* Using ftruncate on a seekable special file (like /dev/null)
- is undefined, so we treat it as if the ftruncate succeeded. */
- if (!s->special_file
- && (
-#ifdef HAVE_FTRUNCATE
- ftruncate (s->fd, s->logical_offset) != 0
-#elif defined HAVE_CHSIZE
- chsize (s->fd, s->logical_offset) != 0
-#else
- /* If we have neither, always fail and exit, noisily. */
- runtime_error ("required ftruncate or chsize support not present"), 1
-#endif
- ))
+ if (offset < 0)
{
- /* The truncation failed and we need to handle this gracefully.
- The file length remains the same, but the file-descriptor
- offset needs adjustment per the successful lseek above.
- (Similarly, the contents of the buffer isn't valid anymore.)
- A ftruncate call does not affect the physical (file-descriptor)
- offset, according to the ftruncate manual, so neither should a
- failed call. */
- s->physical_offset = s->logical_offset;
- s->active = 0;
- return FAILURE;
+ errno = EINVAL;
+ return -1;
}
-
- s->physical_offset = s->file_length = s->logical_offset;
- s->active = 0;
- return SUCCESS;
+ s->logical_offset = offset;
+ return offset;
}
-
-/* Similar to memset(), but operating on a stream instead of a string.
- Takes care of not using too much memory. */
-
-static try
-fd_sset (unix_stream * s, int c, size_t n)
+static off_t
+buf_tell (unix_stream * s)
{
- size_t bytes_left;
- int trans;
- void *p;
-
- bytes_left = n;
-
- while (bytes_left > 0)
- {
- /* memset() in chunks of BUFFER_SIZE. */
- trans = (bytes_left < BUFFER_SIZE) ? bytes_left : BUFFER_SIZE;
-
- p = fd_alloc_w_at (s, &trans);
- if (p)
- memset (p, c, trans);
- else
- return FAILURE;
-
- bytes_left -= trans;
- }
-
- return SUCCESS;
+ return s->logical_offset;
}
-
-/* Stream read function. Avoids using a buffer for big reads. The
- interface is like POSIX read(), but the nbytes argument is a
- pointer; on return it contains the number of bytes written. The
- function return value is the status indicator (0 for success). */
-
static int
-fd_read (unix_stream * s, void * buf, size_t * nbytes)
+buf_truncate (unix_stream * s, off_t length)
{
- void *p;
- int tmp, status;
+ int r;
- if (*nbytes < BUFFER_SIZE && s->method == SYNC_BUFFERED)
- {
- tmp = *nbytes;
- p = fd_alloc_r_at (s, &tmp);
- if (p)
- {
- *nbytes = tmp;
- memcpy (buf, p, *nbytes);
- return 0;
- }
- else
- {
- *nbytes = 0;
- return errno;
- }
- }
-
- /* If the request is bigger than BUFFER_SIZE we flush the buffers
- and read directly. */
- if (fd_flush (s) == FAILURE)
- {
- *nbytes = 0;
- return errno;
- }
-
- if (is_seekable ((stream *) s) && fd_seek (s, s->logical_offset) == FAILURE)
- {
- *nbytes = 0;
- return errno;
- }
-
- status = do_read (s, buf, nbytes);
- reset_stream (s, *nbytes);
- return status;
+ if (buf_flush (s) != 0)
+ return -1;
+ r = raw_truncate (s, length);
+ if (r == 0)
+ s->file_length = length;
+ return r;
}
-
-/* Stream write function. Avoids using a buffer for big writes. The
- interface is like POSIX write(), but the nbytes argument is a
- pointer; on return it contains the number of bytes written. The
- function return value is the status indicator (0 for success). */
-
static int
-fd_write (unix_stream * s, const void * buf, size_t * nbytes)
-{
- void *p;
- int tmp, status;
-
- if (*nbytes < BUFFER_SIZE && s->method == SYNC_BUFFERED)
- {
- tmp = *nbytes;
- p = fd_alloc_w_at (s, &tmp);
- if (p)
- {
- *nbytes = tmp;
- memcpy (p, buf, *nbytes);
- return 0;
- }
- else
- {
- *nbytes = 0;
- return errno;
- }
- }
-
- /* If the request is bigger than BUFFER_SIZE we flush the buffers
- and write directly. */
- if (fd_flush (s) == FAILURE)
- {
- *nbytes = 0;
- return errno;
- }
-
- if (is_seekable ((stream *) s) && fd_seek (s, s->logical_offset) == FAILURE)
- {
- *nbytes = 0;
- return errno;
- }
-
- status = do_write (s, buf, nbytes);
- reset_stream (s, *nbytes);
- return status;
-}
-
-
-static try
-fd_close (unix_stream * s)
+buf_close (unix_stream * s)
{
- if (fd_flush (s) == FAILURE)
- return FAILURE;
-
- if (s->buffer != NULL && s->buffer != s->small_buffer)
- free_mem (s->buffer);
-
- if (s->fd != STDOUT_FILENO && s->fd != STDERR_FILENO && s->fd != STDIN_FILENO)
- {
- if (close (s->fd) < 0)
- return FAILURE;
- }
-
- free_mem (s);
-
- return SUCCESS;
+ if (buf_flush (s) != 0)
+ return -1;
+ free_mem (s->buffer);
+ return raw_close (s);
}
-
-static void
-fd_open (unix_stream * s)
+static int
+buf_init (unix_stream * s)
{
- if (isatty (s->fd))
- s->method = SYNC_UNBUFFERED;
- else
- s->method = SYNC_BUFFERED;
-
- s->st.alloc_w_at = (void *) fd_alloc_w_at;
- s->st.sfree = (void *) fd_sfree;
- s->st.close = (void *) fd_close;
- s->st.seek = (void *) fd_seek;
- s->st.trunc = (void *) fd_truncate;
- s->st.read = (void *) fd_read;
- s->st.write = (void *) fd_write;
- s->st.set = (void *) fd_sset;
+ s->st.read = (void *) buf_read;
+ s->st.write = (void *) buf_write;
+ s->st.seek = (void *) buf_seek;
+ s->st.tell = (void *) buf_tell;
+ s->st.trunc = (void *) buf_truncate;
+ s->st.close = (void *) buf_close;
+ s->st.flush = (void *) buf_flush;
- s->buffer = NULL;
+ s->buffer = get_mem (BUFFER_SIZE);
+ return 0;
}
-
-
/*********************************************************************
memory stream functions - These are used for internal files
@@ -907,33 +549,33 @@ fd_open (unix_stream * s)
*********************************************************************/
-static char *
-mem_alloc_r_at (int_stream * s, int *len)
+char *
+mem_alloc_r (stream * strm, int * len)
{
+ unix_stream * s = (unix_stream *) strm;
gfc_offset n;
gfc_offset where = s->logical_offset;
if (where < s->buffer_offset || where > s->buffer_offset + s->active)
return NULL;
- s->logical_offset = where + *len;
-
n = s->buffer_offset + s->active - where;
if (*len > n)
*len = n;
+ s->logical_offset = where + *len;
+
return s->buffer + (where - s->buffer_offset);
}
-static char *
-mem_alloc_w_at (int_stream * s, int *len)
+char *
+mem_alloc_w (stream * strm, int * len)
{
+ unix_stream * s = (unix_stream *) strm;
gfc_offset m;
gfc_offset where = s->logical_offset;
- assert (*len >= 0); /* Negative values not allowed. */
-
m = where + *len;
if (where < s->buffer_offset)
@@ -950,25 +592,20 @@ mem_alloc_w_at (int_stream * s, int *len)
/* Stream read function for internal units. */
-static int
-mem_read (int_stream * s, void * buf, size_t * nbytes)
+static ssize_t
+mem_read (stream * s, void * buf, ssize_t nbytes)
{
void *p;
- int tmp;
+ int nb = nbytes;
- tmp = *nbytes;
- p = mem_alloc_r_at (s, &tmp);
+ p = mem_alloc_r (s, &nb);
if (p)
{
- *nbytes = tmp;
- memcpy (buf, p, *nbytes);
- return 0;
+ memcpy (buf, p, nb);
+ return (ssize_t) nb;
}
else
- {
- *nbytes = 0;
- return 0;
- }
+ return 0;
}
@@ -976,84 +613,90 @@ mem_read (int_stream * s, void * buf, size_t * nbytes)
at the moment, as all internal IO is formatted and the formatted IO
routines use mem_alloc_w_at. */
-static int
-mem_write (int_stream * s, const void * buf, size_t * nbytes)
+static ssize_t
+mem_write (stream * s, const void * buf, ssize_t nbytes)
{
void *p;
- int tmp;
+ int nb = nbytes;
- tmp = *nbytes;
- p = mem_alloc_w_at (s, &tmp);
+ p = mem_alloc_w (s, &nb);
if (p)
{
- *nbytes = tmp;
- memcpy (p, buf, *nbytes);
- return 0;
+ memcpy (p, buf, nb);
+ return (ssize_t) nb;
}
else
- {
- *nbytes = 0;
- return 0;
- }
+ return 0;
}
-static int
-mem_seek (int_stream * s, gfc_offset offset)
+static off_t
+mem_seek (stream * strm, off_t offset, int whence)
{
+ unix_stream * s = (unix_stream *) strm;
+ switch (whence)
+ {
+ case SEEK_SET:
+ break;
+ case SEEK_CUR:
+ offset += s->logical_offset;
+ break;
+ case SEEK_END:
+ offset += s->file_length;
+ break;
+ default:
+ return -1;
+ }
+
+ /* Note that for internal array I/O it's actually possible to have a
+ negative offset, so don't check for that. */
if (offset > s->file_length)
{
- errno = ESPIPE;
- return FAILURE;
+ errno = EINVAL;
+ return -1;
}
s->logical_offset = offset;
- return SUCCESS;
+
+ /* Returning < 0 is the error indicator for sseek(), so return 0 if
+ offset is negative. Thus if the return value is 0, the caller
+ has to use stell() to get the real value of logical_offset. */
+ if (offset >= 0)
+ return offset;
+ return 0;
}
-static try
-mem_set (int_stream * s, int c, size_t n)
+static off_t
+mem_tell (stream * s)
{
- void *p;
- int len;
-
- len = n;
-
- p = mem_alloc_w_at (s, &len);
- if (p)
- {
- memset (p, c, len);
- return SUCCESS;
- }
- else
- return FAILURE;
+ return ((unix_stream *)s)->logical_offset;
}
static int
-mem_truncate (int_stream * s __attribute__ ((unused)))
+mem_truncate (unix_stream * s __attribute__ ((unused)),
+ off_t length __attribute__ ((unused)))
{
- return SUCCESS;
+ return 0;
}
-static try
-mem_close (int_stream * s)
+static int
+mem_flush (unix_stream * s __attribute__ ((unused)))
{
- if (s != NULL)
- free_mem (s);
-
- return SUCCESS;
+ return 0;
}
-static try
-mem_sfree (int_stream * s __attribute__ ((unused)))
+static int
+mem_close (unix_stream * s)
{
- return SUCCESS;
-}
+ if (s != NULL)
+ free_mem (s);
+ return 0;
+}
/*********************************************************************
@@ -1066,7 +709,7 @@ mem_sfree (int_stream * s __attribute__ ((unused)))
void
empty_internal_buffer(stream *strm)
{
- int_stream * s = (int_stream *) strm;
+ unix_stream * s = (unix_stream *) strm;
memset(s->buffer, ' ', s->file_length);
}
@@ -1075,10 +718,10 @@ empty_internal_buffer(stream *strm)
stream *
open_internal (char *base, int length, gfc_offset offset)
{
- int_stream *s;
+ unix_stream *s;
- s = get_mem (sizeof (int_stream));
- memset (s, '\0', sizeof (int_stream));
+ s = get_mem (sizeof (unix_stream));
+ memset (s, '\0', sizeof (unix_stream));
s->buffer = base;
s->buffer_offset = offset;
@@ -1086,14 +729,13 @@ open_internal (char *base, int length, gfc_offset offset)
s->logical_offset = 0;
s->active = s->file_length = length;
- s->st.alloc_w_at = (void *) mem_alloc_w_at;
- s->st.sfree = (void *) mem_sfree;
s->st.close = (void *) mem_close;
s->st.seek = (void *) mem_seek;
+ s->st.tell = (void *) mem_tell;
s->st.trunc = (void *) mem_truncate;
s->st.read = (void *) mem_read;
s->st.write = (void *) mem_write;
- s->st.set = (void *) mem_set;
+ s->st.flush = (void *) mem_flush;
return (stream *) s;
}
@@ -1128,7 +770,14 @@ fd_to_stream (int fd, int prot)
s->special_file = !S_ISREG (statbuf.st_mode);
- fd_open (s);
+ if (isatty (s->fd) || options.all_unbuffered
+ ||(options.unbuffered_preconnected &&
+ (s->fd == STDIN_FILENO
+ || s->fd == STDOUT_FILENO
+ || s->fd == STDERR_FILENO)))
+ raw_init (s);
+ else
+ buf_init (s);
return (stream *) s;
}
@@ -1412,8 +1061,6 @@ output_stream (void)
#endif
s = fd_to_stream (STDOUT_FILENO, PROT_WRITE);
- if (options.unbuffered_preconnected)
- ((unix_stream *) s)->method = SYNC_UNBUFFERED;
return s;
}
@@ -1431,8 +1078,6 @@ error_stream (void)
#endif
s = fd_to_stream (STDERR_FILENO, PROT_WRITE);
- if (options.unbuffered_preconnected)
- ((unix_stream *) s)->method = SYNC_UNBUFFERED;
return s;
}
@@ -1663,7 +1308,7 @@ flush_all_units_1 (gfc_unit *u, int min_unit)
if (__gthread_mutex_trylock (&u->lock))
return u;
if (u->s)
- flush (u->s);
+ sflush (u->s);
__gthread_mutex_unlock (&u->lock);
}
u = u->right;
@@ -1693,7 +1338,7 @@ flush_all_units (void)
if (u->closed == 0)
{
- flush (u->s);
+ sflush (u->s);
__gthread_mutex_lock (&unit_lock);
__gthread_mutex_unlock (&u->lock);
(void) predec_waiting_locked (u);
@@ -1710,40 +1355,6 @@ flush_all_units (void)
}
-/* stream_at_bof()-- Returns nonzero if the stream is at the beginning
- * of the file. */
-
-int
-stream_at_bof (stream * s)
-{
- unix_stream *us;
-
- if (!is_seekable (s))
- return 0;
-
- us = (unix_stream *) s;
-
- return us->logical_offset == 0;
-}
-
-
-/* stream_at_eof()-- Returns nonzero if the stream is at the end
- * of the file. */
-
-int
-stream_at_eof (stream * s)
-{
- unix_stream *us;
-
- if (!is_seekable (s))
- return 0;
-
- us = (unix_stream *) s;
-
- return us->logical_offset == us->dirty_offset;
-}
-
-
/* delete_file()-- Given a unit structure, delete the file associated
* with the unit. Returns nonzero if something went wrong. */
@@ -1949,16 +1560,15 @@ inquire_readwrite (const char *string, int len)
gfc_offset
file_length (stream * s)
{
- return ((unix_stream *) s)->file_length;
-}
-
-
-/* file_position()-- Return the current position of the file */
-
-gfc_offset
-file_position (stream *s)
-{
- return ((unix_stream *) s)->logical_offset;
+ off_t curr, end;
+ if (!is_seekable (s))
+ return -1;
+ curr = stell (s);
+ if (curr == -1)
+ return curr;
+ end = sseek (s, 0, SEEK_END);
+ sseek (s, curr, SEEK_SET);
+ return end;
}
@@ -1983,12 +1593,6 @@ is_special (stream *s)
}
-try
-flush (stream *s)
-{
- return fd_flush( (unix_stream *) s);
-}
-
int
stream_isatty (stream *s)
{
@@ -2005,12 +1609,6 @@ stream_ttyname (stream *s __attribute__ ((unused)))
#endif
}
-gfc_offset
-stream_offset (stream *s)
-{
- return (((unix_stream *) s)->logical_offset);
-}
-
/* How files are stored: This is an operating-system specific issue,
and therefore belongs here. There are three cases to consider.
diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c
index 5d31e15dffa..b6d6e687736 100644
--- a/libgfortran/io/write.c
+++ b/libgfortran/io/write.c
@@ -108,7 +108,7 @@ write_utf8_char4 (st_parameter_dt *dtp, gfc_char4_t *source,
gfc_char4_t c;
static const uchar masks[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const uchar limits[6] = { 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
- size_t nbytes;
+ int nbytes;
uchar buf[6], d, *q;
/* Take care of preceding blanks. */
@@ -597,7 +597,7 @@ write_decimal (st_parameter_dt *dtp, const fnode *f, const char *source,
n = -n;
nsign = sign == S_NONE ? 0 : 1;
- /* conv calls gfc_itoa which sets the negative sign needed
+ /* conv calls itoa which sets the negative sign needed
by write_integer. The sign '+' or '-' is set below based on sign
calculated above, so we just point past the sign in the string
before proceeding to avoid double signs in corner cases.
@@ -707,6 +707,48 @@ btoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
}
+/* gfc_itoa()-- Integer to decimal conversion.
+ The itoa function is a widespread non-standard extension to standard
+ C, often declared in <stdlib.h>. Even though the itoa defined here
+ is a static function we take care not to conflict with any prior
+ non-static declaration. Hence the 'gfc_' prefix, which is normally
+ reserved for functions with external linkage. */
+
+static const char *
+gfc_itoa (GFC_INTEGER_LARGEST n, char *buffer, size_t len)
+{
+ int negative;
+ char *p;
+ GFC_UINTEGER_LARGEST t;
+
+ assert (len >= GFC_ITOA_BUF_SIZE);
+
+ if (n == 0)
+ return "0";
+
+ negative = 0;
+ t = n;
+ if (n < 0)
+ {
+ negative = 1;
+ t = -n; /*must use unsigned to protect from overflow*/
+ }
+
+ p = buffer + GFC_ITOA_BUF_SIZE - 1;
+ *p = '\0';
+
+ while (t != 0)
+ {
+ *--p = '0' + (t % 10);
+ t /= 10;
+ }
+
+ if (negative)
+ *--p = '-';
+ return p;
+}
+
+
void
write_i (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
@@ -730,7 +772,7 @@ write_o (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
void
write_z (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
- write_int (dtp, f, p, len, xtoa);
+ write_int (dtp, f, p, len, gfc_xtoa);
}
@@ -779,8 +821,7 @@ write_x (st_parameter_dt *dtp, int len, int nspaces)
p = write_block (dtp, len);
if (p == NULL)
return;
-
- if (nspaces > 0)
+ if (nspaces > 0 && len - nspaces >= 0)
memset (&p[len - nspaces], ' ', nspaces);
}
@@ -1168,7 +1209,7 @@ namelist_write_newline (st_parameter_dt *dtp)
/* Now seek to this record */
record = record * dtp->u.p.current_unit->recl;
- if (sseek (dtp->u.p.current_unit->s, record) == FAILURE)
+ if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
{
generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
return;
@@ -1189,13 +1230,13 @@ nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
int rep_ctr;
int num;
int nml_carry;
- index_type len;
+ int len;
index_type obj_size;
index_type nelem;
- index_type dim_i;
- index_type clen;
+ size_t dim_i;
+ size_t clen;
index_type elem_ctr;
- index_type obj_name_len;
+ size_t obj_name_len;
void * p ;
char cup;
char * obj_name;
@@ -1225,14 +1266,16 @@ nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
len = 0;
if (base)
{
- len =strlen (base->var_name);
- for (dim_i = 0; dim_i < (index_type) strlen (base_name); dim_i++)
+ len = strlen (base->var_name);
+ base_name_len = strlen (base_name);
+ for (dim_i = 0; dim_i < base_name_len; dim_i++)
{
cup = toupper (base_name[dim_i]);
write_character (dtp, &cup, 1, 1);
}
}
- for (dim_i =len; dim_i < (index_type) strlen (obj->var_name); dim_i++)
+ clen = strlen (obj->var_name);
+ for (dim_i = len; dim_i < clen; dim_i++)
{
cup = toupper (obj->var_name[dim_i]);
write_character (dtp, &cup, 1, 1);
@@ -1271,7 +1314,7 @@ nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
/* Set the index vector and count the number of elements. */
nelem = 1;
- for (dim_i=0; dim_i < obj->var_rank; dim_i++)
+ for (dim_i = 0; dim_i < (size_t) obj->var_rank; dim_i++)
{
obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
nelem = nelem * (obj->dim[dim_i].ubound + 1 - obj->dim[dim_i].lbound);
@@ -1374,7 +1417,7 @@ nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
/* Append the qualifier. */
tot_len = base_name_len + clen;
- for (dim_i = 0; dim_i < obj->var_rank; dim_i++)
+ for (dim_i = 0; dim_i < (size_t) obj->var_rank; dim_i++)
{
if (!dim_i)
{
@@ -1383,7 +1426,7 @@ nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
}
sprintf (ext_name + tot_len, "%d", (int) obj->ls[dim_i].idx);
tot_len += strlen (ext_name + tot_len);
- ext_name[tot_len] = (dim_i == obj->var_rank - 1) ? ')' : ',';
+ ext_name[tot_len] = ((int) dim_i == obj->var_rank - 1) ? ')' : ',';
tot_len++;
}
@@ -1437,11 +1480,11 @@ nml_write_obj (st_parameter_dt *dtp, namelist_info * obj, index_type offset,
obj_loop:
nml_carry = 1;
- for (dim_i = 0; nml_carry && (dim_i < obj->var_rank); dim_i++)
+ for (dim_i = 0; nml_carry && (dim_i < (size_t) obj->var_rank); dim_i++)
{
obj->ls[dim_i].idx += nml_carry ;
nml_carry = 0;
- if (obj->ls[dim_i].idx > (ssize_t)obj->dim[dim_i].ubound)
+ if (obj->ls[dim_i].idx > (index_type) obj->dim[dim_i].ubound)
{
obj->ls[dim_i].idx = obj->dim[dim_i].lbound;
nml_carry = 1;
diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def
index acf47fbe17e..9804d7b9ab1 100644
--- a/libgfortran/io/write_float.def
+++ b/libgfortran/io/write_float.def
@@ -603,7 +603,7 @@ output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
int d = f->u.real.d;\
int w = f->u.real.w;\
fnode *newf;\
- GFC_REAL_ ## x exp_d;\
+ GFC_REAL_ ## x rexp_d;\
int low, high, mid;\
int ubound, lbound;\
char *p;\
@@ -612,8 +612,8 @@ output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
save_scale_factor = dtp->u.p.scale_factor;\
newf = (fnode *) get_mem (sizeof (fnode));\
\
- exp_d = calculate_exp_ ## x (d);\
- if ((m > 0.0 && m < 0.1 - 0.05 / exp_d) || (m >= exp_d - 0.5 ) ||\
+ rexp_d = calculate_exp_ ## x (-d);\
+ if ((m > 0.0 && m < 0.1 - 0.05 * rexp_d) || (rexp_d * (m + 0.5) >= 1.0) ||\
((m == 0.0) && !(compile_options.allow_std & GFC_STD_F2003)))\
{ \
newf->format = FMT_E;\
@@ -635,8 +635,7 @@ output_float_FMT_G_ ## x (st_parameter_dt *dtp, const fnode *f, \
GFC_REAL_ ## x temp;\
mid = (low + high) / 2;\
\
- temp = (calculate_exp_ ## x (mid) - \
- 5 * calculate_exp_ ## x (mid - d - 1)) / 10;\
+ temp = (calculate_exp_ ## x (mid - 1) * (1 - 0.5 * rexp_d));\
\
if (m < temp)\
{ \
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index 6643d3c797e..3591fa9c279 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -631,11 +631,8 @@ internal_proto(show_backtrace);
extern void sys_exit (int) __attribute__ ((noreturn));
internal_proto(sys_exit);
-extern const char *gfc_itoa (GFC_INTEGER_LARGEST, char *, size_t);
-internal_proto(gfc_itoa);
-
-extern const char *xtoa (GFC_UINTEGER_LARGEST, char *, size_t);
-internal_proto(xtoa);
+extern const char *gfc_xtoa (GFC_UINTEGER_LARGEST, char *, size_t);
+internal_proto(gfc_xtoa);
extern void os_error (const char *) __attribute__ ((noreturn));
iexport_proto(os_error);
diff --git a/libgfortran/runtime/backtrace.c b/libgfortran/runtime/backtrace.c
index 9788673beac..4a831c0d8b2 100644
--- a/libgfortran/runtime/backtrace.c
+++ b/libgfortran/runtime/backtrace.c
@@ -147,7 +147,7 @@ show_backtrace (void)
/* Write the list of addresses in hexadecimal format. */
for (i = 0; i < depth; i++)
- addr[i] = xtoa ((GFC_UINTEGER_LARGEST) (intptr_t) trace[i], addr_buf[i],
+ addr[i] = gfc_xtoa ((GFC_UINTEGER_LARGEST) (intptr_t) trace[i], addr_buf[i],
sizeof (addr_buf[i]));
/* Don't output an error message if something goes wrong, we'll simply
diff --git a/libgfortran/runtime/error.c b/libgfortran/runtime/error.c
index e37d6189cc9..07da6df36e4 100644
--- a/libgfortran/runtime/error.c
+++ b/libgfortran/runtime/error.c
@@ -112,47 +112,10 @@ sys_exit (int code)
* Other error returns are reserved for the STOP statement with a numeric code.
*/
-/* gfc_itoa()-- Integer to decimal conversion. */
+/* gfc_xtoa()-- Integer to hexadecimal conversion. */
const char *
-gfc_itoa (GFC_INTEGER_LARGEST n, char *buffer, size_t len)
-{
- int negative;
- char *p;
- GFC_UINTEGER_LARGEST t;
-
- assert (len >= GFC_ITOA_BUF_SIZE);
-
- if (n == 0)
- return "0";
-
- negative = 0;
- t = n;
- if (n < 0)
- {
- negative = 1;
- t = -n; /*must use unsigned to protect from overflow*/
- }
-
- p = buffer + GFC_ITOA_BUF_SIZE - 1;
- *p = '\0';
-
- while (t != 0)
- {
- *--p = '0' + (t % 10);
- t /= 10;
- }
-
- if (negative)
- *--p = '-';
- return p;
-}
-
-
-/* xtoa()-- Integer to hexadecimal conversion. */
-
-const char *
-xtoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
+gfc_xtoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len)
{
int digit;
char *p;
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 6600f926765..81f3c63e1b6 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,9 @@
+2009-05-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR libgomp/40174
+ * team.c (gomp_thread_start): Destroy thr->release semaphore.
+ (gomp_free_pool_helper): Likewise.
+
2009-04-21 Release Manager
* GCC 4.4.0 released.
diff --git a/libgomp/team.c b/libgomp/team.c
index 4110e3f22b2..44ffd56095f 100644
--- a/libgomp/team.c
+++ b/libgomp/team.c
@@ -125,6 +125,7 @@ gomp_thread_start (void *xdata)
while (local_fn);
}
+ gomp_sem_destroy (&thr->release);
return NULL;
}
@@ -201,6 +202,7 @@ gomp_free_pool_helper (void *thread_pool)
struct gomp_thread_pool *pool
= (struct gomp_thread_pool *) thread_pool;
gomp_barrier_wait_last (&pool->threads_dock);
+ gomp_sem_destroy (&gomp_thread ()->release);
pthread_exit (NULL);
}
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 43d020e5e9a..5faeea293bf 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,9 @@
+2009-05-11 Matthias Klose <doko@ubuntu.com>
+
+ * Makefile.am (install-data-local): Fix symlinks to header files.
+ Don't create a symlink for javac.
+ * Makefile.in: Regenerate.
+
2009-04-28 Andrew Haley <aph@redhat.com>
PR libgcj/39899
@@ -17,11 +23,6 @@
* configure.ac: Create missing directory gnu/java/security/jce/prng.
* configure: Regenerate.
-2009-04-23 Matthias Klose <doko@ubuntu.com>
-
- * Makefile.am (install-data-local): Fix symlinks to header files.
- * Makefile.in: Regenerate.
-
2009-04-21 Release Manager
* GCC 4.4.0 released.
diff --git a/libjava/Makefile.am b/libjava/Makefile.am
index 5122facc88f..839d2963c52 100644
--- a/libjava/Makefile.am
+++ b/libjava/Makefile.am
@@ -585,8 +585,6 @@ if CREATE_JAVA_HOME
RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(SDK_BIN_DIR)); \
ln -sf $$RELATIVE/`echo gij | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
$(DESTDIR)$(SDK_BIN_DIR)/java; \
- ln -sf $$RELATIVE/`echo gcj | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
- $(DESTDIR)$(SDK_BIN_DIR)/javac; \
ln -sf $$RELATIVE/`echo gjar | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
$(DESTDIR)$(SDK_BIN_DIR)/jar; \
ln -sf $$RELATIVE/`echo gjdoc | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
@@ -676,7 +674,7 @@ if CREATE_JAVA_HOME
ln -sf $$RELATIVE/libgcj-tools-$(gcc_version).jar \
$(DESTDIR)$(SDK_LIB_DIR)/tools.jar; \
for headername in jawt jni; do \
- DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+ DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/`echo gcj | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
-print-file-name=include/$$headername.h)); \
RELATIVE=$$(relative $$DIRECTORY \
$(DESTDIR)$(SDK_INCLUDE_DIR)); \
@@ -684,7 +682,7 @@ if CREATE_JAVA_HOME
$(DESTDIR)$(SDK_INCLUDE_DIR)/$$headername.h; \
done; \
for headername in jawt_md jni_md; do \
- DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+ DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/`echo gcj | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
-print-file-name=include/$$headername.h)); \
RELATIVE=$$(relative $$DIRECTORY \
$(DESTDIR)$(SDK_INCLUDE_DIR)/linux); \
diff --git a/libjava/Makefile.in b/libjava/Makefile.in
index 20851a9177f..4e2c89f0393 100644
--- a/libjava/Makefile.in
+++ b/libjava/Makefile.in
@@ -12438,8 +12438,6 @@ install-data-local:
@CREATE_JAVA_HOME_TRUE@ RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(SDK_BIN_DIR)); \
@CREATE_JAVA_HOME_TRUE@ ln -sf $$RELATIVE/`echo gij | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
@CREATE_JAVA_HOME_TRUE@ $(DESTDIR)$(SDK_BIN_DIR)/java; \
-@CREATE_JAVA_HOME_TRUE@ ln -sf $$RELATIVE/`echo gcj | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
-@CREATE_JAVA_HOME_TRUE@ $(DESTDIR)$(SDK_BIN_DIR)/javac; \
@CREATE_JAVA_HOME_TRUE@ ln -sf $$RELATIVE/`echo gjar | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
@CREATE_JAVA_HOME_TRUE@ $(DESTDIR)$(SDK_BIN_DIR)/jar; \
@CREATE_JAVA_HOME_TRUE@ ln -sf $$RELATIVE/`echo gjdoc | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
@@ -12529,7 +12527,7 @@ install-data-local:
@CREATE_JAVA_HOME_TRUE@ ln -sf $$RELATIVE/libgcj-tools-$(gcc_version).jar \
@CREATE_JAVA_HOME_TRUE@ $(DESTDIR)$(SDK_LIB_DIR)/tools.jar; \
@CREATE_JAVA_HOME_TRUE@ for headername in jawt jni; do \
-@CREATE_JAVA_HOME_TRUE@ DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+@CREATE_JAVA_HOME_TRUE@ DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/`echo gcj | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
@CREATE_JAVA_HOME_TRUE@ -print-file-name=include/$$headername.h)); \
@CREATE_JAVA_HOME_TRUE@ RELATIVE=$$(relative $$DIRECTORY \
@CREATE_JAVA_HOME_TRUE@ $(DESTDIR)$(SDK_INCLUDE_DIR)); \
@@ -12537,7 +12535,7 @@ install-data-local:
@CREATE_JAVA_HOME_TRUE@ $(DESTDIR)$(SDK_INCLUDE_DIR)/$$headername.h; \
@CREATE_JAVA_HOME_TRUE@ done; \
@CREATE_JAVA_HOME_TRUE@ for headername in jawt_md jni_md; do \
-@CREATE_JAVA_HOME_TRUE@ DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+@CREATE_JAVA_HOME_TRUE@ DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/`echo gcj | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
@CREATE_JAVA_HOME_TRUE@ -print-file-name=include/$$headername.h)); \
@CREATE_JAVA_HOME_TRUE@ RELATIVE=$$(relative $$DIRECTORY \
@CREATE_JAVA_HOME_TRUE@ $(DESTDIR)$(SDK_INCLUDE_DIR)/linux); \
diff --git a/libjava/classpath/ChangeLog.gcj b/libjava/classpath/ChangeLog.gcj
index e4d7c2fae3c..6398644ad7d 100644
--- a/libjava/classpath/ChangeLog.gcj
+++ b/libjava/classpath/ChangeLog.gcj
@@ -1,3 +1,13 @@
+2009-06-16 Matthias Klose <doko@ubuntu.com>
+
+ * tools/gnu/classpath/tools/gjdoc/Main.java (getGjdocVersion): Use
+ gnu.classpath.Configuration.CLASSPATH_VERSION as version number.
+ * tools/gnu/classpath/tools/doclets/htmldoclet/HtmlDoclet.java
+ (getDocletVersion): Likewise.
+ * tools/classes/gnu/classpath/tools/gjdoc/Main*.class: Regenerate.
+ * tools/classes/gnu/classpath/tools/doclets/htmldoclet/HtmlDoclet*.class:
+ Regenerate.
+
2009-03-16 Matthias Klose <doko@ubuntu.com>
* configure.ac: Detect xulrunner-1.9.
diff --git a/libjava/classpath/tools/classes/gnu/classpath/tools/doclets/htmldoclet/HtmlDoclet.class b/libjava/classpath/tools/classes/gnu/classpath/tools/doclets/htmldoclet/HtmlDoclet.class
index 6e9981b5ee7..e76e4ad0885 100644
--- a/libjava/classpath/tools/classes/gnu/classpath/tools/doclets/htmldoclet/HtmlDoclet.class
+++ b/libjava/classpath/tools/classes/gnu/classpath/tools/doclets/htmldoclet/HtmlDoclet.class
Binary files differ
diff --git a/libjava/classpath/tools/classes/gnu/classpath/tools/gjdoc/Main.class b/libjava/classpath/tools/classes/gnu/classpath/tools/gjdoc/Main.class
index 1ce24d1d49c..e53a62553b3 100644
--- a/libjava/classpath/tools/classes/gnu/classpath/tools/gjdoc/Main.class
+++ b/libjava/classpath/tools/classes/gnu/classpath/tools/gjdoc/Main.class
Binary files differ
diff --git a/libjava/classpath/tools/gnu/classpath/tools/doclets/htmldoclet/HtmlDoclet.java b/libjava/classpath/tools/gnu/classpath/tools/doclets/htmldoclet/HtmlDoclet.java
index 837333ddf0f..e49e1c57341 100644
--- a/libjava/classpath/tools/gnu/classpath/tools/doclets/htmldoclet/HtmlDoclet.java
+++ b/libjava/classpath/tools/gnu/classpath/tools/doclets/htmldoclet/HtmlDoclet.java
@@ -3736,20 +3736,7 @@ public class HtmlDoclet
protected String getDocletVersion()
{
if (null == docletVersion) {
- try {
- Properties versionProperties = new Properties();
- InputStream in = getClass().getResourceAsStream("/version.properties");
- if (in == null) {
- in = new FileInputStream("src/resources/version.properties");
- }
- versionProperties.load(in);
- docletVersion = versionProperties.getProperty("gjdoc.version");
- }
- catch (IOException ignore) {
- }
- if (null == docletVersion) {
- docletVersion = "unknown";
- }
+ docletVersion = gnu.classpath.Configuration.CLASSPATH_VERSION;
}
return docletVersion;
}
diff --git a/libjava/classpath/tools/gnu/classpath/tools/gjdoc/Main.java b/libjava/classpath/tools/gnu/classpath/tools/gjdoc/Main.java
index d1316b34183..cbbc8f4f7dd 100644
--- a/libjava/classpath/tools/gnu/classpath/tools/gjdoc/Main.java
+++ b/libjava/classpath/tools/gnu/classpath/tools/gjdoc/Main.java
@@ -1825,16 +1825,7 @@ public final class Main
public String getGjdocVersion()
{
if (null == gjdocVersion) {
- try {
- Properties versionProperties = new Properties();
- versionProperties.load(getClass().getResourceAsStream("version.properties"));
- gjdocVersion = versionProperties.getProperty("gjdoc.version");
- }
- catch (IOException ignore) {
- }
- if (null == gjdocVersion) {
- gjdocVersion = "unknown";
- }
+ gjdocVersion = gnu.classpath.Configuration.CLASSPATH_VERSION;
}
return gjdocVersion;
}
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 8bd67c94264..9d5d2535182 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,60 @@
+2009-06-16 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * libsupc++/exception_ptr.h (exception_ptr::swap(exception_ptr&&)):
+ Remove.
+ (exception_ptr::operator=(exception_ptr&&)): Cast source to
+ rvalue-reference so that move constructor is called.
+ * testsuite/18_support/exception_ptr/move.cc: New.
+
+2009-06-16 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/std/thread (~thread(), operator=(thread&&)): Call terminate
+ if joinable.
+
+2009-06-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/40296
+ * libsupc++/exception_ptr.h (exception_ptr::operator!,
+ exception_ptr::operator __safe_bool): Only declare when
+ _GLIBCXX_EH_PTR_COMPAT is undefined.
+ * libsupc++/eh_ptr.cc: Define _GLIBCXX_EH_PTR_COMPAT before including
+ exception_ptr.
+ * testsuite/18_support/exception_ptr/40296.cc: New.
+ * testsuite/18_support/exception_ptr/current_exception.cc: Adjust.
+
+2009-06-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/40299
+ * include/ext/memory: Fully qualify calls with __gnu_cxx.
+ * testsuite/ext/rope/40299.cc: New.
+
+2009-05-21 David Billinghurst <billingd@gcc.gnu.org>
+
+ Backport from mainline:
+ PR libstdc++/36211
+ * testsuite/lib/libstdc++.exp(v3_target_compile): Add
+ cxxldflags to additional_flags rather than cxx_final.
+
+2009-05-18 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/40192
+ * include/bits/stl_construct.h (struct _Destroy_aux): Add.
+ (_Destroy(_ForwardIterator, _ForwardIterator)): Use the latter.
+ * testsuite/23_containers/vector/40192.cc: New.
+
+2009-05-13 Ben Elliston <bje@au.ibm.com>
+
+ Backport from mainline:
+ * include/Makefile.am (PCHFLAGS): Remove -Winvalid-pch.
+ * include/Makefile.in: Likewise.
+
+2009-05-12 Johannes Singler <singler@ira.uka.de>
+
+ PR libstdc++/39546
+ * include/parallel/algo.h (find_switch):
+ Parametrize binder2nd with const T& instead of T.
+ * testsuite/25_algorithms/find/39546.cc: new test case
+
2009-05-07 Paolo Carlini <paolo.carlini@oracle.com>
* configure.ac: Bump libtool_VERSION to 6:12:0.
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 02f450052a9..99a627b1d22 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -850,7 +850,7 @@ pch_output_dirs = \
${pch1_output_builddir} ${pch2_output_builddir} ${pch3_output_builddir}
pch_output_anchors = \
${pch1_output_anchor} ${pch2_output_anchor} ${pch3_output_anchor}
-PCHFLAGS=-Winvalid-pch -x c++-header $(CXXFLAGS)
+PCHFLAGS=-x c++-header $(CXXFLAGS)
if GLIBCXX_BUILD_PCH
pch_build = ${pch_output}
else
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index ae85f7eabe8..cdaecace0c5 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -1096,7 +1096,7 @@ pch_output_dirs = \
pch_output_anchors = \
${pch1_output_anchor} ${pch2_output_anchor} ${pch3_output_anchor}
-PCHFLAGS = -Winvalid-pch -x c++-header $(CXXFLAGS)
+PCHFLAGS = -x c++-header $(CXXFLAGS)
@GLIBCXX_BUILD_PCH_FALSE@pch_build =
@GLIBCXX_BUILD_PCH_TRUE@pch_build = ${pch_output}
diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h
index 265c3ab1902..9df37fe1950 100644
--- a/libstdc++-v3/include/bits/stl_construct.h
+++ b/libstdc++-v3/include/bits/stl_construct.h
@@ -82,6 +82,26 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
_Destroy(_Tp* __pointer)
{ __pointer->~_Tp(); }
+ template<bool>
+ struct _Destroy_aux
+ {
+ template<typename _ForwardIterator>
+ static void
+ __destroy(_ForwardIterator __first, _ForwardIterator __last)
+ {
+ for (; __first != __last; ++__first)
+ std::_Destroy(&*__first);
+ }
+ };
+
+ template<>
+ struct _Destroy_aux<true>
+ {
+ template<typename _ForwardIterator>
+ static void
+ __destroy(_ForwardIterator, _ForwardIterator) { }
+ };
+
/**
* Destroy a range of objects. If the value_type of the object has
* a trivial destructor, the compiler should optimize all of this
@@ -93,9 +113,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
{
typedef typename iterator_traits<_ForwardIterator>::value_type
_Value_type;
- if (!__has_trivial_destructor(_Value_type))
- for (; __first != __last; ++__first)
- std::_Destroy(&*__first);
+ std::_Destroy_aux<__has_trivial_destructor(_Value_type)>::
+ __destroy(__first, __last);
}
/**
diff --git a/libstdc++-v3/include/ext/memory b/libstdc++-v3/include/ext/memory
index 048ebe6ca6a..7776d730a4a 100644
--- a/libstdc++-v3/include/ext/memory
+++ b/libstdc++-v3/include/ext/memory
@@ -102,9 +102,9 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
template<typename _InputIter, typename _Size, typename _ForwardIter>
inline pair<_InputIter, _ForwardIter>
__uninitialized_copy_n(_InputIter __first, _Size __count,
- _ForwardIter __result)
- { return __uninitialized_copy_n(__first, __count, __result,
- __iterator_category(__first)); }
+ _ForwardIter __result)
+ { return __gnu_cxx::__uninitialized_copy_n(__first, __count, __result,
+ __iterator_category(__first)); }
/**
* @brief Copies the range [first,last) into result.
@@ -120,8 +120,8 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
inline pair<_InputIter, _ForwardIter>
uninitialized_copy_n(_InputIter __first, _Size __count,
_ForwardIter __result)
- { return __uninitialized_copy_n(__first, __count, __result,
- __iterator_category(__first)); }
+ { return __gnu_cxx::__uninitialized_copy_n(__first, __count, __result,
+ __iterator_category(__first)); }
// An alternative version of uninitialized_copy_n that constructs
@@ -154,7 +154,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
_ForwardIter __result,
std::allocator<_Tp>)
{
- return uninitialized_copy_n(__first, __count, __result);
+ return __gnu_cxx::uninitialized_copy_n(__first, __count, __result);
}
/**
diff --git a/libstdc++-v3/include/parallel/algo.h b/libstdc++-v3/include/parallel/algo.h
index 59106b2d364..a0fbd8d91d6 100644
--- a/libstdc++-v3/include/parallel/algo.h
+++ b/libstdc++-v3/include/parallel/algo.h
@@ -149,8 +149,8 @@ namespace __parallel
if (_GLIBCXX_PARALLEL_CONDITION(true))
{
- binder2nd<__gnu_parallel::equal_to<value_type, T> >
- comp(__gnu_parallel::equal_to<value_type, T>(), val);
+ binder2nd<__gnu_parallel::equal_to<value_type, const T&> >
+ comp(__gnu_parallel::equal_to<value_type, const T&>(), val);
return __gnu_parallel::find_template(begin, end, begin, comp,
__gnu_parallel::
find_if_selector()).first;
diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread
index 8ce9e5cf6a5..6f735a0186c 100644
--- a/libstdc++-v3/include/std/thread
+++ b/libstdc++-v3/include/std/thread
@@ -135,7 +135,7 @@ namespace std
~thread()
{
if (joinable())
- detach();
+ std::terminate();
}
thread& operator=(const thread&) = delete;
@@ -143,7 +143,7 @@ namespace std
thread& operator=(thread&& __t)
{
if (joinable())
- detach();
+ std::terminate();
swap(__t);
return *this;
}
diff --git a/libstdc++-v3/libsupc++/eh_ptr.cc b/libstdc++-v3/libsupc++/eh_ptr.cc
index 769273f3a61..a16b61e0909 100644
--- a/libstdc++-v3/libsupc++/eh_ptr.cc
+++ b/libstdc++-v3/libsupc++/eh_ptr.cc
@@ -26,6 +26,8 @@
#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
+#define _GLIBCXX_EH_PTR_COMPAT
+
#include <exception>
#include <exception_ptr.h>
#include "unwind-cxx.h"
@@ -127,6 +129,7 @@ std::__exception_ptr::exception_ptr::swap(exception_ptr &other) throw()
}
+// Retained for compatibility with CXXABI_1.3.
bool
std::__exception_ptr::exception_ptr::operator!() const throw()
{
@@ -134,6 +137,7 @@ std::__exception_ptr::exception_ptr::operator!() const throw()
}
+// Retained for compatibility with CXXABI_1.3.
std::__exception_ptr::exception_ptr::operator __safe_bool() const throw()
{
return _M_exception_object ? &exception_ptr::_M_safe_bool_dummy : 0;
@@ -235,4 +239,6 @@ std::rethrow_exception(std::exception_ptr ep)
std::terminate ();
}
+#undef _GLIBCXX_EH_PTR_COMPAT
+
#endif
diff --git a/libstdc++-v3/libsupc++/exception_ptr.h b/libstdc++-v3/libsupc++/exception_ptr.h
index 3c44ff113fb..b24ec21d799 100644
--- a/libstdc++-v3/libsupc++/exception_ptr.h
+++ b/libstdc++-v3/libsupc++/exception_ptr.h
@@ -121,7 +121,7 @@ namespace std
exception_ptr&
operator=(exception_ptr&& __o) throw()
{
- exception_ptr(__o).swap(*this);
+ exception_ptr(static_cast<exception_ptr&&>(__o)).swap(*this);
return *this;
}
#endif
@@ -131,18 +131,11 @@ namespace std
void
swap(exception_ptr&) throw();
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
- void
- swap(exception_ptr &&__o) throw()
- {
- void *__tmp = _M_exception_object;
- _M_exception_object = __o._M_exception_object;
- __o._M_exception_object = __tmp;
- }
-#endif
-
+#ifdef _GLIBCXX_EH_PTR_COMPAT
+ // Retained for compatibility with CXXABI_1.3.
bool operator!() const throw();
operator __safe_bool() const throw();
+#endif
friend bool
operator==(const exception_ptr&, const exception_ptr&) throw();
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc
new file mode 100644
index 00000000000..933f4136956
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc
@@ -0,0 +1,30 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2009 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 3, 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 COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <exception>
+
+// libstdc++/40296
+bool test01()
+{
+ std::exception_ptr p;
+
+ return (p == 0);
+}
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc
index ec06b336f1e..4029eaf69e3 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc
@@ -31,7 +31,7 @@ void test01()
using namespace std;
exception_ptr ep = current_exception();
- VERIFY( !ep );
+ VERIFY( ep == 0 );
}
void test02()
@@ -43,7 +43,7 @@ void test02()
throw 0;
} catch(...) {
exception_ptr ep = current_exception();
- VERIFY( ep );
+ VERIFY( ep != 0 );
}
}
@@ -56,7 +56,7 @@ void test03()
throw exception();
} catch(std::exception&) {
exception_ptr ep = current_exception();
- VERIFY( ep );
+ VERIFY( ep != 0 );
}
}
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/move.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/move.cc
new file mode 100644
index 00000000000..ce97bc28c25
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/move.cc
@@ -0,0 +1,45 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2009 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 3, 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 COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <exception>
+#include <utility>
+#include <testsuite_hooks.h>
+
+// Verify move construction and assignment are efficient and do not copy.
+// This behaviour is a GNU extension provided for efficiency.
+void test01()
+{
+ bool test = true;
+
+ std::exception_ptr p1 = std::copy_exception(test);
+ std::exception_ptr p2 = std::move(p1);
+ VERIFY( p1 == 0 );
+ VERIFY( !(p2 == 0) );
+
+ p1 = std::move(p2);
+ VERIFY( !(p1 == 0) );
+ VERIFY( p2 == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/40192.cc b/libstdc++-v3/testsuite/23_containers/vector/40192.cc
new file mode 100644
index 00000000000..eff88d422bd
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/40192.cc
@@ -0,0 +1,28 @@
+// Copyright (C) 2009 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 3, 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 COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile }
+
+// libstdc++/40192
+
+#include <vector>
+
+void test01()
+{
+ typedef float float4[4];
+ std::vector<float4> vals;
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/find/39546.cc b/libstdc++-v3/testsuite/25_algorithms/find/39546.cc
new file mode 100644
index 00000000000..b83a8553436
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/find/39546.cc
@@ -0,0 +1,43 @@
+// Copyright (C) 2009 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 3, 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 COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 25.3.1 algorithms, find()
+
+#include <vector>
+#include <string>
+#include <algorithm>
+#include <testsuite_hooks.h>
+
+// libstdc++/39546
+void
+test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ std::vector<std::string> dict;
+ dict.push_back("one");
+ dict.push_back("two");
+ dict.push_back("three");
+
+ VERIFY( std::find(dict.begin(), dict.end(), "two") == dict.begin() + 1 );
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/ext/rope/40299.cc b/libstdc++-v3/testsuite/ext/rope/40299.cc
new file mode 100644
index 00000000000..4d83fc98ce4
--- /dev/null
+++ b/libstdc++-v3/testsuite/ext/rope/40299.cc
@@ -0,0 +1,27 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2009 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 3, 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 COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <ext/rope>
+
+// libstdc++/40299
+void test01()
+{
+ __gnu_cxx::crope asdf;
+}
diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
index 3adf91c7718..45e92d756ec 100644
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -402,8 +402,7 @@ proc v3_target_compile { source dest type options } {
# Flag setting based on type argument.
if { $type == "executable" } {
# Link the support objects into executables.
- set cxx_final [concat $cxx_final $cxxldflags]
- lappend options "additional_flags=./libtestc++.a"
+ lappend options "additional_flags=./libtestc++.a $cxxldflags"
} else {
if { $type == "sharedlib" } {
# Don't link in anything.