aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Hope <michael.hope@linaro.org>2012-11-07 11:05:59 +1300
committerMichael Hope <michael.hope@linaro.org>2012-11-07 11:05:59 +1300
commitaddd667d711aa9b98d1b9975bb8c8c11f5849817 (patch)
treedce73daf803a3352d20031ed3161edcd29162a50
parent62ca489e2a78d88429a4f7d591584ec2c7a0152a (diff)
Merge from FSF GCC 4.7.2 (svn branches/gcc-4_7-branch 193200).
-rw-r--r--ChangeLog.linaro16
-rw-r--r--gcc/ChangeLog364
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/ada/ChangeLog33
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in35
-rw-r--r--gcc/ada/gcc-interface/Makefile.in3
-rw-r--r--gcc/ada/gcc-interface/decl.c27
-rw-r--r--gcc/ada/gcc-interface/trans.c4
-rw-r--r--gcc/cfgexpand.c2
-rw-r--r--gcc/common/config/m68k/m68k-common.c8
-rw-r--r--gcc/config.gcc17
-rw-r--r--gcc/config/arm/arm.c23
-rw-r--r--gcc/config/arm/arm.h5
-rw-r--r--gcc/config/avr/rtems.h1
-rw-r--r--gcc/config/i386/driver-i386.c23
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c325
-rw-r--r--gcc/config/i386/i386.md21
-rw-r--r--gcc/config/i386/predicates.md6
-rw-r--r--gcc/config/i386/sse.md51
-rw-r--r--gcc/config/microblaze/rtems.h25
-rw-r--r--gcc/config/microblaze/t-rtems1
-rw-r--r--gcc/config/pa/pa.md16
-rw-r--r--gcc/config/rs6000/predicates.md6
-rw-r--r--gcc/config/s390/s390.c1
-rw-r--r--gcc/config/sparc/t-rtems22
-rw-r--r--gcc/config/sparc/t-rtems-6422
-rwxr-xr-xgcc/configure8
-rw-r--r--gcc/configure.ac8
-rw-r--r--gcc/cp/ChangeLog27
-rw-r--r--gcc/cp/decl2.c5
-rw-r--r--gcc/cp/init.c3
-rw-r--r--gcc/cp/semantics.c1
-rw-r--r--gcc/cp/tree.c5
-rw-r--r--gcc/cse.c4
-rw-r--r--gcc/doc/invoke.texi129
-rw-r--r--gcc/dse.c33
-rw-r--r--gcc/dwarf2out.c2
-rw-r--r--gcc/fold-const.c6
-rw-r--r--gcc/fortran/ChangeLog6
-rw-r--r--gcc/fortran/trans-stmt.c12
-rw-r--r--gcc/gimple-fold.c9
-rw-r--r--gcc/gimple.h18
-rw-r--r--gcc/gimplify.c17
-rw-r--r--gcc/go/ChangeLog11
-rw-r--r--gcc/go/gccgo.texi6
-rw-r--r--gcc/go/go-c.h3
-rw-r--r--gcc/go/go-lang.c8
-rw-r--r--gcc/go/gofrontend/go.cc5
-rw-r--r--gcc/go/gofrontend/gogo.cc4
-rw-r--r--gcc/go/gofrontend/gogo.h14
-rw-r--r--gcc/go/gofrontend/import.cc29
-rw-r--r--gcc/go/gofrontend/import.h4
-rw-r--r--gcc/go/gofrontend/parse.cc160
-rw-r--r--gcc/go/gofrontend/parse.h7
-rw-r--r--gcc/go/gofrontend/types.cc12
-rw-r--r--gcc/go/lang.opt4
-rw-r--r--gcc/ifcvt.c123
-rw-r--r--gcc/po/ChangeLog4
-rw-r--r--gcc/po/es.po12
-rw-r--r--gcc/sel-sched-ir.c10
-rw-r--r--gcc/sel-sched.c52
-rw-r--r--gcc/testsuite/ChangeLog125
-rw-r--r--gcc/testsuite/c-c++-common/pr33763.c60
-rw-r--r--gcc/testsuite/c-c++-common/pr54988.c20
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C18
-rw-r--r--gcc/testsuite/g++.dg/debug/pr54828.C14
-rw-r--r--gcc/testsuite/g++.dg/template/new11.C28
-rw-r--r--gcc/testsuite/g++.dg/template/pr54858.C21
-rw-r--r--gcc/testsuite/g++.dg/torture/20121105-1.C42
-rw-r--r--gcc/testsuite/g++.dg/torture/pr54902.C131
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr54985.c36
-rw-r--r--gcc/testsuite/gcc.dg/pr53701.c59
-rw-r--r--gcc/testsuite/gcc.dg/pr55019.c41
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr54877.c23
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr54920.c13
-rw-r--r--gcc/testsuite/gcc.target/arm/arm.exp7
-rw-r--r--gcc/testsuite/gcc.target/arm/pr54892.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx256-unaligned-store-4.c4
-rw-r--r--gcc/testsuite/gfortran.dg/class_allocate_13.f9031
-rw-r--r--gcc/testsuite/gnat.dg/lto14.adb1
-rw-r--r--gcc/testsuite/gnat.dg/modular4.adb11
-rw-r--r--gcc/testsuite/gnat.dg/modular4_pkg.ads9
-rw-r--r--gcc/testsuite/gnat.dg/specs/addr1.ads8
-rw-r--r--gcc/testsuite/gnat.dg/specs/atomic1.ads4
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp8
-rw-r--r--gcc/tree-inline.c6
-rw-r--r--gcc/tree-ssa-pre.c11
-rw-r--r--gcc/tree-ssa-tail-merge.c7
-rw-r--r--gcc/tree-ssa-threadedge.c72
-rw-r--r--gcc/tree-vect-data-refs.c7
-rw-r--r--gcc/tree-vect-loop.c5
-rw-r--r--gcc/tree.c9
-rw-r--r--gcc/tree.h10
-rw-r--r--gcc/var-tracking.c2
-rw-r--r--libgcc/ChangeLog34
-rw-r--r--libgcc/config.host12
-rw-r--r--libgcc/config/i386/32/sfp-machine.h2
-rw-r--r--libgcc/config/i386/64/sfp-machine.h2
-rw-r--r--libgcc/unwind-dw2-fde-dip.c8
-rw-r--r--libgfortran/ChangeLog8
-rw-r--r--libgfortran/runtime/environ.c42
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/Makefile.am1
-rw-r--r--libgo/Makefile.in1
-rw-r--r--libgo/go/bufio/bufio.go3
-rw-r--r--libgo/go/builtin/builtin.go3
-rw-r--r--libgo/go/bytes/bytes.go2
-rw-r--r--libgo/go/compress/flate/inflate.go12
-rw-r--r--libgo/go/compress/flate/reader_test.go95
-rw-r--r--libgo/go/crypto/elliptic/elliptic.go2
-rw-r--r--libgo/go/crypto/rand/rand_test.go11
-rw-r--r--libgo/go/crypto/rand/rand_windows.go4
-rw-r--r--libgo/go/crypto/rsa/pkcs1v15.go29
-rw-r--r--libgo/go/crypto/tls/conn.go10
-rw-r--r--libgo/go/crypto/x509/verify.go2
-rw-r--r--libgo/go/crypto/x509/x509.go55
-rw-r--r--libgo/go/database/sql/fakedb_test.go6
-rw-r--r--libgo/go/database/sql/sql.go9
-rw-r--r--libgo/go/encoding/binary/varint.go2
-rw-r--r--libgo/go/encoding/gob/decode.go6
-rw-r--r--libgo/go/encoding/gob/doc.go2
-rw-r--r--libgo/go/encoding/gob/encoder_test.go29
-rw-r--r--libgo/go/encoding/gob/type.go18
-rw-r--r--libgo/go/encoding/json/encode.go2
-rw-r--r--libgo/go/flag/flag.go4
-rw-r--r--libgo/go/fmt/fmt_test.go12
-rw-r--r--libgo/go/fmt/print.go5
-rw-r--r--libgo/go/go/ast/print.go73
-rw-r--r--libgo/go/go/ast/print_test.go21
-rw-r--r--libgo/go/go/ast/resolve.go2
-rw-r--r--libgo/go/go/ast/walk.go3
-rw-r--r--libgo/go/go/build/build.go6
-rw-r--r--libgo/go/go/build/build_test.go29
-rw-r--r--libgo/go/go/build/doc.go2
-rw-r--r--libgo/go/go/doc/reader.go2
-rw-r--r--libgo/go/go/doc/testdata/error2.1.golden2
-rw-r--r--libgo/go/go/doc/testdata/error2.go2
-rw-r--r--libgo/go/go/printer/nodes.go7
-rw-r--r--libgo/go/go/printer/printer_test.go29
-rw-r--r--libgo/go/go/scanner/errors.go2
-rw-r--r--libgo/go/go/scanner/scanner.go2
-rw-r--r--libgo/go/html/template/content.go2
-rw-r--r--libgo/go/html/template/url.go2
-rw-r--r--libgo/go/image/jpeg/reader.go28
-rw-r--r--libgo/go/image/jpeg/writer.go48
-rw-r--r--libgo/go/image/jpeg/writer_test.go82
-rw-r--r--libgo/go/image/names.go2
-rw-r--r--libgo/go/io/io.go12
-rw-r--r--libgo/go/log/syslog/syslog.go12
-rw-r--r--libgo/go/log/syslog/syslog_test.go40
-rw-r--r--libgo/go/math/all_test.go11
-rw-r--r--libgo/go/math/big/nat.go2
-rw-r--r--libgo/go/math/bits.go2
-rw-r--r--libgo/go/math/remainder.go2
-rw-r--r--libgo/go/mime/grammar.go2
-rw-r--r--libgo/go/mime/multipart/multipart.go2
-rw-r--r--libgo/go/net/dial.go2
-rw-r--r--libgo/go/net/fd.go4
-rw-r--r--libgo/go/net/file.go22
-rw-r--r--libgo/go/net/http/client.go95
-rw-r--r--libgo/go/net/http/client_test.go52
-rw-r--r--libgo/go/net/http/example_test.go2
-rw-r--r--libgo/go/net/http/export_test.go8
-rw-r--r--libgo/go/net/http/fs.go132
-rw-r--r--libgo/go/net/http/fs_test.go263
-rw-r--r--libgo/go/net/http/header.go40
-rw-r--r--libgo/go/net/http/httptest/server.go14
-rw-r--r--libgo/go/net/http/httputil/dump.go2
-rw-r--r--libgo/go/net/http/pprof/pprof.go8
-rw-r--r--libgo/go/net/http/range_test.go22
-rw-r--r--libgo/go/net/http/serve_test.go46
-rw-r--r--libgo/go/net/http/server.go33
-rw-r--r--libgo/go/net/http/transport.go111
-rw-r--r--libgo/go/net/http/transport_test.go115
-rw-r--r--libgo/go/net/iprawsock.go4
-rw-r--r--libgo/go/net/iprawsock_plan9.go4
-rw-r--r--libgo/go/net/iprawsock_posix.go4
-rw-r--r--libgo/go/net/mail/message.go3
-rw-r--r--libgo/go/net/net_posix.go110
-rw-r--r--libgo/go/net/rpc/jsonrpc/all_test.go8
-rw-r--r--libgo/go/net/rpc/server.go11
-rw-r--r--libgo/go/net/sockopt.go16
-rw-r--r--libgo/go/os/error_plan9.go21
-rw-r--r--libgo/go/os/error_posix.go21
-rw-r--r--libgo/go/os/error_test.go27
-rw-r--r--libgo/go/os/error_windows.go21
-rw-r--r--libgo/go/os/exec.go11
-rw-r--r--libgo/go/os/exec/exec.go8
-rw-r--r--libgo/go/os/exec/exec_test.go72
-rw-r--r--libgo/go/os/exec_plan9.go4
-rw-r--r--libgo/go/os/exec_posix.go5
-rw-r--r--libgo/go/os/exec_unix.go4
-rw-r--r--libgo/go/os/exec_windows.go4
-rw-r--r--libgo/go/os/file_posix.go11
-rw-r--r--libgo/go/os/file_unix.go13
-rw-r--r--libgo/go/os/os_test.go10
-rw-r--r--libgo/go/os/types.go2
-rw-r--r--libgo/go/path/path.go3
-rw-r--r--libgo/go/path/path_test.go1
-rw-r--r--libgo/go/reflect/all_test.go23
-rw-r--r--libgo/go/reflect/value.go3
-rw-r--r--libgo/go/regexp/regexp.go9
-rw-r--r--libgo/go/runtime/pprof/pprof.go2
-rw-r--r--libgo/go/runtime/pprof/pprof_test.go19
-rw-r--r--libgo/go/strconv/atoi.go22
-rw-r--r--libgo/go/sync/waitgroup.go3
-rw-r--r--libgo/go/sync/waitgroup_test.go2
-rw-r--r--libgo/go/syscall/env_windows.go20
-rw-r--r--libgo/go/syscall/exec_unix.go62
-rw-r--r--libgo/go/syscall/exec_windows.go20
-rw-r--r--libgo/go/syscall/security_windows.go30
-rw-r--r--libgo/go/syscall/syscall.go39
-rw-r--r--libgo/go/syscall/syscall_linux_386.go8
-rw-r--r--libgo/go/testing/testing.go87
-rw-r--r--libgo/go/text/tabwriter/tabwriter.go2
-rw-r--r--libgo/go/text/template/doc.go2
-rw-r--r--libgo/go/text/template/exec_test.go2
-rw-r--r--libgo/go/text/template/funcs.go4
-rw-r--r--libgo/go/text/template/parse/lex.go5
-rw-r--r--libgo/go/text/template/parse/lex_test.go4
-rw-r--r--libgo/go/time/time.go6
-rwxr-xr-xlibgo/mksysinfo.sh10
-rw-r--r--libgo/runtime/chan.c16
-rw-r--r--libgo/runtime/cpuprof.c14
-rw-r--r--libgo/runtime/print.c4
-rw-r--r--libgo/runtime/runtime.c6
-rw-r--r--libstdc++-v3/ChangeLog94
-rw-r--r--libstdc++-v3/Makefile.am2
-rw-r--r--libstdc++-v3/Makefile.in6
-rw-r--r--libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver8
-rwxr-xr-xlibstdc++-v3/configure64
-rw-r--r--libstdc++-v3/configure.ac40
-rw-r--r--libstdc++-v3/doc/Makefile.in4
-rw-r--r--libstdc++-v3/doc/xml/manual/build_hacking.xml160
-rw-r--r--libstdc++-v3/include/Makefile.in4
-rw-r--r--libstdc++-v3/include/bits/atomic_base.h2
-rw-r--r--libstdc++-v3/include/bits/random.h265
-rw-r--r--libstdc++-v3/include/bits/random.tcc28
-rw-r--r--libstdc++-v3/include/bits/shared_ptr_base.h4
-rw-r--r--libstdc++-v3/libsupc++/Makefile.am76
-rw-r--r--libstdc++-v3/libsupc++/Makefile.in30
-rw-r--r--libstdc++-v3/po/Makefile.in4
-rw-r--r--libstdc++-v3/python/Makefile.in4
-rw-r--r--libstdc++-v3/src/Makefile.am45
-rw-r--r--libstdc++-v3/src/Makefile.in49
-rw-r--r--libstdc++-v3/src/c++11/Makefile.am22
-rw-r--r--libstdc++-v3/src/c++11/Makefile.in26
-rw-r--r--libstdc++-v3/src/c++11/compatibility-atomic-c++0x.cc4
-rw-r--r--libstdc++-v3/src/c++11/compatibility-c++0x.cc2
-rw-r--r--libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc8
-rw-r--r--libstdc++-v3/src/c++98/Makefile.am22
-rw-r--r--libstdc++-v3/src/c++98/Makefile.in26
-rw-r--r--libstdc++-v3/src/c++98/compatibility-list-2.cc2
-rw-r--r--libstdc++-v3/src/c++98/compatibility.cc6
-rw-r--r--libstdc++-v3/testsuite/17_intro/shared_with_static_deps.cc33
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/cons/55123.cc30
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/55028-debug.cc40
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/cons/55215.cc58
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/cons/55215.cc60
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/cons/55215.cc58
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/cons/55215.cc58
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/cons/55215.cc58
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/cons/55215.cc58
-rw-r--r--libstdc++-v3/testsuite/Makefile.in4
273 files changed, 5511 insertions, 1308 deletions
diff --git a/ChangeLog.linaro b/ChangeLog.linaro
index de06d5d4d37..8af28827bd2 100644
--- a/ChangeLog.linaro
+++ b/ChangeLog.linaro
@@ -1,10 +1,14 @@
+2012-11-07 Michael Hope <michael.hope@linaro.org>
+
+ Merge from FSF GCC 4.7.2 (svn branches/gcc-4_7-branch 193200).
+
2012-10-18 Michael Hope <michael.hope@linaro.org>
Merge from FSF arm/aarch64-4.7-branch r192117..r192536.
Backport arm-aarch64-4.7 r192117:
[AARCH64-4.7] Add missing constraints to fnmadd.
-
+
* config/aarch64/aarch64.md (*fnmadd<mode>4): Add missing
constraints.
@@ -13,17 +17,17 @@
Backport arm-aarch64-4.7 r192501:
[AARCH64-4.7] Add predefines for AArch64 code models.
-
+
2012-10-16 Chris Schlumberger-Socha <chris.schlumberger-socha@arm.com>
-
+
* config/aarch64/aarch64.h (TARGET_CPU_CPP_BUILTINS): Add predefine for
AArch64 code models.
Backport arm-aarch64-4.7 r192504:
[AARCH64-4.7] Fix ICE in aarch64_split_doubleword_move.
-
+
2012-10-16 Marcus Shawcroft <marcus.shawcroft@arm.com>
-
+
* config/aarch64/aarch64-protos.h (aarch64_split_doubleword_move):
Rename to aarch64_split_128bit_move.
(aarch64_split_128bit_move_p): New.
@@ -40,7 +44,7 @@
Backport arm-aarch64-4.7 r192536:
[AArch64] Update logical immediate instruction pattern.
-
+
* config/aarch64/aarch64.md (<optab><mode>3):
Update constraint for operand 0.
Update scheduling attribute for the second alternative.
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7c2ebdff590..8467e9effdb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,350 @@
+2012-11-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.c (print_reg): Replace REX_INT_REG_P with
+ REX_INT_REGNO_P.
+
+2012-11-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR tree-optimization/54986
+ * gimple-fold.c (canonicalize_constructor_val): Strip again all no-op
+ conversions on entry but add them back on exit if needed.
+
+2012-11-05 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR target/55204
+ * config/i386/i386.c (ix86_address_subreg_operand): Remove stack
+ pointer check.
+ (print_reg): Use true_regnum rather than REGNO.
+ (ix86_print_operand_address): Remove SUBREG handling.
+
+2012-11-05 Jakub Jelinek <jakub@redhat.com>
+
+ Backported from mainline
+ 2012-10-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/54828
+ * gimple.h (is_gimple_sizepos): New inline function.
+ * gimplify.c (gimplify_one_sizepos): Use it. Remove useless
+ final assignment to expr variable.
+ * tree.c (RETURN_TRUE_IF_VAR): Return true also if
+ !TYPE_SIZES_GIMPLIFIED (type) and _t is going to be gimplified
+ into a local temporary.
+
+ 2012-10-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/54877
+ * tree-vect-loop.c (vect_is_simple_reduction_1): For MINUS_EXPR
+ use make_ssa_name instead of copy_ssa_name.
+
+2012-11-03 Peter Bergner <bergner@vnet.ibm.com>
+
+ Backport from mainline
+ 2012-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/53708
+ * tree-vect-data-refs.c (vect_can_force_dr_alignment_p): Preserve
+ user-supplied alignment when used with an explicit section name.
+
+2012-11-02 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/54985
+ * tree-ssa-threadedge.c (cond_arg_set_in_bb): New function extracted
+ from thread_across_edge.
+ (thread_across_edge): Use it in all cases where we might thread
+ across a back edge.
+
+2012-10-31 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/i386/i386.c (ix86_expand_prologue): Emit frame info for the
+ special register pushes before frame probing and allocation.
+
+2012-10-31 Ralf Corsépius <ralf.corsepius@rtems.org>,
+ Joel Sherrill <joel.sherrill@oarcorp.com>
+
+ * config/sparc/t-rtems: New (Custom multilibs).
+ * config/sparc/t-rtems-64: New (Custom multilibs).
+ * config.gcc (sparc64-*-rtems*): Add sparc/t-rtems-64.
+ (sparc-*-rtems*): Add sparc/t-rtems.
+
+2012-10-30 Eric Botcazou <ebotcazou@adacore.com>
+
+ * cse.c (hash_rtx_cb): Replace RTX_UNCHANGING_P with MEM_READONLY_P in
+ head comment.
+ (hash_rtx): Likewise.
+
+2012-10-29 Terry Guo <terry.guo@arm.com>
+
+ Backport from mainline
+ 2012-10-11 Terry Guo <terry.guo@arm.com>
+
+ * config/arm/arm.c (arm_arch6m): New variable to denote armv6-m
+ architecture.
+ * config/arm/arm.h (TARGET_HAVE_DMB): The armv6-m also has DMB
+ instruction.
+
+2012-10-26 Gunther Nikl <gnikl@users.sourceforge.net>
+
+ * common/config/m68k/m68k-common.c (m68k_handle_option): Set
+ gcc_options fields of opts_set for -m68020-40 and -m68020-60.
+
+2012-10-26 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * config/avr/t-rtems: Revert previous commit.
+
+2012-10-26 Terry Guo <terry.guo@arm.com>
+
+ Backport from mainline
+ 2012-10-23 Terry Guo <terry.guo@arm.com>
+
+ PR target/55019
+ * config/arm/arm.c (thumb1_expand_prologue): Don't push high regs with
+ live argument regs.
+
+2012-10-26 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * config/avr/rtems.h (TARGET_OS_CPP_BUILTINS): Remove
+ __USE_INIT_FINI__.
+ * config/avr/t-rtems (LIB1ASMFUNCS): Filter out _exit.
+
+2012-10-25 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * config.gcc (microblaze*-*-rtems*): New target.
+ * config/microblaze/rtems.h: New.
+ * config/microblaze/t-rtems: New.
+
+2012-10-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/54902
+ * tree-ssa-pre.c (fini_pre): Return TODO.
+ (execute_pre): Adjust.
+ * tree-ssa-tailmerge.c (tail_merge_optimize): Delete unreachable
+ blocks before computing dominators.
+
+2012-10-24 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2012-10-22 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (memory_address_length): Assert that non-null
+ base or index RTXes are registers. Do not check for REG RTXes.
+ Determine addr32 prefix using SImode_address_operand or
+ from original base and index RTXes. Simplify code.
+
+ 2012-10-21 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386-protos.h (memory_address_length): Add new bool
+ argument. Update all uses.
+ * config/i386/i386.c (memory_address_length): If not LEA insn, then
+ add length of addr32 prefix based on mode of base or index register.
+ (ix86_attr_length_address_default) <TYPE_LEA>: Do not handle SImode
+ addresses here. Update call to memory_address_length.
+ (ix86_print_address_operand): Use SImode_address_operand predicate.
+ * config/i386/predicates.md (SImode_address_operand): New.
+ * config/i386/i386.md (lea<mode>): Use SImode_address_operand
+ to calculate "mode" attribute. Use SImode_address_operand predicate
+ instead of open-coding accepted RTX codes.
+
+2012-10-22 Georg-Johann Lay <avr@gjlay.de>
+
+ Backport from 2012-10-22 trunk r192685.
+ * doc/invoke.texi (AVR Options): Document __AVR_ARCH__.
+ Note __AVR_<device>__ is not defined for cores.
+ Don't point to --help=target.
+ Order --mcu= documentation according to trunk:/gcc/doc/avr-mmcu.texi.
+
+2012-10-19 Marek Polacek <polacek@redhat.com>
+
+ Backported from mainline
+ 2012-10-19 Marek Polacek <polacek@redhat.com>
+
+ PR middle-end/54945
+ * fold-const.c (fold_sign_changed_comparison): Punt if folding
+ pointer/non-pointer comparison.
+
+2012-10-19 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ Backported from mainline
+ 2012-10-19 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ PR target/54892
+ * config/arm/arm.c (arm_expand_compare_and_swap): Use SImode to make
+ sure the mode is correct when falling through from above cases.
+
+2012-10-19 Alan Modra <amodra@gmail.com>
+
+ * configure.ac (HAVE_LD_NO_DOT_SYMS): Set if using gold.
+ (HAVE_LD_LARGE_TOC): Likewise.
+ * configure: Regenerate.
+
+2012-10-19 Alan Modra <amodra@gmail.com>
+
+ * config/rs6000/predicates.md (splat_input_operand): Don't call
+ input_operand for MEMs. Instead check for volatile and call
+ memory_address_addr_space_p with modified mode.
+
+2012-10-17 Matthew Gretton-Dann <matthew.gretton-dann@linaro.org>
+
+ Backported from mainline
+ 2012-07-23 Ulrich Weigand <ulrich.weigand@linaro.org>
+
+ * config/arm/arm.c (arm_reorg): Ensure all insns are split.
+
+2012-10-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/54870
+ * tree.h (TREE_ADDRESSABLE): Document special usage on SSA_NAME.
+ * cfgexpand.c (update_alias_info_with_stack_vars ): Set it on the
+ SSA_NAME pointer that points to a partition if there is at least
+ one variable with it set in the partition.
+ * dse.c (local_variable_can_escape): New predicate.
+ (can_escape): Call it.
+ * gimplify.c (mark_addressable): If this is a partitioned decl, also
+ mark the SSA_NAME pointer that points to a partition.
+
+2012-10-16 Andrey Belevantsev <abel@ispras.ru>
+
+ Backport from mainline
+ 2012-08-09 Andrey Belevantsev <abel@ispras.ru>
+
+ PR rtl-optimization/53701
+ * sel-sched.c (vinsn_vec_has_expr_p): Clarify function comment.
+ rocess not only expr's vinsns but all old vinsns from expr's
+ istory of changes.
+
+2012-10-16 Andrey Belevantsev <abel@ispras.ru>
+
+ Backport from mainline
+ 2012-07-31 Andrey Belevantsev <abel@ispras.ru>
+ PR target/53975
+
+ * sel-sched-ir.c (has_dependence_note_reg_use): Clarify comment.
+ Revert
+ 2011-08-04 Sergey Grechanik <mouseentity@ispras.ru>
+ * sel-sched-ir.c (has_dependence_note_reg_use): Call ds_full_merge
+ only if producer writes to the register given by regno.
+
+2012-09-15 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2012-10-15 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (UNSPEC_MOVU): Remove.
+ (UNSPEC_LOADU): New.
+ (UNSPEC_STOREU): Ditto.
+ (<sse>_movu<ssemodesuffix><avxsizesuffix>): Split to ...
+ (<sse>_loadu<ssemodesuffix><avxsizesuffix>): ... this and ...
+ (<sse>_storeu<ssemodesuffix><avxsizesuffix>) ... this.
+ (<sse2>_movdqu<avxsizesuffix>): Split to ...
+ (<sse2>_loaddqu<avxsizesuffix>): ... this and ...
+ (<sse2>_storedqu<avxsizesuffix>): ... this.
+ (*sse4_2_pcmpestr_unaligned): Update.
+ (*sse4_2_pcmpistr_unaligned): Ditto.
+
+ * config/i386/i386.c (ix86_avx256_split_vector_move_misalign): Use
+ gen_avx_load{dqu,ups,upd}256 to load from unaligned memory and
+ gen_avx_store{dqu,ups,upd}256 to store to unaligned memory.
+ (ix86_expand_vector_move_misalign): Use gen_sse_loadups or
+ gen_sse2_load{dqu,upd} to load from unaligned memory and
+ gen_sse_loadups or gen_sse2_store{dqu,upd}256 to store to
+ unaligned memory.
+ (struct builtin_description bdesc_spec) <IX86_BUILTIN_LOADUPS>:
+ Use CODE_FOR_sse_loadups.
+ <IX86_BUILTIN_LOADUPD>: Use CODE_FOR_sse2_loadupd.
+ <IX86_BUILTIN_LOADDQU>: Use CODE_FOR_sse2_loaddqu.
+ <IX86_BUILTIN_STOREUPS>: Use CODE_FOR_sse_storeups.
+ <IX86_BUILTIN_STOREUPD>: Use CODE_FOR_sse2_storeupd.
+ <IX86_BUILTIN_STOREDQU>: Use CODE_FOR_sse2_storedqu.
+ <IX86_BUILTIN_LOADUPS256>: Use CODE_FOR_avx_loadups256.
+ <IX86_BUILTIN_LOADUPD256>: Use CODE_FOR_avx_loadupd256.
+ <IX86_BUILTIN_LOADDQU256>: Use CODE_FOR_avx_loaddqu256.
+ <IX86_BUILTIN_STOREUPS256>: Use CODE_FOR_avx_storeups256.
+ <IX86_BUILTIN_STOREUPD256>: Use CODE_FOR_avx_storeupd256.
+ <IX86_BUILTIN_STOREDQU256>: Use CODE_FOR_avx_storedqu256.
+
+2012-10-15 Steven Bosscher <steven@gcc.gnu.org>
+
+ Backport from trunk (r190222):
+
+ PR tree-optimization/54146
+ * ifcvt.c: Include pointer-set.h.
+ (cond_move_process_if_block): Change type of then_regs and
+ else_regs from alloca'd array to pointer_sets.
+ (check_cond_move_block): Update for this change.
+ (cond_move_convert_if_block): Likewise.
+ * Makefile.in: Fix dependencies for ifcvt.o.
+
+2012-10-15 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/54920
+ * tree-ssa-pre.c (create_expression_by_pieces): Properly
+ allocate temporary storage for all NARY elements.
+
+2012-10-08 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/54854
+ * doc/invoke.texi (AVR Options): Deprecate -mshort-calls.
+
+2012-10-05 Mark Kettenis <kettenis@openbsd.org>
+
+ * config.gcc (*-*-openbsd4.[3-9]|*-*-openbsd[5-9]*): Set
+ default_use_cxa_atexit to yes.
+
+2012-10-05 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
+
+ * config/pa/pa.md: Adjust unamed HImode add insn pattern.
+
+2012-10-05 Jan Hubicka <jh@suse.cz>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/33763
+ * tree-inline.c (expand_call_inline): Silently ignore always_inline
+ attribute for redefined extern inline functions.
+
+2012-10-03 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backported from mainline
+ 2012-10-03 Andrew W. Nosenko <andrew.w.nosenko@gmail.com>
+
+ * config/i386/driver-i386.c (host_detect_local_cpu): Fix logic
+ in SSE and YMM state support check for -march=native.
+
+2012-10-03 Alexandre Oliva <aoliva@redhat.com>
+
+ PR debug/53135
+ * dwarf2out.c (value_format): Use block4 for dw_val_class_loc
+ when needed.
+
+2012-10-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backported from mainline
+ 2012-10-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/54785
+ * doc/invoke.texi: Document -mprefer-avx128.
+
+2012-10-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backported from mainline
+ 2012-10-02 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/54741
+ * config/i386/driver-i386.c (XCR_XFEATURE_ENABLED_MASK): New.
+ (XSTATE_FP): Likewise.
+ (XSTATE_SSE): Likewise.
+ (XSTATE_YMM): Likewise.
+ (host_detect_local_cpu): Disable AVX, AVX2, FMA, FMA4 and XOP if
+ SSE and YMM states aren't supported.
+
+2012-10-01 Tom de Vries <tom@codesourcery.com>
+
+ * var-tracking.c (set_dv_changed): Add an 'inline' function specifier to
+ the prototype.
+
+2012-10-01 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ PR target/54746
+ * config/s390/s390.c (s390_option_override): Add missing break.
+
2012-09-29 Andreas Tobler <andreast@fgznet.ch>
Backport from mainline
@@ -23,8 +370,7 @@
PR target/54703
* simplify-rtx.c (simplify_binary_operation_1): Perform
- (x - (x & y)) -> (x & ~y) optimization only for integral
- modes.
+ (x - (x & y)) -> (x & ~y) optimization only for integral modes.
2012-09-24 Eric Botcazou <ebotcazou@adacore.com>
@@ -102,12 +448,12 @@
Backport from mainline
2012-09-07 Andi Kleen <ak@linux.intel.com>
- * gcc/lto-streamer.h (res_pair): Add.
- (lto_file_decl_data): Replace resolutions with respairs.
- Add max_index.
- * gcc/lto/lto.c (lto_resolution_read): Remove max_index. Add rp.
- Initialize respairs.
- (lto_file_finalize): Set up resolutions vector lazily from respairs.
+ * gcc/lto-streamer.h (res_pair): Add.
+ (lto_file_decl_data): Replace resolutions with respairs.
+ Add max_index.
+ * gcc/lto/lto.c (lto_resolution_read): Remove max_index. Add rp.
+ Initialize respairs.
+ (lto_file_finalize): Set up resolutions vector lazily from respairs.
2012-09-14 Walter Lee <walt@tilera.com>
@@ -173,7 +519,7 @@
2012-09-12 Christian Bruel <christian.bruel@st.com>
- * config/sh/newlib.h (NO_IMPLICIT_EXTERN_C): Define.
+ * config/sh/newlib.h (NO_IMPLICIT_EXTERN_C): Define.
2012-09-12 Jakub Jelinek <jakub@redhat.com>
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 3be6b6d4db2..8dbf6812d54 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20121001
+20121106
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index a49bb6b9c1e..0b015a4821d 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3418,7 +3418,7 @@ regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(REGS_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) insn-config.h $(FUNCTION_H) $(RECOG_H) \
$(TARGET_H) $(BASIC_BLOCK_H) $(EXPR_H) output.h $(EXCEPT_H) $(TM_P_H) \
- $(OPTABS_H) $(CFGLOOP_H) hard-reg-set.h $(TIMEVAR_H) \
+ $(OPTABS_H) $(CFGLOOP_H) hard-reg-set.h pointer-set.h $(TIMEVAR_H) \
$(TREE_PASS_H) $(DF_H) $(DBGCNT_H)
params.o : params.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(COMMON_TARGET_H) \
$(PARAMS_H) $(DIAGNOSTIC_CORE_H)
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 9a48ee5d1a3..c8c9b74d4f5 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,36 @@
+2012-10-30 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/Make-lang.in: Fix and clean up rules for C files.
+
+2012-10-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Type>: Force
+ BLKmode on the type if it is passed by reference.
+ <E_Array_Subtype>: Likewise.
+ <E_Record_Type>: Guard the call to Is_By_Reference_Type predicate.
+ <E_Record_Subtype>: Likewise.
+
+ * gcc-interface/Makefile.in: Remove outdated comment and reference to
+ non-existing file.
+
+2012-10-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Loop_Statement_to_gnu): Use gnat_type_for_size
+ directly to obtain an unsigned version of the base type.
+
+2012-10-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Out_Parameter>: Do not
+ generate the special PARM_DECL for an Out parameter in LTO mode.
+
+2012-10-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interfaces/decl.c (elaborate_expression_1): Use the variable for
+ bounds of loop iteraration scheme only for locally defined subtypes.
+
+ * gcc-interface/trans.c (build_return_expr): Apply the NRV optimization
+ only for BLKmode.
+
2012-09-20 Release Manager
* GCC 4.7.2 released.
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index 06a88030bdb..289f0b7f8b9 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -1225,33 +1225,20 @@ ada/mdll-fil.o : ada/mdll-fil.adb ada/mdll.ads ada/mdll-fil.ads
ada/mdll-utl.o : ada/mdll-utl.adb ada/mdll.ads ada/mdll-utl.ads ada/sdefault.ads ada/types.ads
$(CC) -c $(ALL_ADAFLAGS) $(ADA_INCLUDES) $< $(OUTPUT_OPTION)
-ada/adadecode.o : ada/adadecode.c $(CONFIG_H) $(SYSTEM_H) ada/adadecode.h
-ada/adaint.o : ada/adaint.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
-ada/argv.o : ada/argv.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
-ada/cstreams.o : ada/cstreams.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
-ada/exit.o : ada/exit.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
-ada/final.o : ada/final.c $(CONFIG_H) $(SYSTEM_H) ada/raise.h
-ada/link.o : ada/link.c
-
-ada/targext.o : ada/targext.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
- $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-
+ada/adadecode.o : ada/adadecode.c $(CONFIG_H) $(SYSTEM_H) ada/adadecode.h ada/adaint.h
+ada/adaint.o : ada/adaint.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h version.h
+ada/argv.o : ada/argv.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
ada/cio.o : ada/cio.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
- $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-
+ada/cstreams.o : ada/cstreams.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
+ada/env.o: ada/env.c $(CONFIG_H) $(SYSTEM_H) ada/env.h
+ada/exit.o : ada/exit.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
+ada/final.o : ada/final.c
ada/init.o : ada/init.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h ada/raise.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
- $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-
-ada/initialize.o : ada/initialize.c
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
- $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-
+ada/initialize.o : ada/initialize.c $(CONFIG_H) $(SYSTEM_H) ada/raise.h
+ada/link.o : ada/link.c auto-host.h
ada/raise.o : ada/raise.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h ada/raise.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
- $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+ada/seh_init.o: ada/seh_init.c $(CONFIG_H) $(SYSTEM_H) ada/raise.h
+ada/targext.o : ada/targext.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
ada/cuintp.o : ada/gcc-interface/cuintp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) ada/gcc-interface/ada.h ada/types.h ada/uintp.h \
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index f9e7edab3e1..9b5135e6f89 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -1242,7 +1242,6 @@ ifeq ($(strip $(filter-out %86_64 freebsd%,$(arch) $(osys))),)
s-taprop.adb<s-taprop-posix.adb \
s-taspri.ads<s-taspri-posix.ads \
s-tpopsp.adb<s-tpopsp-posix.adb \
- g-trasym.adb<g-trasym-dwarf.adb \
$(ATOMICS_TARGET_PAIRS) \
$(X86_64_TARGET_PAIRS) \
system.ads<system-freebsd-x86_64.ads
@@ -2518,8 +2517,6 @@ install-gnatlib: ../stamp-gnatlib-$(RTSDIR)
$(RM) ../stamp-gnatlib-$(RTSDIR)
touch ../stamp-gnatlib1-$(RTSDIR)
-# GNULLI End #############################################################
-
ifeq ($(strip $(filter-out alpha64 ia64 dec hp vms% openvms% alphavms%,$(subst -, ,$(host)))),)
OSCONS_CPP=../../$(DECC) -E /comment=as_is -DNATIVE \
-DTARGET='""$(target)""' $(fsrcpfx)ada/s-oscons-tmplt.c
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 33cad2c9f5c..97f8d65d2f5 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -1508,7 +1508,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
the VAR_DECL. Suppress debug info for the latter but make sure it
will live on the stack so that it can be accessed from within the
debugger through the PARM_DECL. */
- if (kind == E_Out_Parameter && definition && !optimize && debug_info_p)
+ if (kind == E_Out_Parameter
+ && definition
+ && debug_info_p
+ && !optimize
+ && !flag_generate_lto)
{
tree param = create_param_decl (gnu_entity_name, gnu_type, false);
gnat_pushdecl (param, gnat_entity);
@@ -2251,6 +2255,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
TYPE_MULTI_ARRAY_P (tem) = (index > 0);
if (array_type_has_nonaliased_component (tem, gnat_entity))
TYPE_NONALIASED_COMPONENT (tem) = 1;
+
+ /* If it is passed by reference, force BLKmode to ensure that
+ objects of this type will always be put in memory. */
+ if (TYPE_MODE (tem) != BLKmode
+ && Is_By_Reference_Type (gnat_entity))
+ SET_TYPE_MODE (tem, BLKmode);
}
/* If an alignment is specified, use it if valid. But ignore it
@@ -2590,6 +2600,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
TYPE_MULTI_ARRAY_P (gnu_type) = (index > 0);
if (array_type_has_nonaliased_component (gnu_type, gnat_entity))
TYPE_NONALIASED_COMPONENT (gnu_type) = 1;
+
+ /* See the E_Array_Type case for the rationale. */
+ if (TYPE_MODE (gnu_type) != BLKmode
+ && Is_By_Reference_Type (gnat_entity))
+ SET_TYPE_MODE (gnu_type, BLKmode);
}
/* Attach the TYPE_STUB_DECL in case we have a parallel type. */
@@ -3158,7 +3173,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
/* If it is passed by reference, force BLKmode to ensure that objects
of this type will always be put in memory. */
- if (Is_By_Reference_Type (gnat_entity))
+ if (TYPE_MODE (gnu_type) != BLKmode
+ && Is_By_Reference_Type (gnat_entity))
SET_TYPE_MODE (gnu_type, BLKmode);
/* We used to remove the associations of the discriminants and _Parent
@@ -3526,12 +3542,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
modify it below. */
gnu_field_list = nreverse (gnu_field_list);
finish_record_type (gnu_type, gnu_field_list, 2, false);
+ compute_record_mode (gnu_type);
/* See the E_Record_Type case for the rationale. */
- if (Is_By_Reference_Type (gnat_entity))
+ if (TYPE_MODE (gnu_type) != BLKmode
+ && Is_By_Reference_Type (gnat_entity))
SET_TYPE_MODE (gnu_type, BLKmode);
- else
- compute_record_mode (gnu_type);
TYPE_VOLATILE (gnu_type) = Treat_As_Volatile (gnat_entity);
@@ -6346,6 +6362,7 @@ elaborate_expression_1 (tree gnu_expr, Entity_Id gnat_entity, tree gnu_name,
use_variable = expr_variable_p
&& (expr_global_p
|| (!optimize
+ && definition
&& Is_Itype (gnat_entity)
&& Nkind (Associated_Node_For_Itype (gnat_entity))
== N_Loop_Parameter_Specification));
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 61648c5664d..aabe9b6bd02 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -2402,7 +2402,8 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
{
if (TYPE_PRECISION (gnu_base_type)
> TYPE_PRECISION (size_type_node))
- gnu_base_type = gnat_unsigned_type (gnu_base_type);
+ gnu_base_type
+ = gnat_type_for_size (TYPE_PRECISION (gnu_base_type), 1);
else
gnu_base_type = size_type_node;
@@ -3123,6 +3124,7 @@ build_return_expr (tree ret_obj, tree ret_val)
if (optimize
&& AGGREGATE_TYPE_P (operation_type)
&& !TYPE_IS_FAT_POINTER_P (operation_type)
+ && TYPE_MODE (operation_type) == BLKmode
&& aggregate_value_p (operation_type, current_function_decl))
{
/* Recognize the temporary created for a return value with variable
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index bde15f69683..c2385685ead 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -697,6 +697,8 @@ update_alias_info_with_stack_vars (void)
(void *)(size_t) uid)) = part;
*((tree *) pointer_map_insert (cfun->gimple_df->decls_to_pointers,
decl)) = name;
+ if (TREE_ADDRESSABLE (decl))
+ TREE_ADDRESSABLE (name) = 1;
}
/* Make the SSA name point to all partition members. */
diff --git a/gcc/common/config/m68k/m68k-common.c b/gcc/common/config/m68k/m68k-common.c
index 3a81b678a24..55b3e4a59c2 100644
--- a/gcc/common/config/m68k/m68k-common.c
+++ b/gcc/common/config/m68k/m68k-common.c
@@ -1,6 +1,6 @@
/* Common hooks for Motorola 68000 family.
Copyright (C) 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This file is part of GCC.
@@ -33,7 +33,7 @@ along with GCC; see the file COPYING3. If not see
static bool
m68k_handle_option (struct gcc_options *opts,
- struct gcc_options *opts_set ATTRIBUTE_UNUSED,
+ struct gcc_options *opts_set,
const struct cl_decoded_option *decoded,
location_t loc)
{
@@ -45,12 +45,16 @@ m68k_handle_option (struct gcc_options *opts,
{
case OPT_m68020_40:
opts->x_m68k_tune_option = u68020_40;
+ opts_set->x_m68k_tune_option = (enum uarch_type) 1;
opts->x_m68k_cpu_option = m68020;
+ opts_set->x_m68k_cpu_option = (enum target_device) 1;
return true;
case OPT_m68020_60:
opts->x_m68k_tune_option = u68020_60;
+ opts_set->x_m68k_tune_option = (enum uarch_type) 1;
opts->x_m68k_cpu_option = m68020;
+ opts_set->x_m68k_cpu_option = (enum target_device) 1;
return true;
case OPT_mshared_library_id_:
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 088ee87aa6a..493d0ce930c 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -699,6 +699,11 @@ case ${target} in
*-*-openbsd2.*|*-*-openbsd3.[012])
tm_defines="${tm_defines} HAS_LIBC_R=1" ;;
esac
+ case ${target} in
+ *-*-openbsd4.[3-9]|*-*-openbsd[5-9]*)
+ default_use_cxa_atexit=yes
+ ;;
+ esac
;;
*-*-rtems*)
case ${enable_threads} in
@@ -1751,6 +1756,14 @@ microblaze*-linux*)
c_target_objs="${c_target_objs} microblaze-c.o"
cxx_target_objs="${cxx_target_objs} microblaze-c.o"
;;
+microblaze*-*-rtems*)
+ tm_file="${tm_file} dbxelf.h"
+ tm_file="${tm_file} microblaze/rtems.h rtems.h newlib-stdint.h"
+ c_target_objs="${c_target_objs} microblaze-c.o"
+ cxx_target_objs="${cxx_target_objs} microblaze-c.o"
+ tmake_file="${tmake_file} microblaze/t-microblaze"
+ tmake_file="${tmake_file} t-rtems microblaze/t-rtems"
+ ;;
microblaze*-*-*)
tm_file="${tm_file} dbxelf.h"
c_target_objs="${c_target_objs} microblaze-c.o"
@@ -2432,7 +2445,7 @@ sparc-*-elf*)
;;
sparc-*-rtems*)
tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h sparc/sp-elf.h sparc/rtemself.h rtems.h newlib-stdint.h"
- tmake_file="sparc/t-sparc sparc/t-elf t-rtems"
+ tmake_file="sparc/t-sparc sparc/t-elf sparc/t-rtems t-rtems"
;;
sparc-*-linux*)
tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/tso.h"
@@ -2485,7 +2498,7 @@ sparc64-*-elf*)
sparc64-*-rtems*)
tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp64-elf.h sparc/rtemself.h rtems.h"
extra_options="${extra_options}"
- tmake_file="${tmake_file} sparc/t-sparc t-rtems"
+ tmake_file="${tmake_file} sparc/t-sparc sparc/t-rtems-64 t-rtems"
;;
sparc64-*-linux*)
tm_file="sparc/biarch64.h ${tm_file} dbxelf.h elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/default-64.h sparc/linux64.h sparc/tso.h"
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 61e7c0ecf63..7d347381209 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -745,6 +745,9 @@ int arm_arch6 = 0;
/* Nonzero if this chip supports the ARM 6K extensions. */
int arm_arch6k = 0;
+/* Nonzero if instructions present in ARMv6-M can be used. */
+int arm_arch6m = 0;
+
/* Nonzero if this chip supports the ARM 7 extensions. */
int arm_arch7 = 0;
@@ -1704,6 +1707,7 @@ arm_option_override (void)
arm_arch6 = (insn_flags & FL_ARCH6) != 0;
arm_arch6k = (insn_flags & FL_ARCH6K) != 0;
arm_arch_notm = (insn_flags & FL_NOTM) != 0;
+ arm_arch6m = arm_arch6 && !arm_arch_notm;
arm_arch7 = (insn_flags & FL_ARCH7) != 0;
arm_arch7em = (insn_flags & FL_ARCH7EM) != 0;
arm_arch_thumb2 = (insn_flags & FL_THUMB2) != 0;
@@ -13589,6 +13593,13 @@ arm_reorg (void)
if (TARGET_THUMB2)
thumb2_reorg ();
+ /* Ensure all insns that must be split have been split at this point.
+ Otherwise, the pool placement code below may compute incorrect
+ insn lengths. Note that when optimizing, all insns have already
+ been split at this point. */
+ if (!optimize)
+ split_all_insns_noflow ();
+
minipool_fix_head = minipool_fix_tail = NULL;
/* The first insn must always be a note, or the code below won't
@@ -22582,12 +22593,18 @@ thumb1_expand_prologue (void)
{
unsigned pushable_regs;
unsigned next_hi_reg;
+ unsigned arg_regs_num = TARGET_AAPCS_BASED ? crtl->args.info.aapcs_ncrn
+ : crtl->args.info.nregs;
+ unsigned arg_regs_mask = (1 << arg_regs_num) - 1;
for (next_hi_reg = 12; next_hi_reg > LAST_LO_REGNUM; next_hi_reg--)
if (live_regs_mask & (1 << next_hi_reg))
break;
- pushable_regs = l_mask & 0xff;
+ /* Here we need to mask out registers used for passing arguments
+ even if they can be pushed. This is to avoid using them to stash the high
+ registers. Such kind of stash may clobber the use of arguments. */
+ pushable_regs = l_mask & (~arg_regs_mask) & 0xff;
if (pushable_regs == 0)
pushable_regs = 1 << thumb_find_work_register (live_regs_mask);
@@ -25148,8 +25165,8 @@ arm_expand_compare_and_swap (rtx operands[])
case SImode:
/* Force the value into a register if needed. We waited until after
the zero-extension above to do this properly. */
- if (!arm_add_operand (oldval, mode))
- oldval = force_reg (mode, oldval);
+ if (!arm_add_operand (oldval, SImode))
+ oldval = force_reg (SImode, oldval);
break;
case DImode:
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 6fbb469bd6a..eb147155281 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -267,7 +267,7 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
#define TARGET_UNIFIED_ASM TARGET_THUMB2
/* Nonzero if this chip provides the DMB instruction. */
-#define TARGET_HAVE_DMB (arm_arch7)
+#define TARGET_HAVE_DMB (arm_arch6m || arm_arch7)
/* Nonzero if this chip implements a memory barrier via CP15. */
#define TARGET_HAVE_DMB_MCR (arm_arch6 && ! TARGET_HAVE_DMB \
@@ -383,6 +383,9 @@ extern int arm_arch6;
/* Nonzero if this chip supports the ARM Architecture 6k extensions. */
extern int arm_arch6k;
+/* Nonzero if instructions present in ARMv6-M can be used. */
+extern int arm_arch6m;
+
/* Nonzero if this chip supports the ARM Architecture 7 extensions. */
extern int arm_arch7;
diff --git a/gcc/config/avr/rtems.h b/gcc/config/avr/rtems.h
index efd8afacefa..4a9c1b4d67b 100644
--- a/gcc/config/avr/rtems.h
+++ b/gcc/config/avr/rtems.h
@@ -23,6 +23,5 @@ along with GCC; see the file COPYING3. If not see
#define TARGET_OS_CPP_BUILTINS() \
do { \
builtin_define ("__rtems__"); \
- builtin_define ("__USE_INIT_FINI__"); \
builtin_assert ("system=rtems"); \
} while (0)
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 0c006a342d0..7b5e4d7c145 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -398,6 +398,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
unsigned int has_fma = 0, has_fma4 = 0, has_xop = 0;
unsigned int has_bmi = 0, has_bmi2 = 0, has_tbm = 0, has_lzcnt = 0;
unsigned int has_rdrnd = 0, has_f16c = 0, has_fsgsbase = 0;
+ unsigned int has_osxsave = 0;
bool arch;
@@ -439,6 +440,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
has_sse4_1 = ecx & bit_SSE4_1;
has_sse4_2 = ecx & bit_SSE4_2;
has_avx = ecx & bit_AVX;
+ has_osxsave = ecx & bit_OSXSAVE;
has_cmpxchg16b = ecx & bit_CMPXCHG16B;
has_movbe = ecx & bit_MOVBE;
has_popcnt = ecx & bit_POPCNT;
@@ -464,6 +466,27 @@ const char *host_detect_local_cpu (int argc, const char **argv)
has_fsgsbase = ebx & bit_FSGSBASE;
}
+ /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */
+#define XCR_XFEATURE_ENABLED_MASK 0x0
+#define XSTATE_FP 0x1
+#define XSTATE_SSE 0x2
+#define XSTATE_YMM 0x4
+ if (has_osxsave)
+ asm (".byte 0x0f; .byte 0x01; .byte 0xd0"
+ : "=a" (eax), "=d" (edx)
+ : "c" (XCR_XFEATURE_ENABLED_MASK));
+
+ /* Check if SSE and YMM states are supported. */
+ if (!has_osxsave
+ || (eax & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM))
+ {
+ has_avx = 0;
+ has_avx2 = 0;
+ has_fma = 0;
+ has_fma4 = 0;
+ has_xop = 0;
+ }
+
/* Check cpuid level of extended features. */
__cpuid (0x80000000, ext_level, ebx, ecx, edx);
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 14bc6729a98..3eb5ef87f73 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -270,7 +270,7 @@ struct ix86_address
};
extern int ix86_decompose_address (rtx, struct ix86_address *);
-extern int memory_address_length (rtx addr);
+extern int memory_address_length (rtx, bool);
extern void x86_output_aligned_bss (FILE *, tree, const char *,
unsigned HOST_WIDE_INT, int);
extern void x86_elf_aligned_common (FILE *, const char *,
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index c2c6cd02c7f..b42870f663f 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -10339,7 +10339,7 @@ ix86_expand_prologue (void)
rtx eax = gen_rtx_REG (Pmode, AX_REG);
rtx r10 = NULL;
rtx (*adjust_stack_insn)(rtx, rtx, rtx);
-
+ const bool sp_is_cfa_reg = (m->fs.cfa_reg == stack_pointer_rtx);
bool eax_live = false;
bool r10_live = false;
@@ -10348,16 +10348,31 @@ ix86_expand_prologue (void)
if (!TARGET_64BIT_MS_ABI)
eax_live = ix86_eax_live_at_start_p ();
+ /* Note that SEH directives need to continue tracking the stack
+ pointer even after the frame pointer has been set up. */
if (eax_live)
{
- emit_insn (gen_push (eax));
+ insn = emit_insn (gen_push (eax));
allocate -= UNITS_PER_WORD;
+ if (sp_is_cfa_reg || TARGET_SEH)
+ {
+ if (sp_is_cfa_reg)
+ m->fs.cfa_offset += UNITS_PER_WORD;
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
}
+
if (r10_live)
{
r10 = gen_rtx_REG (Pmode, R10_REG);
- emit_insn (gen_push (r10));
+ insn = emit_insn (gen_push (r10));
allocate -= UNITS_PER_WORD;
+ if (sp_is_cfa_reg || TARGET_SEH)
+ {
+ if (sp_is_cfa_reg)
+ m->fs.cfa_offset += UNITS_PER_WORD;
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
}
emit_move_insn (eax, GEN_INT (allocate));
@@ -10371,13 +10386,10 @@ ix86_expand_prologue (void)
insn = emit_insn (adjust_stack_insn (stack_pointer_rtx,
stack_pointer_rtx, eax));
- /* Note that SEH directives need to continue tracking the stack
- pointer even after the frame pointer has been set up. */
- if (m->fs.cfa_reg == stack_pointer_rtx || TARGET_SEH)
+ if (sp_is_cfa_reg || TARGET_SEH)
{
- if (m->fs.cfa_reg == stack_pointer_rtx)
+ if (sp_is_cfa_reg)
m->fs.cfa_offset += allocate;
-
RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_FRAME_RELATED_EXPR,
gen_rtx_SET (VOIDmode, stack_pointer_rtx,
@@ -11402,10 +11414,6 @@ ix86_address_subreg_operand (rtx op)
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
return false;
- /* simplify_subreg does not handle stack pointer. */
- if (REGNO (op) == STACK_POINTER_REGNUM)
- return false;
-
/* Allow only SUBREGs of non-eliminable hard registers. */
return register_no_elim_operand (op, mode);
}
@@ -13680,15 +13688,9 @@ void
print_reg (rtx x, int code, FILE *file)
{
const char *reg;
+ unsigned int regno;
bool duplicated = code == 'd' && TARGET_AVX;
- gcc_assert (x == pc_rtx
- || (REGNO (x) != ARG_POINTER_REGNUM
- && REGNO (x) != FRAME_POINTER_REGNUM
- && REGNO (x) != FLAGS_REG
- && REGNO (x) != FPSR_REG
- && REGNO (x) != FPCR_REG));
-
if (ASSEMBLER_DIALECT == ASM_ATT)
putc ('%', file);
@@ -13699,6 +13701,13 @@ print_reg (rtx x, int code, FILE *file)
return;
}
+ regno = true_regnum (x);
+ gcc_assert (regno != ARG_POINTER_REGNUM
+ && regno != FRAME_POINTER_REGNUM
+ && regno != FLAGS_REG
+ && regno != FPSR_REG
+ && regno != FPCR_REG);
+
if (code == 'w' || MMX_REG_P (x))
code = 2;
else if (code == 'b')
@@ -13720,11 +13729,11 @@ print_reg (rtx x, int code, FILE *file)
/* Irritatingly, AMD extended registers use different naming convention
from the normal registers: "r%d[bwd]" */
- if (REX_INT_REG_P (x))
+ if (REX_INT_REGNO_P (regno))
{
gcc_assert (TARGET_64BIT);
putc ('r', file);
- fprint_ul (file, REGNO (x) - FIRST_REX_INT_REG + 8);
+ fprint_ul (file, regno - FIRST_REX_INT_REG + 8);
switch (code)
{
case 0:
@@ -13768,24 +13777,24 @@ print_reg (rtx x, int code, FILE *file)
case 16:
case 2:
normal:
- reg = hi_reg_name[REGNO (x)];
+ reg = hi_reg_name[regno];
break;
case 1:
- if (REGNO (x) >= ARRAY_SIZE (qi_reg_name))
+ if (regno >= ARRAY_SIZE (qi_reg_name))
goto normal;
- reg = qi_reg_name[REGNO (x)];
+ reg = qi_reg_name[regno];
break;
case 0:
- if (REGNO (x) >= ARRAY_SIZE (qi_high_reg_name))
+ if (regno >= ARRAY_SIZE (qi_high_reg_name))
goto normal;
- reg = qi_high_reg_name[REGNO (x)];
+ reg = qi_high_reg_name[regno];
break;
case 32:
if (SSE_REG_P (x))
{
gcc_assert (!duplicated);
putc ('y', file);
- fputs (hi_reg_name[REGNO (x)] + 1, file);
+ fputs (hi_reg_name[regno] + 1, file);
return;
}
break;
@@ -14560,22 +14569,6 @@ ix86_print_operand_address (FILE *file, rtx addr)
gcc_assert (ok);
- if (parts.base && GET_CODE (parts.base) == SUBREG)
- {
- rtx tmp = SUBREG_REG (parts.base);
- parts.base = simplify_subreg (GET_MODE (parts.base),
- tmp, GET_MODE (tmp), 0);
- gcc_assert (parts.base != NULL_RTX);
- }
-
- if (parts.index && GET_CODE (parts.index) == SUBREG)
- {
- rtx tmp = SUBREG_REG (parts.index);
- parts.index = simplify_subreg (GET_MODE (parts.index),
- tmp, GET_MODE (tmp), 0);
- gcc_assert (parts.index != NULL_RTX);
- }
-
base = parts.base;
index = parts.index;
disp = parts.disp;
@@ -14628,19 +14621,24 @@ ix86_print_operand_address (FILE *file, rtx addr)
else
{
/* Print SImode register names to force addr32 prefix. */
- if (GET_CODE (addr) == SUBREG)
- {
- gcc_assert (TARGET_64BIT);
- gcc_assert (GET_MODE (addr) == SImode);
- gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
- gcc_assert (!code);
- code = 'l';
- }
- else if (GET_CODE (addr) == ZERO_EXTEND
- || GET_CODE (addr) == AND)
+ if (SImode_address_operand (addr, VOIDmode))
{
+#ifdef ENABLE_CHECKING
gcc_assert (TARGET_64BIT);
- gcc_assert (GET_MODE (addr) == DImode);
+ switch (GET_CODE (addr))
+ {
+ case SUBREG:
+ gcc_assert (GET_MODE (addr) == SImode);
+ gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
+ break;
+ case ZERO_EXTEND:
+ case AND:
+ gcc_assert (GET_MODE (addr) == DImode);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+#endif
gcc_assert (!code);
code = 'l';
}
@@ -15708,7 +15706,8 @@ ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
{
rtx m;
rtx (*extract) (rtx, rtx, rtx);
- rtx (*move_unaligned) (rtx, rtx);
+ rtx (*load_unaligned) (rtx, rtx);
+ rtx (*store_unaligned) (rtx, rtx);
enum machine_mode mode;
switch (GET_MODE (op0))
@@ -15717,39 +15716,52 @@ ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1)
gcc_unreachable ();
case V32QImode:
extract = gen_avx_vextractf128v32qi;
- move_unaligned = gen_avx_movdqu256;
+ load_unaligned = gen_avx_loaddqu256;
+ store_unaligned = gen_avx_storedqu256;
mode = V16QImode;
break;
case V8SFmode:
extract = gen_avx_vextractf128v8sf;
- move_unaligned = gen_avx_movups256;
+ load_unaligned = gen_avx_loadups256;
+ store_unaligned = gen_avx_storeups256;
mode = V4SFmode;
break;
case V4DFmode:
extract = gen_avx_vextractf128v4df;
- move_unaligned = gen_avx_movupd256;
+ load_unaligned = gen_avx_loadupd256;
+ store_unaligned = gen_avx_storeupd256;
mode = V2DFmode;
break;
}
- if (MEM_P (op1) && TARGET_AVX256_SPLIT_UNALIGNED_LOAD)
+ if (MEM_P (op1))
{
- rtx r = gen_reg_rtx (mode);
- m = adjust_address (op1, mode, 0);
- emit_move_insn (r, m);
- m = adjust_address (op1, mode, 16);
- r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m);
- emit_move_insn (op0, r);
+ if (TARGET_AVX256_SPLIT_UNALIGNED_LOAD)
+ {
+ rtx r = gen_reg_rtx (mode);
+ m = adjust_address (op1, mode, 0);
+ emit_move_insn (r, m);
+ m = adjust_address (op1, mode, 16);
+ r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m);
+ emit_move_insn (op0, r);
+ }
+ else
+ emit_insn (load_unaligned (op0, op1));
}
- else if (MEM_P (op0) && TARGET_AVX256_SPLIT_UNALIGNED_STORE)
+ else if (MEM_P (op0))
{
- m = adjust_address (op0, mode, 0);
- emit_insn (extract (m, op1, const0_rtx));
- m = adjust_address (op0, mode, 16);
- emit_insn (extract (m, op1, const1_rtx));
+ if (TARGET_AVX256_SPLIT_UNALIGNED_STORE)
+ {
+ m = adjust_address (op0, mode, 0);
+ emit_insn (extract (m, op1, const0_rtx));
+ m = adjust_address (op0, mode, 16);
+ emit_insn (extract (m, op1, const1_rtx));
+ }
+ else
+ emit_insn (store_unaligned (op0, op1));
}
else
- emit_insn (move_unaligned (op0, op1));
+ gcc_unreachable ();
}
/* Implement the movmisalign patterns for SSE. Non-SSE modes go
@@ -15808,6 +15820,7 @@ void
ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
{
rtx op0, op1, m;
+ rtx (*move_unaligned) (rtx, rtx);
op0 = operands[0];
op1 = operands[1];
@@ -15824,14 +15837,28 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
/* If we're optimizing for size, movups is the smallest. */
if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
{
+ if (MEM_P (op1))
+ move_unaligned = gen_sse_loadups;
+ else if (MEM_P (op0))
+ move_unaligned = gen_sse_storeups;
+ else
+ gcc_unreachable ();
+
op0 = gen_lowpart (V4SFmode, op0);
op1 = gen_lowpart (V4SFmode, op1);
- emit_insn (gen_sse_movups (op0, op1));
+ emit_insn (move_unaligned (op0, op1));
return;
}
+ if (MEM_P (op1))
+ move_unaligned = gen_sse2_loaddqu;
+ else if (MEM_P (op0))
+ move_unaligned = gen_sse2_storedqu;
+ else
+ gcc_unreachable ();
+
op0 = gen_lowpart (V16QImode, op0);
op1 = gen_lowpart (V16QImode, op1);
- emit_insn (gen_sse2_movdqu (op0, op1));
+ emit_insn (move_unaligned (op0, op1));
break;
case 32:
op0 = gen_lowpart (V32QImode, op0);
@@ -15849,7 +15876,14 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
switch (mode)
{
case V4SFmode:
- emit_insn (gen_sse_movups (op0, op1));
+ if (MEM_P (op1))
+ move_unaligned = gen_sse_loadups;
+ else if (MEM_P (op0))
+ move_unaligned = gen_sse_storeups;
+ else
+ gcc_unreachable ();
+
+ emit_insn (move_unaligned (op0, op1));
break;
case V8SFmode:
ix86_avx256_split_vector_move_misalign (op0, op1);
@@ -15857,12 +15891,26 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
case V2DFmode:
if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
{
+ if (MEM_P (op1))
+ move_unaligned = gen_sse_loadups;
+ else if (MEM_P (op0))
+ move_unaligned = gen_sse_storeups;
+ else
+ gcc_unreachable ();
+
op0 = gen_lowpart (V4SFmode, op0);
op1 = gen_lowpart (V4SFmode, op1);
- emit_insn (gen_sse_movups (op0, op1));
+ emit_insn (move_unaligned (op0, op1));
return;
}
- emit_insn (gen_sse2_movupd (op0, op1));
+ if (MEM_P (op1))
+ move_unaligned = gen_sse2_loadupd;
+ else if (MEM_P (op0))
+ move_unaligned = gen_sse2_storeupd;
+ else
+ gcc_unreachable ();
+
+ emit_insn (move_unaligned (op0, op1));
break;
case V4DFmode:
ix86_avx256_split_vector_move_misalign (op0, op1);
@@ -15887,7 +15935,7 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
{
op0 = gen_lowpart (V4SFmode, op0);
op1 = gen_lowpart (V4SFmode, op1);
- emit_insn (gen_sse_movups (op0, op1));
+ emit_insn (gen_sse_loadups (op0, op1));
return;
}
@@ -15898,7 +15946,7 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
{
op0 = gen_lowpart (V16QImode, op0);
op1 = gen_lowpart (V16QImode, op1);
- emit_insn (gen_sse2_movdqu (op0, op1));
+ emit_insn (gen_sse2_loaddqu (op0, op1));
return;
}
@@ -15910,7 +15958,7 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
{
op0 = gen_lowpart (V2DFmode, op0);
op1 = gen_lowpart (V2DFmode, op1);
- emit_insn (gen_sse2_movupd (op0, op1));
+ emit_insn (gen_sse2_loadupd (op0, op1));
return;
}
@@ -15945,7 +15993,7 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
{
op0 = gen_lowpart (V4SFmode, op0);
op1 = gen_lowpart (V4SFmode, op1);
- emit_insn (gen_sse_movups (op0, op1));
+ emit_insn (gen_sse_loadups (op0, op1));
return;
}
@@ -15970,7 +16018,7 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
{
op0 = gen_lowpart (V4SFmode, op0);
op1 = gen_lowpart (V4SFmode, op1);
- emit_insn (gen_sse_movups (op0, op1));
+ emit_insn (gen_sse_storeups (op0, op1));
return;
}
@@ -15981,7 +16029,7 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
{
op0 = gen_lowpart (V16QImode, op0);
op1 = gen_lowpart (V16QImode, op1);
- emit_insn (gen_sse2_movdqu (op0, op1));
+ emit_insn (gen_sse2_storedqu (op0, op1));
return;
}
@@ -15991,7 +16039,7 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
{
op0 = gen_lowpart (V2DFmode, op0);
op1 = gen_lowpart (V2DFmode, op1);
- emit_insn (gen_sse2_movupd (op0, op1));
+ emit_insn (gen_sse2_storeupd (op0, op1));
}
else
{
@@ -16009,7 +16057,7 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
if (TARGET_SSE_UNALIGNED_STORE_OPTIMAL)
{
op0 = gen_lowpart (V4SFmode, op0);
- emit_insn (gen_sse_movups (op0, op1));
+ emit_insn (gen_sse_storeups (op0, op1));
}
else
{
@@ -23308,10 +23356,10 @@ assign_386_stack_local (enum machine_mode mode, enum ix86_stack_slot n)
/* Calculate the length of the memory address in the instruction encoding.
Includes addr32 prefix, does not include the one-byte modrm, opcode,
- or other prefixes. */
+ or other prefixes. We never generate addr32 prefix for LEA insn. */
int
-memory_address_length (rtx addr)
+memory_address_length (rtx addr, bool lea)
{
struct ix86_address parts;
rtx base, index, disp;
@@ -23327,18 +23375,26 @@ memory_address_length (rtx addr)
ok = ix86_decompose_address (addr, &parts);
gcc_assert (ok);
- if (parts.base && GET_CODE (parts.base) == SUBREG)
- parts.base = SUBREG_REG (parts.base);
- if (parts.index && GET_CODE (parts.index) == SUBREG)
- parts.index = SUBREG_REG (parts.index);
+ len = (parts.seg == SEG_DEFAULT) ? 0 : 1;
+
+ /* If this is not LEA instruction, add the length of addr32 prefix. */
+ if (TARGET_64BIT && !lea
+ && (SImode_address_operand (addr, VOIDmode)
+ || (parts.base && GET_MODE (parts.base) == SImode)
+ || (parts.index && GET_MODE (parts.index) == SImode)))
+ len++;
base = parts.base;
index = parts.index;
disp = parts.disp;
- /* Add length of addr32 prefix. */
- len = (GET_CODE (addr) == ZERO_EXTEND
- || GET_CODE (addr) == AND);
+ if (base && GET_CODE (base) == SUBREG)
+ base = SUBREG_REG (base);
+ if (index && GET_CODE (index) == SUBREG)
+ index = SUBREG_REG (index);
+
+ gcc_assert (base == NULL_RTX || REG_P (base));
+ gcc_assert (index == NULL_RTX || REG_P (index));
/* Rule of thumb:
- esp as the base always wants an index,
@@ -23352,14 +23408,13 @@ memory_address_length (rtx addr)
/* esp (for its index) and ebp (for its displacement) need
the two-byte modrm form. Similarly for r12 and r13 in 64-bit
code. */
- if (REG_P (addr)
- && (addr == arg_pointer_rtx
- || addr == frame_pointer_rtx
- || REGNO (addr) == SP_REG
- || REGNO (addr) == BP_REG
- || REGNO (addr) == R12_REG
- || REGNO (addr) == R13_REG))
- len = 1;
+ if (base == arg_pointer_rtx
+ || base == frame_pointer_rtx
+ || REGNO (base) == SP_REG
+ || REGNO (base) == BP_REG
+ || REGNO (base) == R12_REG
+ || REGNO (base) == R13_REG)
+ len++;
}
/* Direct Addressing. In 64-bit mode mod 00 r/m 5
@@ -23369,7 +23424,7 @@ memory_address_length (rtx addr)
by UNSPEC. */
else if (disp && !base && !index)
{
- len = 4;
+ len += 4;
if (TARGET_64BIT)
{
rtx symbol = disp;
@@ -23387,43 +23442,30 @@ memory_address_length (rtx addr)
|| (XINT (symbol, 1) != UNSPEC_GOTPCREL
&& XINT (symbol, 1) != UNSPEC_PCREL
&& XINT (symbol, 1) != UNSPEC_GOTNTPOFF)))
- len += 1;
+ len++;
}
}
-
else
{
/* Find the length of the displacement constant. */
if (disp)
{
if (base && satisfies_constraint_K (disp))
- len = 1;
+ len += 1;
else
- len = 4;
+ len += 4;
}
/* ebp always wants a displacement. Similarly r13. */
- else if (base && REG_P (base)
- && (REGNO (base) == BP_REG || REGNO (base) == R13_REG))
- len = 1;
+ else if (base && (REGNO (base) == BP_REG || REGNO (base) == R13_REG))
+ len++;
/* An index requires the two-byte modrm form.... */
if (index
/* ...like esp (or r12), which always wants an index. */
|| base == arg_pointer_rtx
|| base == frame_pointer_rtx
- || (base && REG_P (base)
- && (REGNO (base) == SP_REG || REGNO (base) == R12_REG)))
- len += 1;
- }
-
- switch (parts.seg)
- {
- case SEG_FS:
- case SEG_GS:
- len += 1;
- break;
- default:
- break;
+ || (base && (REGNO (base) == SP_REG || REGNO (base) == R12_REG)))
+ len++;
}
return len;
@@ -23477,7 +23519,8 @@ ix86_attr_length_immediate_default (rtx insn, bool shortform)
case MODE_SI:
len = 4;
break;
- /* Immediates for DImode instructions are encoded as 32bit sign extended values. */
+ /* Immediates for DImode instructions are encoded
+ as 32bit sign extended values. */
case MODE_DI:
len = 4;
break;
@@ -23487,6 +23530,7 @@ ix86_attr_length_immediate_default (rtx insn, bool shortform)
}
return len;
}
+
/* Compute default value for "length_address" attribute. */
int
ix86_attr_length_address_default (rtx insn)
@@ -23503,15 +23547,8 @@ ix86_attr_length_address_default (rtx insn)
gcc_assert (GET_CODE (set) == SET);
addr = SET_SRC (set);
- if (TARGET_64BIT && get_attr_mode (insn) == MODE_SI)
- {
- if (GET_CODE (addr) == ZERO_EXTEND)
- addr = XEXP (addr, 0);
- if (GET_CODE (addr) == SUBREG)
- addr = SUBREG_REG (addr);
- }
- return memory_address_length (addr);
+ return memory_address_length (addr, true);
}
extract_insn_cached (insn);
@@ -23533,7 +23570,7 @@ ix86_attr_length_address_default (rtx insn)
if (*constraints == 'X')
continue;
}
- return memory_address_length (XEXP (recog_data.operand[i], 0));
+ return memory_address_length (XEXP (recog_data.operand[i], 0), false);
}
return 0;
}
@@ -25999,9 +26036,9 @@ static const struct builtin_description bdesc_special_args[] =
{ OPTION_MASK_ISA_3DNOW, CODE_FOR_mmx_femms, "__builtin_ia32_femms", IX86_BUILTIN_FEMMS, UNKNOWN, (int) VOID_FTYPE_VOID },
/* SSE */
- { OPTION_MASK_ISA_SSE, CODE_FOR_sse_movups, "__builtin_ia32_storeups", IX86_BUILTIN_STOREUPS, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V4SF },
+ { OPTION_MASK_ISA_SSE, CODE_FOR_sse_storeups, "__builtin_ia32_storeups", IX86_BUILTIN_STOREUPS, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V4SF },
{ OPTION_MASK_ISA_SSE, CODE_FOR_sse_movntv4sf, "__builtin_ia32_movntps", IX86_BUILTIN_MOVNTPS, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V4SF },
- { OPTION_MASK_ISA_SSE, CODE_FOR_sse_movups, "__builtin_ia32_loadups", IX86_BUILTIN_LOADUPS, UNKNOWN, (int) V4SF_FTYPE_PCFLOAT },
+ { OPTION_MASK_ISA_SSE, CODE_FOR_sse_loadups, "__builtin_ia32_loadups", IX86_BUILTIN_LOADUPS, UNKNOWN, (int) V4SF_FTYPE_PCFLOAT },
{ OPTION_MASK_ISA_SSE, CODE_FOR_sse_loadhps_exp, "__builtin_ia32_loadhps", IX86_BUILTIN_LOADHPS, UNKNOWN, (int) V4SF_FTYPE_V4SF_PCV2SF },
{ OPTION_MASK_ISA_SSE, CODE_FOR_sse_loadlps_exp, "__builtin_ia32_loadlps", IX86_BUILTIN_LOADLPS, UNKNOWN, (int) V4SF_FTYPE_V4SF_PCV2SF },
@@ -26015,14 +26052,14 @@ static const struct builtin_description bdesc_special_args[] =
/* SSE2 */
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_lfence, "__builtin_ia32_lfence", IX86_BUILTIN_LFENCE, UNKNOWN, (int) VOID_FTYPE_VOID },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_mfence, 0, IX86_BUILTIN_MFENCE, UNKNOWN, (int) VOID_FTYPE_VOID },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movupd, "__builtin_ia32_storeupd", IX86_BUILTIN_STOREUPD, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V2DF },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movdqu, "__builtin_ia32_storedqu", IX86_BUILTIN_STOREDQU, UNKNOWN, (int) VOID_FTYPE_PCHAR_V16QI },
+ { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_storeupd, "__builtin_ia32_storeupd", IX86_BUILTIN_STOREUPD, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V2DF },
+ { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_storedqu, "__builtin_ia32_storedqu", IX86_BUILTIN_STOREDQU, UNKNOWN, (int) VOID_FTYPE_PCHAR_V16QI },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntv2df, "__builtin_ia32_movntpd", IX86_BUILTIN_MOVNTPD, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V2DF },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntv2di, "__builtin_ia32_movntdq", IX86_BUILTIN_MOVNTDQ, UNKNOWN, (int) VOID_FTYPE_PV2DI_V2DI },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntisi, "__builtin_ia32_movnti", IX86_BUILTIN_MOVNTI, UNKNOWN, (int) VOID_FTYPE_PINT_INT },
{ OPTION_MASK_ISA_SSE2 | OPTION_MASK_ISA_64BIT, CODE_FOR_sse2_movntidi, "__builtin_ia32_movnti64", IX86_BUILTIN_MOVNTI64, UNKNOWN, (int) VOID_FTYPE_PLONGLONG_LONGLONG },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movupd, "__builtin_ia32_loadupd", IX86_BUILTIN_LOADUPD, UNKNOWN, (int) V2DF_FTYPE_PCDOUBLE },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movdqu, "__builtin_ia32_loaddqu", IX86_BUILTIN_LOADDQU, UNKNOWN, (int) V16QI_FTYPE_PCCHAR },
+ { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loadupd, "__builtin_ia32_loadupd", IX86_BUILTIN_LOADUPD, UNKNOWN, (int) V2DF_FTYPE_PCDOUBLE },
+ { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loaddqu, "__builtin_ia32_loaddqu", IX86_BUILTIN_LOADDQU, UNKNOWN, (int) V16QI_FTYPE_PCCHAR },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loadhpd_exp, "__builtin_ia32_loadhpd", IX86_BUILTIN_LOADHPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_PCDOUBLE },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loadlpd_exp, "__builtin_ia32_loadlpd", IX86_BUILTIN_LOADLPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_PCDOUBLE },
@@ -26047,12 +26084,12 @@ static const struct builtin_description bdesc_special_args[] =
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_vbroadcastf128_v4df, "__builtin_ia32_vbroadcastf128_pd256", IX86_BUILTIN_VBROADCASTPD256, UNKNOWN, (int) V4DF_FTYPE_PCV2DF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_vbroadcastf128_v8sf, "__builtin_ia32_vbroadcastf128_ps256", IX86_BUILTIN_VBROADCASTPS256, UNKNOWN, (int) V8SF_FTYPE_PCV4SF },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movupd256, "__builtin_ia32_loadupd256", IX86_BUILTIN_LOADUPD256, UNKNOWN, (int) V4DF_FTYPE_PCDOUBLE },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movups256, "__builtin_ia32_loadups256", IX86_BUILTIN_LOADUPS256, UNKNOWN, (int) V8SF_FTYPE_PCFLOAT },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movupd256, "__builtin_ia32_storeupd256", IX86_BUILTIN_STOREUPD256, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V4DF },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movups256, "__builtin_ia32_storeups256", IX86_BUILTIN_STOREUPS256, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V8SF },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movdqu256, "__builtin_ia32_loaddqu256", IX86_BUILTIN_LOADDQU256, UNKNOWN, (int) V32QI_FTYPE_PCCHAR },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movdqu256, "__builtin_ia32_storedqu256", IX86_BUILTIN_STOREDQU256, UNKNOWN, (int) VOID_FTYPE_PCHAR_V32QI },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_loadupd256, "__builtin_ia32_loadupd256", IX86_BUILTIN_LOADUPD256, UNKNOWN, (int) V4DF_FTYPE_PCDOUBLE },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_loadups256, "__builtin_ia32_loadups256", IX86_BUILTIN_LOADUPS256, UNKNOWN, (int) V8SF_FTYPE_PCFLOAT },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_storeupd256, "__builtin_ia32_storeupd256", IX86_BUILTIN_STOREUPD256, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V4DF },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_storeups256, "__builtin_ia32_storeups256", IX86_BUILTIN_STOREUPS256, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V8SF },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_loaddqu256, "__builtin_ia32_loaddqu256", IX86_BUILTIN_LOADDQU256, UNKNOWN, (int) V32QI_FTYPE_PCCHAR },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_avx_storedqu256, "__builtin_ia32_storedqu256", IX86_BUILTIN_STOREDQU256, UNKNOWN, (int) VOID_FTYPE_PCHAR_V32QI },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_lddqu256, "__builtin_ia32_lddqu256", IX86_BUILTIN_LDDQU256, UNKNOWN, (int) V32QI_FTYPE_PCCHAR },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_movntv4di, "__builtin_ia32_movntdq256", IX86_BUILTIN_MOVNTDQ256, UNKNOWN, (int) VOID_FTYPE_PV4DI_V4DI },
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index eace56d9f78..f1b53a04655 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -5401,18 +5401,9 @@
{
rtx addr = operands[1];
- if (GET_CODE (addr) == SUBREG)
+ if (SImode_address_operand (addr, VOIDmode))
{
gcc_assert (TARGET_64BIT);
- gcc_assert (<MODE>mode == SImode);
- gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
- return "lea{l}\t{%E1, %0|%0, %E1}";
- }
- else if (GET_CODE (addr) == ZERO_EXTEND
- || GET_CODE (addr) == AND)
- {
- gcc_assert (TARGET_64BIT);
- gcc_assert (<MODE>mode == DImode);
return "lea{l}\t{%E1, %k0|%k0, %E1}";
}
else
@@ -5425,7 +5416,11 @@
DONE;
}
[(set_attr "type" "lea")
- (set_attr "mode" "<MODE>")])
+ (set (attr "mode")
+ (if_then_else
+ (match_operand 1 "SImode_address_operand")
+ (const_string "SI")
+ (const_string "<MODE>")))])
;; Add instructions
@@ -17700,7 +17695,7 @@
[(set_attr "type" "sse")
(set_attr "atom_sse_attr" "prefetch")
(set (attr "length_address")
- (symbol_ref "memory_address_length (operands[0])"))
+ (symbol_ref "memory_address_length (operands[0], false)"))
(set_attr "memory" "none")])
(define_insn "*prefetch_3dnow"
@@ -17716,7 +17711,7 @@
}
[(set_attr "type" "mmx")
(set (attr "length_address")
- (symbol_ref "memory_address_length (operands[0])"))
+ (symbol_ref "memory_address_length (operands[0], false)"))
(set_attr "memory" "none")])
(define_expand "stack_protect_set"
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index c78384b300e..9e312915bfc 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -822,6 +822,10 @@
return parts.seg == SEG_DEFAULT;
})
+;; Return true for RTX codes that force SImode address.
+(define_predicate "SImode_address_operand"
+ (match_code "subreg,zero_extend,and"))
+
;; Return true if op if a valid base register, displacement or
;; sum of base register and displacement for VSIB addressing.
(define_predicate "vsib_address_operand"
@@ -991,7 +995,7 @@
;; by the modRM array.
(define_predicate "long_memory_operand"
(and (match_operand 0 "memory_operand")
- (match_test "memory_address_length (op)")))
+ (match_test "memory_address_length (op, false)")))
;; Return true if OP is a comparison operator that can be issued by fcmov.
(define_predicate "fcmov_comparison_operator"
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 1917cb660a5..0621d61d68a 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -21,7 +21,8 @@
(define_c_enum "unspec" [
;; SSE
UNSPEC_MOVNT
- UNSPEC_MOVU
+ UNSPEC_LOADU
+ UNSPEC_STOREU
;; SSE3
UNSPEC_LDDQU
@@ -580,23 +581,51 @@
DONE;
})
-(define_insn "<sse>_movu<ssemodesuffix><avxsizesuffix>"
- [(set (match_operand:VF 0 "nonimmediate_operand" "=x,m")
+(define_insn "<sse>_loadu<ssemodesuffix><avxsizesuffix>"
+ [(set (match_operand:VF 0 "register_operand" "=x")
(unspec:VF
- [(match_operand:VF 1 "nonimmediate_operand" "xm,x")]
- UNSPEC_MOVU))]
- "TARGET_SSE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ [(match_operand:VF 1 "memory_operand" "m")]
+ UNSPEC_LOADU))]
+ "TARGET_SSE"
"%vmovu<ssemodesuffix>\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
(set_attr "movu" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<MODE>")])
-(define_insn "<sse2>_movdqu<avxsizesuffix>"
- [(set (match_operand:VI1 0 "nonimmediate_operand" "=x,m")
- (unspec:VI1 [(match_operand:VI1 1 "nonimmediate_operand" "xm,x")]
- UNSPEC_MOVU))]
- "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+(define_insn "<sse>_storeu<ssemodesuffix><avxsizesuffix>"
+ [(set (match_operand:VF 0 "memory_operand" "=m")
+ (unspec:VF
+ [(match_operand:VF 1 "register_operand" "x")]
+ UNSPEC_STOREU))]
+ "TARGET_SSE"
+ "%vmovu<ssemodesuffix>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "movu" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "<sse2>_loaddqu<avxsizesuffix>"
+ [(set (match_operand:VI1 0 "register_operand" "=x")
+ (unspec:VI1 [(match_operand:VI1 1 "memory_operand" "m")]
+ UNSPEC_LOADU))]
+ "TARGET_SSE2"
+ "%vmovdqu\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "movu" "1")
+ (set (attr "prefix_data16")
+ (if_then_else
+ (match_test "TARGET_AVX")
+ (const_string "*")
+ (const_string "1")))
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "<sseinsnmode>")])
+
+(define_insn "<sse2>_storedqu<avxsizesuffix>"
+ [(set (match_operand:VI1 0 "memory_operand" "=m")
+ (unspec:VI1 [(match_operand:VI1 1 "register_operand" "x")]
+ UNSPEC_STOREU))]
+ "TARGET_SSE2"
"%vmovdqu\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
(set_attr "movu" "1")
diff --git a/gcc/config/microblaze/rtems.h b/gcc/config/microblaze/rtems.h
new file mode 100644
index 00000000000..fecf7a295d5
--- /dev/null
+++ b/gcc/config/microblaze/rtems.h
@@ -0,0 +1,25 @@
+/* Definitions for rtems targeting a microblaze using ELF.
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* Specify predefined symbols in preprocessor. */
+
+#define TARGET_OS_CPP_BUILTINS() do { \
+ builtin_define( "__rtems__" ); \
+ builtin_assert( "system=rtems" ); \
+} while (0)
diff --git a/gcc/config/microblaze/t-rtems b/gcc/config/microblaze/t-rtems
new file mode 100644
index 00000000000..d0c38261aaa
--- /dev/null
+++ b/gcc/config/microblaze/t-rtems
@@ -0,0 +1 @@
+# Custom multilibs for RTEMS
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index a69f2b8a365..057eef0b4b7 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -2881,15 +2881,17 @@
[(set_attr "type" "store")
(set_attr "length" "4")])
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=r")
- (plus:HI (match_operand:HI 1 "register_operand" "r")
- (match_operand 2 "const_int_operand" "J")))]
+(define_insn "addhi3"
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (plus:HI (match_operand:HI 1 "register_operand" "%r,r")
+ (match_operand:HI 2 "arith14_operand" "r,J")))]
""
- "ldo %2(%1),%0"
- [(set_attr "type" "binary")
+ "@
+ {addl|add,l} %1,%2,%0
+ ldo %2(%1),%0"
+ [(set_attr "type" "binary,binary")
(set_attr "pa_combine_type" "addmove")
- (set_attr "length" "4")])
+ (set_attr "length" "4,4")])
(define_expand "movqi"
[(set (match_operand:QI 0 "general_operand" "")
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 29dd18d75bd..72377f9dc42 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -891,12 +891,16 @@
{
if (MEM_P (op))
{
+ if (! volatile_ok && MEM_VOLATILE_P (op))
+ return 0;
if (mode == DFmode)
mode = V2DFmode;
else if (mode == DImode)
mode = V2DImode;
else
- gcc_unreachable ();
+ gcc_unreachable ();
+ return memory_address_addr_space_p (mode, XEXP (op, 0),
+ MEM_ADDR_SPACE (op));
}
return input_operand (op, mode);
})
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index d6e250fd5a8..0454f5b69e0 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -1579,6 +1579,7 @@ s390_option_override (void)
break;
case PROCESSOR_2097_Z10:
s390_cost = &z10_cost;
+ break;
case PROCESSOR_2817_Z196:
s390_cost = &z196_cost;
break;
diff --git a/gcc/config/sparc/t-rtems b/gcc/config/sparc/t-rtems
new file mode 100644
index 00000000000..4a01e1eaaf3
--- /dev/null
+++ b/gcc/config/sparc/t-rtems
@@ -0,0 +1,22 @@
+# Copyright (C) 2012 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC 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.
+#
+# GCC 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 GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+#
+
+MULTILIB_OPTIONS = msoft-float mcpu=v8
+MULTILIB_DIRNAMES = soft v8
+MULTILIB_MATCHES = msoft-float=mno-fpu
diff --git a/gcc/config/sparc/t-rtems-64 b/gcc/config/sparc/t-rtems-64
new file mode 100644
index 00000000000..d6a6e3eea37
--- /dev/null
+++ b/gcc/config/sparc/t-rtems-64
@@ -0,0 +1,22 @@
+# Copyright (C) 2012 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC 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.
+#
+# GCC 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 GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+#
+
+MULTILIB_OPTIONS = msoft-float
+MULTILIB_DIRNAMES = soft
+MULTILIB_MATCHES = msoft-float=mno-fpu
diff --git a/gcc/configure b/gcc/configure
index fa7e3b68dba..418ea924a89 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -26544,7 +26544,9 @@ if test "${gcc_cv_ld_no_dot_syms+set}" = set; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_ld_no_dot_syms=no
- if test $in_tree_ld = yes ; then
+ if test x"$ld_is_gold" = xyes; then
+ gcc_cv_ld_no_dot_syms=yes
+ elif test $in_tree_ld = yes ; then
if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2; then
gcc_cv_ld_no_dot_syms=yes
fi
@@ -26588,7 +26590,9 @@ if test "${gcc_cv_ld_large_toc+set}" = set; then :
$as_echo_n "(cached) " >&6
else
gcc_cv_ld_large_toc=no
- if test $in_tree_ld = yes ; then
+ if test x"$ld_is_gold" = xyes; then
+ gcc_cv_ld_large_toc=yes
+ elif test $in_tree_ld = yes ; then
if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2; then
gcc_cv_ld_large_toc=yes
fi
diff --git a/gcc/configure.ac b/gcc/configure.ac
index a0ce0548387..7b553607fa3 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -4472,7 +4472,9 @@ case "$target:$tm_file" in
AC_CACHE_CHECK(linker support for omitting dot symbols,
gcc_cv_ld_no_dot_syms,
[gcc_cv_ld_no_dot_syms=no
- if test $in_tree_ld = yes ; then
+ if test x"$ld_is_gold" = xyes; then
+ gcc_cv_ld_no_dot_syms=yes
+ elif test $in_tree_ld = yes ; then
if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2; then
gcc_cv_ld_no_dot_syms=yes
fi
@@ -4509,7 +4511,9 @@ EOF
AC_CACHE_CHECK(linker large toc support,
gcc_cv_ld_large_toc,
[gcc_cv_ld_large_toc=no
- if test $in_tree_ld = yes ; then
+ if test x"$ld_is_gold" = xyes; then
+ gcc_cv_ld_large_toc=yes
+ elif test $in_tree_ld = yes ; then
if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2; then
gcc_cv_ld_large_toc=yes
fi
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1c836d39f89..d125ab37cf4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,30 @@
+2012-11-05 Jakub Jelinek <jakub@redhat.com>
+
+ Backported from mainline
+ 2012-10-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/54988
+ * decl2.c (cplus_decl_attributes): Don't return early
+ if attributes is NULL.
+
+2012-10-26 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/54984
+ * init.c (build_new): Don't turn a null *init into a pointer to
+ empty vector orig_init.
+
+2012-10-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/54858
+ * tree.c (cp_tree_equal): Handle FIELD_DECL.
+
+2012-10-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/54777
+ * semantics.c (cxx_eval_constant_expression) <case COMPOUND_EXPR>: If
+ not ignoring the second operand, pass the original second operand
+ and not one with stripped nops to cxx_eval_constant_expression.
+
2012-09-20 Release Manager
* GCC 4.7.2 released.
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index bdc962abcf9..36e74c7b380 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1302,8 +1302,7 @@ void
cplus_decl_attributes (tree *decl, tree attributes, int flags)
{
if (*decl == NULL_TREE || *decl == void_type_node
- || *decl == error_mark_node
- || attributes == NULL_TREE)
+ || *decl == error_mark_node)
return;
if (processing_template_decl)
@@ -1312,8 +1311,6 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags)
return;
save_template_attributes (&attributes, decl);
- if (attributes == NULL_TREE)
- return;
}
cp_check_const_attributes (attributes);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index fe5d040ee98..a84d1f97a0d 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2794,7 +2794,8 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts,
orig_placement = make_tree_vector_copy (*placement);
orig_nelts = nelts;
- orig_init = make_tree_vector_copy (*init);
+ if (*init)
+ orig_init = make_tree_vector_copy (*init);
make_args_non_dependent (*placement);
if (nelts)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index a64c5b7f4ad..7371b446786 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7682,6 +7682,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
/* Check that the LHS is constant and then discard it. */
cxx_eval_constant_expression (call, op0, allow_non_constant,
false, non_constant_p);
+ op1 = TREE_OPERAND (t, 1);
r = cxx_eval_constant_expression (call, op1, allow_non_constant,
addr, non_constant_p);
}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index de9e0f60136..2878ba57689 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1,7 +1,7 @@
/* Language-dependent node constructors for parse phase of GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011,
+ 2012 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
@@ -2366,6 +2366,7 @@ cp_tree_equal (tree t1, tree t2)
case VAR_DECL:
case CONST_DECL:
+ case FIELD_DECL:
case FUNCTION_DECL:
case TEMPLATE_DECL:
case IDENTIFIER_NODE:
diff --git a/gcc/cse.c b/gcc/cse.c
index 6424bb1864f..0904ee688b6 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -2555,7 +2555,7 @@ hash_rtx_cb (const_rtx x, enum machine_mode mode,
Store 1 in DO_NOT_RECORD_P if any subexpression is volatile.
If HASH_ARG_IN_MEMORY_P is not NULL, store 1 in it if X contains
- a MEM rtx which does not have the RTX_UNCHANGING_P bit set.
+ a MEM rtx which does not have the MEM_READONLY_P flag set.
Note that cse_insn knows that the hash code of a MEM expression
is just (int) MEM plus the hash code of the address. */
@@ -2571,7 +2571,7 @@ hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p,
/* Hash an rtx X for cse via hash_rtx.
Stores 1 in do_not_record if any subexpression is volatile.
Stores 1 in hash_arg_in_memory if X contains a mem rtx which
- does not have the RTX_UNCHANGING_P bit set. */
+ does not have the MEM_READONLY_P flag set. */
static inline unsigned
canon_hash (rtx x, enum machine_mode mode)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c710dc8c71e..5137c00f0a5 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -636,7 +636,7 @@ Objective-C and Objective-C++ Dialects}.
-mincoming-stack-boundary=@var{num} @gol
-mcld -mcx16 -msahf -mmovbe -mcrc32 @gol
-mrecip -mrecip=@var{opt} @gol
--mvzeroupper @gol
+-mvzeroupper -mprefer-avx128 @gol
-mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx @gol
-mavx2 -maes -mpclmul -mfsgsbase -mrdrnd -mf16c -mfma @gol
-msse4a -m3dnow -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop -mlzcnt @gol
@@ -11090,9 +11090,6 @@ defined.
@opindex mmcu
Specify Atmel AVR instruction set architectures (ISA) or MCU type.
-For a complete list of @var{mcu} values that are supported by @command{avr-gcc},
-see the compiler output when called with the @option{--help=target}
-command line option.
The default for this option is@tie{}@code{avr2}.
GCC supports the following AVR devices and ISAs:
@@ -11101,22 +11098,22 @@ GCC supports the following AVR devices and ISAs:
@item avr2
``Classic'' devices with up to 8@tie{}KiB of program memory.
-@*@var{mcu}@tie{}= @code{at90c8534}, @code{at90s2313},
-@code{at90s2323}, @code{at90s2333}, @code{at90s2343},
-@code{at90s4414}, @code{at90s4433}, @code{at90s4434},
-@code{at90s8515}, @code{at90s8535}, @code{attiny22}, @code{attiny26}.
+@*@var{mcu}@tie{}= @code{attiny22}, @code{attiny26}, @code{at90c8534},
+@code{at90s2313}, @code{at90s2323}, @code{at90s2333},
+@code{at90s2343}, @code{at90s4414}, @code{at90s4433},
+@code{at90s4434}, @code{at90s8515}, @code{at90s8535}.
@item avr25
``Classic'' devices with up to 8@tie{}KiB of program memory and with
the @code{MOVW} instruction.
-@*@var{mcu}@tie{}= @code{at86rf401}, @code{ata6289}, @code{attiny13},
-@code{attiny13a}, @code{attiny2313}, @code{attiny2313a},
-@code{attiny24}, @code{attiny24a}, @code{attiny25}, @code{attiny261},
-@code{attiny261a}, @code{attiny4313}, @code{attiny43u},
+@*@var{mcu}@tie{}= @code{ata6289}, @code{attiny13}, @code{attiny13a},
+@code{attiny2313}, @code{attiny2313a}, @code{attiny24},
+@code{attiny24a}, @code{attiny25}, @code{attiny261},
+@code{attiny261a}, @code{attiny43u}, @code{attiny4313},
@code{attiny44}, @code{attiny44a}, @code{attiny45}, @code{attiny461},
@code{attiny461a}, @code{attiny48}, @code{attiny84}, @code{attiny84a},
@code{attiny85}, @code{attiny861}, @code{attiny861a}, @code{attiny87},
-@code{attiny88}.
+@code{attiny88}, @code{at86rf401}.
@item avr3
``Classic'' devices with 16@tie{}KiB up to 64@tie{}KiB of program memory.
@@ -11124,57 +11121,58 @@ the @code{MOVW} instruction.
@item avr31
``Classic'' devices with 128@tie{}KiB of program memory.
-@*@var{mcu}@tie{}= @code{at43usb320}, @code{atmega103}.
+@*@var{mcu}@tie{}= @code{atmega103}, @code{at43usb320}.
@item avr35
``Classic'' devices with 16@tie{}KiB up to 64@tie{}KiB of program
memory and with the @code{MOVW} instruction.
-@*@var{mcu}@tie{}= @code{at90usb162}, @code{at90usb82},
-@code{atmega16u2}, @code{atmega32u2}, @code{atmega8u2},
-@code{attiny167}.
+@*@var{mcu}@tie{}= @code{atmega16u2}, @code{atmega32u2},
+@code{atmega8u2}, @code{attiny167}, @code{at90usb162},
+@code{at90usb82}.
@item avr4
``Enhanced'' devices with up to 8@tie{}KiB of program memory.
-@*@var{mcu}@tie{}= @code{at90pwm1}, @code{at90pwm2}, @code{at90pwm2b},
-@code{at90pwm3}, @code{at90pwm3b}, @code{at90pwm81}, @code{atmega48},
-@code{atmega48a}, @code{atmega48p}, @code{atmega8}, @code{atmega8515},
-@code{atmega8535}, @code{atmega88}, @code{atmega88a},
-@code{atmega88p}, @code{atmega88pa}, @code{atmega8hva}.
+@*@var{mcu}@tie{}= @code{atmega48}, @code{atmega48a},
+@code{atmega48p}, @code{atmega8}, @code{atmega8hva},
+@code{atmega8515}, @code{atmega8535}, @code{atmega88},
+@code{atmega88a}, @code{atmega88p}, @code{atmega88pa},
+@code{at90pwm1}, @code{at90pwm2}, @code{at90pwm2b}, @code{at90pwm3},
+@code{at90pwm3b}, @code{at90pwm81}.
@item avr5
``Enhanced'' devices with 16@tie{}KiB up to 64@tie{}KiB of program memory.
-@*@var{mcu}@tie{}= @code{at90can32}, @code{at90can64},
-@code{at90pwm216}, @code{at90pwm316}, @code{at90scr100},
-@code{at90usb646}, @code{at90usb647}, @code{at94k}, @code{atmega16},
-@code{atmega161}, @code{atmega162}, @code{atmega163},
-@code{atmega164a}, @code{atmega164p}, @code{atmega165},
-@code{atmega165a}, @code{atmega165p}, @code{atmega168},
-@code{atmega168a}, @code{atmega168p}, @code{atmega169},
-@code{atmega169a}, @code{atmega169p}, @code{atmega169pa},
-@code{atmega16a}, @code{atmega16hva}, @code{atmega16hva2},
-@code{atmega16hvb}, @code{atmega16m1}, @code{atmega16u4},
-@code{atmega32}, @code{atmega323}, @code{atmega324a},
-@code{atmega324p}, @code{atmega324pa}, @code{atmega325},
+@*@var{mcu}@tie{}= @code{atmega16}, @code{atmega16a},
+@code{atmega16hva}, @code{atmega16hva2}, @code{atmega16hvb},
+@code{atmega16m1}, @code{atmega16u4}, @code{atmega161},
+@code{atmega162}, @code{atmega163}, @code{atmega164a},
+@code{atmega164p}, @code{atmega165}, @code{atmega165a},
+@code{atmega165p}, @code{atmega168}, @code{atmega168a},
+@code{atmega168p}, @code{atmega169}, @code{atmega169a},
+@code{atmega169p}, @code{atmega169pa}, @code{atmega32},
+@code{atmega32c1}, @code{atmega32hvb}, @code{atmega32m1},
+@code{atmega32u4}, @code{atmega32u6}, @code{atmega323},
+@code{atmega324a}, @code{atmega324p}, @code{atmega324pa},
+@code{atmega325}, @code{atmega325a}, @code{atmega325p},
@code{atmega3250}, @code{atmega3250a}, @code{atmega3250p},
-@code{atmega325a}, @code{atmega325p}, @code{atmega328},
-@code{atmega328p}, @code{atmega329}, @code{atmega3290},
-@code{atmega3290a}, @code{atmega3290p}, @code{atmega329a},
-@code{atmega329p}, @code{atmega329pa}, @code{atmega32c1},
-@code{atmega32hvb}, @code{atmega32m1}, @code{atmega32u4},
-@code{atmega32u6}, @code{atmega406}, @code{atmega64},
-@code{atmega640}, @code{atmega644}, @code{atmega644a},
-@code{atmega644p}, @code{atmega644pa}, @code{atmega645},
-@code{atmega6450}, @code{atmega6450a}, @code{atmega6450p},
-@code{atmega645a}, @code{atmega645p}, @code{atmega649},
-@code{atmega6490}, @code{atmega649a}, @code{atmega649p},
-@code{atmega64c1}, @code{atmega64hve}, @code{atmega64m1},
+@code{atmega328}, @code{atmega328p}, @code{atmega329},
+@code{atmega329a}, @code{atmega329p}, @code{atmega329pa},
+@code{atmega3290}, @code{atmega3290a}, @code{atmega3290p},
+@code{atmega406}, @code{atmega64}, @code{atmega64c1},
+@code{atmega64hve}, @code{atmega64m1}, @code{atmega640},
+@code{atmega644}, @code{atmega644a}, @code{atmega644p},
+@code{atmega644pa}, @code{atmega645}, @code{atmega645a},
+@code{atmega645p}, @code{atmega6450}, @code{atmega6450a},
+@code{atmega6450p}, @code{atmega649}, @code{atmega649a},
+@code{atmega649p}, @code{atmega6490}, @code{at90can32},
+@code{at90can64}, @code{at90pwm216}, @code{at90pwm316},
+@code{at90scr100}, @code{at90usb646}, @code{at90usb647}, @code{at94k},
@code{m3000}.
@item avr51
``Enhanced'' devices with 128@tie{}KiB of program memory.
-@*@var{mcu}@tie{}= @code{at90can128}, @code{at90usb1286},
-@code{at90usb1287}, @code{atmega128}, @code{atmega1280},
-@code{atmega1281}, @code{atmega1284p}, @code{atmega128rfa1}.
+@*@var{mcu}@tie{}= @code{atmega128}, @code{atmega128rfa1},
+@code{atmega1280}, @code{atmega1281}, @code{atmega1284p},
+@code{at90can128}, @code{at90usb1286}, @code{at90usb1287}.
@item avr6
``Enhanced'' devices with 3-byte PC, i.e.@: with more than
@@ -11212,8 +11210,8 @@ more than 64@tie{}KiB of RAM.
@item avr1
This ISA is implemented by the minimal AVR core and supported for
assembler only.
-@*@var{mcu}@tie{}= @code{at90s1200}, @code{attiny11}, @code{attiny12},
-@code{attiny15}, @code{attiny28}.
+@*@var{mcu}@tie{}= @code{attiny11}, @code{attiny12}, @code{attiny15},
+@code{attiny28}, @code{at90s1200}.
@end table
@@ -11274,10 +11272,12 @@ section on @code{EIND} and linker stubs below.
@item -mshort-calls
@opindex mshort-calls
+This option has been deprecated and will be removed in GCC 4.8.
+See @code{-mrelax} for a replacement.
+
Use @code{RCALL}/@code{RJMP} instructions even on devices with
16@tie{}KiB or more of program memory, i.e.@: on devices that
have the @code{CALL} and @code{JMP} instructions.
-See also the @code{-mrelax} command line option.
@item -msp8
@opindex msp8
@@ -11508,6 +11508,23 @@ For even more AVR-specific built-in macros see
@table @code
+@item __AVR_ARCH__
+Build-in macro that resolves to a decimal number that identifies the
+architecture and depends on the @code{-mmcu=@var{mcu}} option.
+Possible values are:
+
+@code{2}, @code{25}, @code{3}, @code{31}, @code{35},
+@code{4}, @code{5}, @code{51}, @code{6}, @code{102}, @code{104},
+@code{105}, @code{106}, @code{107}
+
+for @var{mcu}=@code{avr2}, @code{avr25}, @code{avr3},
+@code{avr31}, @code{avr35}, @code{avr4}, @code{avr5}, @code{avr51},
+@code{avr6}, @code{avrxmega2}, @code{avrxmega4}, @code{avrxmega5},
+@code{avrxmega6}, @code{avrxmega7}, respectively.
+If @var{mcu} specifies a device, this built-in macro is set
+accordingly. For example, with @code{-mmcu=atmega8} the macro will be
+defined to @code{4}.
+
@item __AVR_@var{Device}__
Setting @code{-mmcu=@var{device}} defines this built-in macro which reflects
the device's name. For example, @code{-mmcu=atmega8} defines the
@@ -11520,6 +11537,9 @@ the device name as from the AVR user manual. The difference between
@var{Device} in the built-in macro and @var{device} in
@code{-mmcu=@var{device}} is that the latter is always lowercase.
+If @var{device} is not a device but only a core architecture like
+@code{avr51}, this macro will not be defined.
+
@item __AVR_HAVE_ELPM__
The device has the the @code{ELPM} instruction.
@@ -13814,6 +13834,11 @@ before a transfer of control flow out of the function to minimize
AVX to SSE transition penalty as well as remove unnecessary zeroupper
intrinsics.
+@item -mprefer-avx128
+@opindex mprefer-avx128
+This option instructs GCC to use 128-bit AVX instructions instead of
+256-bit AVX instructions in the auto-vectorizer.
+
@item -mcx16
@opindex mcx16
This option will enable GCC to use CMPXCHG16B instruction in generated code.
diff --git a/gcc/dse.c b/gcc/dse.c
index a9fe9249369..7d4dbf45a1a 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -996,7 +996,32 @@ delete_dead_store_insn (insn_info_t insn_info)
insn_info->wild_read = false;
}
-/* Check if EXPR can possibly escape the current function scope. */
+/* Return whether DECL, a local variable, can possibly escape the current
+ function scope. */
+
+static bool
+local_variable_can_escape (tree decl)
+{
+ if (TREE_ADDRESSABLE (decl))
+ return true;
+
+ /* If this is a partitioned variable, we need to consider all the variables
+ in the partition. This is necessary because a store into one of them can
+ be replaced with a store into another and this may not change the outcome
+ of the escape analysis. */
+ if (cfun->gimple_df->decls_to_pointers != NULL)
+ {
+ void *namep
+ = pointer_map_contains (cfun->gimple_df->decls_to_pointers, decl);
+ if (namep)
+ return TREE_ADDRESSABLE (*(tree *)namep);
+ }
+
+ return false;
+}
+
+/* Return whether EXPR can possibly escape the current function scope. */
+
static bool
can_escape (tree expr)
{
@@ -1005,7 +1030,11 @@ can_escape (tree expr)
return true;
base = get_base_address (expr);
if (DECL_P (base)
- && !may_be_aliased (base))
+ && !may_be_aliased (base)
+ && !(TREE_CODE (base) == VAR_DECL
+ && !DECL_EXTERNAL (base)
+ && !TREE_STATIC (base)
+ && local_variable_can_escape (base)))
return false;
return true;
}
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 051e01585b4..06c6c9de4cf 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -8012,6 +8012,8 @@ value_format (dw_attr_ref a)
return DW_FORM_block1;
case 2:
return DW_FORM_block2;
+ case 4:
+ return DW_FORM_block4;
default:
gcc_unreachable ();
}
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 26d43e41e82..3636a2f34ee 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -6781,12 +6781,14 @@ fold_sign_changed_comparison (location_t loc, enum tree_code code, tree type,
&& TREE_TYPE (TREE_OPERAND (arg1, 0)) == inner_type))
return NULL_TREE;
- if ((TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
- || POINTER_TYPE_P (inner_type) != POINTER_TYPE_P (outer_type))
+ if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
&& code != NE_EXPR
&& code != EQ_EXPR)
return NULL_TREE;
+ if (POINTER_TYPE_P (inner_type) != POINTER_TYPE_P (outer_type))
+ return NULL_TREE;
+
if (TREE_CODE (arg1) == INTEGER_CST)
arg1 = force_fit_type_double (inner_type, tree_to_double_int (arg1),
0, TREE_OVERFLOW (arg1));
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index fc827cb7061..688f5723821 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,9 @@
+2012-10-14 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/54784
+ * trans-stmt.c (gfc_trans_allocate): Correctly determine the reference
+ to the _data component for polymorphic allocation with SOURCE.
+
2012-09-20 Release Manager
* GCC 4.7.2 released.
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index bb3a89084e0..630816ed401 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -5087,7 +5087,7 @@ gfc_trans_allocate (gfc_code * code)
gfc_actual_arglist *actual;
gfc_expr *ppc;
gfc_code *ppc_code;
- gfc_ref *dataref;
+ gfc_ref *ref, *dataref;
/* Do a polymorphic deep copy. */
actual = gfc_get_actual_arglist ();
@@ -5099,13 +5099,15 @@ gfc_trans_allocate (gfc_code * code)
actual->next->expr->ts.type = BT_CLASS;
gfc_add_data_component (actual->next->expr);
- dataref = actual->next->expr->ref;
+ dataref = NULL;
/* Make sure we go up through the reference chain to
the _data reference, where the arrayspec is found. */
- while (dataref->next && dataref->next->type != REF_ARRAY)
- dataref = dataref->next;
+ for (ref = actual->next->expr->ref; ref; ref = ref->next)
+ if (ref->type == REF_COMPONENT
+ && strcmp (ref->u.c.component->name, "_data") == 0)
+ dataref = ref;
- if (dataref->u.c.component->as)
+ if (dataref && dataref->u.c.component->as)
{
int dim;
gfc_expr *temp;
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 5980854d94d..5e4bd23db51 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -115,7 +115,8 @@ can_refer_decl_in_current_unit_p (tree decl)
tree
canonicalize_constructor_val (tree cval)
{
- STRIP_USELESS_TYPE_CONVERSION (cval);
+ tree orig_cval = cval;
+ STRIP_NOPS (cval);
if (TREE_CODE (cval) == POINTER_PLUS_EXPR
&& TREE_CODE (TREE_OPERAND (cval, 1)) == INTEGER_CST)
{
@@ -146,8 +147,12 @@ canonicalize_constructor_val (tree cval)
/* Fixup types in global initializers. */
if (TREE_TYPE (TREE_TYPE (cval)) != TREE_TYPE (TREE_OPERAND (cval, 0)))
cval = build_fold_addr_expr (TREE_OPERAND (cval, 0));
+
+ if (!useless_type_conversion_p (TREE_TYPE (orig_cval), TREE_TYPE (cval)))
+ cval = fold_convert (TREE_TYPE (orig_cval), cval);
+ return cval;
}
- return cval;
+ return orig_cval;
}
/* If SYM is a constant variable with known value, return the value.
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 7f075515531..47e46b784f5 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1087,6 +1087,24 @@ struct gimplify_ctx
bool in_cleanup_point_expr;
};
+/* Return true if gimplify_one_sizepos doesn't need to gimplify
+ expr (when in TYPE_SIZE{,_UNIT} and similar type/decl size/bitsize
+ fields). */
+static inline bool
+is_gimple_sizepos (tree expr)
+{
+ /* gimplify_one_sizepos doesn't need to do anything if the value isn't there,
+ is constant, or contains A PLACEHOLDER_EXPR. We also don't want to do
+ anything if it's already a VAR_DECL. If it's a VAR_DECL from another
+ function, the gimplifier will want to replace it with a new variable,
+ but that will cause problems if this type is from outside the function.
+ It's OK to have that here. */
+ return (expr == NULL_TREE
+ || TREE_CONSTANT (expr)
+ || TREE_CODE (expr) == VAR_DECL
+ || CONTAINS_PLACEHOLDER_P (expr));
+}
+
extern enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
bool (*) (tree), fallback_t);
extern void gimplify_type_sizes (tree, gimple_seq *);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index a10d17e10da..531565e6499 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -119,6 +119,19 @@ mark_addressable (tree x)
&& TREE_CODE (x) != RESULT_DECL)
return;
TREE_ADDRESSABLE (x) = 1;
+
+ /* Also mark the artificial SSA_NAME that points to the partition of X. */
+ if (TREE_CODE (x) == VAR_DECL
+ && !DECL_EXTERNAL (x)
+ && !TREE_STATIC (x)
+ && cfun->gimple_df != NULL
+ && cfun->gimple_df->decls_to_pointers != NULL)
+ {
+ void *namep
+ = pointer_map_contains (cfun->gimple_df->decls_to_pointers, x);
+ if (namep)
+ TREE_ADDRESSABLE (*(tree *)namep) = 1;
+ }
}
/* Return a hash value for a formal temporary table entry. */
@@ -7935,9 +7948,7 @@ gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p)
a VAR_DECL. If it's a VAR_DECL from another function, the gimplifier
will want to replace it with a new variable, but that will cause problems
if this type is from outside the function. It's OK to have that here. */
- if (expr == NULL_TREE || TREE_CONSTANT (expr)
- || TREE_CODE (expr) == VAR_DECL
- || CONTAINS_PLACEHOLDER_P (expr))
+ if (is_gimple_sizepos (expr))
return;
type = TREE_TYPE (expr);
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 2165911fa72..d78924ba60c 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,14 @@
+2012-10-30 Ian Lance Taylor <iant@google.com>
+
+ * lang.opt (-fgo-relative-import-path): New option.
+ * go-lang.c (go_relative_import_path): New static variable.
+ (go_langhook_init): Pass go_relative_import_path to
+ go_create_gogo.
+ (go_langhook_handle_option): Handle -fgo-relative-import-path.
+ * go-c.h (go_create_gogo): Update declaration.
+ * gccgo.texi (Invoking gccgo): Document
+ -fgo-relative-import-path.
+
2012-09-20 Ian Lance Taylor <iant@google.com>
* Make-lang.in (go/gogo.o): Depend on filenames.h.
diff --git a/gcc/go/gccgo.texi b/gcc/go/gccgo.texi
index a5e37e76e80..91930c812f6 100644
--- a/gcc/go/gccgo.texi
+++ b/gcc/go/gccgo.texi
@@ -184,6 +184,12 @@ Using either @option{-fgo-pkgpath} or @option{-fgo-prefix} disables
the special treatment of the @code{main} package and permits that
package to be imported like any other.
+@item -fgo-relative-import-path=@var{dir}
+@cindex @option{-fgo-relative-import-path}
+A relative import is an import that starts with @file{./} or
+@file{../}. If this option is used, @command{gccgo} will use
+@var{dir} as a prefix for the relative import when searching for it.
+
@item -frequire-return-statement
@itemx -fno-require-return-statement
@cindex @option{-frequire-return-statement}
diff --git a/gcc/go/go-c.h b/gcc/go/go-c.h
index d46a08796e3..ea59fb6b39a 100644
--- a/gcc/go/go-c.h
+++ b/gcc/go/go-c.h
@@ -42,7 +42,8 @@ extern int go_enable_optimize (const char*);
extern void go_add_search_path (const char*);
extern void go_create_gogo (int int_type_size, int pointer_size,
- const char* pkgpath, const char *prefix);
+ const char* pkgpath, const char *prefix,
+ const char *relative_import_path);
extern void go_parse_input_files (const char**, unsigned int,
bool only_check_syntax,
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index f02f769252b..61ca1478be6 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -85,6 +85,7 @@ struct GTY(()) language_function
static const char *go_pkgpath = NULL;
static const char *go_prefix = NULL;
+static const char *go_relative_import_path = NULL;
/* Language hooks. */
@@ -101,7 +102,8 @@ go_langhook_init (void)
to, e.g., unsigned_char_type_node) but before calling
build_common_builtin_nodes (because it calls, indirectly,
go_type_for_size). */
- go_create_gogo (INT_TYPE_SIZE, POINTER_SIZE, go_pkgpath, go_prefix);
+ go_create_gogo (INT_TYPE_SIZE, POINTER_SIZE, go_pkgpath, go_prefix,
+ go_relative_import_path);
build_common_builtin_nodes ();
@@ -240,6 +242,10 @@ go_langhook_handle_option (
go_prefix = arg;
break;
+ case OPT_fgo_relative_import_path_:
+ go_relative_import_path = arg;
+ break;
+
default:
/* Just return 1 to indicate that the option is valid. */
break;
diff --git a/gcc/go/gofrontend/go.cc b/gcc/go/gofrontend/go.cc
index 1f2ce8adcde..11692af8095 100644
--- a/gcc/go/gofrontend/go.cc
+++ b/gcc/go/gofrontend/go.cc
@@ -21,7 +21,7 @@ static Gogo* gogo;
GO_EXTERN_C
void
go_create_gogo(int int_type_size, int pointer_size, const char *pkgpath,
- const char *prefix)
+ const char *prefix, const char *relative_import_path)
{
go_assert(::gogo == NULL);
Linemap* linemap = go_get_linemap();
@@ -32,6 +32,9 @@ go_create_gogo(int int_type_size, int pointer_size, const char *pkgpath,
else if (prefix != NULL)
::gogo->set_prefix(prefix);
+ if (relative_import_path != NULL)
+ ::gogo->set_relative_import_path(relative_import_path);
+
// FIXME: This should be in the gcc dependent code.
::gogo->define_builtin_function_trees();
}
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index fa61808ec3c..c0aa496acc3 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -44,6 +44,7 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size,
pkgpath_set_(false),
pkgpath_from_option_(false),
prefix_from_option_(false),
+ relative_import_path_(),
verify_types_(),
interface_types_(),
specific_type_functions_(),
@@ -477,7 +478,8 @@ Gogo::import_package(const std::string& filename,
return;
}
- Import::Stream* stream = Import::open_package(filename, location);
+ Import::Stream* stream = Import::open_package(filename, location,
+ this->relative_import_path_);
if (stream == NULL)
{
error_at(location, "import file %qs not found", filename.c_str());
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index 36709f5b45b..cc707ad2dde 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -206,6 +206,17 @@ class Gogo
pkgpath_from_option() const
{ return this->pkgpath_from_option_; }
+ // Return the relative import path as set from the command line.
+ // Returns an empty string if it was not set.
+ const std::string&
+ relative_import_path() const
+ { return this->relative_import_path_; }
+
+ // Set the relative import path from a command line option.
+ void
+ set_relative_import_path(const std::string& s)
+ {this->relative_import_path_ = s; }
+
// Return the priority to use for the package we are compiling.
// This is two more than the largest priority of any package we
// import.
@@ -732,6 +743,9 @@ class Gogo
bool pkgpath_from_option_;
// Whether an explicit prefix was set by -fgo-prefix.
bool prefix_from_option_;
+ // The relative import path, from the -fgo-relative-import-path
+ // option.
+ std::string relative_import_path_;
// A list of types to verify.
std::vector<Type*> verify_types_;
// A list of interface types defined while parsing.
diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc
index 9febf231897..4913100b5fd 100644
--- a/gcc/go/gofrontend/import.cc
+++ b/gcc/go/gofrontend/import.cc
@@ -41,6 +41,9 @@ go_add_search_path(const char* path)
// When FILENAME is not an absolute path and does not start with ./ or
// ../, we use the search path provided by -I and -L options.
+// When FILENAME does start with ./ or ../, we use
+// RELATIVE_IMPORT_PATH as a prefix.
+
// When FILENAME does not exist, we try modifying FILENAME to find the
// file. We use the first of these which exists:
// * We append ".gox".
@@ -55,19 +58,35 @@ go_add_search_path(const char* path)
// later in the search path.
Import::Stream*
-Import::open_package(const std::string& filename, Location location)
+Import::open_package(const std::string& filename, Location location,
+ const std::string& relative_import_path)
{
bool is_local;
if (IS_ABSOLUTE_PATH(filename))
is_local = true;
- else if (filename[0] == '.' && IS_DIR_SEPARATOR(filename[1]))
+ else if (filename[0] == '.'
+ && (filename[1] == '\0' || IS_DIR_SEPARATOR(filename[1])))
is_local = true;
else if (filename[0] == '.'
&& filename[1] == '.'
- && IS_DIR_SEPARATOR(filename[2]))
+ && (filename[2] == '\0' || IS_DIR_SEPARATOR(filename[2])))
is_local = true;
else
is_local = false;
+
+ std::string fn = filename;
+ if (is_local && !IS_ABSOLUTE_PATH(filename) && !relative_import_path.empty())
+ {
+ if (fn == ".")
+ {
+ // A special case.
+ fn = relative_import_path;
+ }
+ else
+ fn = relative_import_path + '/' + fn;
+ is_local = false;
+ }
+
if (!is_local)
{
for (std::vector<std::string>::const_iterator p = search_path.begin();
@@ -77,14 +96,14 @@ Import::open_package(const std::string& filename, Location location)
std::string indir = *p;
if (!indir.empty() && indir[indir.size() - 1] != '/')
indir += '/';
- indir += filename;
+ indir += fn;
Stream* s = Import::try_package_in_directory(indir, location);
if (s != NULL)
return s;
}
}
- Stream* s = Import::try_package_in_directory(filename, location);
+ Stream* s = Import::try_package_in_directory(fn, location);
if (s != NULL)
return s;
diff --git a/gcc/go/gofrontend/import.h b/gcc/go/gofrontend/import.h
index 67bdcb02d57..c6844cda8a5 100644
--- a/gcc/go/gofrontend/import.h
+++ b/gcc/go/gofrontend/import.h
@@ -124,8 +124,10 @@ class Import
// Find import data. This searches the file system for FILENAME and
// returns a pointer to a Stream object to read the data that it
// exports. LOCATION is the location of the import statement.
+ // RELATIVE_IMPORT_PATH is used as a prefix for a relative import.
static Stream*
- open_package(const std::string& filename, Location location);
+ open_package(const std::string& filename, Location location,
+ const std::string& relative_import_path);
// Constructor.
Import(Stream*, Location);
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index f6b9715d4c1..ab2bb7cf29d 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -1631,12 +1631,16 @@ Parse::init_vars(const Typed_identifier_list* til, Type* type,
// Note that INIT was already parsed with the old name bindings, so
// we don't have to worry that it will accidentally refer to the
- // newly declared variables.
+ // newly declared variables. But we do have to worry about a mix of
+ // newly declared variables and old variables if the old variables
+ // appear in the initializations.
Expression_list::const_iterator pexpr;
if (init != NULL)
pexpr = init->begin();
bool any_new = false;
+ Expression_list* vars = new Expression_list();
+ Expression_list* vals = new Expression_list();
for (Typed_identifier_list::const_iterator p = til->begin();
p != til->end();
++p)
@@ -1644,7 +1648,7 @@ Parse::init_vars(const Typed_identifier_list* til, Type* type,
if (init != NULL)
go_assert(pexpr != init->end());
this->init_var(*p, type, init == NULL ? NULL : *pexpr, is_coloneq,
- false, &any_new);
+ false, &any_new, vars, vals);
if (init != NULL)
++pexpr;
}
@@ -1652,6 +1656,7 @@ Parse::init_vars(const Typed_identifier_list* til, Type* type,
go_assert(pexpr == init->end());
if (is_coloneq && !any_new)
error_at(location, "variables redeclared but no variable is new");
+ this->finish_init_vars(vars, vals, location);
}
// See if we need to initialize a list of variables from a function
@@ -1674,13 +1679,15 @@ Parse::init_vars_from_call(const Typed_identifier_list* vars, Type* type,
Named_object* first_var = NULL;
unsigned int index = 0;
bool any_new = false;
+ Expression_list* ivars = new Expression_list();
+ Expression_list* ivals = new Expression_list();
for (Typed_identifier_list::const_iterator pv = vars->begin();
pv != vars->end();
++pv, ++index)
{
Expression* init = Expression::make_call_result(call, index);
Named_object* no = this->init_var(*pv, type, init, is_coloneq, false,
- &any_new);
+ &any_new, ivars, ivals);
if (this->gogo_->in_global_scope() && no->is_variable())
{
@@ -1700,6 +1707,8 @@ Parse::init_vars_from_call(const Typed_identifier_list* vars, Type* type,
if (is_coloneq && !any_new)
error_at(location, "variables redeclared but no variable is new");
+ this->finish_init_vars(ivars, ivals, location);
+
return true;
}
@@ -1725,7 +1734,7 @@ Parse::init_vars_from_map(const Typed_identifier_list* vars, Type* type,
Typed_identifier_list::const_iterator p = vars->begin();
Expression* init = type == NULL ? index : NULL;
Named_object* val_no = this->init_var(*p, type, init, is_coloneq,
- type == NULL, &any_new);
+ type == NULL, &any_new, NULL, NULL);
if (type == NULL && any_new && val_no->is_variable())
val_no->var_value()->set_type_from_init_tuple();
Expression* val_var = Expression::make_var_reference(val_no, location);
@@ -1735,7 +1744,7 @@ Parse::init_vars_from_map(const Typed_identifier_list* vars, Type* type,
if (var_type == NULL)
var_type = Type::lookup_bool_type();
Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false,
- &any_new);
+ &any_new, NULL, NULL);
Expression* present_var = Expression::make_var_reference(no, location);
if (is_coloneq && !any_new)
@@ -1790,7 +1799,7 @@ Parse::init_vars_from_receive(const Typed_identifier_list* vars, Type* type,
Typed_identifier_list::const_iterator p = vars->begin();
Expression* init = type == NULL ? receive : NULL;
Named_object* val_no = this->init_var(*p, type, init, is_coloneq,
- type == NULL, &any_new);
+ type == NULL, &any_new, NULL, NULL);
if (type == NULL && any_new && val_no->is_variable())
val_no->var_value()->set_type_from_init_tuple();
Expression* val_var = Expression::make_var_reference(val_no, location);
@@ -1800,7 +1809,7 @@ Parse::init_vars_from_receive(const Typed_identifier_list* vars, Type* type,
if (var_type == NULL)
var_type = Type::lookup_bool_type();
Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false,
- &any_new);
+ &any_new, NULL, NULL);
Expression* received_var = Expression::make_var_reference(no, location);
if (is_coloneq && !any_new)
@@ -1857,7 +1866,7 @@ Parse::init_vars_from_type_guard(const Typed_identifier_list* vars,
if (var_type == NULL)
var_type = type_guard->type();
Named_object* val_no = this->init_var(*p, var_type, NULL, is_coloneq, false,
- &any_new);
+ &any_new, NULL, NULL);
Expression* val_var = Expression::make_var_reference(val_no, location);
++p;
@@ -1865,7 +1874,7 @@ Parse::init_vars_from_type_guard(const Typed_identifier_list* vars,
if (var_type == NULL)
var_type = Type::lookup_bool_type();
Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false,
- &any_new);
+ &any_new, NULL, NULL);
Expression* ok_var = Expression::make_var_reference(no, location);
Expression* texpr = type_guard->expr();
@@ -1904,7 +1913,8 @@ Parse::init_vars_from_type_guard(const Typed_identifier_list* vars,
Named_object*
Parse::init_var(const Typed_identifier& tid, Type* type, Expression* init,
- bool is_coloneq, bool type_from_init, bool* is_new)
+ bool is_coloneq, bool type_from_init, bool* is_new,
+ Expression_list* vars, Expression_list* vals)
{
Location location = tid.location();
@@ -1946,9 +1956,9 @@ Parse::init_var(const Typed_identifier& tid, Type* type, Expression* init,
// like v, ok := x.(int).
if (!type_from_init && init != NULL)
{
- Expression *v = Expression::make_var_reference(no, location);
- Statement *s = Statement::make_assignment(v, init, location);
- this->gogo_->add_statement(s);
+ go_assert(vars != NULL && vals != NULL);
+ vars->push_back(Expression::make_var_reference(no, location));
+ vals->push_back(init);
}
return no;
}
@@ -1983,6 +1993,36 @@ Parse::create_dummy_global(Type* type, Expression* init,
return this->gogo_->add_variable(buf, var);
}
+// Finish the variable initialization by executing any assignments to
+// existing variables when using :=. These must be done as a tuple
+// assignment in case of something like n, a, b := 1, b, a.
+
+void
+Parse::finish_init_vars(Expression_list* vars, Expression_list* vals,
+ Location location)
+{
+ if (vars->empty())
+ {
+ delete vars;
+ delete vals;
+ }
+ else if (vars->size() == 1)
+ {
+ go_assert(!this->gogo_->in_global_scope());
+ this->gogo_->add_statement(Statement::make_assignment(vars->front(),
+ vals->front(),
+ location));
+ delete vars;
+ delete vals;
+ }
+ else
+ {
+ go_assert(!this->gogo_->in_global_scope());
+ this->gogo_->add_statement(Statement::make_tuple_assignment(vars, vals,
+ location));
+ }
+}
+
// SimpleVarDecl = identifier ":=" Expression .
// We've already seen the identifier.
@@ -3315,6 +3355,61 @@ Parse::unary_expr(bool may_be_sink, bool may_be_composite_lit,
bool* is_type_switch)
{
const Token* token = this->peek_token();
+
+ // There is a complex parse for <- chan. The choices are
+ // Convert x to type <- chan int:
+ // (<- chan int)(x)
+ // Receive from (x converted to type chan <- chan int):
+ // (<- chan <- chan int (x))
+ // Convert x to type <- chan (<- chan int).
+ // (<- chan <- chan int)(x)
+ if (token->is_op(OPERATOR_CHANOP))
+ {
+ Location location = token->location();
+ if (this->advance_token()->is_keyword(KEYWORD_CHAN))
+ {
+ Expression* expr = this->primary_expr(false, may_be_composite_lit,
+ NULL);
+ if (expr->is_error_expression())
+ return expr;
+ else if (!expr->is_type_expression())
+ return Expression::make_receive(expr, location);
+ else
+ {
+ if (expr->type()->is_error_type())
+ return expr;
+
+ // We picked up "chan TYPE", but it is not a type
+ // conversion.
+ Channel_type* ct = expr->type()->channel_type();
+ if (ct == NULL)
+ {
+ // This is probably impossible.
+ error_at(location, "expected channel type");
+ return Expression::make_error(location);
+ }
+ else if (ct->may_receive())
+ {
+ // <- chan TYPE.
+ Type* t = Type::make_channel_type(false, true,
+ ct->element_type());
+ return Expression::make_type(t, location);
+ }
+ else
+ {
+ // <- chan <- TYPE. Because we skipped the leading
+ // <-, we parsed this as chan <- TYPE. With the
+ // leading <-, we parse it as <- chan (<- TYPE).
+ Type *t = this->reassociate_chan_direction(ct, location);
+ return Expression::make_type(t, location);
+ }
+ }
+ }
+
+ this->unget_token(Token::make_operator_token(OPERATOR_CHANOP, location));
+ token = this->peek_token();
+ }
+
if (token->is_op(OPERATOR_PLUS)
|| token->is_op(OPERATOR_MINUS)
|| token->is_op(OPERATOR_NOT)
@@ -3327,14 +3422,6 @@ Parse::unary_expr(bool may_be_sink, bool may_be_composite_lit,
Operator op = token->op();
this->advance_token();
- if (op == OPERATOR_CHANOP
- && this->peek_token()->is_keyword(KEYWORD_CHAN))
- {
- // This is "<- chan" which must be the start of a type.
- this->unget_token(Token::make_operator_token(op, location));
- return Expression::make_type(this->type(), location);
- }
-
Expression* expr = this->unary_expr(false, may_be_composite_lit, NULL);
if (expr->is_error_expression())
;
@@ -3354,6 +3441,32 @@ Parse::unary_expr(bool may_be_sink, bool may_be_composite_lit,
is_type_switch);
}
+// This is called for the obscure case of
+// (<- chan <- chan int)(x)
+// In unary_expr we remove the leading <- and parse the remainder,
+// which gives us
+// chan <- (chan int)
+// When we add the leading <- back in, we really want
+// <- chan (<- chan int)
+// This means that we need to reassociate.
+
+Type*
+Parse::reassociate_chan_direction(Channel_type *ct, Location location)
+{
+ Channel_type* ele = ct->element_type()->channel_type();
+ if (ele == NULL)
+ {
+ error_at(location, "parse error");
+ return Type::make_error_type();
+ }
+ Type* sub = ele;
+ if (ele->may_send())
+ sub = Type::make_channel_type(false, true, ele->element_type());
+ else
+ sub = this->reassociate_chan_direction(ele, location);
+ return Type::make_channel_type(false, true, sub);
+}
+
// Statement =
// Declaration | LabeledStmt | SimpleStmt |
// GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
@@ -5040,7 +5153,8 @@ Parse::range_clause_decl(const Typed_identifier_list* til,
bool any_new = false;
const Typed_identifier* pti = &til->front();
- Named_object* no = this->init_var(*pti, NULL, expr, true, true, &any_new);
+ Named_object* no = this->init_var(*pti, NULL, expr, true, true, &any_new,
+ NULL, NULL);
if (any_new && no->is_variable())
no->var_value()->set_type_from_range_index();
p_range_clause->index = Expression::make_var_reference(no, location);
@@ -5051,7 +5165,7 @@ Parse::range_clause_decl(const Typed_identifier_list* til,
{
pti = &til->back();
bool is_new = false;
- no = this->init_var(*pti, NULL, expr, true, true, &is_new);
+ no = this->init_var(*pti, NULL, expr, true, true, &is_new, NULL, NULL);
if (is_new && no->is_variable())
no->var_value()->set_type_from_range_value();
if (is_new)
diff --git a/gcc/go/gofrontend/parse.h b/gcc/go/gofrontend/parse.h
index 3139f7e8908..a355b7d2b3b 100644
--- a/gcc/go/gofrontend/parse.h
+++ b/gcc/go/gofrontend/parse.h
@@ -14,6 +14,7 @@ class Named_object;
class Type;
class Typed_identifier;
class Typed_identifier_list;
+class Channel_type;
class Function_type;
class Block;
class Expression;
@@ -205,8 +206,11 @@ class Parse
Expression*, bool is_coloneq,
Location);
Named_object* init_var(const Typed_identifier&, Type*, Expression*,
- bool is_coloneq, bool type_from_init, bool* is_new);
+ bool is_coloneq, bool type_from_init, bool* is_new,
+ Expression_list* vars, Expression_list* vals);
Named_object* create_dummy_global(Type*, Expression*, Location);
+ void finish_init_vars(Expression_list* vars, Expression_list* vals,
+ Location);
void simple_var_decl_or_assignment(const std::string&, Location,
bool may_be_composite_lit,
Range_clause*, Type_switch*);
@@ -229,6 +233,7 @@ class Parse
bool expression_may_start_here();
Expression* unary_expr(bool may_be_sink, bool may_be_composite_lit,
bool* is_type_switch);
+ Type* reassociate_chan_direction(Channel_type*, Location);
Expression* qualified_expr(Expression*, Location);
Expression* id_to_expression(const std::string&, Location);
void statement(Label*);
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index b7fbc91fd8e..90856a0c05d 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -4928,14 +4928,15 @@ Struct_type::write_equal_function(Gogo* gogo, Named_type* name)
void
Struct_type::do_reflection(Gogo* gogo, std::string* ret) const
{
- ret->append("struct { ");
+ ret->append("struct {");
for (Struct_field_list::const_iterator p = this->fields_->begin();
p != this->fields_->end();
++p)
{
if (p != this->fields_->begin())
- ret->append("; ");
+ ret->push_back(';');
+ ret->push_back(' ');
if (p->is_anonymous())
ret->push_back('?');
else
@@ -4968,7 +4969,10 @@ Struct_type::do_reflection(Gogo* gogo, std::string* ret) const
}
}
- ret->append(" }");
+ if (!this->fields_->empty())
+ ret->push_back(' ');
+
+ ret->push_back('}');
}
// Mangled name.
@@ -8399,6 +8403,7 @@ Named_type::do_reflection(Gogo* gogo, std::string* ret) const
}
if (this->in_function_ != NULL)
{
+ ret->push_back('\t');
ret->append(Gogo::unpack_hidden_name(this->in_function_->name()));
ret->push_back('$');
if (this->in_function_index_ > 0)
@@ -8408,6 +8413,7 @@ Named_type::do_reflection(Gogo* gogo, std::string* ret) const
ret->append(buf);
ret->push_back('$');
}
+ ret->push_back('\t');
}
ret->append(Gogo::unpack_hidden_name(this->named_object_->name()));
}
diff --git a/gcc/go/lang.opt b/gcc/go/lang.opt
index eb9ed9a63a0..22197a71e3d 100644
--- a/gcc/go/lang.opt
+++ b/gcc/go/lang.opt
@@ -61,6 +61,10 @@ fgo-prefix=
Go Joined RejectNegative
-fgo-prefix=<string> Set package-specific prefix for exported Go names
+fgo-relative-import-path=
+Go Joined RejectNegative
+-fgo-relative-import-path=<path> Treat a relative import as relative to path
+
frequire-return-statement
Go Var(go_require_return_statement) Init(1) Warning
Functions which return values must end with return statements
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index e4e13abe0aa..49b489e0707 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -44,6 +44,7 @@
#include "tree-pass.h"
#include "df.h"
#include "vec.h"
+#include "pointer-set.h"
#include "vecprim.h"
#include "dbgcnt.h"
@@ -2689,12 +2690,14 @@ noce_process_if_block (struct noce_if_info *if_info)
/* Check whether a block is suitable for conditional move conversion.
Every insn must be a simple set of a register to a constant or a
- register. For each assignment, store the value in the array VALS,
- indexed by register number, then store the register number in
- REGS. COND is the condition we will test. */
+ register. For each assignment, store the value in the pointer map
+ VALS, keyed indexed by register pointer, then store the register
+ pointer in REGS. COND is the condition we will test. */
static int
-check_cond_move_block (basic_block bb, rtx *vals, VEC (int, heap) **regs,
+check_cond_move_block (basic_block bb,
+ struct pointer_map_t *vals,
+ VEC (rtx, heap) **regs,
rtx cond)
{
rtx insn;
@@ -2708,6 +2711,7 @@ check_cond_move_block (basic_block bb, rtx *vals, VEC (int, heap) **regs,
FOR_BB_INSNS (bb, insn)
{
rtx set, dest, src;
+ void **slot;
if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
continue;
@@ -2734,14 +2738,14 @@ check_cond_move_block (basic_block bb, rtx *vals, VEC (int, heap) **regs,
/* Don't try to handle this if the source register was
modified earlier in the block. */
if ((REG_P (src)
- && vals[REGNO (src)] != NULL)
+ && pointer_map_contains (vals, src))
|| (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src))
- && vals[REGNO (SUBREG_REG (src))] != NULL))
+ && pointer_map_contains (vals, SUBREG_REG (src))))
return FALSE;
/* Don't try to handle this if the destination register was
modified earlier in the block. */
- if (vals[REGNO (dest)] != NULL)
+ if (pointer_map_contains (vals, dest))
return FALSE;
/* Don't try to handle this if the condition uses the
@@ -2755,17 +2759,18 @@ check_cond_move_block (basic_block bb, rtx *vals, VEC (int, heap) **regs,
&& modified_between_p (src, insn, NEXT_INSN (BB_END (bb))))
return FALSE;
- vals[REGNO (dest)] = src;
+ slot = pointer_map_insert (vals, (void *) dest);
+ *slot = (void *) src;
- VEC_safe_push (int, heap, *regs, REGNO (dest));
+ VEC_safe_push (rtx, heap, *regs, dest);
}
return TRUE;
}
/* Given a basic block BB suitable for conditional move conversion,
- a condition COND, and arrays THEN_VALS and ELSE_VALS containing the
- register values depending on COND, emit the insns in the block as
+ a condition COND, and pointer maps THEN_VALS and ELSE_VALS containing
+ the register values depending on COND, emit the insns in the block as
conditional moves. If ELSE_BLOCK is true, THEN_BB was already
processed. The caller has started a sequence for the conversion.
Return true if successful, false if something goes wrong. */
@@ -2773,7 +2778,8 @@ check_cond_move_block (basic_block bb, rtx *vals, VEC (int, heap) **regs,
static bool
cond_move_convert_if_block (struct noce_if_info *if_infop,
basic_block bb, rtx cond,
- rtx *then_vals, rtx *else_vals,
+ struct pointer_map_t *then_vals,
+ struct pointer_map_t *else_vals,
bool else_block_p)
{
enum rtx_code code;
@@ -2786,7 +2792,7 @@ cond_move_convert_if_block (struct noce_if_info *if_infop,
FOR_BB_INSNS (bb, insn)
{
rtx set, target, dest, t, e;
- unsigned int regno;
+ void **then_slot, **else_slot;
/* ??? Maybe emit conditional debug insn? */
if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
@@ -2795,10 +2801,11 @@ cond_move_convert_if_block (struct noce_if_info *if_infop,
gcc_assert (set && REG_P (SET_DEST (set)));
dest = SET_DEST (set);
- regno = REGNO (dest);
- t = then_vals[regno];
- e = else_vals[regno];
+ then_slot = pointer_map_contains (then_vals, dest);
+ else_slot = pointer_map_contains (else_vals, dest);
+ t = then_slot ? (rtx) *then_slot : NULL_RTX;
+ e = else_slot ? (rtx) *else_slot : NULL_RTX;
if (else_block_p)
{
@@ -2842,31 +2849,25 @@ cond_move_process_if_block (struct noce_if_info *if_info)
rtx jump = if_info->jump;
rtx cond = if_info->cond;
rtx seq, loc_insn;
- int max_reg, size, c, reg;
- rtx *then_vals;
- rtx *else_vals;
- VEC (int, heap) *then_regs = NULL;
- VEC (int, heap) *else_regs = NULL;
+ rtx reg;
+ int c;
+ struct pointer_map_t *then_vals;
+ struct pointer_map_t *else_vals;
+ VEC (rtx, heap) *then_regs = NULL;
+ VEC (rtx, heap) *else_regs = NULL;
unsigned int i;
+ int success_p = FALSE;
/* Build a mapping for each block to the value used for each
register. */
- max_reg = max_reg_num ();
- size = (max_reg + 1) * sizeof (rtx);
- then_vals = (rtx *) alloca (size);
- else_vals = (rtx *) alloca (size);
- memset (then_vals, 0, size);
- memset (else_vals, 0, size);
+ then_vals = pointer_map_create ();
+ else_vals = pointer_map_create ();
/* Make sure the blocks are suitable. */
if (!check_cond_move_block (then_bb, then_vals, &then_regs, cond)
|| (else_bb
&& !check_cond_move_block (else_bb, else_vals, &else_regs, cond)))
- {
- VEC_free (int, heap, then_regs);
- VEC_free (int, heap, else_regs);
- return FALSE;
- }
+ goto done;
/* Make sure the blocks can be used together. If the same register
is set in both blocks, and is not set to a constant in both
@@ -2875,41 +2876,38 @@ cond_move_process_if_block (struct noce_if_info *if_info)
source register does not change after the assignment. Also count
the number of registers set in only one of the blocks. */
c = 0;
- FOR_EACH_VEC_ELT (int, then_regs, i, reg)
+ FOR_EACH_VEC_ELT (rtx, then_regs, i, reg)
{
- if (!then_vals[reg] && !else_vals[reg])
- continue;
+ void **then_slot = pointer_map_contains (then_vals, reg);
+ void **else_slot = pointer_map_contains (else_vals, reg);
- if (!else_vals[reg])
+ gcc_checking_assert (then_slot);
+ if (!else_slot)
++c;
else
{
- if (!CONSTANT_P (then_vals[reg])
- && !CONSTANT_P (else_vals[reg])
- && !rtx_equal_p (then_vals[reg], else_vals[reg]))
- {
- VEC_free (int, heap, then_regs);
- VEC_free (int, heap, else_regs);
- return FALSE;
- }
+ rtx then_val = (rtx) *then_slot;
+ rtx else_val = (rtx) *else_slot;
+ if (!CONSTANT_P (then_val) && !CONSTANT_P (else_val)
+ && !rtx_equal_p (then_val, else_val))
+ goto done;
}
}
/* Finish off c for MAX_CONDITIONAL_EXECUTE. */
- FOR_EACH_VEC_ELT (int, else_regs, i, reg)
- if (!then_vals[reg])
- ++c;
+ FOR_EACH_VEC_ELT (rtx, else_regs, i, reg)
+ {
+ gcc_checking_assert (pointer_map_contains (else_vals, reg));
+ if (!pointer_map_contains (then_vals, reg))
+ ++c;
+ }
/* Make sure it is reasonable to convert this block. What matters
is the number of assignments currently made in only one of the
branches, since if we convert we are going to always execute
them. */
if (c > MAX_CONDITIONAL_EXECUTE)
- {
- VEC_free (int, heap, then_regs);
- VEC_free (int, heap, else_regs);
- return FALSE;
- }
+ goto done;
/* Try to emit the conditional moves. First do the then block,
then do anything left in the else blocks. */
@@ -2921,17 +2919,11 @@ cond_move_process_if_block (struct noce_if_info *if_info)
then_vals, else_vals, true)))
{
end_sequence ();
- VEC_free (int, heap, then_regs);
- VEC_free (int, heap, else_regs);
- return FALSE;
+ goto done;
}
seq = end_ifcvt_sequence (if_info);
if (!seq)
- {
- VEC_free (int, heap, then_regs);
- VEC_free (int, heap, else_regs);
- return FALSE;
- }
+ goto done;
loc_insn = first_active_insn (then_bb);
if (!loc_insn)
@@ -2962,9 +2954,14 @@ cond_move_process_if_block (struct noce_if_info *if_info)
num_updated_if_blocks++;
- VEC_free (int, heap, then_regs);
- VEC_free (int, heap, else_regs);
- return TRUE;
+ success_p = TRUE;
+
+done:
+ pointer_map_destroy (then_vals);
+ pointer_map_destroy (else_vals);
+ VEC_free (rtx, heap, then_regs);
+ VEC_free (rtx, heap, else_regs);
+ return success_p;
}
diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog
index 60e1ccd5357..23c448f8338 100644
--- a/gcc/po/ChangeLog
+++ b/gcc/po/ChangeLog
@@ -1,3 +1,7 @@
+2012-10-08 Joseph Myers <joseph@codesourcery.com>
+
+ * es.po: Update.
+
2012-09-26 Joseph Myers <joseph@codesourcery.com>
* sv.po: Update.
diff --git a/gcc/po/es.po b/gcc/po/es.po
index 245d16d71a4..07878db195a 100644
--- a/gcc/po/es.po
+++ b/gcc/po/es.po
@@ -1,4 +1,4 @@
-# Mensajes en español para gcc-4.7.1.
+# Mensajes en español para gcc-4.7.2.
# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
# This file is distributed under the same license as the gcc package.
# Cristian Othón Martínez Vera <cfuga@cfuga.mx>, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
@@ -7,10 +7,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: gcc 4.7.1\n"
+"Project-Id-Version: gcc 4.7.2\n"
"Report-Msgid-Bugs-To: http://gcc.gnu.org/bugs.html\n"
"POT-Creation-Date: 2012-09-19 14:50+0000\n"
-"PO-Revision-Date: 2012-06-22 13:49-0500\n"
+"PO-Revision-Date: 2012-09-24 13:50-0500\n"
"Last-Translator: Cristian Othón Martínez Vera <cfuga@cfuga.mx>\n"
"Language-Team: Spanish <es@li.org>\n"
"Language: es\n"
@@ -7589,10 +7589,8 @@ msgid "Follow Renesas (formerly Hitachi) / SuperH calling conventions"
msgstr "Sigue las convenciones de llamada Renesas (anteriormente Hitachi) / SuperH"
#: config/sh/sh.opt:274
-#, fuzzy
-#| msgid "Increase the IEEE compliance for floating-point code"
msgid "Increase the IEEE compliance for floating-point comparisons"
-msgstr "Incrementa el cumplimiento con IEEE para el código de coma flotante"
+msgstr "Incrementa el cumplimiento con IEEE para las comparaciones de coma flotante"
#: config/sh/sh.opt:278
msgid "Enable the use of the indexed addressing mode for SHmedia32/SHcompact"
@@ -12044,7 +12042,7 @@ msgstr "se esperaba una expresión booleana"
#: go/gofrontend/statements.cc:4198
msgid "cannot type switch on non-interface value"
-msgstr ""
+msgstr "no se puede cambiar el tipo en valores que no son de interfaz"
#: go/gofrontend/statements.cc:4320
msgid "incompatible types in send"
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index e74fee248b5..74089df38d7 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -3224,7 +3224,11 @@ has_dependence_note_reg_use (int regno)
if (reg_last->clobbers)
*dsp = (*dsp & ~SPECULATIVE) | DEP_ANTI;
- /* Handle BE_IN_SPEC. */
+ /* Merge BE_IN_SPEC bits into *DSP when the dependency producer
+ is actually a check insn. We need to do this for any register
+ read-read dependency with the check unless we track properly
+ all registers written by BE_IN_SPEC-speculated insns, as
+ we don't have explicit dependence lists. See PR 53975. */
if (reg_last->uses)
{
ds_t pro_spec_checked_ds;
@@ -3232,9 +3236,7 @@ has_dependence_note_reg_use (int regno)
pro_spec_checked_ds = INSN_SPEC_CHECKED_DS (has_dependence_data.pro);
pro_spec_checked_ds = ds_get_max_dep_weak (pro_spec_checked_ds);
- if (pro_spec_checked_ds != 0
- && bitmap_bit_p (INSN_REG_SETS (has_dependence_data.pro), regno))
- /* Merge BE_IN_SPEC bits into *DSP. */
+ if (pro_spec_checked_ds != 0)
*dsp = ds_full_merge (*dsp, pro_spec_checked_ds,
NULL_RTX, NULL_RTX);
}
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index 2af01aea99e..abbfa84ff3a 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -3567,29 +3567,41 @@ process_use_exprs (av_set_t *av_ptr)
return NULL;
}
-/* Lookup EXPR in VINSN_VEC and return TRUE if found. */
+/* Lookup EXPR in VINSN_VEC and return TRUE if found. Also check patterns from
+ EXPR's history of changes. */
static bool
vinsn_vec_has_expr_p (vinsn_vec_t vinsn_vec, expr_t expr)
{
- vinsn_t vinsn;
+ vinsn_t vinsn, expr_vinsn;
int n;
+ unsigned i;
- FOR_EACH_VEC_ELT (vinsn_t, vinsn_vec, n, vinsn)
- if (VINSN_SEPARABLE_P (vinsn))
- {
- if (vinsn_equal_p (vinsn, EXPR_VINSN (expr)))
- return true;
- }
- else
- {
- /* For non-separable instructions, the blocking insn can have
- another pattern due to substitution, and we can't choose
- different register as in the above case. Check all registers
- being written instead. */
- if (bitmap_intersect_p (VINSN_REG_SETS (vinsn),
- VINSN_REG_SETS (EXPR_VINSN (expr))))
- return true;
- }
+ /* Start with checking expr itself and then proceed with all the old forms
+ of expr taken from its history vector. */
+ for (i = 0, expr_vinsn = EXPR_VINSN (expr);
+ expr_vinsn;
+ expr_vinsn = (i < VEC_length (expr_history_def,
+ EXPR_HISTORY_OF_CHANGES (expr))
+ ? VEC_index (expr_history_def,
+ EXPR_HISTORY_OF_CHANGES (expr),
+ i++)->old_expr_vinsn
+ : NULL))
+ FOR_EACH_VEC_ELT (vinsn_t, vinsn_vec, n, vinsn)
+ if (VINSN_SEPARABLE_P (vinsn))
+ {
+ if (vinsn_equal_p (vinsn, expr_vinsn))
+ return true;
+ }
+ else
+ {
+ /* For non-separable instructions, the blocking insn can have
+ another pattern due to substitution, and we can't choose
+ different register as in the above case. Check all registers
+ being written instead. */
+ if (bitmap_intersect_p (VINSN_REG_SETS (vinsn),
+ VINSN_REG_SETS (expr_vinsn)))
+ return true;
+ }
return false;
}
@@ -5697,8 +5709,8 @@ update_and_record_unavailable_insns (basic_block book_block)
|| EXPR_TARGET_AVAILABLE (new_expr)
!= EXPR_TARGET_AVAILABLE (cur_expr))
/* Unfortunately, the below code could be also fired up on
- separable insns.
- FIXME: add an example of how this could happen. */
+ separable insns, e.g. when moving insns through the new
+ speculation check as in PR 53701. */
vinsn_vec_add (&vec_bookkeeping_blocked_vinsns, cur_expr);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 48f6ead5807..8e2c69b73bd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,128 @@
+2012-11-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * g++.dg/torture/20121105-1.C: New test.
+
+2012-11-05 Jakub Jelinek <jakub@redhat.com>
+
+ Backported from mainline
+ 2012-10-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/54828
+ * g++.dg/debug/pr54828.C: New test.
+
+ 2012-10-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/54988
+ * c-c++-common/pr54988.c: New test.
+
+ 2012-10-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/54877
+ * gcc.dg/torture/pr54877.c: New test.
+
+2012-11-02 Jeff Law <law@redhat.com>
+
+ * gcc.c-torture/execute/pr54985.c: New test.
+
+2012-10-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/53517
+ * gnat.dg/lto14.adb: Skip on Solaris.
+
+2012-10-26 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/54984
+ * g++.dg/template/new11.C: New.
+
+2012-10-26 Terry Guo <terry.guo@arm.com>
+
+ Backport from mainline
+ 2012-10-23 Terry Guo <terry.guo@arm.com>
+
+ PR target/55019
+ * gcc.dg/pr55019.c: New.
+
+2012-10-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/54902
+ * g++.dg/torture/pr54902.C: New testcase.
+
+2012-10-22 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/modular4.adb: New test.
+ * gnat.dg/modular4_pkg.ads: New helper.
+
+2012-10-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/atomic1.ads: XFAIL on MIPS.
+ * gnat.dg/specs/addr1.ads: Likewise.
+
+2012-10-19 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ Backport from mainline
+ 2012-10-19 Zhenqiang Chen <zhenqiang.chen@linaro.org>
+
+ PR target/54892
+ * gcc.target/arm/pr54892.c: New.
+
+2012-10-16 Andrey Belevantsev <abel@ispras.ru>
+
+ Backport from mainline
+ 2012-08-09 Andrey Belevantsev <abel@ispras.ru>
+
+ PR rtl-optimization/53701
+ * gcc.dg/pr53701.c: New test.
+
+2012-10-15 Uros Bizjak <ubizjak@gmail.com>
+
+ Backport from mainline
+ 2012-10-15 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/avx256-unaligned-load-1.c: Update asm scan patterns.
+ * gcc.target/i386/avx256-unaligned-load-2.c: Ditto.
+ * gcc.target/i386/avx256-unaligned-load-3.c: Ditto.
+ * gcc.target/i386/avx256-unaligned-load-4.c: Ditto.
+ * gcc.target/i386/avx256-unaligned-store-1.c: Ditto.
+ * gcc.target/i386/avx256-unaligned-store-2.c: Ditto.
+ * gcc.target/i386/avx256-unaligned-store-3.c: Ditto.
+ * gcc.target/i386/avx256-unaligned-store-4.c: Ditto.
+
+2012-10-15 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/54920
+ * gcc.dg/torture/pr54920.c: New testcase.
+
+2012-10-14 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/54784
+ * gfortran.dg/class_allocate_13.f90: New.
+
+2012-10-08 Terry Guo <terry.guo@arm.com>
+
+ Backported from mainline
+ 2012-09-19 Terry Guo <terry.guo@arm.com>
+
+ * lib/gcc-dg.exp (dg_runtest_extra_prunes): New variable to define
+ extra prune rules that will be applied to all tests in a .exp file.
+ (gcc-dg-prune): Use rules defined by the above variable.
+ * gcc.target/arm/arm.exp (dg_runtest_extra_prunes): Skip all the
+ harmless warnings on architecture switch conflict.
+
+2012-10-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/54858
+ * g++.dg/template/pr54858.C: New test.
+
+2012-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/33763
+ * c-c++-common/pr33763.c: New test.
+
+2012-10-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/54777
+ * g++.dg/cpp0x/constexpr-ref4.C: New test.
+
2012-09-30 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR target/54083
diff --git a/gcc/testsuite/c-c++-common/pr33763.c b/gcc/testsuite/c-c++-common/pr33763.c
new file mode 100644
index 00000000000..dbdfa77fc3d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr33763.c
@@ -0,0 +1,60 @@
+/* PR tree-optimization/33763 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef struct
+{
+ void *a;
+ void *b;
+} T;
+extern void *foo (const char *, const char *);
+extern void *bar (void *, const char *, T);
+extern int baz (const char *, int);
+
+extern inline __attribute__ ((always_inline, gnu_inline)) int
+baz (const char *x, int y)
+{
+ return 2;
+}
+
+int
+baz (const char *x, int y)
+{
+ return 1;
+}
+
+int xa, xb;
+
+static void *
+inl (const char *x, const char *y)
+{
+ T t = { &xa, &xb };
+ int *f = (int *) __builtin_malloc (sizeof (int));
+ const char *z;
+ int o = 0;
+ void *r = 0;
+
+ for (z = y; *z; z++)
+ {
+ if (*z == 'r')
+ o |= 1;
+ if (*z == 'w')
+ o |= 2;
+ }
+ if (o == 1)
+ *f = baz (x, 0);
+ if (o == 2)
+ *f = baz (x, 1);
+ if (o == 3)
+ *f = baz (x, 2);
+
+ if (o && *f > 0)
+ r = bar (f, "w", t);
+ return r;
+}
+
+void *
+foo (const char *x, const char *y)
+{
+ return inl (x, y);
+}
diff --git a/gcc/testsuite/c-c++-common/pr54988.c b/gcc/testsuite/c-c++-common/pr54988.c
new file mode 100644
index 00000000000..59406d6ab24
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr54988.c
@@ -0,0 +1,20 @@
+/* PR c++/54988 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-msse2" { target { i?86-*-* x86_64-*-* } } } */
+
+#if defined(__i386__) || defined(__x86_64__)
+#pragma GCC target "fpmath=sse"
+#endif
+
+static inline __attribute__ ((always_inline)) int
+foo (int x)
+{
+ return x;
+}
+
+int
+bar (int x)
+{
+ return foo (x);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C
new file mode 100644
index 00000000000..6ae355a273f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C
@@ -0,0 +1,18 @@
+// PR c++/54777
+// { dg-options -std=c++0x }
+
+struct S
+{
+ int s[1];
+ constexpr const int &foo (unsigned i) { return (i < 1 ? 0 : throw 1), s[i]; }
+ constexpr const int &bar (unsigned i) { return i < 1 ? s[i] : (throw 0, s[i]); }
+};
+
+int
+main ()
+{
+ constexpr S a {};
+ constexpr int i = a.foo (0);
+ constexpr int j = a.bar (0);
+ static_assert (i == j, "Ouch");
+}
diff --git a/gcc/testsuite/g++.dg/debug/pr54828.C b/gcc/testsuite/g++.dg/debug/pr54828.C
new file mode 100644
index 00000000000..80b9a3ce070
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/pr54828.C
@@ -0,0 +1,14 @@
+// PR debug/54828
+// { dg-do compile }
+// { dg-options "-g" }
+
+struct T { T (); virtual ~T (); };
+struct S : public virtual T { S (); virtual ~S (); };
+int v;
+void foo (char *);
+
+S::S ()
+{
+ char s[v];
+ foo (s);
+}
diff --git a/gcc/testsuite/g++.dg/template/new11.C b/gcc/testsuite/g++.dg/template/new11.C
new file mode 100644
index 00000000000..76f6c66997f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/new11.C
@@ -0,0 +1,28 @@
+// PR c++/54984
+// { dg-do run }
+
+int n = 1;
+
+void* operator new(__SIZE_TYPE__)
+{
+ n = -1;
+ return &n;
+}
+
+template <class T>
+struct Foo
+{
+ Foo()
+ : x(new int)
+ {
+ if (*x != -1)
+ __builtin_abort();
+ }
+
+ int* x;
+};
+
+int main()
+{
+ Foo<float> foo;
+}
diff --git a/gcc/testsuite/g++.dg/template/pr54858.C b/gcc/testsuite/g++.dg/template/pr54858.C
new file mode 100644
index 00000000000..51610ad689a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr54858.C
@@ -0,0 +1,21 @@
+// PR c++/54858
+// { dg-do compile }
+
+template <int> struct A {};
+template <typename T, T *> struct B {};
+template <typename D> struct C
+{
+ A<0> c0; B<A<0>, &C::c0> d0; // { dg-error "could not convert template argument" }
+ A<0> c1; B<A<0>, &C::c1> d1; // { dg-error "could not convert template argument" }
+ A<0> c2; B<A<0>, &C::c2> d2; // { dg-error "could not convert template argument" }
+ A<0> c3; B<A<0>, &C::c3> d3; // { dg-error "could not convert template argument" }
+ A<0> c4; B<A<0>, &C::c4> d4; // { dg-error "could not convert template argument" }
+ A<0> c5; B<A<0>, &C::c5> d5; // { dg-error "could not convert template argument" }
+ A<0> c6; B<A<0>, &C::c6> d6; // { dg-error "could not convert template argument" }
+ A<0> c7; B<A<0>, &C::c7> d7; // { dg-error "could not convert template argument" }
+ A<0> c8; B<A<0>, &C::c8> d8; // { dg-error "could not convert template argument" }
+ A<0> c9; B<A<0>, &C::c9> d9; // { dg-error "could not convert template argument" }
+ A<0> ca; B<A<0>, &C::ca> da; // { dg-error "could not convert template argument" }
+ A<0> cb; B<A<0>, &C::cb> db; // { dg-error "could not convert template argument" }
+};
+C<int> e;
diff --git a/gcc/testsuite/g++.dg/torture/20121105-1.C b/gcc/testsuite/g++.dg/torture/20121105-1.C
new file mode 100644
index 00000000000..03323421a5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/20121105-1.C
@@ -0,0 +1,42 @@
+// PR tree-optimization/54986
+// Reported by Remi Vanicat <vanicat@debian.org>
+// Reduced testcase by Markus Trippelsdorf <markus@trippelsdorf.de>
+
+struct A;
+struct B
+{
+ int *_ptr;
+ bool operator==(B *p1)
+ {
+ return p1->_ptr;
+ }
+};
+struct C {
+ A* ref_SYMBptr();
+};
+struct A
+{
+ B sommet;
+};
+typedef C *gen_op_context;
+struct D
+{
+ D(gen_op_context) {}
+};
+
+D c(0);
+const long d = (long)&c;
+B *const e = (B *)&d;
+
+static bool
+fn1(C& p1)
+{
+ return p1.ref_SYMBptr()->sommet == e;
+}
+
+void
+fn2()
+{
+ C b;
+ fn1(b);
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr54902.C b/gcc/testsuite/g++.dg/torture/pr54902.C
new file mode 100644
index 00000000000..790ffe5fcb5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr54902.C
@@ -0,0 +1,131 @@
+// { dg-do compile }
+
+namespace std __attribute__ ((__visibility__ ("default"))) {
+ template<typename _Iterator> struct iterator_traits {
+ };
+ template<typename _Tp> struct iterator_traits<_Tp*> {
+ typedef _Tp& reference;
+ };
+}
+namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) {
+ using std::iterator_traits;
+ template<typename _Iterator, typename _Container> class __normal_iterator {
+ _Iterator _M_current;
+ typedef iterator_traits<_Iterator> __traits_type;
+ public:
+ typedef typename __traits_type::reference reference;
+ explicit __normal_iterator(const _Iterator& __i) : _M_current(__i) {
+ }
+ reference operator*() const {
+ return *_M_current;
+ }
+ __normal_iterator operator++(int) {
+ return __normal_iterator(_M_current++);
+ }
+ };
+ template<typename _Tp> class new_allocator {
+ public:
+ typedef _Tp* pointer;
+ template<typename _Tp1> struct rebind {
+ typedef new_allocator<_Tp1> other;
+ };
+ };
+}
+namespace std __attribute__ ((__visibility__ ("default"))) {
+ template<typename _Tp> class allocator: public __gnu_cxx::new_allocator<_Tp> {
+ };
+}
+namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) {
+ template<typename _Alloc> struct __alloc_traits {
+ typedef typename _Alloc::pointer pointer;
+ template<typename _Tp> struct rebind {
+ typedef typename _Alloc::template rebind<_Tp>::other other;
+ };
+ };
+}
+namespace std __attribute__ ((__visibility__ ("default"))) {
+ template<typename _Tp, typename _Alloc> struct _Vector_base {
+ typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_Tp>::other _Tp_alloc_type;
+ typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer pointer;
+ struct _Vector_impl : public _Tp_alloc_type {
+ pointer _M_start;
+ };
+ _Vector_impl _M_impl;
+ };
+ template<typename _Tp, typename _Alloc = std::allocator<_Tp> > class vector : protected _Vector_base<_Tp, _Alloc> {
+ typedef _Vector_base<_Tp, _Alloc> _Base;
+ public:
+ typedef typename _Base::pointer pointer;
+ typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;
+ iterator begin() {
+ return iterator(this->_M_impl._M_start);
+ }
+ };
+}
+class myServer {
+ static std::vector<myServer *> server_list;
+ class Callback;
+ class myFolder *currentFolder;
+ static bool eventloop(Callback *);
+};
+extern "C" {
+ typedef unsigned int uint32_t;
+ typedef uint32_t unicode_char;
+ extern int strcmp (__const char *__s1, __const char *__s2) throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
+};
+class CursesObj {
+};
+class Curses : public CursesObj {
+public:
+ class Key {
+ public:
+ unicode_char ukey;
+ const char *keycode;
+ Key(unicode_char ch) : ukey(ch), keycode(0) {
+ }
+ bool plain() const {
+ }
+ bool nokey() const {
+ }
+ bool operator==(const Key &k) const {
+ return strcmp(keycode ? keycode:
+ "", k.keycode ? k.keycode:
+ "") == 0 && ukey == k.ukey;
+ }
+ };
+ static bool processKey(const Key &k);
+};
+class CursesContainer : public Curses {
+};
+class myFolder {
+public:
+ void checkExpunged();
+};
+class Typeahead {
+public:
+ static Typeahead *typeahead;
+ bool empty() {
+ }
+ Curses::Key pop() {
+ }
+};
+class CursesScreen : public CursesContainer {
+public:
+ Key getKey();
+};
+using namespace std;
+extern CursesScreen *cursesScreen;
+bool myServer::eventloop(myServer::Callback *callback) {
+ Curses::Key k1= (callback == __null && !Typeahead::typeahead->empty() ? Typeahead::typeahead->pop() : cursesScreen->getKey());
+ if (callback == __null || (k1.plain() && k1.ukey == '\x03')) {
+ if (!k1.nokey()) {
+ bool rc=Curses::processKey(k1);
+ if (rc) { while (k1.plain() && k1 == '\x03' && !Typeahead::typeahead->empty()) Typeahead::typeahead->pop(); }
+ }
+ }
+ vector<myServer *>::iterator b=server_list.begin();
+ while (1) {
+ myServer *p= *b++;
+ if (p->currentFolder) p->currentFolder->checkExpunged();
+ }
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr54985.c b/gcc/testsuite/gcc.c-torture/execute/pr54985.c
new file mode 100644
index 00000000000..678c9f47ae7
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr54985.c
@@ -0,0 +1,36 @@
+
+typedef struct st {
+ int a;
+} ST;
+
+int __attribute__((noinline,noclone))
+foo(ST *s, int c)
+{
+ int first = 1;
+ int count = c;
+ ST *item = s;
+ int a = s->a;
+ int x;
+
+ while (count--)
+ {
+ x = item->a;
+ if (first)
+ first = 0;
+ else if (x >= a)
+ return 1;
+ a = x;
+ item++;
+ }
+ return 0;
+}
+
+extern void abort (void);
+
+int main ()
+{
+ ST _1[2] = {{2}, {1}};
+ if (foo(_1, 2) != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr53701.c b/gcc/testsuite/gcc.dg/pr53701.c
new file mode 100644
index 00000000000..2c852238110
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr53701.c
@@ -0,0 +1,59 @@
+/* { dg-do compile { target powerpc*-*-* ia64-*-* i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O3 -fselective-scheduling2 -fsel-sched-pipelining" } */
+typedef unsigned short int uint16_t;
+typedef unsigned long int uintptr_t;
+typedef struct GFX_VTABLE
+{
+ int color_depth;
+ unsigned char *line[];
+}
+BITMAP;
+extern int _drawing_mode;
+extern BITMAP *_drawing_pattern;
+extern int _drawing_y_anchor;
+extern unsigned int _drawing_x_mask;
+extern unsigned int _drawing_y_mask;
+extern uintptr_t bmp_write_line (BITMAP *, int);
+ void
+_linear_hline15 (BITMAP * dst, int dx1, int dy, int dx2, int color)
+{
+ int w;
+ if (_drawing_mode == 0)
+ {
+ int x, curw;
+ unsigned short *sline =
+ (unsigned short *) (_drawing_pattern->
+ line[((dy) -
+ _drawing_y_anchor) & _drawing_y_mask]);
+ unsigned short *s;
+ unsigned short *d =
+ ((unsigned short *) (bmp_write_line (dst, dy)) + (dx1));
+ s = ((unsigned short *) (sline) + (x));
+ if (_drawing_mode == 2)
+ {
+ }
+ else if (_drawing_mode == 3)
+ {
+ do
+ {
+ w -= curw;
+ do
+ {
+ unsigned long c = (*(s));
+ if (!((unsigned long) (c) == 0x7C1F))
+ {
+ (*((uint16_t *) ((uintptr_t) (d))) = ((color)));
+ }
+ ((s)++);
+ }
+ while (--curw > 0);
+ s = sline;
+ curw =
+ (((w) <
+ ((int) _drawing_x_mask +
+ 1)) ? (w) : ((int) _drawing_x_mask + 1));
+ }
+ while (curw > 0);
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr55019.c b/gcc/testsuite/gcc.dg/pr55019.c
new file mode 100644
index 00000000000..1548fb258c0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr55019.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-O1 -funroll-loops" } */
+/* { dg-add-options ieee } */
+
+extern void exit (int);
+extern void abort (void);
+
+void
+compare (double a, double b)
+{
+ do
+ {
+ double s1 = __builtin_copysign ((double) 1.0, a);
+ double s2 = __builtin_copysign ((double) 1.0, b);
+
+ if (s1 != s2)
+ abort ();
+
+ if ((__builtin_isnan (a) != 0) != (__builtin_isnan (b) != 0))
+ abort ();
+
+ if ((a != b) != (__builtin_isnan (a) != 0))
+ abort ();
+ } while (0);
+}
+
+int
+main ()
+{
+ double a = 0.0;
+ double b = 0.0;
+ _Complex double cr = __builtin_complex (a, b);
+ static _Complex double cs = __builtin_complex (0.0, 0.0);
+
+ compare (__real__ cr, 0.0);
+ compare (__imag__ cr, 0.0);
+ compare (__real__ cs, 0.0);
+ compare (__imag__ cs, 0.0);
+
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr54877.c b/gcc/testsuite/gcc.dg/torture/pr54877.c
new file mode 100644
index 00000000000..cee406e50d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr54877.c
@@ -0,0 +1,23 @@
+/* PR tree-optimization/54877 */
+/* { dg-do run } */
+/* { dg-options "-ffast-math" } */
+
+extern void abort (void);
+
+int
+foo (void)
+{
+ double d;
+ int i;
+ for (i = 0, d = 0; i < 64; i++)
+ d--;
+ return (int) d;
+}
+
+int
+main ()
+{
+ if (foo () != -64)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr54920.c b/gcc/testsuite/gcc.dg/torture/pr54920.c
new file mode 100644
index 00000000000..d1622f765a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr54920.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+typedef short __v8hi __attribute__ ((__vector_size__ (16)));
+typedef long long __m128i __attribute__ ((__vector_size__ (16)));
+int a;
+__m128i b;
+
+void
+fn1 ()
+{
+ while (1)
+ b = (__m128i) (__v8hi) { a, 0, 0, 0, 0, 0 };
+}
diff --git a/gcc/testsuite/gcc.target/arm/arm.exp b/gcc/testsuite/gcc.target/arm/arm.exp
index 0838d37b3f0..dc6c16ad522 100644
--- a/gcc/testsuite/gcc.target/arm/arm.exp
+++ b/gcc/testsuite/gcc.target/arm/arm.exp
@@ -30,6 +30,11 @@ if ![info exists DEFAULT_CFLAGS] then {
set DEFAULT_CFLAGS " -ansi -pedantic-errors"
}
+# This variable should only apply to tests called in this exp file.
+global dg_runtest_extra_prunes
+set dg_runtest_extra_prunes ""
+lappend dg_runtest_extra_prunes "warning: switch -m(cpu|arch)=.* conflicts with -m(cpu|arch)=.* switch"
+
# Initialize `dg'.
dg-init
@@ -39,3 +44,5 @@ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
# All done.
dg-finish
+
+set dg_runtest_extra_prunes ""
diff --git a/gcc/testsuite/gcc.target/arm/pr54892.c b/gcc/testsuite/gcc.target/arm/pr54892.c
new file mode 100644
index 00000000000..a7fe1bc6676
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr54892.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+
+int set_role(unsigned char role_id, short m_role)
+{
+ return __sync_bool_compare_and_swap(&m_role, -1, role_id);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c
index c2511c643b4..e7eef6d7a90 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c
@@ -14,6 +14,6 @@ avx_test (void)
c[i] = a[i] * b[i+3];
}
-/* { dg-final { scan-assembler-not "avx_movups256/1" } } */
-/* { dg-final { scan-assembler "sse_movups/1" } } */
+/* { dg-final { scan-assembler-not "avx_loadups256" } } */
+/* { dg-final { scan-assembler "sse_loadups" } } */
/* { dg-final { scan-assembler "vinsertf128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c
index 9d7167304e3..3f4fbf76479 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c
@@ -24,6 +24,6 @@ avx_test (void)
}
}
-/* { dg-final { scan-assembler-not "avx_movdqu256/1" } } */
-/* { dg-final { scan-assembler "sse2_movdqu/1" } } */
+/* { dg-final { scan-assembler-not "avx_loaddqu256" } } */
+/* { dg-final { scan-assembler "sse2_loaddqu" } } */
/* { dg-final { scan-assembler "vinsert.128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c
index efb5f573fae..b0e0e79bdd8 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c
@@ -14,6 +14,6 @@ avx_test (void)
c[i] = a[i] * b[i+3];
}
-/* { dg-final { scan-assembler-not "avx_movupd256/1" } } */
-/* { dg-final { scan-assembler "sse2_movupd/1" } } */
+/* { dg-final { scan-assembler-not "avx_loadupd256" } } */
+/* { dg-final { scan-assembler "sse2_loadupd" } } */
/* { dg-final { scan-assembler "vinsertf128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c
index 7c015a8b90a..b3927be70ab 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c
@@ -14,6 +14,6 @@ avx_test (void)
b[i] = a[i+3] * 2;
}
-/* { dg-final { scan-assembler "avx_movups256/1" } } */
-/* { dg-final { scan-assembler-not "avx_movups/1" } } */
+/* { dg-final { scan-assembler "avx_loadups256" } } */
+/* { dg-final { scan-assembler-not "sse_loadups" } } */
/* { dg-final { scan-assembler-not "vinsertf128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c
index 0b5839669a7..1a53ba14a00 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-1.c
@@ -17,6 +17,6 @@ avx_test (void)
d[i] = c[i] * 20.0;
}
-/* { dg-final { scan-assembler-not "avx_movups256/2" } } */
+/* { dg-final { scan-assembler-not "avx_storeups256" } } */
/* { dg-final { scan-assembler "vmovups.*\\*movv4sf_internal/3" } } */
/* { dg-final { scan-assembler "vextractf128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c
index eac460fef97..e98d1b684de 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-2.c
@@ -24,6 +24,6 @@ avx_test (void)
}
}
-/* { dg-final { scan-assembler-not "avx_movdqu256/2" } } */
+/* { dg-final { scan-assembler-not "avx_storedqu256" } } */
/* { dg-final { scan-assembler "vmovdqu.*\\*movv16qi_internal/3" } } */
/* { dg-final { scan-assembler "vextract.128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
index 753625892d7..26c993be7e9 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-3.c
@@ -17,6 +17,6 @@ avx_test (void)
d[i] = c[i] * 20.0;
}
-/* { dg-final { scan-assembler-not "avx_movupd256/2" } } */
+/* { dg-final { scan-assembler-not "avx_storeupd256" } } */
/* { dg-final { scan-assembler "vmovupd.*\\*movv2df_internal/3" } } */
/* { dg-final { scan-assembler "vextractf128" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-4.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-4.c
index 39b6f3bef16..6d734faa25e 100644
--- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-4.c
+++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-store-4.c
@@ -14,7 +14,7 @@ avx_test (void)
b[i+3] = a[i] * c[i];
}
-/* { dg-final { scan-assembler "avx_movups256/2" } } */
-/* { dg-final { scan-assembler-not "avx_movups/2" } } */
+/* { dg-final { scan-assembler "avx_storeups256" } } */
+/* { dg-final { scan-assembler-not "sse_storeups" } } */
/* { dg-final { scan-assembler-not "\\*avx_movv4sf_internal/3" } } */
/* { dg-final { scan-assembler-not "vextractf128" } } */
diff --git a/gcc/testsuite/gfortran.dg/class_allocate_13.f90 b/gcc/testsuite/gfortran.dg/class_allocate_13.f90
new file mode 100644
index 00000000000..64f37dc59b5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_allocate_13.f90
@@ -0,0 +1,31 @@
+! { dg-do run }
+!
+! PR 54784: [4.7/4.8 Regression] [OOP] wrong code in polymorphic allocation with SOURCE
+!
+! Contributed by Jeremy Kozdon <jkozdon@gmail.com>
+
+program bug
+ implicit none
+
+ type :: block
+ real, allocatable :: fields
+ end type
+
+ type :: list
+ class(block),allocatable :: B
+ end type
+
+ type :: domain
+ type(list),dimension(2) :: L
+ end type
+
+ type(domain) :: d
+ type(block) :: b1
+
+ allocate(b1%fields,source=5.)
+
+ allocate(d%L(2)%B,source=b1) ! wrong code
+
+ if (d%L(2)%B%fields/=5.) call abort()
+
+end program
diff --git a/gcc/testsuite/gnat.dg/lto14.adb b/gcc/testsuite/gnat.dg/lto14.adb
index d81db7af325..22038a6ff93 100644
--- a/gcc/testsuite/gnat.dg/lto14.adb
+++ b/gcc/testsuite/gnat.dg/lto14.adb
@@ -1,5 +1,6 @@
-- { dg-do link }
-- { dg-options "-largs -f -margs -flto" { target lto } }
+-- { dg-skip-if "missing linker support" { *-*-solaris2.* } }
procedure Lto14 is
begin
diff --git a/gcc/testsuite/gnat.dg/modular4.adb b/gcc/testsuite/gnat.dg/modular4.adb
new file mode 100644
index 00000000000..e8e8f2956e1
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/modular4.adb
@@ -0,0 +1,11 @@
+-- { dg-do compile }
+-- { dg-options "-O" }
+
+with Modular4_Pkg; use Modular4_Pkg;
+
+procedure Modular4 is
+begin
+ for I in Zero .. F mod 8 loop
+ raise Program_Error;
+ end loop;
+end;
diff --git a/gcc/testsuite/gnat.dg/modular4_pkg.ads b/gcc/testsuite/gnat.dg/modular4_pkg.ads
new file mode 100644
index 00000000000..b38026201ed
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/modular4_pkg.ads
@@ -0,0 +1,9 @@
+package Modular4_Pkg is
+
+ type Word is mod 2**48;
+
+ Zero : constant Word := 0;
+
+ function F return Word;
+
+end Modular4_Pkg;
diff --git a/gcc/testsuite/gnat.dg/specs/addr1.ads b/gcc/testsuite/gnat.dg/specs/addr1.ads
index ed048f68ef3..bcb833bec69 100644
--- a/gcc/testsuite/gnat.dg/specs/addr1.ads
+++ b/gcc/testsuite/gnat.dg/specs/addr1.ads
@@ -18,18 +18,18 @@ package Addr1 is
A: Arr (1 .. 4);
Obj1: Rec1;
- for Obj1'Address use A'Address; -- { dg-bogus "alignment" }
+ for Obj1'Address use A'Address; -- { dg-bogus "(alignment|erroneous)" }
Obj2: Rec2;
- for Obj2'Address use A'Address; -- { dg-bogus "alignment" }
+ for Obj2'Address use A'Address; -- { dg-bogus "(alignment|erroneous)" "" { xfail mips*-*-* } }
Obj3: Rec1;
- for Obj3'Address use A(1)'Address; -- { dg-bogus "alignment" }
+ for Obj3'Address use A(1)'Address; -- { dg-bogus "(alignment|erroneous)" }
Obj4: Rec1;
for Obj4'Address use A(2)'Address; -- { dg-warning "(alignment|erroneous)" }
Obj5: Rec1;
- for Obj5'Address use A(3)'Address; -- { dg-bogus "alignment" }
+ for Obj5'Address use A(3)'Address; -- { dg-bogus "(alignment|erroneous)" }
end Addr1;
diff --git a/gcc/testsuite/gnat.dg/specs/atomic1.ads b/gcc/testsuite/gnat.dg/specs/atomic1.ads
index 500cad787f3..02e98b64314 100644
--- a/gcc/testsuite/gnat.dg/specs/atomic1.ads
+++ b/gcc/testsuite/gnat.dg/specs/atomic1.ads
@@ -6,11 +6,11 @@ package Atomic1 is
type UA is access all Arr;
U : UA;
- pragma Atomic (U); -- { dg-error "atomic access" }
+ pragma Atomic (U); -- { dg-error "atomic access" "" { xfail mips*-*-* } }
type R is record
U : UA;
- pragma Atomic (U); -- { dg-error "atomic access" }
+ pragma Atomic (U); -- { dg-error "atomic access" "" { xfail mips*-*-* } }
end record;
end Atomic1;
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index b6a73fe0d50..8d8c538706a 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -211,9 +211,13 @@ proc gcc-dg-test { prog do_what extra_tool_flags } {
proc gcc-dg-prune { system text } {
global additional_prunes
+ # Extra prune rules that will apply to tests defined in a .exp file.
+ # Always remember to clear it in .exp file after executed all tests.
+ global dg_runtest_extra_prunes
+
set text [prune_gcc_output $text]
- foreach p $additional_prunes {
+ foreach p "$additional_prunes $dg_runtest_extra_prunes" {
if { [string length $p] > 0 } {
# Following regexp matches a complete line containing $p.
regsub -all "(^|\n)\[^\n\]*$p\[^\n\]*" $text "" text
@@ -672,6 +676,7 @@ if { [info procs saved-dg-test] == [list] } {
set additional_files ""
set additional_sources ""
set additional_prunes ""
+ set dg_runtest_extra_prunes ""
set shouldfail 0
if [info exists compiler_conditional_xfail_data] {
unset compiler_conditional_xfail_data
@@ -809,3 +814,4 @@ proc gdb-exists { args } {
}
set additional_prunes ""
+set dg_runtest_extra_prunes ""
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 349e0b0186f..5854bd934ab 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3836,6 +3836,12 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
goto egress;
if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))
+ /* For extern inline functions that get redefined we always
+ silently ignored always_inline flag. Better behaviour would
+ be to be able to keep both bodies and use extern inline body
+ for inlining, but we can't do that because frontends overwrite
+ the body. */
+ && !cg_edge->callee->local.redefined_extern_inline
/* Avoid warnings during early inline pass. */
&& cgraph_global_info_ready
/* PR 20090218-1_0.c. Body can be provided by another module. */
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 8e7f2550ef3..8d58e9c88fc 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -3063,7 +3063,7 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
case NARY:
{
vn_nary_op_t nary = PRE_EXPR_NARY (expr);
- tree genop[4];
+ tree *genop = XALLOCAVEC (tree, nary->length);
unsigned i;
for (i = 0; i < nary->length; ++i)
{
@@ -4851,11 +4851,12 @@ init_pre (bool do_fre)
/* Deallocate data structures used by PRE. */
-static void
+static unsigned
fini_pre (bool do_fre)
{
bool do_eh_cleanup = !bitmap_empty_p (need_eh_cleanup);
bool do_ab_cleanup = !bitmap_empty_p (need_ab_cleanup);
+ unsigned todo = 0;
free (postorder);
VEC_free (bitmap_set_t, heap, value_expressions);
@@ -4882,10 +4883,12 @@ fini_pre (bool do_fre)
BITMAP_FREE (need_ab_cleanup);
if (do_eh_cleanup || do_ab_cleanup)
- cleanup_tree_cfg ();
+ todo = TODO_cleanup_cfg;
if (!do_fre)
loop_optimizer_finalize ();
+
+ return todo;
}
/* Main entry point to the SSA-PRE pass. DO_FRE is true if the caller
@@ -4965,7 +4968,7 @@ execute_pre (bool do_fre)
}
scev_finalize ();
- fini_pre (do_fre);
+ todo |= fini_pre (do_fre);
if (!do_fre)
/* TODO: tail_merge_optimize may merge all predecessors of a block, in which
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 25ec43ebd7d..4be35f69522 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -1559,7 +1559,12 @@ tail_merge_optimize (unsigned int todo)
timevar_push (TV_TREE_TAIL_MERGE);
- calculate_dominance_info (CDI_DOMINATORS);
+ if (!dom_info_available_p (CDI_DOMINATORS))
+ {
+ /* PRE can leave us with unreachable blocks, remove them now. */
+ delete_unreachable_blocks ();
+ calculate_dominance_info (CDI_DOMINATORS);
+ }
init_worklist ();
while (!VEC_empty (same_succ, worklist))
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 707c8df3ec5..a2860f6f978 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -574,6 +574,44 @@ simplify_control_stmt_condition (edge e,
return cached_lhs;
}
+/* Return TRUE if the statement at the end of e->dest depends on
+ the output of any statement in BB. Otherwise return FALSE.
+
+ This is used when we are threading a backedge and need to ensure
+ that temporary equivalences from BB do not affect the condition
+ in e->dest. */
+
+static bool
+cond_arg_set_in_bb (edge e, basic_block bb)
+{
+ ssa_op_iter iter;
+ use_operand_p use_p;
+ gimple last = last_stmt (e->dest);
+
+ /* E->dest does not have to end with a control transferring
+ instruction. This can occurr when we try to extend a jump
+ threading opportunity deeper into the CFG. In that case
+ it is safe for this check to return false. */
+ if (!last)
+ return false;
+
+ if (gimple_code (last) != GIMPLE_COND
+ && gimple_code (last) != GIMPLE_GOTO
+ && gimple_code (last) != GIMPLE_SWITCH)
+ return false;
+
+ FOR_EACH_SSA_USE_OPERAND (use_p, last, iter, SSA_OP_USE | SSA_OP_VUSE)
+ {
+ tree use = USE_FROM_PTR (use_p);
+
+ if (TREE_CODE (use) == SSA_NAME
+ && gimple_code (SSA_NAME_DEF_STMT (use)) != GIMPLE_PHI
+ && gimple_bb (SSA_NAME_DEF_STMT (use)) == bb)
+ return true;
+ }
+ return false;
+}
+
/* TAKEN_EDGE represents the an edge taken as a result of jump threading.
See if we can thread around TAKEN_EDGE->dest as well. If so, return
the edge out of TAKEN_EDGE->dest that we can statically compute will be
@@ -707,19 +745,8 @@ thread_across_edge (gimple dummy_cond,
safe to thread this edge. */
if (e->flags & EDGE_DFS_BACK)
{
- ssa_op_iter iter;
- use_operand_p use_p;
- gimple last = gsi_stmt (gsi_last_bb (e->dest));
-
- FOR_EACH_SSA_USE_OPERAND (use_p, last, iter, SSA_OP_USE | SSA_OP_VUSE)
- {
- tree use = USE_FROM_PTR (use_p);
-
- if (TREE_CODE (use) == SSA_NAME
- && gimple_code (SSA_NAME_DEF_STMT (use)) != GIMPLE_PHI
- && gimple_bb (SSA_NAME_DEF_STMT (use)) == e->dest)
- goto fail;
- }
+ if (cond_arg_set_in_bb (e, e->dest))
+ goto fail;
}
stmt_count = 0;
@@ -760,7 +787,9 @@ thread_across_edge (gimple dummy_cond,
address. If DEST is not null, then see if we can thread
through it as well, this helps capture secondary effects
of threading without having to re-run DOM or VRP. */
- if (dest)
+ if (dest
+ && ((e->flags & EDGE_DFS_BACK) == 0
+ || ! cond_arg_set_in_bb (taken_edge, e->dest)))
{
/* We don't want to thread back to a block we have already
visited. This may be overly conservative. */
@@ -818,11 +847,16 @@ thread_across_edge (gimple dummy_cond,
e3 = taken_edge;
do
{
- e2 = thread_around_empty_block (e3,
- dummy_cond,
- handle_dominating_asserts,
- simplify,
- visited);
+ if ((e->flags & EDGE_DFS_BACK) == 0
+ || ! cond_arg_set_in_bb (e3, e->dest))
+ e2 = thread_around_empty_block (e3,
+ dummy_cond,
+ handle_dominating_asserts,
+ simplify,
+ visited);
+ else
+ e2 = NULL;
+
if (e2)
{
e3 = e2;
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 3fd906aec5e..6ef834cb788 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -4590,6 +4590,13 @@ vect_can_force_dr_alignment_p (const_tree decl, unsigned int alignment)
if (TREE_ASM_WRITTEN (decl))
return false;
+ /* Do not override explicit alignment set by the user when an explicit
+ section name is also used. This is a common idiom used by many
+ software projects. */
+ if (DECL_SECTION_NAME (decl) != NULL_TREE
+ && !DECL_HAS_IMPLICIT_SECTION_NAME_P (decl))
+ return false;
+
if (TREE_STATIC (decl))
return (alignment <= MAX_OFILE_ALIGNMENT);
else
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 56348a10d9e..4e50fb854b2 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -2257,7 +2257,10 @@ vect_is_simple_reduction_1 (loop_vec_info loop_info, gimple phi,
if (orig_code == MINUS_EXPR)
{
tree rhs = gimple_assign_rhs2 (def_stmt);
- tree negrhs = make_ssa_name (SSA_NAME_VAR (rhs), NULL);
+ tree var = TREE_CODE (rhs) == SSA_NAME
+ ? SSA_NAME_VAR (rhs)
+ : create_tmp_reg (TREE_TYPE (rhs), NULL);
+ tree negrhs = make_ssa_name (var, NULL);
gimple negate_stmt = gimple_build_assign_with_ops (NEGATE_EXPR, negrhs,
rhs, NULL);
gimple_stmt_iterator gsi = gsi_for_stmt (def_stmt);
diff --git a/gcc/tree.c b/gcc/tree.c
index 72a284c4c0c..155bbf2628a 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -8445,14 +8445,19 @@ variably_modified_type_p (tree type, tree fn)
tree t;
/* Test if T is either variable (if FN is zero) or an expression containing
- a variable in FN. */
+ a variable in FN. If TYPE isn't gimplified, return true also if
+ gimplify_one_sizepos would gimplify the expression into a local
+ variable. */
#define RETURN_TRUE_IF_VAR(T) \
do { tree _t = (T); \
if (_t != NULL_TREE \
&& _t != error_mark_node \
&& TREE_CODE (_t) != INTEGER_CST \
&& TREE_CODE (_t) != PLACEHOLDER_EXPR \
- && (!fn || walk_tree (&_t, find_var_from_fn, fn, NULL))) \
+ && (!fn \
+ || (!TYPE_SIZES_GIMPLIFIED (type) \
+ && !is_gimple_sizepos (_t)) \
+ || walk_tree (&_t, find_var_from_fn, fn, NULL))) \
return true; } while (0)
if (type == error_mark_node)
diff --git a/gcc/tree.h b/gcc/tree.h
index 7162dab0847..dbffe96e082 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -490,9 +490,10 @@ struct GTY(()) tree_common {
TREE_ADDRESSABLE in
VAR_DECL, PARM_DECL, RESULT_DECL, FUNCTION_DECL, LABEL_DECL
+ SSA_NAME
all types
CONSTRUCTOR, IDENTIFIER_NODE
- STMT_EXPR, it means we want the result of the enclosed expression
+ STMT_EXPR
CALL_EXPR_TAILCALL in
CALL_EXPR
@@ -1181,15 +1182,18 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
/* In VAR_DECL, PARM_DECL and RESULT_DECL nodes, nonzero means address
of this is needed. So it cannot be in a register.
In a FUNCTION_DECL it has no meaning.
- In CONSTRUCTOR nodes, it means object constructed must be in memory.
In LABEL_DECL nodes, it means a goto for this label has been seen
from a place outside all binding contours that restore stack levels.
+ In an artificial SSA_NAME that points to a stack partition with at least
+ two variables, it means that at least one variable has TREE_ADDRESSABLE.
In ..._TYPE nodes, it means that objects of this type must be fully
addressable. This means that pieces of this object cannot go into
register parameters, for example. If this a function type, this
means that the value must be returned in memory.
+ In CONSTRUCTOR nodes, it means object constructed must be in memory.
In IDENTIFIER_NODEs, this means that some extern decl for this name
- had its address taken. That matters for inline functions. */
+ had its address taken. That matters for inline functions.
+ In a STMT_EXPR, it means we want the result of the enclosed expression. */
#define TREE_ADDRESSABLE(NODE) ((NODE)->base.addressable_flag)
/* Set on a CALL_EXPR if the call is in a tail position, ie. just before the
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index c6280e2c1f1..d05c814091f 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -555,7 +555,7 @@ static void dump_vars (htab_t);
static void dump_dataflow_set (dataflow_set *);
static void dump_dataflow_sets (void);
-static void set_dv_changed (decl_or_value, bool);
+static inline void set_dv_changed (decl_or_value, bool);
static void variable_was_changed (variable, dataflow_set *);
static void **set_slot_part (dataflow_set *, rtx, void **,
decl_or_value, HOST_WIDE_INT,
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 1e8640a5007..c91be9a1c29 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,35 @@
+2012-11-04 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/55175
+ * config/i386/32/sfp-machine.h: Guard exception handling and
+ rounding handling code with _SOFT_FLOAT.
+ * config/i386/64/sfp-machine.h: Ditto.
+
+2012-10-31 Joel Sherrill <joel.sherrill@oarcorp.com>
+
+ * config.host (m32r-*-rtems*): Include crtinit.o and crtfinit.o
+ as extra_parts.
+
+2012-10-25 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * config.host (sparc64-*-rtems*): Remove sparc/t-elf.
+
+2012-10-25 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * config.host (sh*-*-rtems*): Add sh*-*-elf*'s extra_parts.
+
+2012-10-25 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * config.host (powerpc-*-rtems*): Add rs6000/t-savresfgpr to
+ tmake_file.
+
+2012-10-06 Mark Kettenis <kettenis@openbsd.org>
+
+ * config.host (*-*-openbsd*): Add t-eh-dw2-dip to tmake_file.
+ * unwind-dw2-fde-dip.c: Don't include <elf.h> on OpenBSD.
+ (USE_PT_GNU_EH_FRAME): Define for OpenBSD.
+ (ElfW): Likewise.
+
2012-09-20 Release Manager
* GCC 4.7.2 released.
@@ -5,7 +37,7 @@
2012-09-05 Georg-Johann Lay <avr@gjlay.de>
Backport from 2012-09-05 mainline r190697.
-
+
PR target/54461
* config.host (tmake_file,host=avr-*-*): Add avr/t-avrlibc if
configured --with-avrlibc.
diff --git a/libgcc/config.host b/libgcc/config.host
index 7f51f1e6ef7..7fa6d2bb9cd 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -216,7 +216,7 @@ case ${host} in
esac
;;
*-*-openbsd*)
- tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic"
+ tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic t-eh-dw2-dip"
case ${target_thread_file} in
posix)
tmake_file="$tmake_file t-openbsd-thread"
@@ -706,6 +706,7 @@ m32r-*-elf*)
;;
m32r-*-rtems*)
tmake_file="$tmake_file m32r/t-m32r t-fdpbit"
+ extra_parts="$extra_parts crtinit.o crtfini.o"
;;
m32rle-*-elf*)
tmake_file=t-fdpbit
@@ -904,7 +905,7 @@ powerpc-*-eabi*)
extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpc-*-rtems*)
- tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-savresfgpr rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
extra_parts="$extra_parts crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpc-*-linux* | powerpc64-*-linux*)
@@ -1008,7 +1009,10 @@ sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
sh-*-rtems*)
tmake_file="$tmake_file sh/t-sh t-crtstuff-pic t-fdpbit"
extra_parts="$extra_parts crt1.o crti.o crtn.o crtbeginS.o crtendS.o \
- $sh_ic_extra_parts $sh_opt_extra_parts"
+ libic_invalidate_array_4-100.a \
+ libic_invalidate_array_4-200.a \
+ libic_invalidate_array_4a.a \
+ libgcc-Os-4-200.a libgcc-4-300.a"
;;
sh-wrs-vxworks)
tmake_file="$tmake_file sh/t-sh t-crtstuff-pic t-fdpbit"
@@ -1067,7 +1071,7 @@ sparc64-*-elf*)
extra_parts="$extra_parts crti.o crtn.o crtfastmath.o"
;;
sparc64-*-rtems*)
- tmake_file="$tmake_file sparc/t-elf t-crtfm"
+ tmake_file="$tmake_file t-crtfm"
extra_parts="$extra_parts crti.o crtn.o crtfastmath.o"
;;
sparc-wrs-vxworks)
diff --git a/libgcc/config/i386/32/sfp-machine.h b/libgcc/config/i386/32/sfp-machine.h
index 1600a7fe2c7..131b2c453f2 100644
--- a/libgcc/config/i386/32/sfp-machine.h
+++ b/libgcc/config/i386/32/sfp-machine.h
@@ -107,6 +107,7 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
R##_c = FP_CLS_NAN; \
} while (0)
+#ifndef _SOFT_FLOAT
#define FP_EX_INVALID 0x01
#define FP_EX_DENORM 0x02
#define FP_EX_DIVZERO 0x04
@@ -187,6 +188,7 @@ struct fenv
} while (0)
#define FP_ROUNDMODE (_fcw & 0xc00)
+#endif
#define __LITTLE_ENDIAN 1234
#define __BIG_ENDIAN 4321
diff --git a/libgcc/config/i386/64/sfp-machine.h b/libgcc/config/i386/64/sfp-machine.h
index 7a2a4beaaaf..f90305a7642 100644
--- a/libgcc/config/i386/64/sfp-machine.h
+++ b/libgcc/config/i386/64/sfp-machine.h
@@ -49,6 +49,7 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
R##_c = FP_CLS_NAN; \
} while (0)
+#ifndef _SOFT_FLOAT
#define FP_EX_INVALID 0x01
#define FP_EX_DENORM 0x02
#define FP_EX_DIVZERO 0x04
@@ -133,6 +134,7 @@ struct fenv
} while (0)
#define FP_ROUNDMODE (_fcw & 0xc00)
+#endif
#define __LITTLE_ENDIAN 1234
#define __BIG_ENDIAN 4321
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
index f57dc8c3925..a04849544bb 100644
--- a/libgcc/unwind-dw2-fde-dip.c
+++ b/libgcc/unwind-dw2-fde-dip.c
@@ -33,7 +33,7 @@
#include "tconfig.h"
#include "tsystem.h"
-#ifndef inhibit_libc
+#if !defined(inhibit_libc) && !defined(__OpenBSD__)
#include <elf.h> /* Get DT_CONFIG. */
#endif
#include "coretypes.h"
@@ -60,6 +60,12 @@
#endif
#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
+ && defined(__OpenBSD__)
+# define ElfW(type) Elf_##type
+# define USE_PT_GNU_EH_FRAME
+#endif
+
+#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
&& defined(TARGET_DL_ITERATE_PHDR) \
&& defined(__sun__) && defined(__svr4__)
# define USE_PT_GNU_EH_FRAME
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index cfddafe90f7..a9c38c8102b 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,11 @@
+2012-10-12 Thomas König <tkoenig@gcc.gnu.org>
+
+ PR libfortran/54736
+ Backport from trunk
+ * runtime/environ.c (search_unit): Correct logic
+ for binary search.
+ (mark_single): Fix index errors.
+
2012-09-20 Release Manager
* GCC 4.7.2 released.
diff --git a/libgfortran/runtime/environ.c b/libgfortran/runtime/environ.c
index 6bd88865d89..a7bda45ce80 100644
--- a/libgfortran/runtime/environ.c
+++ b/libgfortran/runtime/environ.c
@@ -446,21 +446,35 @@ search_unit (int unit, int *ip)
{
int low, high, mid;
- low = -1;
- high = n_elist;
- while (high - low > 1)
+ if (n_elist == 0)
+ {
+ *ip = 0;
+ return 0;
+ }
+
+ low = 0;
+ high = n_elist - 1;
+
+ do
{
mid = (low + high) / 2;
- if (unit <= elist[mid].unit)
- high = mid;
+ if (unit == elist[mid].unit)
+ {
+ *ip = mid;
+ return 1;
+ }
+ else if (unit > elist[mid].unit)
+ low = mid + 1;
else
- low = mid;
- }
- *ip = high;
- if (elist[high].unit == unit)
- return 1;
+ high = mid - 1;
+ } while (low <= high);
+
+ if (unit > elist[mid].unit)
+ *ip = mid + 1;
else
- return 0;
+ *ip = mid;
+
+ return 0;
}
/* This matches a keyword. If it is found, return the token supplied,
@@ -575,13 +589,13 @@ mark_single (int unit)
}
if (search_unit (unit, &i))
{
- elist[unit].conv = endian;
+ elist[i].conv = endian;
}
else
{
- for (j=n_elist; j>=i; j--)
+ for (j=n_elist-1; j>=i; j--)
elist[j+1] = elist[j];
-
+
n_elist += 1;
elist[i].unit = unit;
elist[i].conv = endian;
diff --git a/libgo/MERGE b/libgo/MERGE
index e3e47d3bd1e..89116d1feef 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-5e806355a9e1
+2d8bc3c94ecb
The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources.
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index f59b0048495..82587cad689 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -715,6 +715,7 @@ go_net_files = \
go/net/lookup_unix.go \
go/net/mac.go \
go/net/net.go \
+ go/net/net_posix.go \
go/net/parse.go \
go/net/pipe.go \
go/net/port.go \
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 0931ed13535..30f92743bac 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -981,6 +981,7 @@ go_net_files = \
go/net/lookup_unix.go \
go/net/mac.go \
go/net/net.go \
+ go/net/net_posix.go \
go/net/parse.go \
go/net/pipe.go \
go/net/port.go \
diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go
index b44d0e7d167..0e284825bd0 100644
--- a/libgo/go/bufio/bufio.go
+++ b/libgo/go/bufio/bufio.go
@@ -272,6 +272,9 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) {
panic("not reached")
}
+// ReadLine is a low-level line-reading primitive. Most callers should use
+// ReadBytes('\n') or ReadString('\n') instead.
+//
// ReadLine tries to return a single line, not including the end-of-line bytes.
// If the line was too long for the buffer then isPrefix is set and the
// beginning of the line is returned. The rest of the line will be returned
diff --git a/libgo/go/builtin/builtin.go b/libgo/go/builtin/builtin.go
index e81616ca418..a30943b894f 100644
--- a/libgo/go/builtin/builtin.go
+++ b/libgo/go/builtin/builtin.go
@@ -81,9 +81,8 @@ type uintptr uintptr
// integer values.
type byte byte
-// rune is an alias for int and is equivalent to int in all ways. It is
+// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
-// In a future version of Go, it will change to an alias of int32.
type rune rune
// Type is here for the purposes of documentation only. It is a stand-in
diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go
index 7d1426fb417..09b3c1a2705 100644
--- a/libgo/go/bytes/bytes.go
+++ b/libgo/go/bytes/bytes.go
@@ -415,7 +415,7 @@ func Repeat(b []byte, count int) []byte {
// ToUpper returns a copy of the byte array s with all Unicode letters mapped to their upper case.
func ToUpper(s []byte) []byte { return Map(unicode.ToUpper, s) }
-// ToUpper returns a copy of the byte array s with all Unicode letters mapped to their lower case.
+// ToLower returns a copy of the byte array s with all Unicode letters mapped to their lower case.
func ToLower(s []byte) []byte { return Map(unicode.ToLower, s) }
// ToTitle returns a copy of the byte array s with all Unicode letters mapped to their title case.
diff --git a/libgo/go/compress/flate/inflate.go b/libgo/go/compress/flate/inflate.go
index 3f2042bfe92..394c32fa3a6 100644
--- a/libgo/go/compress/flate/inflate.go
+++ b/libgo/go/compress/flate/inflate.go
@@ -16,9 +16,10 @@ import (
const (
maxCodeLen = 16 // max length of Huffman code
maxHist = 32768 // max history required
- maxLit = 286
- maxDist = 32
- numCodes = 19 // number of codes in Huffman meta-code
+ // The next three numbers come from the RFC, section 3.2.7.
+ maxLit = 286
+ maxDist = 32
+ numCodes = 19 // number of codes in Huffman meta-code
)
// A CorruptInputError reports the presence of corrupt input at a given offset.
@@ -306,10 +307,15 @@ func (f *decompressor) readHuffman() error {
}
}
nlit := int(f.b&0x1F) + 257
+ if nlit > maxLit {
+ return CorruptInputError(f.roffset)
+ }
f.b >>= 5
ndist := int(f.b&0x1F) + 1
+ // maxDist is 32, so ndist is always valid.
f.b >>= 5
nclen := int(f.b&0xF) + 4
+ // numCodes is 19, so nclen is always valid.
f.b >>= 4
f.nb -= 5 + 5 + 4
diff --git a/libgo/go/compress/flate/reader_test.go b/libgo/go/compress/flate/reader_test.go
new file mode 100644
index 00000000000..54ed788dbd3
--- /dev/null
+++ b/libgo/go/compress/flate/reader_test.go
@@ -0,0 +1,95 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package flate
+
+import (
+ "bytes"
+ "io"
+ "io/ioutil"
+ "runtime"
+ "strings"
+ "testing"
+)
+
+func TestNlitOutOfRange(t *testing.T) {
+ // Trying to decode this bogus flate data, which has a Huffman table
+ // with nlit=288, should not panic.
+ io.Copy(ioutil.Discard, NewReader(strings.NewReader(
+ "\xfc\xfe\x36\xe7\x5e\x1c\xef\xb3\x55\x58\x77\xb6\x56\xb5\x43\xf4"+
+ "\x6f\xf2\xd2\xe6\x3d\x99\xa0\x85\x8c\x48\xeb\xf8\xda\x83\x04\x2a"+
+ "\x75\xc4\xf8\x0f\x12\x11\xb9\xb4\x4b\x09\xa0\xbe\x8b\x91\x4c")))
+}
+
+const (
+ digits = iota
+ twain
+)
+
+var testfiles = []string{
+ // Digits is the digits of the irrational number e. Its decimal representation
+ // does not repeat, but there are only 10 posible digits, so it should be
+ // reasonably compressible.
+ digits: "../testdata/e.txt",
+ // Twain is Project Gutenberg's edition of Mark Twain's classic English novel.
+ twain: "../testdata/Mark.Twain-Tom.Sawyer.txt",
+}
+
+func benchmarkDecode(b *testing.B, testfile, level, n int) {
+ b.StopTimer()
+ b.SetBytes(int64(n))
+ buf0, err := ioutil.ReadFile(testfiles[testfile])
+ if err != nil {
+ b.Fatal(err)
+ }
+ if len(buf0) == 0 {
+ b.Fatalf("test file %q has no data", testfiles[testfile])
+ }
+ compressed := new(bytes.Buffer)
+ w, err := NewWriter(compressed, level)
+ if err != nil {
+ b.Fatal(err)
+ }
+ for i := 0; i < n; i += len(buf0) {
+ if len(buf0) > n-i {
+ buf0 = buf0[:n-i]
+ }
+ io.Copy(w, bytes.NewBuffer(buf0))
+ }
+ w.Close()
+ buf1 := compressed.Bytes()
+ buf0, compressed, w = nil, nil, nil
+ runtime.GC()
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ io.Copy(ioutil.Discard, NewReader(bytes.NewBuffer(buf1)))
+ }
+}
+
+// These short names are so that gofmt doesn't break the BenchmarkXxx function
+// bodies below over multiple lines.
+const (
+ speed = BestSpeed
+ default_ = DefaultCompression
+ compress = BestCompression
+)
+
+func BenchmarkDecodeDigitsSpeed1e4(b *testing.B) { benchmarkDecode(b, digits, speed, 1e4) }
+func BenchmarkDecodeDigitsSpeed1e5(b *testing.B) { benchmarkDecode(b, digits, speed, 1e5) }
+func BenchmarkDecodeDigitsSpeed1e6(b *testing.B) { benchmarkDecode(b, digits, speed, 1e6) }
+func BenchmarkDecodeDigitsDefault1e4(b *testing.B) { benchmarkDecode(b, digits, default_, 1e4) }
+func BenchmarkDecodeDigitsDefault1e5(b *testing.B) { benchmarkDecode(b, digits, default_, 1e5) }
+func BenchmarkDecodeDigitsDefault1e6(b *testing.B) { benchmarkDecode(b, digits, default_, 1e6) }
+func BenchmarkDecodeDigitsCompress1e4(b *testing.B) { benchmarkDecode(b, digits, compress, 1e4) }
+func BenchmarkDecodeDigitsCompress1e5(b *testing.B) { benchmarkDecode(b, digits, compress, 1e5) }
+func BenchmarkDecodeDigitsCompress1e6(b *testing.B) { benchmarkDecode(b, digits, compress, 1e6) }
+func BenchmarkDecodeTwainSpeed1e4(b *testing.B) { benchmarkDecode(b, twain, speed, 1e4) }
+func BenchmarkDecodeTwainSpeed1e5(b *testing.B) { benchmarkDecode(b, twain, speed, 1e5) }
+func BenchmarkDecodeTwainSpeed1e6(b *testing.B) { benchmarkDecode(b, twain, speed, 1e6) }
+func BenchmarkDecodeTwainDefault1e4(b *testing.B) { benchmarkDecode(b, twain, default_, 1e4) }
+func BenchmarkDecodeTwainDefault1e5(b *testing.B) { benchmarkDecode(b, twain, default_, 1e5) }
+func BenchmarkDecodeTwainDefault1e6(b *testing.B) { benchmarkDecode(b, twain, default_, 1e6) }
+func BenchmarkDecodeTwainCompress1e4(b *testing.B) { benchmarkDecode(b, twain, compress, 1e4) }
+func BenchmarkDecodeTwainCompress1e5(b *testing.B) { benchmarkDecode(b, twain, compress, 1e5) }
+func BenchmarkDecodeTwainCompress1e6(b *testing.B) { benchmarkDecode(b, twain, compress, 1e6) }
diff --git a/libgo/go/crypto/elliptic/elliptic.go b/libgo/go/crypto/elliptic/elliptic.go
index 30835a90b91..a3990891be3 100644
--- a/libgo/go/crypto/elliptic/elliptic.go
+++ b/libgo/go/crypto/elliptic/elliptic.go
@@ -370,7 +370,7 @@ func P384() Curve {
return p384
}
-// P256 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5)
+// P521 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5)
func P521() Curve {
initonce.Do(initAll)
return p521
diff --git a/libgo/go/crypto/rand/rand_test.go b/libgo/go/crypto/rand/rand_test.go
index da091ba8c73..e46e61d374a 100644
--- a/libgo/go/crypto/rand/rand_test.go
+++ b/libgo/go/crypto/rand/rand_test.go
@@ -30,3 +30,14 @@ func TestRead(t *testing.T) {
t.Fatalf("Compressed %d -> %d", len(b), z.Len())
}
}
+
+func TestReadEmpty(t *testing.T) {
+ n, err := Reader.Read(make([]byte, 0))
+ if n != 0 || err != nil {
+ t.Fatalf("Read(make([]byte, 0)) = %d, %v", n, err)
+ }
+ n, err = Reader.Read(nil)
+ if n != 0 || err != nil {
+ t.Fatalf("Read(nil) = %d, %v", n, err)
+ }
+}
diff --git a/libgo/go/crypto/rand/rand_windows.go b/libgo/go/crypto/rand/rand_windows.go
index 2b2bd4bba6b..82b39b64a3c 100644
--- a/libgo/go/crypto/rand/rand_windows.go
+++ b/libgo/go/crypto/rand/rand_windows.go
@@ -35,6 +35,10 @@ func (r *rngReader) Read(b []byte) (n int, err error) {
}
}
r.mu.Unlock()
+
+ if len(b) == 0 {
+ return 0, nil
+ }
err = syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
if err != nil {
return 0, os.NewSyscallError("CryptGenRandom", err)
diff --git a/libgo/go/crypto/rsa/pkcs1v15.go b/libgo/go/crypto/rsa/pkcs1v15.go
index a32236e4729..f39a48a6af6 100644
--- a/libgo/go/crypto/rsa/pkcs1v15.go
+++ b/libgo/go/crypto/rsa/pkcs1v15.go
@@ -25,10 +25,10 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er
return
}
- // EM = 0x02 || PS || 0x00 || M
- em := make([]byte, k-1)
- em[0] = 2
- ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
+ // EM = 0x00 || 0x02 || PS || 0x00 || M
+ em := make([]byte, k)
+ em[1] = 2
+ ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):]
err = nonZeroRandomBytes(ps, rand)
if err != nil {
return
@@ -38,7 +38,9 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er
m := new(big.Int).SetBytes(em)
c := encrypt(new(big.Int), pub, m)
- out = c.Bytes()
+
+ copyWithLeftPad(em, c.Bytes())
+ out = em
return
}
@@ -185,9 +187,12 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
m := new(big.Int).SetBytes(em)
c, err := decrypt(rand, priv, m)
- if err == nil {
- s = c.Bytes()
+ if err != nil {
+ return
}
+
+ copyWithLeftPad(em, c.Bytes())
+ s = em
return
}
@@ -241,3 +246,13 @@ func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte,
}
return
}
+
+// copyWithLeftPad copies src to the end of dest, padding with zero bytes as
+// needed.
+func copyWithLeftPad(dest, src []byte) {
+ numPaddingBytes := len(dest) - len(src)
+ for i := 0; i < numPaddingBytes; i++ {
+ dest[i] = 0
+ }
+ copy(dest[numPaddingBytes:], src)
+}
diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go
index 2a5115dc6ab..455910af415 100644
--- a/libgo/go/crypto/tls/conn.go
+++ b/libgo/go/crypto/tls/conn.go
@@ -487,6 +487,16 @@ Again:
return err
}
typ := recordType(b.data[0])
+
+ // No valid TLS record has a type of 0x80, however SSLv2 handshakes
+ // start with a uint16 length where the MSB is set and the first record
+ // is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
+ // an SSLv2 client.
+ if want == recordTypeHandshake && typ == 0x80 {
+ c.sendAlert(alertProtocolVersion)
+ return errors.New("tls: unsupported SSLv2 handshake received")
+ }
+
vers := uint16(b.data[1])<<8 | uint16(b.data[2])
n := int(b.data[3])<<8 | int(b.data[4])
if c.haveVers && vers != c.vers {
diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go
index 307c5ef0339..28814539d13 100644
--- a/libgo/go/crypto/x509/verify.go
+++ b/libgo/go/crypto/x509/verify.go
@@ -39,7 +39,7 @@ type CertificateInvalidError struct {
func (e CertificateInvalidError) Error() string {
switch e.Reason {
case NotAuthorizedToSign:
- return "x509: certificate is not authorized to sign other other certificates"
+ return "x509: certificate is not authorized to sign other certificates"
case Expired:
return "x509: certificate has expired or is not yet valid"
case CANotAuthorizedForThisName:
diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go
index c4d85e67f0c..e6b0c58eef5 100644
--- a/libgo/go/crypto/x509/x509.go
+++ b/libgo/go/crypto/x509/x509.go
@@ -344,6 +344,55 @@ func (c *Certificate) Equal(other *Certificate) bool {
return bytes.Equal(c.Raw, other.Raw)
}
+// Entrust have a broken root certificate (CN=Entrust.net Certification
+// Authority (2048)) which isn't marked as a CA certificate and is thus invalid
+// according to PKIX.
+// We recognise this certificate by its SubjectPublicKeyInfo and exempt it
+// from the Basic Constraints requirement.
+// See http://www.entrust.net/knowledge-base/technote.cfm?tn=7869
+//
+// TODO(agl): remove this hack once their reissued root is sufficiently
+// widespread.
+var entrustBrokenSPKI = []byte{
+ 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00,
+ 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
+ 0x00, 0x97, 0xa3, 0x2d, 0x3c, 0x9e, 0xde, 0x05,
+ 0xda, 0x13, 0xc2, 0x11, 0x8d, 0x9d, 0x8e, 0xe3,
+ 0x7f, 0xc7, 0x4b, 0x7e, 0x5a, 0x9f, 0xb3, 0xff,
+ 0x62, 0xab, 0x73, 0xc8, 0x28, 0x6b, 0xba, 0x10,
+ 0x64, 0x82, 0x87, 0x13, 0xcd, 0x57, 0x18, 0xff,
+ 0x28, 0xce, 0xc0, 0xe6, 0x0e, 0x06, 0x91, 0x50,
+ 0x29, 0x83, 0xd1, 0xf2, 0xc3, 0x2a, 0xdb, 0xd8,
+ 0xdb, 0x4e, 0x04, 0xcc, 0x00, 0xeb, 0x8b, 0xb6,
+ 0x96, 0xdc, 0xbc, 0xaa, 0xfa, 0x52, 0x77, 0x04,
+ 0xc1, 0xdb, 0x19, 0xe4, 0xae, 0x9c, 0xfd, 0x3c,
+ 0x8b, 0x03, 0xef, 0x4d, 0xbc, 0x1a, 0x03, 0x65,
+ 0xf9, 0xc1, 0xb1, 0x3f, 0x72, 0x86, 0xf2, 0x38,
+ 0xaa, 0x19, 0xae, 0x10, 0x88, 0x78, 0x28, 0xda,
+ 0x75, 0xc3, 0x3d, 0x02, 0x82, 0x02, 0x9c, 0xb9,
+ 0xc1, 0x65, 0x77, 0x76, 0x24, 0x4c, 0x98, 0xf7,
+ 0x6d, 0x31, 0x38, 0xfb, 0xdb, 0xfe, 0xdb, 0x37,
+ 0x02, 0x76, 0xa1, 0x18, 0x97, 0xa6, 0xcc, 0xde,
+ 0x20, 0x09, 0x49, 0x36, 0x24, 0x69, 0x42, 0xf6,
+ 0xe4, 0x37, 0x62, 0xf1, 0x59, 0x6d, 0xa9, 0x3c,
+ 0xed, 0x34, 0x9c, 0xa3, 0x8e, 0xdb, 0xdc, 0x3a,
+ 0xd7, 0xf7, 0x0a, 0x6f, 0xef, 0x2e, 0xd8, 0xd5,
+ 0x93, 0x5a, 0x7a, 0xed, 0x08, 0x49, 0x68, 0xe2,
+ 0x41, 0xe3, 0x5a, 0x90, 0xc1, 0x86, 0x55, 0xfc,
+ 0x51, 0x43, 0x9d, 0xe0, 0xb2, 0xc4, 0x67, 0xb4,
+ 0xcb, 0x32, 0x31, 0x25, 0xf0, 0x54, 0x9f, 0x4b,
+ 0xd1, 0x6f, 0xdb, 0xd4, 0xdd, 0xfc, 0xaf, 0x5e,
+ 0x6c, 0x78, 0x90, 0x95, 0xde, 0xca, 0x3a, 0x48,
+ 0xb9, 0x79, 0x3c, 0x9b, 0x19, 0xd6, 0x75, 0x05,
+ 0xa0, 0xf9, 0x88, 0xd7, 0xc1, 0xe8, 0xa5, 0x09,
+ 0xe4, 0x1a, 0x15, 0xdc, 0x87, 0x23, 0xaa, 0xb2,
+ 0x75, 0x8c, 0x63, 0x25, 0x87, 0xd8, 0xf8, 0x3d,
+ 0xa6, 0xc2, 0xcc, 0x66, 0xff, 0xa5, 0x66, 0x68,
+ 0x55, 0x02, 0x03, 0x01, 0x00, 0x01,
+}
+
// CheckSignatureFrom verifies that the signature on c is a valid signature
// from parent.
func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) {
@@ -352,8 +401,10 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err error) {
// certificate, or the extension is present but the cA boolean is not
// asserted, then the certified public key MUST NOT be used to verify
// certificate signatures."
- if parent.Version == 3 && !parent.BasicConstraintsValid ||
- parent.BasicConstraintsValid && !parent.IsCA {
+ // (except for Entrust, see comment above entrustBrokenSPKI)
+ if (parent.Version == 3 && !parent.BasicConstraintsValid ||
+ parent.BasicConstraintsValid && !parent.IsCA) &&
+ !bytes.Equal(c.RawSubjectPublicKeyInfo, entrustBrokenSPKI) {
return ConstraintViolationError{}
}
diff --git a/libgo/go/database/sql/fakedb_test.go b/libgo/go/database/sql/fakedb_test.go
index 184e7756c51..a11fb788ef7 100644
--- a/libgo/go/database/sql/fakedb_test.go
+++ b/libgo/go/database/sql/fakedb_test.go
@@ -31,7 +31,7 @@ var _ = log.Printf
// INSERT|<tablename>|col=val,col2=val2,col3=?
// SELECT|<tablename>|projectcol1,projectcol2|filtercol=?,filtercol2=?
//
-// When opening a a fakeDriver's database, it starts empty with no
+// When opening a fakeDriver's database, it starts empty with no
// tables. All tables and data are stored in memory only.
type fakeDriver struct {
mu sync.Mutex
@@ -234,7 +234,7 @@ func checkSubsetTypes(args []driver.Value) error {
func (c *fakeConn) Exec(query string, args []driver.Value) (driver.Result, error) {
// This is an optional interface, but it's implemented here
- // just to check that all the args of of the proper types.
+ // just to check that all the args are of the proper types.
// ErrSkip is returned so the caller acts as if we didn't
// implement this at all.
err := checkSubsetTypes(args)
@@ -249,7 +249,7 @@ func errf(msg string, args ...interface{}) error {
}
// parts are table|selectCol1,selectCol2|whereCol=?,whereCol2=?
-// (note that where where columns must always contain ? marks,
+// (note that where columns must always contain ? marks,
// just a limitation for fakedb)
func (c *fakeConn) prepareSelect(stmt *fakeStmt, parts []string) (driver.Stmt, error) {
if len(parts) != 3 {
diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go
index 89136ef6e40..d557fc83034 100644
--- a/libgo/go/database/sql/sql.go
+++ b/libgo/go/database/sql/sql.go
@@ -311,7 +311,10 @@ func (db *DB) prepare(query string) (stmt *Stmt, err error) {
if err != nil {
return nil, err
}
- defer db.putConn(ci, err)
+ defer func() {
+ db.putConn(ci, err)
+ }()
+
si, err := ci.Prepare(query)
if err != nil {
return nil, err
@@ -345,7 +348,9 @@ func (db *DB) exec(query string, sargs []driver.Value) (res Result, err error) {
if err != nil {
return nil, err
}
- defer db.putConn(ci, err)
+ defer func() {
+ db.putConn(ci, err)
+ }()
if execer, ok := ci.(driver.Execer); ok {
resi, err := execer.Exec(query, sargs)
diff --git a/libgo/go/encoding/binary/varint.go b/libgo/go/encoding/binary/varint.go
index b756afdd040..719018b6033 100644
--- a/libgo/go/encoding/binary/varint.go
+++ b/libgo/go/encoding/binary/varint.go
@@ -123,7 +123,7 @@ func ReadUvarint(r io.ByteReader) (uint64, error) {
panic("unreachable")
}
-// ReadVarint reads an encoded unsigned integer from r and returns it as a uint64.
+// ReadVarint reads an encoded unsigned integer from r and returns it as an int64.
func ReadVarint(r io.ByteReader) (int64, error) {
ux, err := ReadUvarint(r) // ok to continue in presence of error
x := int64(ux >> 1)
diff --git a/libgo/go/encoding/gob/decode.go b/libgo/go/encoding/gob/decode.go
index e32a178aba3..8690b35d714 100644
--- a/libgo/go/encoding/gob/decode.go
+++ b/libgo/go/encoding/gob/decode.go
@@ -562,6 +562,9 @@ func (dec *Decoder) ignoreSingle(engine *decEngine) {
func (dec *Decoder) decodeArrayHelper(state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) {
instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl}
for i := 0; i < length; i++ {
+ if state.b.Len() == 0 {
+ errorf("decoding array or slice: length exceeds input size (%d elements)", length)
+ }
up := unsafe.Pointer(p)
if elemIndir > 1 {
up = decIndirect(up, elemIndir)
@@ -652,9 +655,6 @@ func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) {
// Slices are encoded as an unsigned length followed by the elements.
func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl error) {
nr := state.decodeUint()
- if nr > uint64(state.b.Len()) {
- errorf("length of slice exceeds input size (%d elements)", nr)
- }
n := int(nr)
if indir > 0 {
up := unsafe.Pointer(p)
diff --git a/libgo/go/encoding/gob/doc.go b/libgo/go/encoding/gob/doc.go
index 821d9a3fe8e..6d77c171f41 100644
--- a/libgo/go/encoding/gob/doc.go
+++ b/libgo/go/encoding/gob/doc.go
@@ -118,7 +118,7 @@ elements using the standard gob encoding for their type, recursively.
Maps are sent as an unsigned count followed by that many key, element
pairs. Empty but non-nil maps are sent, so if the sender has allocated
-a map, the receiver will allocate a map even no elements are
+a map, the receiver will allocate a map even if no elements are
transmitted.
Structs are sent as a sequence of (field number, field value) pairs. The field
diff --git a/libgo/go/encoding/gob/encoder_test.go b/libgo/go/encoding/gob/encoder_test.go
index c4947cbb8d3..db824d99917 100644
--- a/libgo/go/encoding/gob/encoder_test.go
+++ b/libgo/go/encoding/gob/encoder_test.go
@@ -736,3 +736,32 @@ func TestPtrToMapOfMap(t *testing.T) {
t.Fatalf("expected %v got %v", data, newData)
}
}
+
+// There was an error check comparing the length of the input with the
+// length of the slice being decoded. It was wrong because the next
+// thing in the input might be a type definition, which would lead to
+// an incorrect length check. This test reproduces the corner case.
+
+type Z struct {
+}
+
+func Test29ElementSlice(t *testing.T) {
+ Register(Z{})
+ src := make([]interface{}, 100) // Size needs to be bigger than size of type definition.
+ for i := range src {
+ src[i] = Z{}
+ }
+ buf := new(bytes.Buffer)
+ err := NewEncoder(buf).Encode(src)
+ if err != nil {
+ t.Fatalf("encode: %v", err)
+ return
+ }
+
+ var dst []interface{}
+ err = NewDecoder(buf).Decode(&dst)
+ if err != nil {
+ t.Errorf("decode: %v", err)
+ return
+ }
+}
diff --git a/libgo/go/encoding/gob/type.go b/libgo/go/encoding/gob/type.go
index 0dd7a0a770e..a8ee2fa4a5a 100644
--- a/libgo/go/encoding/gob/type.go
+++ b/libgo/go/encoding/gob/type.go
@@ -749,12 +749,28 @@ func Register(value interface{}) {
rt := reflect.TypeOf(value)
name := rt.String()
- // But for named types (or pointers to them), qualify with import path.
+ // But for named types (or pointers to them), qualify with import path (but see inner comment).
// Dereference one pointer looking for a named type.
star := ""
if rt.Name() == "" {
if pt := rt; pt.Kind() == reflect.Ptr {
star = "*"
+ // NOTE: The following line should be rt = pt.Elem() to implement
+ // what the comment above claims, but fixing it would break compatibility
+ // with existing gobs.
+ //
+ // Given package p imported as "full/p" with these definitions:
+ // package p
+ // type T1 struct { ... }
+ // this table shows the intended and actual strings used by gob to
+ // name the types:
+ //
+ // Type Correct string Actual string
+ //
+ // T1 full/p.T1 full/p.T1
+ // *T1 *full/p.T1 *p.T1
+ //
+ // The missing full path cannot be fixed without breaking existing gob decoders.
rt = pt
}
}
diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go
index b6e1cb16e5a..d2c1c4424c7 100644
--- a/libgo/go/encoding/json/encode.go
+++ b/libgo/go/encoding/json/encode.go
@@ -55,7 +55,7 @@ import (
// nil pointer or interface value, and any array, slice, map, or string of
// length zero. The object's default key string is the struct field name
// but can be specified in the struct field's tag value. The "json" key in
-// struct field's tag value is the key name, followed by an optional comma
+// the struct field's tag value is the key name, followed by an optional comma
// and options. Examples:
//
// // Field is ignored by this package.
diff --git a/libgo/go/flag/flag.go b/libgo/go/flag/flag.go
index 5444ad141c5..bbabd88c8ca 100644
--- a/libgo/go/flag/flag.go
+++ b/libgo/go/flag/flag.go
@@ -33,7 +33,7 @@
After parsing, the arguments after the flag are available as the
slice flag.Args() or individually as flag.Arg(i).
- The arguments are indexed from 0 up to flag.NArg().
+ The arguments are indexed from 0 through flag.NArg()-1.
Command line flag syntax:
-flag
@@ -707,7 +707,7 @@ func (f *FlagSet) parseOne() (bool, error) {
if fv, ok := flag.Value.(*boolValue); ok { // special case: doesn't need an arg
if has_value {
if err := fv.Set(value); err != nil {
- f.failf("invalid boolean value %q for -%s: %v", value, name, err)
+ return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err)
}
} else {
fv.Set("true")
diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go
index 500a45944d8..98ebfb74161 100644
--- a/libgo/go/fmt/fmt_test.go
+++ b/libgo/go/fmt/fmt_test.go
@@ -844,3 +844,15 @@ func TestIsSpace(t *testing.T) {
}
}
}
+
+func TestNilDoesNotBecomeTyped(t *testing.T) {
+ type A struct{}
+ type B struct{}
+ var a *A = nil
+ var b B = B{}
+ got := Sprintf("%s %s %s %s %s", nil, a, nil, b, nil)
+ const expect = "%!s(<nil>) %!s(*fmt_test.A=<nil>) %!s(<nil>) {} %!s(<nil>)"
+ if got != expect {
+ t.Errorf("expected:\n\t%q\ngot:\n\t%q", expect, got)
+ }
+}
diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go
index 13438243cdd..f29e8c8e9f1 100644
--- a/libgo/go/fmt/print.go
+++ b/libgo/go/fmt/print.go
@@ -712,6 +712,9 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString
}
func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth int) (wasString bool) {
+ p.field = field
+ p.value = reflect.Value{}
+
if field == nil {
if verb == 'T' || verb == 'v' {
p.buf.Write(nilAngleBytes)
@@ -721,8 +724,6 @@ func (p *pp) printField(field interface{}, verb rune, plus, goSyntax bool, depth
return false
}
- p.field = field
- p.value = reflect.Value{}
// Special processing considerations.
// %T (the value's type) and %p (its address) are special; we always do them first.
switch verb {
diff --git a/libgo/go/go/ast/print.go b/libgo/go/go/ast/print.go
index 02cf9e02234..2de9af299e5 100644
--- a/libgo/go/go/ast/print.go
+++ b/libgo/go/go/ast/print.go
@@ -34,7 +34,8 @@ func NotNilFilter(_ string, v reflect.Value) bool {
//
// A non-nil FieldFilter f may be provided to control the output:
// struct fields for which f(fieldname, fieldvalue) is true are
-// are printed; all others are filtered from the output.
+// are printed; all others are filtered from the output. Unexported
+// struct fields are never printed.
//
func Fprint(w io.Writer, fset *token.FileSet, x interface{}, f FieldFilter) (err error) {
// setup printer
@@ -145,15 +146,18 @@ func (p *printer) print(x reflect.Value) {
p.print(x.Elem())
case reflect.Map:
- p.printf("%s (len = %d) {\n", x.Type(), x.Len())
- p.indent++
- for _, key := range x.MapKeys() {
- p.print(key)
- p.printf(": ")
- p.print(x.MapIndex(key))
+ p.printf("%s (len = %d) {", x.Type(), x.Len())
+ if x.Len() > 0 {
+ p.indent++
p.printf("\n")
+ for _, key := range x.MapKeys() {
+ p.print(key)
+ p.printf(": ")
+ p.print(x.MapIndex(key))
+ p.printf("\n")
+ }
+ p.indent--
}
- p.indent--
p.printf("}")
case reflect.Ptr:
@@ -169,32 +173,57 @@ func (p *printer) print(x reflect.Value) {
p.print(x.Elem())
}
+ case reflect.Array:
+ p.printf("%s {", x.Type())
+ if x.Len() > 0 {
+ p.indent++
+ p.printf("\n")
+ for i, n := 0, x.Len(); i < n; i++ {
+ p.printf("%d: ", i)
+ p.print(x.Index(i))
+ p.printf("\n")
+ }
+ p.indent--
+ }
+ p.printf("}")
+
case reflect.Slice:
if s, ok := x.Interface().([]byte); ok {
p.printf("%#q", s)
return
}
- p.printf("%s (len = %d) {\n", x.Type(), x.Len())
- p.indent++
- for i, n := 0, x.Len(); i < n; i++ {
- p.printf("%d: ", i)
- p.print(x.Index(i))
+ p.printf("%s (len = %d) {", x.Type(), x.Len())
+ if x.Len() > 0 {
+ p.indent++
p.printf("\n")
+ for i, n := 0, x.Len(); i < n; i++ {
+ p.printf("%d: ", i)
+ p.print(x.Index(i))
+ p.printf("\n")
+ }
+ p.indent--
}
- p.indent--
p.printf("}")
case reflect.Struct:
- p.printf("%s {\n", x.Type())
- p.indent++
t := x.Type()
+ p.printf("%s {", t)
+ p.indent++
+ first := true
for i, n := 0, t.NumField(); i < n; i++ {
- name := t.Field(i).Name
- value := x.Field(i)
- if p.filter == nil || p.filter(name, value) {
- p.printf("%s: ", name)
- p.print(value)
- p.printf("\n")
+ // exclude non-exported fields because their
+ // values cannot be accessed via reflection
+ if name := t.Field(i).Name; IsExported(name) {
+ value := x.Field(i)
+ if p.filter == nil || p.filter(name, value) {
+ if first {
+ p.printf("\n")
+ first = false
+ }
+ p.printf("%s: ", name)
+ p.print(value)
+ p.printf("\n")
+ }
}
}
p.indent--
diff --git a/libgo/go/go/ast/print_test.go b/libgo/go/go/ast/print_test.go
index 71c028e7537..210f1643010 100644
--- a/libgo/go/go/ast/print_test.go
+++ b/libgo/go/go/ast/print_test.go
@@ -23,6 +23,7 @@ var tests = []struct {
{"foobar", "0 \"foobar\""},
// maps
+ {map[Expr]string{}, `0 map[ast.Expr]string (len = 0) {}`},
{map[string]int{"a": 1},
`0 map[string]int (len = 1) {
1 . "a": 1
@@ -31,7 +32,21 @@ var tests = []struct {
// pointers
{new(int), "0 *0"},
+ // arrays
+ {[0]int{}, `0 [0]int {}`},
+ {[3]int{1, 2, 3},
+ `0 [3]int {
+ 1 . 0: 1
+ 2 . 1: 2
+ 3 . 2: 3
+ 4 }`},
+ {[...]int{42},
+ `0 [1]int {
+ 1 . 0: 42
+ 2 }`},
+
// slices
+ {[]int{}, `0 []int (len = 0) {}`},
{[]int{1, 2, 3},
`0 []int (len = 3) {
1 . 0: 1
@@ -40,6 +55,12 @@ var tests = []struct {
4 }`},
// structs
+ {struct{}{}, `0 struct {} {}`},
+ {struct{ x int }{007}, `0 struct { x int } {}`},
+ {struct{ X, y int }{42, 991},
+ `0 struct { X int; y int } {
+ 1 . X: 42
+ 2 }`},
{struct{ X, Y int }{42, 991},
`0 struct { X int; Y int } {
1 . X: 42
diff --git a/libgo/go/go/ast/resolve.go b/libgo/go/go/ast/resolve.go
index 908e61c5da0..54b5d73252d 100644
--- a/libgo/go/go/ast/resolve.go
+++ b/libgo/go/go/ast/resolve.go
@@ -136,7 +136,7 @@ func NewPackage(fset *token.FileSet, files map[string]*File, importer Importer,
for _, obj := range pkg.Data.(*Scope).Objects {
p.declare(fileScope, pkgScope, obj)
}
- } else {
+ } else if name != "_" {
// declare imported package object in file scope
// (do not re-use pkg in the file scope but create
// a new object instead; the Decl field is different
diff --git a/libgo/go/go/ast/walk.go b/libgo/go/go/ast/walk.go
index 181cfd1491a..66b1dc2499b 100644
--- a/libgo/go/go/ast/walk.go
+++ b/libgo/go/go/ast/walk.go
@@ -344,9 +344,6 @@ func Walk(v Visitor, node Node) {
}
Walk(v, n.Name)
walkDeclList(v, n.Decls)
- for _, g := range n.Comments {
- Walk(v, g)
- }
// don't walk n.Comments - they have been
// visited already through the individual
// nodes
diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go
index 7a81d50303d..67e73c5e4a4 100644
--- a/libgo/go/go/build/build.go
+++ b/libgo/go/go/build/build.go
@@ -536,7 +536,7 @@ Found:
return p, err
}
- pkg := string(pf.Name.Name)
+ pkg := pf.Name.Name
if pkg == "documentation" {
continue
}
@@ -570,7 +570,7 @@ Found:
if !ok {
continue
}
- quoted := string(spec.Path.Value)
+ quoted := spec.Path.Value
path, err := strconv.Unquote(quoted)
if err != nil {
log.Panicf("%s: parser returned invalid quoted string: <%s>", filename, quoted)
@@ -678,7 +678,7 @@ func (ctxt *Context) shouldBuild(content []byte) bool {
}
line = bytes.TrimSpace(line)
if len(line) == 0 { // Blank line
- end = cap(content) - cap(line) // &line[0] - &content[0]
+ end = len(content) - len(p)
continue
}
if !bytes.HasPrefix(line, slashslash) { // Not comment line
diff --git a/libgo/go/go/build/build_test.go b/libgo/go/go/build/build_test.go
index 560ebad5c97..caa4f26f332 100644
--- a/libgo/go/go/build/build_test.go
+++ b/libgo/go/go/build/build_test.go
@@ -75,3 +75,32 @@ func TestLocalDirectory(t *testing.T) {
t.Fatalf("ImportPath=%q, want %q", p.ImportPath, "go/build")
}
}
+
+func TestShouldBuild(t *testing.T) {
+ const file1 = "// +build tag1\n\n" +
+ "package main\n"
+
+ const file2 = "// +build cgo\n\n" +
+ "// This package implements parsing of tags like\n" +
+ "// +build tag1\n" +
+ "package build"
+
+ const file3 = "// Copyright The Go Authors.\n\n" +
+ "package build\n\n" +
+ "// shouldBuild checks tags given by lines of the form\n" +
+ "// +build tag\n" +
+ "func shouldBuild(content []byte)\n"
+
+ ctx := &Context{BuildTags: []string{"tag1"}}
+ if !ctx.shouldBuild([]byte(file1)) {
+ t.Errorf("should not build file1, expected the contrary")
+ }
+ if ctx.shouldBuild([]byte(file2)) {
+ t.Errorf("should build file2, expected the contrary")
+ }
+
+ ctx = &Context{BuildTags: nil}
+ if !ctx.shouldBuild([]byte(file3)) {
+ t.Errorf("should not build file3, expected the contrary")
+ }
+}
diff --git a/libgo/go/go/build/doc.go b/libgo/go/go/build/doc.go
index 67c26ac7f4f..9b7a946f2b8 100644
--- a/libgo/go/go/build/doc.go
+++ b/libgo/go/go/build/doc.go
@@ -60,7 +60,7 @@
// A build constraint is a line comment beginning with the directive +build
// that lists the conditions under which a file should be included in the package.
// Constraints may appear in any kind of source file (not just Go), but
-// they must be appear near the top of the file, preceded
+// they must appear near the top of the file, preceded
// only by blank lines and other line comments.
//
// A build constraint is evaluated as the OR of space-separated options;
diff --git a/libgo/go/go/doc/reader.go b/libgo/go/go/doc/reader.go
index 5eaae37b7de..60b174fecd8 100644
--- a/libgo/go/go/doc/reader.go
+++ b/libgo/go/go/doc/reader.go
@@ -494,7 +494,7 @@ func (r *reader) readPackage(pkg *ast.Package, mode Mode) {
r.funcs = make(methodSet)
// sort package files before reading them so that the
- // result result does not depend on map iteration order
+ // result does not depend on map iteration order
i := 0
for filename := range pkg.Files {
r.filenames[i] = filename
diff --git a/libgo/go/go/doc/testdata/error2.1.golden b/libgo/go/go/doc/testdata/error2.1.golden
index 776bd1b3e40..dbcc1b03e78 100644
--- a/libgo/go/go/doc/testdata/error2.1.golden
+++ b/libgo/go/go/doc/testdata/error2.1.golden
@@ -10,7 +10,7 @@ FILENAMES
TYPES
//
type I0 interface {
- // When embedded, the the locally declared error interface
+ // When embedded, the locally-declared error interface
// is only visible if all declarations are shown.
error
}
diff --git a/libgo/go/go/doc/testdata/error2.go b/libgo/go/go/doc/testdata/error2.go
index 6cc36feef3e..6ee96c2450b 100644
--- a/libgo/go/go/doc/testdata/error2.go
+++ b/libgo/go/go/doc/testdata/error2.go
@@ -5,7 +5,7 @@
package error2
type I0 interface {
- // When embedded, the the locally declared error interface
+ // When embedded, the locally-declared error interface
// is only visible if all declarations are shown.
error
}
diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go
index f13f9a5a843..e346b93643b 100644
--- a/libgo/go/go/printer/nodes.go
+++ b/libgo/go/go/printer/nodes.go
@@ -325,9 +325,14 @@ func (p *printer) parameters(fields *ast.FieldList) {
}
func (p *printer) signature(params, result *ast.FieldList) {
- p.parameters(params)
+ if params != nil {
+ p.parameters(params)
+ } else {
+ p.print(token.LPAREN, token.RPAREN)
+ }
n := result.NumFields()
if n > 0 {
+ // result != nil
p.print(blank)
if n == 1 && result.List[0].Names == nil {
// single anonymous result; no ()'s
diff --git a/libgo/go/go/printer/printer_test.go b/libgo/go/go/printer/printer_test.go
index 497d671f240..ab9e9b2ec8c 100644
--- a/libgo/go/go/printer/printer_test.go
+++ b/libgo/go/go/printer/printer_test.go
@@ -385,6 +385,35 @@ func (t *t) foo(a, b, c int) int {
}
}
+// TestFuncType tests that an ast.FuncType with a nil Params field
+// can be printed (per go/ast specification). Test case for issue 3870.
+func TestFuncType(t *testing.T) {
+ src := &ast.File{
+ Name: &ast.Ident{Name: "p"},
+ Decls: []ast.Decl{
+ &ast.FuncDecl{
+ Name: &ast.Ident{Name: "f"},
+ Type: &ast.FuncType{},
+ },
+ },
+ }
+
+ var buf bytes.Buffer
+ if err := Fprint(&buf, fset, src); err != nil {
+ t.Fatal(err)
+ }
+ got := buf.String()
+
+ const want = `package p
+
+func f()
+`
+
+ if got != want {
+ t.Fatalf("got:\n%s\nwant:\n%s\n", got, want)
+ }
+}
+
// TextX is a skeleton test that can be filled in for debugging one-off cases.
// Do not remove.
func TestX(t *testing.T) {
diff --git a/libgo/go/go/scanner/errors.go b/libgo/go/go/scanner/errors.go
index 8a75a96508e..22de69c3c1c 100644
--- a/libgo/go/go/scanner/errors.go
+++ b/libgo/go/go/scanner/errors.go
@@ -120,7 +120,7 @@ func PrintError(w io.Writer, err error) {
for _, e := range list {
fmt.Fprintf(w, "%s\n", e)
}
- } else {
+ } else if err != nil {
fmt.Fprintf(w, "%s\n", err)
}
}
diff --git a/libgo/go/go/scanner/scanner.go b/libgo/go/go/scanner/scanner.go
index da508747a6d..6ef3e14d0bd 100644
--- a/libgo/go/go/scanner/scanner.go
+++ b/libgo/go/go/scanner/scanner.go
@@ -81,7 +81,7 @@ func (s *Scanner) next() {
}
}
-// A mode value is set of flags (or 0).
+// A mode value is a set of flags (or 0).
// They control scanner behavior.
//
type Mode uint
diff --git a/libgo/go/html/template/content.go b/libgo/go/html/template/content.go
index c1bd2e4949b..42ea7930f07 100644
--- a/libgo/go/html/template/content.go
+++ b/libgo/go/html/template/content.go
@@ -47,7 +47,7 @@ type (
// JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not.
JSStr string
- // URL encapsulates a known safe URL as defined in RFC 3896.
+ // URL encapsulates a known safe URL or URL substring (see RFC 3986).
// A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()`
// from a trusted source should go in the page, but by default dynamic
// `javascript:` URLs are filtered out since they are a frequently
diff --git a/libgo/go/html/template/url.go b/libgo/go/html/template/url.go
index 454c791ec31..2ca76bf389f 100644
--- a/libgo/go/html/template/url.go
+++ b/libgo/go/html/template/url.go
@@ -60,7 +60,7 @@ func urlProcessor(norm bool, args ...interface{}) string {
c := s[i]
switch c {
// Single quote and parens are sub-delims in RFC 3986, but we
- // escape them so the output can be embedded in in single
+ // escape them so the output can be embedded in single
// quoted attributes and unquoted CSS url(...) constructs.
// Single quotes are reserved in URLs, but are only used in
// the obsolete "mark" rule in an appendix in RFC 3986
diff --git a/libgo/go/image/jpeg/reader.go b/libgo/go/image/jpeg/reader.go
index d9adf6e5876..8da3611919e 100644
--- a/libgo/go/image/jpeg/reader.go
+++ b/libgo/go/image/jpeg/reader.go
@@ -74,7 +74,9 @@ const (
comMarker = 0xfe // COMment.
)
-// Maps from the zig-zag ordering to the natural ordering.
+// unzig maps from the zig-zag ordering to the natural ordering. For example,
+// unzig[3] is the column and row of the fourth element in zig-zag order. The
+// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2).
var unzig = [blockSize]int{
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
@@ -101,7 +103,7 @@ type decoder struct {
nComp int
comp [nColorComponent]component
huff [maxTc + 1][maxTh + 1]huffman
- quant [maxTq + 1]block
+ quant [maxTq + 1]block // Quantization tables, in zig-zag order.
b bits
tmp [1024]byte
}
@@ -264,6 +266,7 @@ func (d *decoder) processSOS(n int) error {
for j := 0; j < d.comp[i].h*d.comp[i].v; j++ {
// TODO(nigeltao): make this a "var b block" once the compiler's escape
// analysis is good enough to allocate it on the stack, not the heap.
+ // b is in natural (not zig-zag) order.
b = block{}
// Decode the DC coefficient, as specified in section F.2.2.1.
@@ -282,7 +285,7 @@ func (d *decoder) processSOS(n int) error {
b[0] = dc[i] * qt[0]
// Decode the AC coefficients, as specified in section F.2.2.2.
- for k := 1; k < blockSize; k++ {
+ for zig := 1; zig < blockSize; zig++ {
value, err := d.decodeHuffman(&d.huff[acTable][scan[i].ta])
if err != nil {
return err
@@ -290,20 +293,20 @@ func (d *decoder) processSOS(n int) error {
val0 := value >> 4
val1 := value & 0x0f
if val1 != 0 {
- k += int(val0)
- if k > blockSize {
+ zig += int(val0)
+ if zig > blockSize {
return FormatError("bad DCT index")
}
ac, err := d.receiveExtend(val1)
if err != nil {
return err
}
- b[unzig[k]] = ac * qt[k]
+ b[unzig[zig]] = ac * qt[zig]
} else {
if val0 != 0x0f {
break
}
- k += 0x0f
+ zig += 0x0f
}
}
@@ -393,6 +396,15 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
if marker == eoiMarker { // End Of Image.
break
}
+ if rst0Marker <= marker && marker <= rst7Marker {
+ // Figures B.2 and B.16 of the specification suggest that restart markers should
+ // only occur between Entropy Coded Segments and not after the final ECS.
+ // However, some encoders may generate incorrect JPEGs with a final restart
+ // marker. That restart marker will be seen here instead of inside the processSOS
+ // method, and is ignored as a harmless error. Restart markers have no extra data,
+ // so we check for this before we read the 16-bit length of the segment.
+ continue
+ }
// Read the 16-bit length of the segment. The value includes the 2 bytes for the
// length itself, so we subtract 2 to get the number of remaining bytes.
@@ -421,7 +433,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) (image.Image, error) {
err = d.processSOS(n)
case marker == driMarker: // Define Restart Interval.
err = d.processDRI(n)
- case marker >= app0Marker && marker <= app15Marker || marker == comMarker: // APPlication specific, or COMment.
+ case app0Marker <= marker && marker <= app15Marker || marker == comMarker: // APPlication specific, or COMment.
err = d.ignore(n)
default:
err = UnsupportedError("unknown marker")
diff --git a/libgo/go/image/jpeg/writer.go b/libgo/go/image/jpeg/writer.go
index 3322c09fe71..099298e462e 100644
--- a/libgo/go/image/jpeg/writer.go
+++ b/libgo/go/image/jpeg/writer.go
@@ -56,26 +56,28 @@ const (
nQuantIndex
)
-// unscaledQuant are the unscaled quantization tables. Each encoder copies and
-// scales the tables according to its quality parameter.
+// unscaledQuant are the unscaled quantization tables in zig-zag order. Each
+// encoder copies and scales the tables according to its quality parameter.
+// The values are derived from section K.1 after converting from natural to
+// zig-zag order.
var unscaledQuant = [nQuantIndex][blockSize]byte{
// Luminance.
{
- 16, 11, 10, 16, 24, 40, 51, 61,
- 12, 12, 14, 19, 26, 58, 60, 55,
- 14, 13, 16, 24, 40, 57, 69, 56,
- 14, 17, 22, 29, 51, 87, 80, 62,
- 18, 22, 37, 56, 68, 109, 103, 77,
- 24, 35, 55, 64, 81, 104, 113, 92,
- 49, 64, 78, 87, 103, 121, 120, 101,
- 72, 92, 95, 98, 112, 100, 103, 99,
+ 16, 11, 12, 14, 12, 10, 16, 14,
+ 13, 14, 18, 17, 16, 19, 24, 40,
+ 26, 24, 22, 22, 24, 49, 35, 37,
+ 29, 40, 58, 51, 61, 60, 57, 51,
+ 56, 55, 64, 72, 92, 78, 64, 68,
+ 87, 69, 55, 56, 80, 109, 81, 87,
+ 95, 98, 103, 104, 103, 62, 77, 113,
+ 121, 112, 100, 120, 92, 101, 103, 99,
},
// Chrominance.
{
- 17, 18, 24, 47, 99, 99, 99, 99,
- 18, 21, 26, 66, 99, 99, 99, 99,
- 24, 26, 56, 99, 99, 99, 99, 99,
- 47, 66, 99, 99, 99, 99, 99, 99,
+ 17, 18, 18, 24, 21, 24, 47, 26,
+ 26, 47, 99, 66, 56, 66, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
@@ -222,7 +224,7 @@ type encoder struct {
buf [16]byte
// bits and nBits are accumulated bits to write to w.
bits, nBits uint32
- // quant is the scaled quantization tables.
+ // quant is the scaled quantization tables, in zig-zag order.
quant [nQuantIndex][blockSize]byte
}
@@ -301,7 +303,7 @@ func (e *encoder) writeMarkerHeader(marker uint8, markerlen int) {
// writeDQT writes the Define Quantization Table marker.
func (e *encoder) writeDQT() {
- markerlen := 2 + int(nQuantIndex)*(1+blockSize)
+ const markerlen = 2 + int(nQuantIndex)*(1+blockSize)
e.writeMarkerHeader(dqtMarker, markerlen)
for i := range e.quant {
e.writeByte(uint8(i))
@@ -311,7 +313,7 @@ func (e *encoder) writeDQT() {
// writeSOF0 writes the Start Of Frame (Baseline) marker.
func (e *encoder) writeSOF0(size image.Point) {
- markerlen := 8 + 3*nColorComponent
+ const markerlen = 8 + 3*nColorComponent
e.writeMarkerHeader(sof0Marker, markerlen)
e.buf[0] = 8 // 8-bit color.
e.buf[1] = uint8(size.Y >> 8)
@@ -344,6 +346,7 @@ func (e *encoder) writeDHT() {
// writeBlock writes a block of pixel data using the given quantization table,
// returning the post-quantized DC value of the DCT-transformed block.
+// b is in natural (not zig-zag) order.
func (e *encoder) writeBlock(b *block, q quantIndex, prevDC int) int {
fdct(b)
// Emit the DC delta.
@@ -351,8 +354,8 @@ func (e *encoder) writeBlock(b *block, q quantIndex, prevDC int) int {
e.emitHuffRLE(huffIndex(2*q+0), 0, dc-prevDC)
// Emit the AC components.
h, runLength := huffIndex(2*q+1), 0
- for k := 1; k < blockSize; k++ {
- ac := div(b[unzig[k]], (8 * int(e.quant[q][k])))
+ for zig := 1; zig < blockSize; zig++ {
+ ac := div(b[unzig[zig]], (8 * int(e.quant[q][zig])))
if ac == 0 {
runLength++
} else {
@@ -433,10 +436,12 @@ func scale(dst *block, src *[4]block) {
// - component 1 uses DC table 0 and AC table 0 "\x01\x00",
// - component 2 uses DC table 1 and AC table 1 "\x02\x11",
// - component 3 uses DC table 1 and AC table 1 "\x03\x11",
-// - padding "\x00\x00\x00".
+// - the bytes "\x00\x3f\x00". Section B.2.3 of the spec says that for
+// sequential DCTs, those bytes (8-bit Ss, 8-bit Se, 4-bit Ah, 4-bit Al)
+// should be 0x00, 0x3f, 0x00<<4 | 0x00.
var sosHeader = []byte{
0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
- 0x11, 0x03, 0x11, 0x00, 0x00, 0x00,
+ 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
}
// writeSOS writes the StartOfScan marker.
@@ -444,6 +449,7 @@ func (e *encoder) writeSOS(m image.Image) {
e.write(sosHeader)
var (
// Scratch buffers to hold the YCbCr values.
+ // The blocks are in natural (not zig-zag) order.
yBlock block
cbBlock [4]block
crBlock [4]block
diff --git a/libgo/go/image/jpeg/writer_test.go b/libgo/go/image/jpeg/writer_test.go
index b8e8fa34e18..8732df8459a 100644
--- a/libgo/go/image/jpeg/writer_test.go
+++ b/libgo/go/image/jpeg/writer_test.go
@@ -6,6 +6,7 @@ package jpeg
import (
"bytes"
+ "fmt"
"image"
"image/color"
"image/png"
@@ -15,6 +16,87 @@ import (
"testing"
)
+// zigzag maps from the natural ordering to the zig-zag ordering. For example,
+// zigzag[0*8 + 3] is the zig-zag sequence number of the element in the fourth
+// column and first row.
+var zigzag = [blockSize]int{
+ 0, 1, 5, 6, 14, 15, 27, 28,
+ 2, 4, 7, 13, 16, 26, 29, 42,
+ 3, 8, 12, 17, 25, 30, 41, 43,
+ 9, 11, 18, 24, 31, 40, 44, 53,
+ 10, 19, 23, 32, 39, 45, 52, 54,
+ 20, 22, 33, 38, 46, 51, 55, 60,
+ 21, 34, 37, 47, 50, 56, 59, 61,
+ 35, 36, 48, 49, 57, 58, 62, 63,
+}
+
+func TestZigUnzig(t *testing.T) {
+ for i := 0; i < blockSize; i++ {
+ if unzig[zigzag[i]] != i {
+ t.Errorf("unzig[zigzag[%d]] == %d", i, unzig[zigzag[i]])
+ }
+ if zigzag[unzig[i]] != i {
+ t.Errorf("zigzag[unzig[%d]] == %d", i, zigzag[unzig[i]])
+ }
+ }
+}
+
+// unscaledQuantInNaturalOrder are the unscaled quantization tables in
+// natural (not zig-zag) order, as specified in section K.1.
+var unscaledQuantInNaturalOrder = [nQuantIndex][blockSize]byte{
+ // Luminance.
+ {
+ 16, 11, 10, 16, 24, 40, 51, 61,
+ 12, 12, 14, 19, 26, 58, 60, 55,
+ 14, 13, 16, 24, 40, 57, 69, 56,
+ 14, 17, 22, 29, 51, 87, 80, 62,
+ 18, 22, 37, 56, 68, 109, 103, 77,
+ 24, 35, 55, 64, 81, 104, 113, 92,
+ 49, 64, 78, 87, 103, 121, 120, 101,
+ 72, 92, 95, 98, 112, 100, 103, 99,
+ },
+ // Chrominance.
+ {
+ 17, 18, 24, 47, 99, 99, 99, 99,
+ 18, 21, 26, 66, 99, 99, 99, 99,
+ 24, 26, 56, 99, 99, 99, 99, 99,
+ 47, 66, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ },
+}
+
+func TestUnscaledQuant(t *testing.T) {
+ bad := false
+ for i := quantIndex(0); i < nQuantIndex; i++ {
+ for zig := 0; zig < blockSize; zig++ {
+ got := unscaledQuant[i][zig]
+ want := unscaledQuantInNaturalOrder[i][unzig[zig]]
+ if got != want {
+ t.Errorf("i=%d, zig=%d: got %d, want %d", i, zig, got, want)
+ bad = true
+ }
+ }
+ }
+ if bad {
+ names := [nQuantIndex]string{"Luminance", "Chrominance"}
+ buf := &bytes.Buffer{}
+ for i, name := range names {
+ fmt.Fprintf(buf, "// %s.\n{\n", name)
+ for zig := 0; zig < blockSize; zig++ {
+ fmt.Fprintf(buf, "%d, ", unscaledQuantInNaturalOrder[i][unzig[zig]])
+ if zig%8 == 7 {
+ buf.WriteString("\n")
+ }
+ }
+ buf.WriteString("},\n")
+ }
+ t.Logf("expected unscaledQuant values:\n%s", buf.String())
+ }
+}
+
var testCase = []struct {
filename string
quality int
diff --git a/libgo/go/image/names.go b/libgo/go/image/names.go
index 55f634c17c1..04ee2cfb47c 100644
--- a/libgo/go/image/names.go
+++ b/libgo/go/image/names.go
@@ -20,7 +20,7 @@ var (
)
// Uniform is an infinite-sized Image of uniform color.
-// It implements the color.Color, color.ColorModel, and Image interfaces.
+// It implements the color.Color, color.Model, and Image interfaces.
type Uniform struct {
C color.Color
}
diff --git a/libgo/go/io/io.go b/libgo/go/io/io.go
index 54bf159eb41..5187eff70a9 100644
--- a/libgo/go/io/io.go
+++ b/libgo/go/io/io.go
@@ -130,11 +130,23 @@ type ReadWriteSeeker interface {
}
// ReaderFrom is the interface that wraps the ReadFrom method.
+//
+// ReadFrom reads data from r until EOF or error.
+// The return value n is the number of bytes read.
+// Any error except io.EOF encountered during the read is also returned.
+//
+// The Copy function uses ReaderFrom if available.
type ReaderFrom interface {
ReadFrom(r Reader) (n int64, err error)
}
// WriterTo is the interface that wraps the WriteTo method.
+//
+// WriteTo writes data to w until there's no more data to write or
+// when an error occurs. The return value n is the number of bytes
+// written. Any error encountered during the write is also returned.
+//
+// The Copy function uses WriterTo if available.
type WriterTo interface {
WriteTo(w Writer) (n int64, err error)
}
diff --git a/libgo/go/log/syslog/syslog.go b/libgo/go/log/syslog/syslog.go
index f53310cb0a1..e5620e1aa2a 100644
--- a/libgo/go/log/syslog/syslog.go
+++ b/libgo/go/log/syslog/syslog.go
@@ -138,7 +138,11 @@ func (w *Writer) Debug(m string) (err error) {
}
func (n netConn) writeBytes(p Priority, prefix string, b []byte) (int, error) {
- _, err := fmt.Fprintf(n.conn, "<%d>%s: %s\n", p, prefix, b)
+ nl := ""
+ if len(b) == 0 || b[len(b)-1] != '\n' {
+ nl = "\n"
+ }
+ _, err := fmt.Fprintf(n.conn, "<%d>%s: %s%s", p, prefix, b, nl)
if err != nil {
return 0, err
}
@@ -146,7 +150,11 @@ func (n netConn) writeBytes(p Priority, prefix string, b []byte) (int, error) {
}
func (n netConn) writeString(p Priority, prefix string, s string) (int, error) {
- _, err := fmt.Fprintf(n.conn, "<%d>%s: %s\n", p, prefix, s)
+ nl := ""
+ if len(s) == 0 || s[len(s)-1] != '\n' {
+ nl = "\n"
+ }
+ _, err := fmt.Fprintf(n.conn, "<%d>%s: %s%s", p, prefix, s, nl)
if err != nil {
return 0, err
}
diff --git a/libgo/go/log/syslog/syslog_test.go b/libgo/go/log/syslog/syslog_test.go
index 0fd6239059a..b7579c363d3 100644
--- a/libgo/go/log/syslog/syslog_test.go
+++ b/libgo/go/log/syslog/syslog_test.go
@@ -98,20 +98,32 @@ func TestUDPDial(t *testing.T) {
}
func TestWrite(t *testing.T) {
- done := make(chan string)
- startServer(done)
- l, err := Dial("udp", serverAddr, LOG_ERR, "syslog_test")
- if err != nil {
- t.Fatalf("syslog.Dial() failed: %s", err)
+ tests := []struct {
+ pri Priority
+ pre string
+ msg string
+ exp string
+ }{
+ {LOG_ERR, "syslog_test", "", "<3>syslog_test: \n"},
+ {LOG_ERR, "syslog_test", "write test", "<3>syslog_test: write test\n"},
+ // Write should not add \n if there already is one
+ {LOG_ERR, "syslog_test", "write test 2\n", "<3>syslog_test: write test 2\n"},
}
- msg := "write test"
- _, err = io.WriteString(l, msg)
- if err != nil {
- t.Fatalf("WriteString() failed: %s", err)
- }
- expected := "<3>syslog_test: write test\n"
- rcvd := <-done
- if rcvd != expected {
- t.Fatalf("s.Info() = '%q', but wanted '%q'", rcvd, expected)
+
+ for _, test := range tests {
+ done := make(chan string)
+ startServer(done)
+ l, err := Dial("udp", serverAddr, test.pri, test.pre)
+ if err != nil {
+ t.Fatalf("syslog.Dial() failed: %s", err)
+ }
+ _, err = io.WriteString(l, test.msg)
+ if err != nil {
+ t.Fatalf("WriteString() failed: %s", err)
+ }
+ rcvd := <-done
+ if rcvd != test.exp {
+ t.Fatalf("s.Info() = '%q', but wanted '%q'", rcvd, test.exp)
+ }
}
}
diff --git a/libgo/go/math/all_test.go b/libgo/go/math/all_test.go
index ed66a42fb00..35c33ce3859 100644
--- a/libgo/go/math/all_test.go
+++ b/libgo/go/math/all_test.go
@@ -1693,6 +1693,17 @@ func alike(a, b float64) bool {
return false
}
+func TestNaN(t *testing.T) {
+ f64 := NaN()
+ if f64 == f64 {
+ t.Fatalf("NaN() returns %g, expected NaN", f64)
+ }
+ f32 := float32(f64)
+ if f32 == f32 {
+ t.Fatalf("float32(NaN()) is %g, expected NaN", f32)
+ }
+}
+
func TestAcos(t *testing.T) {
for i := 0; i < len(vf); i++ {
a := vf[i] / 10
diff --git a/libgo/go/math/big/nat.go b/libgo/go/math/big/nat.go
index eaa6ff0666c..6d81823bb4a 100644
--- a/libgo/go/math/big/nat.go
+++ b/libgo/go/math/big/nat.go
@@ -396,7 +396,7 @@ func (z nat) mul(x, y nat) nat {
}
// use basic multiplication if the numbers are small
- if n < karatsubaThreshold || n < 2 {
+ if n < karatsubaThreshold {
z = z.make(m + n)
basicMul(z, x, y)
return z.norm()
diff --git a/libgo/go/math/bits.go b/libgo/go/math/bits.go
index 1cf60ce7df2..0df0b1cc9f1 100644
--- a/libgo/go/math/bits.go
+++ b/libgo/go/math/bits.go
@@ -5,7 +5,7 @@
package math
const (
- uvnan = 0x7FF0000000000001
+ uvnan = 0x7FF8000000000001
uvinf = 0x7FF0000000000000
uvneginf = 0xFFF0000000000000
mask = 0x7FF
diff --git a/libgo/go/math/remainder.go b/libgo/go/math/remainder.go
index a233e8ef188..98bb04dc794 100644
--- a/libgo/go/math/remainder.go
+++ b/libgo/go/math/remainder.go
@@ -4,7 +4,7 @@
package math
-// The original C code and the the comment below are from
+// The original C code and the comment below are from
// FreeBSD's /usr/src/lib/msun/src/e_remainder.c and came
// with this notice. The go code is a simplified version of
// the original C.
diff --git a/libgo/go/mime/grammar.go b/libgo/go/mime/grammar.go
index 83cc411343f..09e941e3ec0 100644
--- a/libgo/go/mime/grammar.go
+++ b/libgo/go/mime/grammar.go
@@ -22,7 +22,7 @@ func isTokenChar(r rune) bool {
return r > 0x20 && r < 0x7f && !isTSpecial(r)
}
-// isToken returns true if s is a 'token' as as defined by RFC 1521
+// isToken returns true if s is a 'token' as defined by RFC 1521
// and RFC 2045.
func isToken(s string) bool {
if s == "" {
diff --git a/libgo/go/mime/multipart/multipart.go b/libgo/go/mime/multipart/multipart.go
index e9e337b9222..fb07e1a56d5 100644
--- a/libgo/go/mime/multipart/multipart.go
+++ b/libgo/go/mime/multipart/multipart.go
@@ -71,7 +71,7 @@ func (p *Part) parseContentDisposition() {
}
}
-// NewReader creates a new multipart Reader reading from r using the
+// NewReader creates a new multipart Reader reading from reader using the
// given MIME boundary.
func NewReader(reader io.Reader, boundary string) *Reader {
b := []byte("\r\n--" + boundary + "--")
diff --git a/libgo/go/net/dial.go b/libgo/go/net/dial.go
index 10ca5faf707..51912397a46 100644
--- a/libgo/go/net/dial.go
+++ b/libgo/go/net/dial.go
@@ -173,7 +173,7 @@ func (a stringAddr) String() string { return a.addr }
// Listen announces on the local network address laddr.
// The network string net must be a stream-oriented network:
-// "tcp", "tcp4", "tcp6", or "unix", or "unixpacket".
+// "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
func Listen(net, laddr string) (Listener, error) {
afnet, a, err := resolveNetAddr("listen", net, laddr)
if err != nil {
diff --git a/libgo/go/net/fd.go b/libgo/go/net/fd.go
index 76c953b9b4e..ff4f4f899e5 100644
--- a/libgo/go/net/fd.go
+++ b/libgo/go/net/fd.go
@@ -645,10 +645,14 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err e
}
func (fd *netFD) dup() (f *os.File, err error) {
+ syscall.ForkLock.RLock()
ns, err := syscall.Dup(fd.sysfd)
if err != nil {
+ syscall.ForkLock.RUnlock()
return nil, &OpError{"dup", fd.net, fd.laddr, err}
}
+ syscall.CloseOnExec(ns)
+ syscall.ForkLock.RUnlock()
// We want blocking mode for the new fd, hence the double negative.
if err = syscall.SetNonblock(ns, false); err != nil {
diff --git a/libgo/go/net/file.go b/libgo/go/net/file.go
index fc6c6fad8e1..837326e12e6 100644
--- a/libgo/go/net/file.go
+++ b/libgo/go/net/file.go
@@ -12,13 +12,18 @@ import (
)
func newFileFD(f *os.File) (*netFD, error) {
+ syscall.ForkLock.RLock()
fd, err := syscall.Dup(int(f.Fd()))
if err != nil {
+ syscall.ForkLock.RUnlock()
return nil, os.NewSyscallError("dup", err)
}
+ syscall.CloseOnExec(fd)
+ syscall.ForkLock.RUnlock()
- proto, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
+ sotype, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE)
if err != nil {
+ closesocket(fd)
return nil, os.NewSyscallError("getsockopt", err)
}
@@ -31,24 +36,24 @@ func newFileFD(f *os.File) (*netFD, error) {
return nil, syscall.EINVAL
case *syscall.SockaddrInet4:
family = syscall.AF_INET
- if proto == syscall.SOCK_DGRAM {
+ if sotype == syscall.SOCK_DGRAM {
toAddr = sockaddrToUDP
- } else if proto == syscall.SOCK_RAW {
+ } else if sotype == syscall.SOCK_RAW {
toAddr = sockaddrToIP
}
case *syscall.SockaddrInet6:
family = syscall.AF_INET6
- if proto == syscall.SOCK_DGRAM {
+ if sotype == syscall.SOCK_DGRAM {
toAddr = sockaddrToUDP
- } else if proto == syscall.SOCK_RAW {
+ } else if sotype == syscall.SOCK_RAW {
toAddr = sockaddrToIP
}
case *syscall.SockaddrUnix:
family = syscall.AF_UNIX
toAddr = sockaddrToUnix
- if proto == syscall.SOCK_DGRAM {
+ if sotype == syscall.SOCK_DGRAM {
toAddr = sockaddrToUnixgram
- } else if proto == syscall.SOCK_SEQPACKET {
+ } else if sotype == syscall.SOCK_SEQPACKET {
toAddr = sockaddrToUnixpacket
}
}
@@ -56,8 +61,9 @@ func newFileFD(f *os.File) (*netFD, error) {
sa, _ = syscall.Getpeername(fd)
raddr := toAddr(sa)
- netfd, err := newFD(fd, family, proto, laddr.Network())
+ netfd, err := newFD(fd, family, sotype, laddr.Network())
if err != nil {
+ closesocket(fd)
return nil, err
}
netfd.setAddr(laddr, raddr)
diff --git a/libgo/go/net/http/client.go b/libgo/go/net/http/client.go
index 54564e0989e..89441424e1d 100644
--- a/libgo/go/net/http/client.go
+++ b/libgo/go/net/http/client.go
@@ -14,6 +14,7 @@ import (
"errors"
"fmt"
"io"
+ "log"
"net/url"
"strings"
)
@@ -35,7 +36,8 @@ type Client struct {
// following an HTTP redirect. The arguments req and via
// are the upcoming request and the requests made already,
// oldest first. If CheckRedirect returns an error, the client
- // returns that error instead of issue the Request req.
+ // returns that error (wrapped in a url.Error) instead of
+ // issuing the Request req.
//
// If CheckRedirect is nil, the Client uses its default policy,
// which is to stop after 10 consecutive requests.
@@ -87,9 +89,13 @@ type readClose struct {
// Do sends an HTTP request and returns an HTTP response, following
// policy (e.g. redirects, cookies, auth) as configured on the client.
//
-// A non-nil response always contains a non-nil resp.Body.
+// An error is returned if caused by client policy (such as
+// CheckRedirect), or if there was an HTTP protocol error.
+// A non-2xx response doesn't cause an error.
//
-// Callers should close resp.Body when done reading from it. If
+// When err is nil, resp always contains a non-nil resp.Body.
+//
+// Callers should close res.Body when done reading from it. If
// resp.Body is not closed, the Client's underlying RoundTripper
// (typically Transport) may not be able to re-use a persistent TCP
// connection to the server for a subsequent "keep-alive" request.
@@ -102,7 +108,8 @@ func (c *Client) Do(req *Request) (resp *Response, err error) {
return send(req, c.Transport)
}
-// send issues an HTTP request. Caller should close resp.Body when done reading from it.
+// send issues an HTTP request.
+// Caller should close resp.Body when done reading from it.
func send(req *Request, t RoundTripper) (resp *Response, err error) {
if t == nil {
t = DefaultTransport
@@ -130,7 +137,14 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
if u := req.URL.User; u != nil {
req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(u.String())))
}
- return t.RoundTrip(req)
+ resp, err = t.RoundTrip(req)
+ if err != nil {
+ if resp != nil {
+ log.Printf("RoundTripper returned a response & error; ignoring response")
+ }
+ return nil, err
+ }
+ return resp, nil
}
// True if the specified HTTP status code is one for which the Get utility should
@@ -151,10 +165,15 @@ func shouldRedirect(statusCode int) bool {
// 303 (See Other)
// 307 (Temporary Redirect)
//
-// Caller should close r.Body when done reading from it.
+// An error is returned if there were too many redirects or if there
+// was an HTTP protocol error. A non-2xx response doesn't cause an
+// error.
+//
+// When err is nil, resp always contains a non-nil resp.Body.
+// Caller should close resp.Body when done reading from it.
//
// Get is a wrapper around DefaultClient.Get.
-func Get(url string) (r *Response, err error) {
+func Get(url string) (resp *Response, err error) {
return DefaultClient.Get(url)
}
@@ -167,8 +186,13 @@ func Get(url string) (r *Response, err error) {
// 303 (See Other)
// 307 (Temporary Redirect)
//
-// Caller should close r.Body when done reading from it.
-func (c *Client) Get(url string) (r *Response, err error) {
+// An error is returned if the Client's CheckRedirect function fails
+// or if there was an HTTP protocol error. A non-2xx response doesn't
+// cause an error.
+//
+// When err is nil, resp always contains a non-nil resp.Body.
+// Caller should close resp.Body when done reading from it.
+func (c *Client) Get(url string) (resp *Response, err error) {
req, err := NewRequest("GET", url, nil)
if err != nil {
return nil, err
@@ -176,7 +200,7 @@ func (c *Client) Get(url string) (r *Response, err error) {
return c.doFollowingRedirects(req)
}
-func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err error) {
+func (c *Client) doFollowingRedirects(ireq *Request) (resp *Response, err error) {
// TODO: if/when we add cookie support, the redirected request shouldn't
// necessarily supply the same cookies as the original.
var base *url.URL
@@ -224,17 +248,17 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err error) {
req.AddCookie(cookie)
}
urlStr = req.URL.String()
- if r, err = send(req, c.Transport); err != nil {
+ if resp, err = send(req, c.Transport); err != nil {
break
}
- if c := r.Cookies(); len(c) > 0 {
+ if c := resp.Cookies(); len(c) > 0 {
jar.SetCookies(req.URL, c)
}
- if shouldRedirect(r.StatusCode) {
- r.Body.Close()
- if urlStr = r.Header.Get("Location"); urlStr == "" {
- err = errors.New(fmt.Sprintf("%d response missing Location header", r.StatusCode))
+ if shouldRedirect(resp.StatusCode) {
+ resp.Body.Close()
+ if urlStr = resp.Header.Get("Location"); urlStr == "" {
+ err = errors.New(fmt.Sprintf("%d response missing Location header", resp.StatusCode))
break
}
base = req.URL
@@ -244,13 +268,16 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err error) {
return
}
+ if resp != nil {
+ resp.Body.Close()
+ }
+
method := ireq.Method
- err = &url.Error{
+ return nil, &url.Error{
Op: method[0:1] + strings.ToLower(method[1:]),
URL: urlStr,
Err: err,
}
- return
}
func defaultCheckRedirect(req *Request, via []*Request) error {
@@ -262,17 +289,17 @@ func defaultCheckRedirect(req *Request, via []*Request) error {
// Post issues a POST to the specified URL.
//
-// Caller should close r.Body when done reading from it.
+// Caller should close resp.Body when done reading from it.
//
// Post is a wrapper around DefaultClient.Post
-func Post(url string, bodyType string, body io.Reader) (r *Response, err error) {
+func Post(url string, bodyType string, body io.Reader) (resp *Response, err error) {
return DefaultClient.Post(url, bodyType, body)
}
// Post issues a POST to the specified URL.
//
-// Caller should close r.Body when done reading from it.
-func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response, err error) {
+// Caller should close resp.Body when done reading from it.
+func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *Response, err error) {
req, err := NewRequest("POST", url, body)
if err != nil {
return nil, err
@@ -283,28 +310,30 @@ func (c *Client) Post(url string, bodyType string, body io.Reader) (r *Response,
req.AddCookie(cookie)
}
}
- r, err = send(req, c.Transport)
+ resp, err = send(req, c.Transport)
if err == nil && c.Jar != nil {
- c.Jar.SetCookies(req.URL, r.Cookies())
+ c.Jar.SetCookies(req.URL, resp.Cookies())
}
- return r, err
+ return
}
-// PostForm issues a POST to the specified URL,
-// with data's keys and values urlencoded as the request body.
+// PostForm issues a POST to the specified URL, with data's keys and
+// values URL-encoded as the request body.
//
-// Caller should close r.Body when done reading from it.
+// When err is nil, resp always contains a non-nil resp.Body.
+// Caller should close resp.Body when done reading from it.
//
// PostForm is a wrapper around DefaultClient.PostForm
-func PostForm(url string, data url.Values) (r *Response, err error) {
+func PostForm(url string, data url.Values) (resp *Response, err error) {
return DefaultClient.PostForm(url, data)
}
// PostForm issues a POST to the specified URL,
// with data's keys and values urlencoded as the request body.
//
-// Caller should close r.Body when done reading from it.
-func (c *Client) PostForm(url string, data url.Values) (r *Response, err error) {
+// When err is nil, resp always contains a non-nil resp.Body.
+// Caller should close resp.Body when done reading from it.
+func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) {
return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}
@@ -318,7 +347,7 @@ func (c *Client) PostForm(url string, data url.Values) (r *Response, err error)
// 307 (Temporary Redirect)
//
// Head is a wrapper around DefaultClient.Head
-func Head(url string) (r *Response, err error) {
+func Head(url string) (resp *Response, err error) {
return DefaultClient.Head(url)
}
@@ -330,7 +359,7 @@ func Head(url string) (r *Response, err error) {
// 302 (Found)
// 303 (See Other)
// 307 (Temporary Redirect)
-func (c *Client) Head(url string) (r *Response, err error) {
+func (c *Client) Head(url string) (resp *Response, err error) {
req, err := NewRequest("HEAD", url, nil)
if err != nil {
return nil, err
diff --git a/libgo/go/net/http/client_test.go b/libgo/go/net/http/client_test.go
index 9b4261b9f61..09fcc1c0b40 100644
--- a/libgo/go/net/http/client_test.go
+++ b/libgo/go/net/http/client_test.go
@@ -8,6 +8,7 @@ package http_test
import (
"crypto/tls"
+ "crypto/x509"
"errors"
"fmt"
"io"
@@ -231,9 +232,8 @@ func TestRedirects(t *testing.T) {
checkErr = errors.New("no redirects allowed")
res, err = c.Get(ts.URL)
- finalUrl = res.Request.URL.String()
- if e, g := "Get /?n=1: no redirects allowed", fmt.Sprintf("%v", err); e != g {
- t.Errorf("with redirects forbidden, expected error %q, got %q", e, g)
+ if urlError, ok := err.(*url.Error); !ok || urlError.Err != checkErr {
+ t.Errorf("with redirects forbidden, expected a *url.Error with our 'no redirects allowed' error inside; got %#v (%q)", err, err)
}
}
@@ -465,3 +465,49 @@ func TestClientErrorWithRequestURI(t *testing.T) {
t.Errorf("wanted error mentioning RequestURI; got error: %v", err)
}
}
+
+func newTLSTransport(t *testing.T, ts *httptest.Server) *Transport {
+ certs := x509.NewCertPool()
+ for _, c := range ts.TLS.Certificates {
+ roots, err := x509.ParseCertificates(c.Certificate[len(c.Certificate)-1])
+ if err != nil {
+ t.Fatalf("error parsing server's root cert: %v", err)
+ }
+ for _, root := range roots {
+ certs.AddCert(root)
+ }
+ }
+ return &Transport{
+ TLSClientConfig: &tls.Config{RootCAs: certs},
+ }
+}
+
+func TestClientWithCorrectTLSServerName(t *testing.T) {
+ ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ if r.TLS.ServerName != "127.0.0.1" {
+ t.Errorf("expected client to set ServerName 127.0.0.1, got: %q", r.TLS.ServerName)
+ }
+ }))
+ defer ts.Close()
+
+ c := &Client{Transport: newTLSTransport(t, ts)}
+ if _, err := c.Get(ts.URL); err != nil {
+ t.Fatalf("expected successful TLS connection, got error: %v", err)
+ }
+}
+
+func TestClientWithIncorrectTLSServerName(t *testing.T) {
+ ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+ defer ts.Close()
+
+ trans := newTLSTransport(t, ts)
+ trans.TLSClientConfig.ServerName = "badserver"
+ c := &Client{Transport: trans}
+ _, err := c.Get(ts.URL)
+ if err == nil {
+ t.Fatalf("expected an error")
+ }
+ if !strings.Contains(err.Error(), "127.0.0.1") || !strings.Contains(err.Error(), "badserver") {
+ t.Errorf("wanted error mentioning 127.0.0.1 and badserver; got error: %v", err)
+ }
+}
diff --git a/libgo/go/net/http/example_test.go b/libgo/go/net/http/example_test.go
index ec814407ddb..22073eaf7aa 100644
--- a/libgo/go/net/http/example_test.go
+++ b/libgo/go/net/http/example_test.go
@@ -43,10 +43,10 @@ func ExampleGet() {
log.Fatal(err)
}
robots, err := ioutil.ReadAll(res.Body)
+ res.Body.Close()
if err != nil {
log.Fatal(err)
}
- res.Body.Close()
fmt.Printf("%s", robots)
}
diff --git a/libgo/go/net/http/export_test.go b/libgo/go/net/http/export_test.go
index 13640ca85ee..313c6af7a82 100644
--- a/libgo/go/net/http/export_test.go
+++ b/libgo/go/net/http/export_test.go
@@ -11,8 +11,8 @@ import "time"
func (t *Transport) IdleConnKeysForTesting() (keys []string) {
keys = make([]string, 0)
- t.lk.Lock()
- defer t.lk.Unlock()
+ t.idleLk.Lock()
+ defer t.idleLk.Unlock()
if t.idleConn == nil {
return
}
@@ -23,8 +23,8 @@ func (t *Transport) IdleConnKeysForTesting() (keys []string) {
}
func (t *Transport) IdleConnCountForTesting(cacheKey string) int {
- t.lk.Lock()
- defer t.lk.Unlock()
+ t.idleLk.Lock()
+ defer t.idleLk.Unlock()
if t.idleConn == nil {
return 0
}
diff --git a/libgo/go/net/http/fs.go b/libgo/go/net/http/fs.go
index f35dd32c305..208d6cabb2c 100644
--- a/libgo/go/net/http/fs.go
+++ b/libgo/go/net/http/fs.go
@@ -11,6 +11,8 @@ import (
"fmt"
"io"
"mime"
+ "mime/multipart"
+ "net/textproto"
"os"
"path"
"path/filepath"
@@ -26,7 +28,8 @@ import (
type Dir string
func (d Dir) Open(name string) (File, error) {
- if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 {
+ if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
+ strings.Contains(name, "\x00") {
return nil, errors.New("http: invalid character in file path")
}
dir := string(d)
@@ -123,8 +126,9 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
code := StatusOK
// If Content-Type isn't set, use the file's extension to find it.
- if w.Header().Get("Content-Type") == "" {
- ctype := mime.TypeByExtension(filepath.Ext(name))
+ ctype := w.Header().Get("Content-Type")
+ if ctype == "" {
+ ctype = mime.TypeByExtension(filepath.Ext(name))
if ctype == "" {
// read a chunk to decide between utf-8 text and binary
var buf [1024]byte
@@ -141,18 +145,34 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
}
// handle Content-Range header.
- // TODO(adg): handle multiple ranges
sendSize := size
+ var sendContent io.Reader = content
if size >= 0 {
ranges, err := parseRange(r.Header.Get("Range"), size)
- if err == nil && len(ranges) > 1 {
- err = errors.New("multiple ranges not supported")
- }
if err != nil {
Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
return
}
- if len(ranges) == 1 {
+ if sumRangesSize(ranges) >= size {
+ // The total number of bytes in all the ranges
+ // is larger than the size of the file by
+ // itself, so this is probably an attack, or a
+ // dumb client. Ignore the range request.
+ ranges = nil
+ }
+ switch {
+ case len(ranges) == 1:
+ // RFC 2616, Section 14.16:
+ // "When an HTTP message includes the content of a single
+ // range (for example, a response to a request for a
+ // single range, or to a request for a set of ranges
+ // that overlap without any holes), this content is
+ // transmitted with a Content-Range header, and a
+ // Content-Length header showing the number of bytes
+ // actually transferred.
+ // ...
+ // A response to a request for a single range MUST NOT
+ // be sent using the multipart/byteranges media type."
ra := ranges[0]
if _, err := content.Seek(ra.start, os.SEEK_SET); err != nil {
Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
@@ -160,7 +180,41 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
}
sendSize = ra.length
code = StatusPartialContent
- w.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", ra.start, ra.start+ra.length-1, size))
+ w.Header().Set("Content-Range", ra.contentRange(size))
+ case len(ranges) > 1:
+ for _, ra := range ranges {
+ if ra.start > size {
+ Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
+ return
+ }
+ }
+ sendSize = rangesMIMESize(ranges, ctype, size)
+ code = StatusPartialContent
+
+ pr, pw := io.Pipe()
+ mw := multipart.NewWriter(pw)
+ w.Header().Set("Content-Type", "multipart/byteranges; boundary="+mw.Boundary())
+ sendContent = pr
+ defer pr.Close() // cause writing goroutine to fail and exit if CopyN doesn't finish.
+ go func() {
+ for _, ra := range ranges {
+ part, err := mw.CreatePart(ra.mimeHeader(ctype, size))
+ if err != nil {
+ pw.CloseWithError(err)
+ return
+ }
+ if _, err := content.Seek(ra.start, os.SEEK_SET); err != nil {
+ pw.CloseWithError(err)
+ return
+ }
+ if _, err := io.CopyN(part, content, ra.length); err != nil {
+ pw.CloseWithError(err)
+ return
+ }
+ }
+ mw.Close()
+ pw.Close()
+ }()
}
w.Header().Set("Accept-Ranges", "bytes")
@@ -172,11 +226,7 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
w.WriteHeader(code)
if r.Method != "HEAD" {
- if sendSize == -1 {
- io.Copy(w, content)
- } else {
- io.CopyN(w, content, sendSize)
- }
+ io.CopyN(w, sendContent, sendSize)
}
}
@@ -243,9 +293,6 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
// use contents of index.html for directory, if present
if d.IsDir() {
- if checkLastModified(w, r, d.ModTime()) {
- return
- }
index := name + indexPage
ff, err := fs.Open(index)
if err == nil {
@@ -259,11 +306,16 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
}
}
+ // Still a directory? (we didn't find an index.html file)
if d.IsDir() {
+ if checkLastModified(w, r, d.ModTime()) {
+ return
+ }
dirList(w, f)
return
}
+ // serverContent will check modification time
serveContent(w, r, d.Name(), d.ModTime(), d.Size(), f)
}
@@ -312,6 +364,17 @@ type httpRange struct {
start, length int64
}
+func (r httpRange) contentRange(size int64) string {
+ return fmt.Sprintf("bytes %d-%d/%d", r.start, r.start+r.length-1, size)
+}
+
+func (r httpRange) mimeHeader(contentType string, size int64) textproto.MIMEHeader {
+ return textproto.MIMEHeader{
+ "Content-Range": {r.contentRange(size)},
+ "Content-Type": {contentType},
+ }
+}
+
// parseRange parses a Range header string as per RFC 2616.
func parseRange(s string, size int64) ([]httpRange, error) {
if s == "" {
@@ -323,11 +386,15 @@ func parseRange(s string, size int64) ([]httpRange, error) {
}
var ranges []httpRange
for _, ra := range strings.Split(s[len(b):], ",") {
+ ra = strings.TrimSpace(ra)
+ if ra == "" {
+ continue
+ }
i := strings.Index(ra, "-")
if i < 0 {
return nil, errors.New("invalid range")
}
- start, end := ra[:i], ra[i+1:]
+ start, end := strings.TrimSpace(ra[:i]), strings.TrimSpace(ra[i+1:])
var r httpRange
if start == "" {
// If no start is specified, end specifies the
@@ -365,3 +432,32 @@ func parseRange(s string, size int64) ([]httpRange, error) {
}
return ranges, nil
}
+
+// countingWriter counts how many bytes have been written to it.
+type countingWriter int64
+
+func (w *countingWriter) Write(p []byte) (n int, err error) {
+ *w += countingWriter(len(p))
+ return len(p), nil
+}
+
+// rangesMIMESize returns the nunber of bytes it takes to encode the
+// provided ranges as a multipart response.
+func rangesMIMESize(ranges []httpRange, contentType string, contentSize int64) (encSize int64) {
+ var w countingWriter
+ mw := multipart.NewWriter(&w)
+ for _, ra := range ranges {
+ mw.CreatePart(ra.mimeHeader(contentType, contentSize))
+ encSize += ra.length
+ }
+ mw.Close()
+ encSize += int64(w)
+ return
+}
+
+func sumRangesSize(ranges []httpRange) (size int64) {
+ for _, ra := range ranges {
+ size += ra.length
+ }
+ return
+}
diff --git a/libgo/go/net/http/fs_test.go b/libgo/go/net/http/fs_test.go
index ffba6a7bcb7..17329fbd59a 100644
--- a/libgo/go/net/http/fs_test.go
+++ b/libgo/go/net/http/fs_test.go
@@ -10,12 +10,15 @@ import (
"fmt"
"io"
"io/ioutil"
+ "mime"
+ "mime/multipart"
"net"
. "net/http"
"net/http/httptest"
"net/url"
"os"
"os/exec"
+ "path"
"path/filepath"
"regexp"
"runtime"
@@ -25,21 +28,29 @@ import (
)
const (
- testFile = "testdata/file"
- testFileLength = 11
+ testFile = "testdata/file"
+ testFileLen = 11
)
+type wantRange struct {
+ start, end int64 // range [start,end)
+}
+
var ServeFileRangeTests = []struct {
- start, end int
- r string
- code int
+ r string
+ code int
+ ranges []wantRange
}{
- {0, testFileLength, "", StatusOK},
- {0, 5, "0-4", StatusPartialContent},
- {2, testFileLength, "2-", StatusPartialContent},
- {testFileLength - 5, testFileLength, "-5", StatusPartialContent},
- {3, 8, "3-7", StatusPartialContent},
- {0, 0, "20-", StatusRequestedRangeNotSatisfiable},
+ {r: "", code: StatusOK},
+ {r: "bytes=0-4", code: StatusPartialContent, ranges: []wantRange{{0, 5}}},
+ {r: "bytes=2-", code: StatusPartialContent, ranges: []wantRange{{2, testFileLen}}},
+ {r: "bytes=-5", code: StatusPartialContent, ranges: []wantRange{{testFileLen - 5, testFileLen}}},
+ {r: "bytes=3-7", code: StatusPartialContent, ranges: []wantRange{{3, 8}}},
+ {r: "bytes=20-", code: StatusRequestedRangeNotSatisfiable},
+ {r: "bytes=0-0,-2", code: StatusPartialContent, ranges: []wantRange{{0, 1}, {testFileLen - 2, testFileLen}}},
+ {r: "bytes=0-1,5-8", code: StatusPartialContent, ranges: []wantRange{{0, 2}, {5, 9}}},
+ {r: "bytes=0-1,5-", code: StatusPartialContent, ranges: []wantRange{{0, 2}, {5, testFileLen}}},
+ {r: "bytes=0-,1-,2-,3-,4-", code: StatusOK}, // ignore wasteful range request
}
func TestServeFile(t *testing.T) {
@@ -65,33 +76,81 @@ func TestServeFile(t *testing.T) {
// straight GET
_, body := getBody(t, "straight get", req)
- if !equal(body, file) {
+ if !bytes.Equal(body, file) {
t.Fatalf("body mismatch: got %q, want %q", body, file)
}
// Range tests
- for i, rt := range ServeFileRangeTests {
- req.Header.Set("Range", "bytes="+rt.r)
- if rt.r == "" {
- req.Header["Range"] = nil
+ for _, rt := range ServeFileRangeTests {
+ if rt.r != "" {
+ req.Header.Set("Range", rt.r)
}
- r, body := getBody(t, fmt.Sprintf("test %d", i), req)
- if r.StatusCode != rt.code {
- t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, r.StatusCode, rt.code)
+ resp, body := getBody(t, fmt.Sprintf("range test %q", rt.r), req)
+ if resp.StatusCode != rt.code {
+ t.Errorf("range=%q: StatusCode=%d, want %d", rt.r, resp.StatusCode, rt.code)
}
if rt.code == StatusRequestedRangeNotSatisfiable {
continue
}
- h := fmt.Sprintf("bytes %d-%d/%d", rt.start, rt.end-1, testFileLength)
- if rt.r == "" {
- h = ""
+ wantContentRange := ""
+ if len(rt.ranges) == 1 {
+ rng := rt.ranges[0]
+ wantContentRange = fmt.Sprintf("bytes %d-%d/%d", rng.start, rng.end-1, testFileLen)
+ }
+ cr := resp.Header.Get("Content-Range")
+ if cr != wantContentRange {
+ t.Errorf("range=%q: Content-Range = %q, want %q", rt.r, cr, wantContentRange)
}
- cr := r.Header.Get("Content-Range")
- if cr != h {
- t.Errorf("header mismatch: range=%q: got %q, want %q", rt.r, cr, h)
+ ct := resp.Header.Get("Content-Type")
+ if len(rt.ranges) == 1 {
+ rng := rt.ranges[0]
+ wantBody := file[rng.start:rng.end]
+ if !bytes.Equal(body, wantBody) {
+ t.Errorf("range=%q: body = %q, want %q", rt.r, body, wantBody)
+ }
+ if strings.HasPrefix(ct, "multipart/byteranges") {
+ t.Errorf("range=%q content-type = %q; unexpected multipart/byteranges", rt.r)
+ }
}
- if !equal(body, file[rt.start:rt.end]) {
- t.Errorf("body mismatch: range=%q: got %q, want %q", rt.r, body, file[rt.start:rt.end])
+ if len(rt.ranges) > 1 {
+ typ, params, err := mime.ParseMediaType(ct)
+ if err != nil {
+ t.Errorf("range=%q content-type = %q; %v", rt.r, ct, err)
+ continue
+ }
+ if typ != "multipart/byteranges" {
+ t.Errorf("range=%q content-type = %q; want multipart/byteranges", rt.r)
+ continue
+ }
+ if params["boundary"] == "" {
+ t.Errorf("range=%q content-type = %q; lacks boundary", rt.r, ct)
+ }
+ if g, w := resp.ContentLength, int64(len(body)); g != w {
+ t.Errorf("range=%q Content-Length = %d; want %d", rt.r, g, w)
+ }
+ mr := multipart.NewReader(bytes.NewReader(body), params["boundary"])
+ for ri, rng := range rt.ranges {
+ part, err := mr.NextPart()
+ if err != nil {
+ t.Fatalf("range=%q, reading part index %d: %v", rt.r, ri, err)
+ }
+ body, err := ioutil.ReadAll(part)
+ if err != nil {
+ t.Fatalf("range=%q, reading part index %d body: %v", rt.r, ri, err)
+ }
+ wantContentRange = fmt.Sprintf("bytes %d-%d/%d", rng.start, rng.end-1, testFileLen)
+ wantBody := file[rng.start:rng.end]
+ if !bytes.Equal(body, wantBody) {
+ t.Errorf("range=%q: body = %q, want %q", rt.r, body, wantBody)
+ }
+ if g, w := part.Header.Get("Content-Range"), wantContentRange; g != w {
+ t.Errorf("range=%q: part Content-Range = %q; want %q", rt.r, g, w)
+ }
+ }
+ _, err = mr.NextPart()
+ if err != io.EOF {
+ t.Errorf("range=%q; expected final error io.EOF; got %v", err)
+ }
}
}
}
@@ -276,6 +335,11 @@ func TestServeFileMimeType(t *testing.T) {
}
func TestServeFileFromCWD(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ // TODO(brainman): find out why this test is broken
+ t.Logf("Temporarily skipping test on Windows; see http://golang.org/issue/3917")
+ return
+ }
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
ServeFile(w, r, "fs_test.go")
}))
@@ -325,6 +389,139 @@ func TestServeIndexHtml(t *testing.T) {
}
}
+func TestFileServerZeroByte(t *testing.T) {
+ ts := httptest.NewServer(FileServer(Dir(".")))
+ defer ts.Close()
+
+ res, err := Get(ts.URL + "/..\x00")
+ if err != nil {
+ t.Fatal(err)
+ }
+ b, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal("reading Body:", err)
+ }
+ if res.StatusCode == 200 {
+ t.Errorf("got status 200; want an error. Body is:\n%s", string(b))
+ }
+}
+
+type fakeFileInfo struct {
+ dir bool
+ basename string
+ modtime time.Time
+ ents []*fakeFileInfo
+ contents string
+}
+
+func (f *fakeFileInfo) Name() string { return f.basename }
+func (f *fakeFileInfo) Sys() interface{} { return nil }
+func (f *fakeFileInfo) ModTime() time.Time { return f.modtime }
+func (f *fakeFileInfo) IsDir() bool { return f.dir }
+func (f *fakeFileInfo) Size() int64 { return int64(len(f.contents)) }
+func (f *fakeFileInfo) Mode() os.FileMode {
+ if f.dir {
+ return 0755 | os.ModeDir
+ }
+ return 0644
+}
+
+type fakeFile struct {
+ io.ReadSeeker
+ fi *fakeFileInfo
+ path string // as opened
+}
+
+func (f *fakeFile) Close() error { return nil }
+func (f *fakeFile) Stat() (os.FileInfo, error) { return f.fi, nil }
+func (f *fakeFile) Readdir(count int) ([]os.FileInfo, error) {
+ if !f.fi.dir {
+ return nil, os.ErrInvalid
+ }
+ var fis []os.FileInfo
+ for _, fi := range f.fi.ents {
+ fis = append(fis, fi)
+ }
+ return fis, nil
+}
+
+type fakeFS map[string]*fakeFileInfo
+
+func (fs fakeFS) Open(name string) (File, error) {
+ name = path.Clean(name)
+ f, ok := fs[name]
+ if !ok {
+ println("fake filesystem didn't find file", name)
+ return nil, os.ErrNotExist
+ }
+ return &fakeFile{ReadSeeker: strings.NewReader(f.contents), fi: f, path: name}, nil
+}
+
+func TestDirectoryIfNotModified(t *testing.T) {
+ const indexContents = "I am a fake index.html file"
+ fileMod := time.Unix(1000000000, 0).UTC()
+ fileModStr := fileMod.Format(TimeFormat)
+ dirMod := time.Unix(123, 0).UTC()
+ indexFile := &fakeFileInfo{
+ basename: "index.html",
+ modtime: fileMod,
+ contents: indexContents,
+ }
+ fs := fakeFS{
+ "/": &fakeFileInfo{
+ dir: true,
+ modtime: dirMod,
+ ents: []*fakeFileInfo{indexFile},
+ },
+ "/index.html": indexFile,
+ }
+
+ ts := httptest.NewServer(FileServer(fs))
+ defer ts.Close()
+
+ res, err := Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ b, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(b) != indexContents {
+ t.Fatalf("Got body %q; want %q", b, indexContents)
+ }
+ res.Body.Close()
+
+ lastMod := res.Header.Get("Last-Modified")
+ if lastMod != fileModStr {
+ t.Fatalf("initial Last-Modified = %q; want %q", lastMod, fileModStr)
+ }
+
+ req, _ := NewRequest("GET", ts.URL, nil)
+ req.Header.Set("If-Modified-Since", lastMod)
+
+ res, err = DefaultClient.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if res.StatusCode != 304 {
+ t.Fatalf("Code after If-Modified-Since request = %v; want 304", res.StatusCode)
+ }
+ res.Body.Close()
+
+ // Advance the index.html file's modtime, but not the directory's.
+ indexFile.modtime = indexFile.modtime.Add(1 * time.Hour)
+
+ res, err = DefaultClient.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if res.StatusCode != 200 {
+ t.Fatalf("Code after second If-Modified-Since request = %v; want 200; res is %#v", res.StatusCode, res)
+ }
+ res.Body.Close()
+}
+
func TestServeContent(t *testing.T) {
type req struct {
name string
@@ -464,15 +661,3 @@ func TestLinuxSendfileChild(*testing.T) {
panic(err)
}
}
-
-func equal(a, b []byte) bool {
- if len(a) != len(b) {
- return false
- }
- for i := range a {
- if a[i] != b[i] {
- return false
- }
- }
- return true
-}
diff --git a/libgo/go/net/http/header.go b/libgo/go/net/http/header.go
index b107c312da7..6be94f98e74 100644
--- a/libgo/go/net/http/header.go
+++ b/libgo/go/net/http/header.go
@@ -76,3 +76,43 @@ func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
// the rest are converted to lowercase. For example, the
// canonical key for "accept-encoding" is "Accept-Encoding".
func CanonicalHeaderKey(s string) string { return textproto.CanonicalMIMEHeaderKey(s) }
+
+// hasToken returns whether token appears with v, ASCII
+// case-insensitive, with space or comma boundaries.
+// token must be all lowercase.
+// v may contain mixed cased.
+func hasToken(v, token string) bool {
+ if len(token) > len(v) || token == "" {
+ return false
+ }
+ if v == token {
+ return true
+ }
+ for sp := 0; sp <= len(v)-len(token); sp++ {
+ // Check that first character is good.
+ // The token is ASCII, so checking only a single byte
+ // is sufficient. We skip this potential starting
+ // position if both the first byte and its potential
+ // ASCII uppercase equivalent (b|0x20) don't match.
+ // False positives ('^' => '~') are caught by EqualFold.
+ if b := v[sp]; b != token[0] && b|0x20 != token[0] {
+ continue
+ }
+ // Check that start pos is on a valid token boundary.
+ if sp > 0 && !isTokenBoundary(v[sp-1]) {
+ continue
+ }
+ // Check that end pos is on a valid token boundary.
+ if endPos := sp + len(token); endPos != len(v) && !isTokenBoundary(v[endPos]) {
+ continue
+ }
+ if strings.EqualFold(v[sp:sp+len(token)], token) {
+ return true
+ }
+ }
+ return false
+}
+
+func isTokenBoundary(b byte) bool {
+ return b == ' ' || b == ',' || b == '\t'
+}
diff --git a/libgo/go/net/http/httptest/server.go b/libgo/go/net/http/httptest/server.go
index 57cf0c9417d..165600e52be 100644
--- a/libgo/go/net/http/httptest/server.go
+++ b/libgo/go/net/http/httptest/server.go
@@ -184,15 +184,15 @@ func (h *waitGroupHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
// of ASN.1 time).
var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
-MIIBOTCB5qADAgECAgEAMAsGCSqGSIb3DQEBBTAAMB4XDTcwMDEwMTAwMDAwMFoX
+MIIBTTCB+qADAgECAgEAMAsGCSqGSIb3DQEBBTAAMB4XDTcwMDEwMTAwMDAwMFoX
DTQ5MTIzMTIzNTk1OVowADBaMAsGCSqGSIb3DQEBAQNLADBIAkEAsuA5mAFMj6Q7
qoBzcvKzIq4kzuT5epSp2AkcQfyBHm7K13Ws7u+0b5Vb9gqTf5cAiIKcrtrXVqkL
-8i1UQF6AzwIDAQABo08wTTAOBgNVHQ8BAf8EBAMCACQwDQYDVR0OBAYEBAECAwQw
-DwYDVR0jBAgwBoAEAQIDBDAbBgNVHREEFDASggkxMjcuMC4wLjGCBVs6OjFdMAsG
-CSqGSIb3DQEBBQNBAJH30zjLWRztrWpOCgJL8RQWLaKzhK79pVhAx6q/3NrF16C7
-+l1BRZstTwIGdoGId8BRpErK1TXkniFb95ZMynM=
------END CERTIFICATE-----
-`)
+8i1UQF6AzwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCACQwEgYDVR0TAQH/BAgwBgEB
+/wIBATANBgNVHQ4EBgQEAQIDBDAPBgNVHSMECDAGgAQBAgMEMBsGA1UdEQQUMBKC
+CTEyNy4wLjAuMYIFWzo6MV0wCwYJKoZIhvcNAQEFA0EAj1Jsn/h2KHy7dgqutZNB
+nCGlNN+8vw263Bax9MklR85Ti6a0VWSvp/fDQZUADvmFTDkcXeA24pqmdUxeQDWw
+Pg==
+-----END CERTIFICATE-----`)
// localhostKey is the private key for localhostCert.
var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
diff --git a/libgo/go/net/http/httputil/dump.go b/libgo/go/net/http/httputil/dump.go
index 892ef4eded0..0fb2eeb8c00 100644
--- a/libgo/go/net/http/httputil/dump.go
+++ b/libgo/go/net/http/httputil/dump.go
@@ -89,7 +89,7 @@ func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
t := &http.Transport{
Dial: func(net, addr string) (net.Conn, error) {
- return &dumpConn{io.MultiWriter(pw, &buf), dr}, nil
+ return &dumpConn{io.MultiWriter(&buf, pw), dr}, nil
},
}
diff --git a/libgo/go/net/http/pprof/pprof.go b/libgo/go/net/http/pprof/pprof.go
index b8874f35d2f..f578725d043 100644
--- a/libgo/go/net/http/pprof/pprof.go
+++ b/libgo/go/net/http/pprof/pprof.go
@@ -14,6 +14,14 @@
// To use pprof, link this package into your program:
// import _ "net/http/pprof"
//
+// If your application is not already running an http server, you
+// need to start one. Add "net/http" and "log" to your imports and
+// the following code to your main function:
+//
+// go func() {
+// log.Println(http.ListenAndServe("localhost:6060", nil))
+// }()
+//
// Then use the pprof tool to look at the heap profile:
//
// go tool pprof http://localhost:6060/debug/pprof/heap
diff --git a/libgo/go/net/http/range_test.go b/libgo/go/net/http/range_test.go
index 5274a81fa34..ef911af7b08 100644
--- a/libgo/go/net/http/range_test.go
+++ b/libgo/go/net/http/range_test.go
@@ -14,15 +14,34 @@ var ParseRangeTests = []struct {
r []httpRange
}{
{"", 0, nil},
+ {"", 1000, nil},
{"foo", 0, nil},
{"bytes=", 0, nil},
+ {"bytes=7", 10, nil},
+ {"bytes= 7 ", 10, nil},
+ {"bytes=1-", 0, nil},
{"bytes=5-4", 10, nil},
{"bytes=0-2,5-4", 10, nil},
+ {"bytes=2-5,4-3", 10, nil},
+ {"bytes=--5,4--3", 10, nil},
+ {"bytes=A-", 10, nil},
+ {"bytes=A- ", 10, nil},
+ {"bytes=A-Z", 10, nil},
+ {"bytes= -Z", 10, nil},
+ {"bytes=5-Z", 10, nil},
+ {"bytes=Ran-dom, garbage", 10, nil},
+ {"bytes=0x01-0x02", 10, nil},
+ {"bytes= ", 10, nil},
+ {"bytes= , , , ", 10, nil},
+
{"bytes=0-9", 10, []httpRange{{0, 10}}},
{"bytes=0-", 10, []httpRange{{0, 10}}},
{"bytes=5-", 10, []httpRange{{5, 5}}},
{"bytes=0-20", 10, []httpRange{{0, 10}}},
{"bytes=15-,0-5", 10, nil},
+ {"bytes=1-2,5-", 10, []httpRange{{1, 2}, {5, 5}}},
+ {"bytes=-2 , 7-", 11, []httpRange{{9, 2}, {7, 4}}},
+ {"bytes=0-0 ,2-2, 7-", 11, []httpRange{{0, 1}, {2, 1}, {7, 4}}},
{"bytes=-5", 10, []httpRange{{5, 5}}},
{"bytes=-15", 10, []httpRange{{0, 10}}},
{"bytes=0-499", 10000, []httpRange{{0, 500}}},
@@ -32,6 +51,9 @@ var ParseRangeTests = []struct {
{"bytes=0-0,-1", 10000, []httpRange{{0, 1}, {9999, 1}}},
{"bytes=500-600,601-999", 10000, []httpRange{{500, 101}, {601, 399}}},
{"bytes=500-700,601-999", 10000, []httpRange{{500, 201}, {601, 399}}},
+
+ // Match Apache laxity:
+ {"bytes= 1 -2 , 4- 5, 7 - 8 , ,,", 11, []httpRange{{1, 2}, {4, 2}, {7, 2}}},
}
func TestParseRange(t *testing.T) {
diff --git a/libgo/go/net/http/serve_test.go b/libgo/go/net/http/serve_test.go
index b6a6b4c77d1..c9d73932bb9 100644
--- a/libgo/go/net/http/serve_test.go
+++ b/libgo/go/net/http/serve_test.go
@@ -386,17 +386,18 @@ func testTcpConnectionCloses(t *testing.T, req string, h Handler) {
}
r := bufio.NewReader(conn)
- _, err = ReadResponse(r, &Request{Method: "GET"})
+ res, err := ReadResponse(r, &Request{Method: "GET"})
if err != nil {
t.Fatal("ReadResponse error:", err)
}
- success := make(chan bool)
+ didReadAll := make(chan bool, 1)
go func() {
select {
case <-time.After(5 * time.Second):
- t.Fatal("body not closed after 5s")
- case <-success:
+ t.Error("body not closed after 5s")
+ return
+ case <-didReadAll:
}
}()
@@ -404,8 +405,11 @@ func testTcpConnectionCloses(t *testing.T, req string, h Handler) {
if err != nil {
t.Fatal("read error:", err)
}
+ didReadAll <- true
- success <- true
+ if !res.Close {
+ t.Errorf("Response.Close = false; want true")
+ }
}
// TestServeHTTP10Close verifies that HTTP/1.0 requests won't be kept alive.
@@ -1108,6 +1112,38 @@ func TestServerBufferedChunking(t *testing.T) {
}
}
+// TestContentLengthZero tests that for both an HTTP/1.0 and HTTP/1.1
+// request (both keep-alive), when a Handler never writes any
+// response, the net/http package adds a "Content-Length: 0" response
+// header.
+func TestContentLengthZero(t *testing.T) {
+ ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {}))
+ defer ts.Close()
+
+ for _, version := range []string{"HTTP/1.0", "HTTP/1.1"} {
+ conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+ if err != nil {
+ t.Fatalf("error dialing: %v", err)
+ }
+ _, err = fmt.Fprintf(conn, "GET / %v\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n", version)
+ if err != nil {
+ t.Fatalf("error writing: %v", err)
+ }
+ req, _ := NewRequest("GET", "/", nil)
+ res, err := ReadResponse(bufio.NewReader(conn), req)
+ if err != nil {
+ t.Fatalf("error reading response: %v", err)
+ }
+ if te := res.TransferEncoding; len(te) > 0 {
+ t.Errorf("For version %q, Transfer-Encoding = %q; want none", version, te)
+ }
+ if cl := res.ContentLength; cl != 0 {
+ t.Errorf("For version %q, Content-Length = %v; want 0", version, cl)
+ }
+ conn.Close()
+ }
+}
+
// goTimeout runs f, failing t if f takes more than ns to complete.
func goTimeout(t *testing.T, d time.Duration, f func()) {
ch := make(chan bool, 2)
diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go
index 0572b4ae347..b74b7629809 100644
--- a/libgo/go/net/http/server.go
+++ b/libgo/go/net/http/server.go
@@ -390,6 +390,11 @@ func (w *response) WriteHeader(code int) {
if !w.req.ProtoAtLeast(1, 0) {
return
}
+
+ if w.closeAfterReply && !hasToken(w.header.Get("Connection"), "close") {
+ w.header.Set("Connection", "close")
+ }
+
proto := "HTTP/1.0"
if w.req.ProtoAtLeast(1, 1) {
proto = "HTTP/1.1"
@@ -508,8 +513,16 @@ func (w *response) Write(data []byte) (n int, err error) {
}
func (w *response) finishRequest() {
- // If this was an HTTP/1.0 request with keep-alive and we sent a Content-Length
- // back, we can make this a keep-alive response ...
+ // If the handler never wrote any bytes and never sent a Content-Length
+ // response header, set the length explicitly to zero. This helps
+ // HTTP/1.0 clients keep their "keep-alive" connections alive, and for
+ // HTTP/1.1 clients is just as good as the alternative: sending a
+ // chunked response and immediately sending the zero-length EOF chunk.
+ if w.written == 0 && w.header.Get("Content-Length") == "" {
+ w.header.Set("Content-Length", "0")
+ }
+ // If this was an HTTP/1.0 request with keep-alive and we sent a
+ // Content-Length back, we can make this a keep-alive response ...
if w.req.wantsHttp10KeepAlive() {
sentLength := w.header.Get("Content-Length") != ""
if sentLength && w.header.Get("Connection") == "keep-alive" {
@@ -817,13 +830,13 @@ func RedirectHandler(url string, code int) Handler {
// patterns and calls the handler for the pattern that
// most closely matches the URL.
//
-// Patterns named fixed, rooted paths, like "/favicon.ico",
+// Patterns name fixed, rooted paths, like "/favicon.ico",
// or rooted subtrees, like "/images/" (note the trailing slash).
// Longer patterns take precedence over shorter ones, so that
// if there are handlers registered for both "/images/"
// and "/images/thumbnails/", the latter handler will be
// called for paths beginning "/images/thumbnails/" and the
-// former will receiver requests for any other paths in the
+// former will receive requests for any other paths in the
// "/images/" subtree.
//
// Patterns may optionally begin with a host name, restricting matches to
@@ -917,11 +930,13 @@ func (mux *ServeMux) handler(r *Request) Handler {
// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
- // Clean path to canonical form and redirect.
- if p := cleanPath(r.URL.Path); p != r.URL.Path {
- w.Header().Set("Location", p)
- w.WriteHeader(StatusMovedPermanently)
- return
+ if r.Method != "CONNECT" {
+ // Clean path to canonical form and redirect.
+ if p := cleanPath(r.URL.Path); p != r.URL.Path {
+ w.Header().Set("Location", p)
+ w.WriteHeader(StatusMovedPermanently)
+ return
+ }
}
mux.handler(r).ServeHTTP(w, r)
}
diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go
index 6efe191eb0b..6131d0d1ee1 100644
--- a/libgo/go/net/http/transport.go
+++ b/libgo/go/net/http/transport.go
@@ -41,8 +41,9 @@ const DefaultMaxIdleConnsPerHost = 2
// https, and http proxies (for either http or https with CONNECT).
// Transport can also cache connections for future re-use.
type Transport struct {
- lk sync.Mutex
+ idleLk sync.Mutex
idleConn map[string][]*persistConn
+ altLk sync.RWMutex
altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper
// TODO: tunable on global max cached connections
@@ -131,12 +132,12 @@ func (t *Transport) RoundTrip(req *Request) (resp *Response, err error) {
return nil, errors.New("http: nil Request.Header")
}
if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
- t.lk.Lock()
+ t.altLk.RLock()
var rt RoundTripper
if t.altProto != nil {
rt = t.altProto[req.URL.Scheme]
}
- t.lk.Unlock()
+ t.altLk.RUnlock()
if rt == nil {
return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
}
@@ -170,8 +171,8 @@ func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
if scheme == "http" || scheme == "https" {
panic("protocol " + scheme + " already registered")
}
- t.lk.Lock()
- defer t.lk.Unlock()
+ t.altLk.Lock()
+ defer t.altLk.Unlock()
if t.altProto == nil {
t.altProto = make(map[string]RoundTripper)
}
@@ -186,17 +187,18 @@ func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
// a "keep-alive" state. It does not interrupt any connections currently
// in use.
func (t *Transport) CloseIdleConnections() {
- t.lk.Lock()
- defer t.lk.Unlock()
- if t.idleConn == nil {
+ t.idleLk.Lock()
+ m := t.idleConn
+ t.idleConn = nil
+ t.idleLk.Unlock()
+ if m == nil {
return
}
- for _, conns := range t.idleConn {
+ for _, conns := range m {
for _, pconn := range conns {
pconn.close()
}
}
- t.idleConn = make(map[string][]*persistConn)
}
//
@@ -242,8 +244,6 @@ func (cm *connectMethod) proxyAuth() string {
// If pconn is no longer needed or not in a good state, putIdleConn
// returns false.
func (t *Transport) putIdleConn(pconn *persistConn) bool {
- t.lk.Lock()
- defer t.lk.Unlock()
if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
pconn.close()
return false
@@ -256,21 +256,27 @@ func (t *Transport) putIdleConn(pconn *persistConn) bool {
if max == 0 {
max = DefaultMaxIdleConnsPerHost
}
+ t.idleLk.Lock()
+ if t.idleConn == nil {
+ t.idleConn = make(map[string][]*persistConn)
+ }
if len(t.idleConn[key]) >= max {
+ t.idleLk.Unlock()
pconn.close()
return false
}
t.idleConn[key] = append(t.idleConn[key], pconn)
+ t.idleLk.Unlock()
return true
}
func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) {
- t.lk.Lock()
- defer t.lk.Unlock()
+ key := cm.String()
+ t.idleLk.Lock()
+ defer t.idleLk.Unlock()
if t.idleConn == nil {
- t.idleConn = make(map[string][]*persistConn)
+ return nil
}
- key := cm.String()
for {
pconns, ok := t.idleConn[key]
if !ok {
@@ -365,7 +371,18 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, error) {
if cm.targetScheme == "https" {
// Initiate TLS and check remote host name against certificate.
- conn = tls.Client(conn, t.TLSClientConfig)
+ cfg := t.TLSClientConfig
+ if cfg == nil || cfg.ServerName == "" {
+ host, _, _ := net.SplitHostPort(cm.addr())
+ if cfg == nil {
+ cfg = &tls.Config{ServerName: host}
+ } else {
+ clone := *cfg // shallow clone
+ clone.ServerName = host
+ cfg = &clone
+ }
+ }
+ conn = tls.Client(conn, cfg)
if err = conn.(*tls.Conn).Handshake(); err != nil {
return nil, err
}
@@ -484,6 +501,7 @@ type persistConn struct {
t *Transport
cacheKey string // its connectMethod.String()
conn net.Conn
+ closed bool // whether conn has been closed
br *bufio.Reader // from conn
bw *bufio.Writer // to conn
reqch chan requestAndChan // written by roundTrip(); read by readLoop()
@@ -501,8 +519,9 @@ type persistConn struct {
func (pc *persistConn) isBroken() bool {
pc.lk.Lock()
- defer pc.lk.Unlock()
- return pc.broken
+ b := pc.broken
+ pc.lk.Unlock()
+ return b
}
var remoteSideClosedFunc func(error) bool // or nil to use default
@@ -571,29 +590,32 @@ func (pc *persistConn) readLoop() {
hasBody := resp != nil && resp.ContentLength != 0
var waitForBodyRead chan bool
- if alive {
- if hasBody {
- lastbody = resp.Body
- waitForBodyRead = make(chan bool)
- resp.Body.(*bodyEOFSignal).fn = func() {
- if !pc.t.putIdleConn(pc) {
- alive = false
- }
- waitForBodyRead <- true
- }
- } else {
- // When there's no response body, we immediately
- // reuse the TCP connection (putIdleConn), but
- // we need to prevent ClientConn.Read from
- // closing the Response.Body on the next
- // loop, otherwise it might close the body
- // before the client code has had a chance to
- // read it (even though it'll just be 0, EOF).
- lastbody = nil
-
- if !pc.t.putIdleConn(pc) {
+ if hasBody {
+ lastbody = resp.Body
+ waitForBodyRead = make(chan bool)
+ resp.Body.(*bodyEOFSignal).fn = func() {
+ if alive && !pc.t.putIdleConn(pc) {
alive = false
}
+ if !alive {
+ pc.close()
+ }
+ waitForBodyRead <- true
+ }
+ }
+
+ if alive && !hasBody {
+ // When there's no response body, we immediately
+ // reuse the TCP connection (putIdleConn), but
+ // we need to prevent ClientConn.Read from
+ // closing the Response.Body on the next
+ // loop, otherwise it might close the body
+ // before the client code has had a chance to
+ // read it (even though it'll just be 0, EOF).
+ lastbody = nil
+
+ if !pc.t.putIdleConn(pc) {
+ alive = false
}
}
@@ -604,6 +626,10 @@ func (pc *persistConn) readLoop() {
if waitForBodyRead != nil {
<-waitForBodyRead
}
+
+ if !alive {
+ pc.close()
+ }
}
}
@@ -669,7 +695,10 @@ func (pc *persistConn) close() {
func (pc *persistConn) closeLocked() {
pc.broken = true
- pc.conn.Close()
+ if !pc.closed {
+ pc.conn.Close()
+ pc.closed = true
+ }
pc.mutateHeaderFunc = nil
}
diff --git a/libgo/go/net/http/transport_test.go b/libgo/go/net/http/transport_test.go
index a9e401de58d..e676bf6db39 100644
--- a/libgo/go/net/http/transport_test.go
+++ b/libgo/go/net/http/transport_test.go
@@ -13,6 +13,7 @@ import (
"fmt"
"io"
"io/ioutil"
+ "net"
. "net/http"
"net/http/httptest"
"net/url"
@@ -20,6 +21,7 @@ import (
"runtime"
"strconv"
"strings"
+ "sync"
"testing"
"time"
)
@@ -35,6 +37,68 @@ var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
w.Write([]byte(r.RemoteAddr))
})
+// testCloseConn is a net.Conn tracked by a testConnSet.
+type testCloseConn struct {
+ net.Conn
+ set *testConnSet
+}
+
+func (c *testCloseConn) Close() error {
+ c.set.remove(c)
+ return c.Conn.Close()
+}
+
+// testConnSet tracks a set of TCP connections and whether they've
+// been closed.
+type testConnSet struct {
+ t *testing.T
+ closed map[net.Conn]bool
+ list []net.Conn // in order created
+ mutex sync.Mutex
+}
+
+func (tcs *testConnSet) insert(c net.Conn) {
+ tcs.mutex.Lock()
+ defer tcs.mutex.Unlock()
+ tcs.closed[c] = false
+ tcs.list = append(tcs.list, c)
+}
+
+func (tcs *testConnSet) remove(c net.Conn) {
+ tcs.mutex.Lock()
+ defer tcs.mutex.Unlock()
+ tcs.closed[c] = true
+}
+
+// some tests use this to manage raw tcp connections for later inspection
+func makeTestDial(t *testing.T) (*testConnSet, func(n, addr string) (net.Conn, error)) {
+ connSet := &testConnSet{
+ t: t,
+ closed: make(map[net.Conn]bool),
+ }
+ dial := func(n, addr string) (net.Conn, error) {
+ c, err := net.Dial(n, addr)
+ if err != nil {
+ return nil, err
+ }
+ tc := &testCloseConn{c, connSet}
+ connSet.insert(tc)
+ return tc, nil
+ }
+ return connSet, dial
+}
+
+func (tcs *testConnSet) check(t *testing.T) {
+ tcs.mutex.Lock()
+ defer tcs.mutex.Unlock()
+
+ for i, c := range tcs.list {
+ if !tcs.closed[c] {
+ t.Errorf("TCP connection #%d, %p (of %d total) was not closed", i+1, c, len(tcs.list))
+ }
+ }
+}
+
// Two subsequent requests and verify their response is the same.
// The response from the server is our own IP:port
func TestTransportKeepAlives(t *testing.T) {
@@ -72,8 +136,12 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) {
ts := httptest.NewServer(hostPortHandler)
defer ts.Close()
+ connSet, testDial := makeTestDial(t)
+
for _, connectionClose := range []bool{false, true} {
- tr := &Transport{}
+ tr := &Transport{
+ Dial: testDial,
+ }
c := &Client{Transport: tr}
fetch := func(n int) string {
@@ -92,8 +160,8 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) {
if err != nil {
t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
}
- body, err := ioutil.ReadAll(res.Body)
defer res.Body.Close()
+ body, err := ioutil.ReadAll(res.Body)
if err != nil {
t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
}
@@ -107,15 +175,23 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) {
t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
connectionClose, bodiesDiffer, body1, body2)
}
+
+ tr.CloseIdleConnections()
}
+
+ connSet.check(t)
}
func TestTransportConnectionCloseOnRequest(t *testing.T) {
ts := httptest.NewServer(hostPortHandler)
defer ts.Close()
+ connSet, testDial := makeTestDial(t)
+
for _, connectionClose := range []bool{false, true} {
- tr := &Transport{}
+ tr := &Transport{
+ Dial: testDial,
+ }
c := &Client{Transport: tr}
fetch := func(n int) string {
@@ -149,7 +225,11 @@ func TestTransportConnectionCloseOnRequest(t *testing.T) {
t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
connectionClose, bodiesDiffer, body1, body2)
}
+
+ tr.CloseIdleConnections()
}
+
+ connSet.check(t)
}
func TestTransportIdleCacheKeys(t *testing.T) {
@@ -724,6 +804,35 @@ func TestTransportIdleConnCrash(t *testing.T) {
<-didreq
}
+// Test that the transport doesn't close the TCP connection early,
+// before the response body has been read. This was a regression
+// which sadly lacked a triggering test. The large response body made
+// the old race easier to trigger.
+func TestIssue3644(t *testing.T) {
+ const numFoos = 5000
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.Header().Set("Connection", "close")
+ for i := 0; i < numFoos; i++ {
+ w.Write([]byte("foo "))
+ }
+ }))
+ defer ts.Close()
+ tr := &Transport{}
+ c := &Client{Transport: tr}
+ res, err := c.Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ bs, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(bs) != numFoos*len("foo ") {
+ t.Errorf("unexpected response length")
+ }
+}
+
type fooProto struct{}
func (fooProto) RoundTrip(req *Request) (*Response, error) {
diff --git a/libgo/go/net/iprawsock.go b/libgo/go/net/iprawsock.go
index b23213ee191..ae21b3c3dde 100644
--- a/libgo/go/net/iprawsock.go
+++ b/libgo/go/net/iprawsock.go
@@ -6,7 +6,7 @@
package net
-// IPAddr represents the address of a IP end point.
+// IPAddr represents the address of an IP end point.
type IPAddr struct {
IP IP
}
@@ -21,7 +21,7 @@ func (a *IPAddr) String() string {
return a.IP.String()
}
-// ResolveIPAddr parses addr as a IP address and resolves domain
+// ResolveIPAddr parses addr as an IP address and resolves domain
// names to numeric addresses on the network net, which must be
// "ip", "ip4" or "ip6". A literal IPv6 host address must be
// enclosed in square brackets, as in "[::]".
diff --git a/libgo/go/net/iprawsock_plan9.go b/libgo/go/net/iprawsock_plan9.go
index 43719fc99cd..ea3321b7e2f 100644
--- a/libgo/go/net/iprawsock_plan9.go
+++ b/libgo/go/net/iprawsock_plan9.go
@@ -59,7 +59,7 @@ func (c *IPConn) RemoteAddr() Addr {
// IP-specific methods.
-// ReadFromIP reads a IP packet from c, copying the payload into b.
+// ReadFromIP reads an IP packet from c, copying the payload into b.
// It returns the number of bytes copied into b and the return address
// that was on the packet.
//
@@ -75,7 +75,7 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
return 0, nil, syscall.EPLAN9
}
-// WriteToIP writes a IP packet to addr via c, copying the payload from b.
+// WriteToIP writes an IP packet to addr via c, copying the payload from b.
//
// WriteToIP can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
diff --git a/libgo/go/net/iprawsock_posix.go b/libgo/go/net/iprawsock_posix.go
index 9fc7ecdb942..dda81ddf881 100644
--- a/libgo/go/net/iprawsock_posix.go
+++ b/libgo/go/net/iprawsock_posix.go
@@ -146,7 +146,7 @@ func (c *IPConn) SetWriteBuffer(bytes int) error {
// IP-specific methods.
-// ReadFromIP reads a IP packet from c, copying the payload into b.
+// ReadFromIP reads an IP packet from c, copying the payload into b.
// It returns the number of bytes copied into b and the return address
// that was on the packet.
//
@@ -184,7 +184,7 @@ func (c *IPConn) ReadFrom(b []byte) (int, Addr, error) {
return n, uaddr.toAddr(), err
}
-// WriteToIP writes a IP packet to addr via c, copying the payload from b.
+// WriteToIP writes an IP packet to addr via c, copying the payload from b.
//
// WriteToIP can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
diff --git a/libgo/go/net/mail/message.go b/libgo/go/net/mail/message.go
index b610ccf3f04..93cc4d1edd4 100644
--- a/libgo/go/net/mail/message.go
+++ b/libgo/go/net/mail/message.go
@@ -47,7 +47,8 @@ type Message struct {
}
// ReadMessage reads a message from r.
-// The headers are parsed, and the body of the message will be reading from r.
+// The headers are parsed, and the body of the message will be available
+// for reading from r.
func ReadMessage(r io.Reader) (msg *Message, err error) {
tp := textproto.NewReader(bufio.NewReader(r))
diff --git a/libgo/go/net/net_posix.go b/libgo/go/net/net_posix.go
new file mode 100644
index 00000000000..3bcc54fe53a
--- /dev/null
+++ b/libgo/go/net/net_posix.go
@@ -0,0 +1,110 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux netbsd openbsd windows
+
+// Base posix socket functions.
+
+package net
+
+import (
+ "os"
+ "syscall"
+ "time"
+)
+
+type conn struct {
+ fd *netFD
+}
+
+func (c *conn) ok() bool { return c != nil && c.fd != nil }
+
+// Implementation of the Conn interface - see Conn for documentation.
+
+// Read implements the Conn Read method.
+func (c *conn) Read(b []byte) (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ return c.fd.Read(b)
+}
+
+// Write implements the Conn Write method.
+func (c *conn) Write(b []byte) (int, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ return c.fd.Write(b)
+}
+
+// LocalAddr returns the local network address.
+func (c *conn) LocalAddr() Addr {
+ if !c.ok() {
+ return nil
+ }
+ return c.fd.laddr
+}
+
+// RemoteAddr returns the remote network address.
+func (c *conn) RemoteAddr() Addr {
+ if !c.ok() {
+ return nil
+ }
+ return c.fd.raddr
+}
+
+// SetDeadline implements the Conn SetDeadline method.
+func (c *conn) SetDeadline(t time.Time) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return setDeadline(c.fd, t)
+}
+
+// SetReadDeadline implements the Conn SetReadDeadline method.
+func (c *conn) SetReadDeadline(t time.Time) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return setReadDeadline(c.fd, t)
+}
+
+// SetWriteDeadline implements the Conn SetWriteDeadline method.
+func (c *conn) SetWriteDeadline(t time.Time) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return setWriteDeadline(c.fd, t)
+}
+
+// SetReadBuffer sets the size of the operating system's
+// receive buffer associated with the connection.
+func (c *conn) SetReadBuffer(bytes int) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return setReadBuffer(c.fd, bytes)
+}
+
+// SetWriteBuffer sets the size of the operating system's
+// transmit buffer associated with the connection.
+func (c *conn) SetWriteBuffer(bytes int) error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return setWriteBuffer(c.fd, bytes)
+}
+
+// File returns a copy of the underlying os.File, set to blocking mode.
+// It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+func (c *conn) File() (f *os.File, err error) { return c.fd.dup() }
+
+// Close closes the connection.
+func (c *conn) Close() error {
+ if !c.ok() {
+ return syscall.EINVAL
+ }
+ return c.fd.Close()
+}
diff --git a/libgo/go/net/rpc/jsonrpc/all_test.go b/libgo/go/net/rpc/jsonrpc/all_test.go
index e6c7441f06b..adc29d5a1b3 100644
--- a/libgo/go/net/rpc/jsonrpc/all_test.go
+++ b/libgo/go/net/rpc/jsonrpc/all_test.go
@@ -108,7 +108,7 @@ func TestClient(t *testing.T) {
t.Errorf("Add: expected no error but got string %q", err.Error())
}
if reply.C != args.A+args.B {
- t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+ t.Errorf("Add: got %d expected %d", reply.C, args.A+args.B)
}
args = &Args{7, 8}
@@ -118,7 +118,7 @@ func TestClient(t *testing.T) {
t.Errorf("Mul: expected no error but got string %q", err.Error())
}
if reply.C != args.A*args.B {
- t.Errorf("Mul: expected %d got %d", reply.C, args.A*args.B)
+ t.Errorf("Mul: got %d expected %d", reply.C, args.A*args.B)
}
// Out of order.
@@ -133,7 +133,7 @@ func TestClient(t *testing.T) {
t.Errorf("Add: expected no error but got string %q", addCall.Error.Error())
}
if addReply.C != args.A+args.B {
- t.Errorf("Add: expected %d got %d", addReply.C, args.A+args.B)
+ t.Errorf("Add: got %d expected %d", addReply.C, args.A+args.B)
}
mulCall = <-mulCall.Done
@@ -141,7 +141,7 @@ func TestClient(t *testing.T) {
t.Errorf("Mul: expected no error but got string %q", mulCall.Error.Error())
}
if mulReply.C != args.A*args.B {
- t.Errorf("Mul: expected %d got %d", mulReply.C, args.A*args.B)
+ t.Errorf("Mul: got %d expected %d", mulReply.C, args.A*args.B)
}
// Error test
diff --git a/libgo/go/net/rpc/server.go b/libgo/go/net/rpc/server.go
index 1680e2f0d70..e5282202c3d 100644
--- a/libgo/go/net/rpc/server.go
+++ b/libgo/go/net/rpc/server.go
@@ -24,12 +24,13 @@
where T, T1 and T2 can be marshaled by encoding/gob.
These requirements apply even if a different codec is used.
- (In future, these requirements may soften for custom codecs.)
+ (In the future, these requirements may soften for custom codecs.)
The method's first argument represents the arguments provided by the caller; the
second argument represents the result parameters to be returned to the caller.
The method's return value, if non-nil, is passed back as a string that the client
- sees as if created by errors.New.
+ sees as if created by errors.New. If an error is returned, the reply parameter
+ will not be sent back to the client.
The server may handle requests on a single connection by calling ServeConn. More
typically it will create a network listener and call Accept or, for an HTTP
@@ -181,7 +182,7 @@ type Response struct {
// Server represents an RPC Server.
type Server struct {
- mu sync.Mutex // protects the serviceMap
+ mu sync.RWMutex // protects the serviceMap
serviceMap map[string]*service
reqLock sync.Mutex // protects freeReq
freeReq *Request
@@ -538,9 +539,9 @@ func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mt
return
}
// Look up the request.
- server.mu.Lock()
+ server.mu.RLock()
service = server.serviceMap[serviceMethod[0]]
- server.mu.Unlock()
+ server.mu.RUnlock()
if service == nil {
err = errors.New("rpc: can't find service " + req.ServiceMethod)
return
diff --git a/libgo/go/net/sockopt.go b/libgo/go/net/sockopt.go
index 0cd19266fe0..b139c427654 100644
--- a/libgo/go/net/sockopt.go
+++ b/libgo/go/net/sockopt.go
@@ -144,22 +144,6 @@ func setDeadline(fd *netFD, t time.Time) error {
return setWriteDeadline(fd, t)
}
-func setReuseAddr(fd *netFD, reuse bool) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse)))
-}
-
-func setDontRoute(fd *netFD, dontroute bool) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute)))
-}
-
func setKeepAlive(fd *netFD, keepalive bool) error {
if err := fd.incref(false); err != nil {
return err
diff --git a/libgo/go/os/error_plan9.go b/libgo/go/os/error_plan9.go
index 3c9dfb0b158..85260c82aea 100644
--- a/libgo/go/os/error_plan9.go
+++ b/libgo/go/os/error_plan9.go
@@ -5,21 +5,36 @@
package os
func isExist(err error) bool {
- if pe, ok := err.(*PathError); ok {
+ switch pe := err.(type) {
+ case nil:
+ return false
+ case *PathError:
+ err = pe.Err
+ case *LinkError:
err = pe.Err
}
return contains(err.Error(), " exists")
}
func isNotExist(err error) bool {
- if pe, ok := err.(*PathError); ok {
+ switch pe := err.(type) {
+ case nil:
+ return false
+ case *PathError:
+ err = pe.Err
+ case *LinkError:
err = pe.Err
}
return contains(err.Error(), "does not exist")
}
func isPermission(err error) bool {
- if pe, ok := err.(*PathError); ok {
+ switch pe := err.(type) {
+ case nil:
+ return false
+ case *PathError:
+ err = pe.Err
+ case *LinkError:
err = pe.Err
}
return contains(err.Error(), "permission denied")
diff --git a/libgo/go/os/error_posix.go b/libgo/go/os/error_posix.go
index 1685c1f2132..81b626aecb2 100644
--- a/libgo/go/os/error_posix.go
+++ b/libgo/go/os/error_posix.go
@@ -9,21 +9,36 @@ package os
import "syscall"
func isExist(err error) bool {
- if pe, ok := err.(*PathError); ok {
+ switch pe := err.(type) {
+ case nil:
+ return false
+ case *PathError:
+ err = pe.Err
+ case *LinkError:
err = pe.Err
}
return err == syscall.EEXIST || err == ErrExist
}
func isNotExist(err error) bool {
- if pe, ok := err.(*PathError); ok {
+ switch pe := err.(type) {
+ case nil:
+ return false
+ case *PathError:
+ err = pe.Err
+ case *LinkError:
err = pe.Err
}
return err == syscall.ENOENT || err == ErrNotExist
}
func isPermission(err error) bool {
- if pe, ok := err.(*PathError); ok {
+ switch pe := err.(type) {
+ case nil:
+ return false
+ case *PathError:
+ err = pe.Err
+ case *LinkError:
err = pe.Err
}
return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission
diff --git a/libgo/go/os/error_test.go b/libgo/go/os/error_test.go
index 42f846fa3c5..054bb3fcbcc 100644
--- a/libgo/go/os/error_test.go
+++ b/libgo/go/os/error_test.go
@@ -79,3 +79,30 @@ func checkErrorPredicate(predName string, pred func(error) bool, err error) stri
}
return ""
}
+
+var isExistTests = []struct {
+ err error
+ is bool
+ isnot bool
+}{
+ {&os.PathError{Err: os.ErrInvalid}, false, false},
+ {&os.PathError{Err: os.ErrPermission}, false, false},
+ {&os.PathError{Err: os.ErrExist}, true, false},
+ {&os.PathError{Err: os.ErrNotExist}, false, true},
+ {&os.LinkError{Err: os.ErrInvalid}, false, false},
+ {&os.LinkError{Err: os.ErrPermission}, false, false},
+ {&os.LinkError{Err: os.ErrExist}, true, false},
+ {&os.LinkError{Err: os.ErrNotExist}, false, true},
+ {nil, false, false},
+}
+
+func TestIsExist(t *testing.T) {
+ for _, tt := range isExistTests {
+ if is := os.IsExist(tt.err); is != tt.is {
+ t.Errorf("os.IsExist(%T %v) = %v, want %v", tt.err, tt.err, is, tt.is)
+ }
+ if isnot := os.IsNotExist(tt.err); isnot != tt.isnot {
+ t.Errorf("os.IsNotExist(%T %v) = %v, want %v", tt.err, tt.err, isnot, tt.isnot)
+ }
+ }
+}
diff --git a/libgo/go/os/error_windows.go b/libgo/go/os/error_windows.go
index fbb0d4f3fe0..83db6c07845 100644
--- a/libgo/go/os/error_windows.go
+++ b/libgo/go/os/error_windows.go
@@ -7,7 +7,12 @@ package os
import "syscall"
func isExist(err error) bool {
- if pe, ok := err.(*PathError); ok {
+ switch pe := err.(type) {
+ case nil:
+ return false
+ case *PathError:
+ err = pe.Err
+ case *LinkError:
err = pe.Err
}
return err == syscall.ERROR_ALREADY_EXISTS ||
@@ -15,7 +20,12 @@ func isExist(err error) bool {
}
func isNotExist(err error) bool {
- if pe, ok := err.(*PathError); ok {
+ switch pe := err.(type) {
+ case nil:
+ return false
+ case *PathError:
+ err = pe.Err
+ case *LinkError:
err = pe.Err
}
return err == syscall.ERROR_FILE_NOT_FOUND ||
@@ -23,7 +33,12 @@ func isNotExist(err error) bool {
}
func isPermission(err error) bool {
- if pe, ok := err.(*PathError); ok {
+ switch pe := err.(type) {
+ case nil:
+ return false
+ case *PathError:
+ err = pe.Err
+ case *LinkError:
err = pe.Err
}
return err == syscall.ERROR_ACCESS_DENIED || err == ErrPermission
diff --git a/libgo/go/os/exec.go b/libgo/go/os/exec.go
index 531b87ca556..6681acfd43b 100644
--- a/libgo/go/os/exec.go
+++ b/libgo/go/os/exec.go
@@ -6,6 +6,7 @@ package os
import (
"runtime"
+ "sync/atomic"
"syscall"
)
@@ -13,7 +14,7 @@ import (
type Process struct {
Pid int
handle uintptr
- done bool // process has been successfully waited on
+ isdone uint32 // process has been successfully waited on, non zero if true
}
func newProcess(pid int, handle uintptr) *Process {
@@ -22,6 +23,14 @@ func newProcess(pid int, handle uintptr) *Process {
return p
}
+func (p *Process) setDone() {
+ atomic.StoreUint32(&p.isdone, 1)
+}
+
+func (p *Process) done() bool {
+ return atomic.LoadUint32(&p.isdone) > 0
+}
+
// ProcAttr holds the attributes that will be applied to a new process
// started by StartProcess.
type ProcAttr struct {
diff --git a/libgo/go/os/exec/exec.go b/libgo/go/os/exec/exec.go
index 9a8e1817014..c4907cd7d7b 100644
--- a/libgo/go/os/exec/exec.go
+++ b/libgo/go/os/exec/exec.go
@@ -16,7 +16,7 @@ import (
"syscall"
)
-// Error records the name of a binary that failed to be be executed
+// Error records the name of a binary that failed to be executed
// and the reason it failed.
type Error struct {
Name string
@@ -143,6 +143,9 @@ func (c *Cmd) argv() []string {
func (c *Cmd) stdin() (f *os.File, err error) {
if c.Stdin == nil {
f, err = os.Open(os.DevNull)
+ if err != nil {
+ return
+ }
c.closeAfterStart = append(c.closeAfterStart, f)
return
}
@@ -182,6 +185,9 @@ func (c *Cmd) stderr() (f *os.File, err error) {
func (c *Cmd) writerDescriptor(w io.Writer) (f *os.File, err error) {
if w == nil {
f, err = os.OpenFile(os.DevNull, os.O_WRONLY, 0)
+ if err != nil {
+ return
+ }
c.closeAfterStart = append(c.closeAfterStart, f)
return
}
diff --git a/libgo/go/os/exec/exec_test.go b/libgo/go/os/exec/exec_test.go
index 52f4bce3aea..27ebb60d3d0 100644
--- a/libgo/go/os/exec/exec_test.go
+++ b/libgo/go/os/exec/exec_test.go
@@ -167,6 +167,18 @@ func TestExtraFiles(t *testing.T) {
}
defer ln.Close()
+ // Make sure duplicated fds don't leak to the child.
+ f, err := ln.(*net.TCPListener).File()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+ ln2, err := net.FileListener(f)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln2.Close()
+
// Force TLS root certs to be loaded (which might involve
// cgo), to make sure none of that potential C code leaks fds.
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -203,6 +215,56 @@ func TestExtraFiles(t *testing.T) {
}
}
+func TestExtraFilesRace(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Logf("no operating system support; skipping")
+ return
+ }
+ listen := func() net.Listener {
+ ln, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatal(err)
+ }
+ return ln
+ }
+ listenerFile := func(ln net.Listener) *os.File {
+ f, err := ln.(*net.TCPListener).File()
+ if err != nil {
+ t.Fatal(err)
+ }
+ return f
+ }
+ runCommand := func(c *Cmd, out chan<- string) {
+ bout, err := c.CombinedOutput()
+ if err != nil {
+ out <- "ERROR:" + err.Error()
+ } else {
+ out <- string(bout)
+ }
+ }
+
+ for i := 0; i < 10; i++ {
+ la := listen()
+ ca := helperCommand("describefiles")
+ ca.ExtraFiles = []*os.File{listenerFile(la)}
+ lb := listen()
+ cb := helperCommand("describefiles")
+ cb.ExtraFiles = []*os.File{listenerFile(lb)}
+ ares := make(chan string)
+ bres := make(chan string)
+ go runCommand(ca, ares)
+ go runCommand(cb, bres)
+ if got, want := <-ares, fmt.Sprintf("fd3: listener %s\n", la.Addr()); got != want {
+ t.Errorf("iteration %d, process A got:\n%s\nwant:\n%s\n", i, got, want)
+ }
+ if got, want := <-bres, fmt.Sprintf("fd3: listener %s\n", lb.Addr()); got != want {
+ t.Errorf("iteration %d, process B got:\n%s\nwant:\n%s\n", i, got, want)
+ }
+ la.Close()
+ lb.Close()
+ }
+}
+
// TestHelperProcess isn't a real test. It's used as a helper process
// for TestParameterRun.
func TestHelperProcess(*testing.T) {
@@ -318,6 +380,16 @@ func TestHelperProcess(*testing.T) {
case "exit":
n, _ := strconv.Atoi(args[0])
os.Exit(n)
+ case "describefiles":
+ for fd := uintptr(3); fd < 25; fd++ {
+ f := os.NewFile(fd, fmt.Sprintf("fd-%d", fd))
+ ln, err := net.FileListener(f)
+ if err == nil {
+ fmt.Printf("fd%d: listener %s\n", fd, ln.Addr())
+ ln.Close()
+ }
+ }
+ os.Exit(0)
default:
fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
os.Exit(2)
diff --git a/libgo/go/os/exec_plan9.go b/libgo/go/os/exec_plan9.go
index 41cc8c26f4c..01f06e2cf93 100644
--- a/libgo/go/os/exec_plan9.go
+++ b/libgo/go/os/exec_plan9.go
@@ -38,7 +38,7 @@ func (note Plan9Note) String() string {
}
func (p *Process) signal(sig Signal) error {
- if p.done {
+ if p.done() {
return errors.New("os: process already finished")
}
@@ -76,7 +76,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
}
if waitmsg.Pid == p.Pid {
- p.done = true
+ p.setDone()
break
}
}
diff --git a/libgo/go/os/exec_posix.go b/libgo/go/os/exec_posix.go
index 70351cfb313..40fd0fd0ee6 100644
--- a/libgo/go/os/exec_posix.go
+++ b/libgo/go/os/exec_posix.go
@@ -11,9 +11,10 @@ import (
)
func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
- // Double-check existence of the directory we want
+ // If there is no SysProcAttr (ie. no Chroot or changed
+ // UID/GID), double-check existence of the directory we want
// to chdir into. We can make the error clearer this way.
- if attr != nil && attr.Dir != "" {
+ if attr != nil && attr.Sys == nil && attr.Dir != "" {
if _, err := Stat(attr.Dir); err != nil {
pe := err.(*PathError)
pe.Op = "chdir"
diff --git a/libgo/go/os/exec_unix.go b/libgo/go/os/exec_unix.go
index ecfe5353bc1..fa3ba8a19e4 100644
--- a/libgo/go/os/exec_unix.go
+++ b/libgo/go/os/exec_unix.go
@@ -24,7 +24,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
return nil, NewSyscallError("wait", e)
}
if pid1 != 0 {
- p.done = true
+ p.setDone()
}
ps = &ProcessState{
pid: pid1,
@@ -35,7 +35,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
}
func (p *Process) signal(sig Signal) error {
- if p.done {
+ if p.done() {
return errors.New("os: process already finished")
}
s, ok := sig.(syscall.Signal)
diff --git a/libgo/go/os/exec_windows.go b/libgo/go/os/exec_windows.go
index 5beca4a6509..4aa2ade631e 100644
--- a/libgo/go/os/exec_windows.go
+++ b/libgo/go/os/exec_windows.go
@@ -32,7 +32,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
if e != nil {
return nil, NewSyscallError("GetProcessTimes", e)
}
- p.done = true
+ p.setDone()
// NOTE(brainman): It seems that sometimes process is not dead
// when WaitForSingleObject returns. But we do not know any
// other way to wait for it. Sleeping for a while seems to do
@@ -43,7 +43,7 @@ func (p *Process) wait() (ps *ProcessState, err error) {
}
func (p *Process) signal(sig Signal) error {
- if p.done {
+ if p.done() {
return errors.New("os: process already finished")
}
if sig == Kill {
diff --git a/libgo/go/os/file_posix.go b/libgo/go/os/file_posix.go
index 073bd56a471..1ba32931541 100644
--- a/libgo/go/os/file_posix.go
+++ b/libgo/go/os/file_posix.go
@@ -13,17 +13,6 @@ import (
func sigpipe() // implemented in package runtime
-func epipecheck(file *File, e error) {
- if e == syscall.EPIPE {
- file.nepipe++
- if file.nepipe >= 10 {
- sigpipe()
- }
- } else {
- file.nepipe = 0
- }
-}
-
// Link creates newname as a hard link to the oldname file.
// If there is an error, it will be of type *LinkError.
func Link(oldname, newname string) error {
diff --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go
index b8fb2e22c98..f677dbb986a 100644
--- a/libgo/go/os/file_unix.go
+++ b/libgo/go/os/file_unix.go
@@ -8,6 +8,7 @@ package os
import (
"runtime"
+ "sync/atomic"
"syscall"
)
@@ -24,7 +25,7 @@ type file struct {
fd int
name string
dirinfo *dirInfo // nil unless directory being read
- nepipe int // number of consecutive EPIPE in Write
+ nepipe int32 // number of consecutive EPIPE in Write
}
// Fd returns the integer Unix file descriptor referencing the open file.
@@ -52,6 +53,16 @@ type dirInfo struct {
dir *syscall.DIR // from opendir
}
+func epipecheck(file *File, e error) {
+ if e == syscall.EPIPE {
+ if atomic.AddInt32(&file.nepipe, 1) >= 10 {
+ sigpipe()
+ }
+ } else {
+ atomic.StoreInt32(&file.nepipe, 0)
+ }
+}
+
// DevNull is the name of the operating system's ``null device.''
// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
const DevNull = "/dev/null"
diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go
index 8d3f677fd4e..5046e60af43 100644
--- a/libgo/go/os/os_test.go
+++ b/libgo/go/os/os_test.go
@@ -67,10 +67,10 @@ var sysdir = func() (sd *sysDir) {
func size(name string, t *testing.T) int64 {
file, err := Open(name)
- defer file.Close()
if err != nil {
t.Fatal("open failed:", err)
}
+ defer file.Close()
var buf [100]byte
len := 0
for {
@@ -132,10 +132,10 @@ func TestStat(t *testing.T) {
func TestFstat(t *testing.T) {
path := sfdir + "/" + sfname
file, err1 := Open(path)
- defer file.Close()
if err1 != nil {
t.Fatal("open failed:", err1)
}
+ defer file.Close()
dir, err2 := file.Stat()
if err2 != nil {
t.Fatal("fstat failed:", err2)
@@ -187,10 +187,10 @@ func TestRead0(t *testing.T) {
func testReaddirnames(dir string, contents []string, t *testing.T) {
file, err := Open(dir)
- defer file.Close()
if err != nil {
t.Fatalf("open %q failed: %v", dir, err)
}
+ defer file.Close()
s, err2 := file.Readdirnames(-1)
if err2 != nil {
t.Fatalf("readdirnames %q failed: %v", dir, err2)
@@ -216,10 +216,10 @@ func testReaddirnames(dir string, contents []string, t *testing.T) {
func testReaddir(dir string, contents []string, t *testing.T) {
file, err := Open(dir)
- defer file.Close()
if err != nil {
t.Fatalf("open %q failed: %v", dir, err)
}
+ defer file.Close()
s, err2 := file.Readdir(-1)
if err2 != nil {
t.Fatalf("readdir %q failed: %v", dir, err2)
@@ -283,10 +283,10 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
dir = "/bin"
}
file, err := Open(dir)
- defer file.Close()
if err != nil {
t.Fatalf("open %q failed: %v", dir, err)
}
+ defer file.Close()
all, err1 := file.Readdirnames(-1)
if err1 != nil {
t.Fatalf("readdirnames %q failed: %v", dir, err1)
diff --git a/libgo/go/os/types.go b/libgo/go/os/types.go
index 0c95c9cece0..ecb57872d52 100644
--- a/libgo/go/os/types.go
+++ b/libgo/go/os/types.go
@@ -12,7 +12,7 @@ import (
// Getpagesize returns the underlying system's memory page size.
func Getpagesize() int { return syscall.Getpagesize() }
-// A FileInfo describes a file and is returned by Stat and Lstat
+// A FileInfo describes a file and is returned by Stat and Lstat.
type FileInfo interface {
Name() string // base name of the file
Size() int64 // length in bytes for regular files; system-dependent for others
diff --git a/libgo/go/path/path.go b/libgo/go/path/path.go
index a7e0415689c..b07534b36f4 100644
--- a/libgo/go/path/path.go
+++ b/libgo/go/path/path.go
@@ -166,7 +166,8 @@ func IsAbs(path string) bool {
}
// Dir returns all but the last element of path, typically the path's directory.
-// The path is Cleaned and trailing slashes are removed before processing.
+// After dropping the final element using Split, the path is Cleaned and trailing
+// slashes are removed.
// If the path is empty, Dir returns ".".
// If the path consists entirely of slashes followed by non-slash bytes, Dir
// returns a single slash. In any other case, the returned path does not end in a
diff --git a/libgo/go/path/path_test.go b/libgo/go/path/path_test.go
index 77f080433b6..65be5506042 100644
--- a/libgo/go/path/path_test.go
+++ b/libgo/go/path/path_test.go
@@ -181,6 +181,7 @@ var dirtests = []PathTest{
{"x/", "x"},
{"abc", "."},
{"abc/def", "abc"},
+ {"abc////def", "abc"},
{"a/b/.x", "a/b"},
{"a/b/c.", "a/b"},
{"a/b/c.x", "a/b"},
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index e946c0adfca..56ba8a824c2 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -1384,7 +1384,30 @@ func TestImportPath(t *testing.T) {
path string
}{
{TypeOf(&base64.Encoding{}).Elem(), "encoding/base64"},
+ {TypeOf(int(0)), ""},
+ {TypeOf(int8(0)), ""},
+ {TypeOf(int16(0)), ""},
+ {TypeOf(int32(0)), ""},
+ {TypeOf(int64(0)), ""},
{TypeOf(uint(0)), ""},
+ {TypeOf(uint8(0)), ""},
+ {TypeOf(uint16(0)), ""},
+ {TypeOf(uint32(0)), ""},
+ {TypeOf(uint64(0)), ""},
+ {TypeOf(uintptr(0)), ""},
+ {TypeOf(float32(0)), ""},
+ {TypeOf(float64(0)), ""},
+ {TypeOf(complex64(0)), ""},
+ {TypeOf(complex128(0)), ""},
+ {TypeOf(byte(0)), ""},
+ {TypeOf(rune(0)), ""},
+ {TypeOf([]byte(nil)), ""},
+ {TypeOf([]rune(nil)), ""},
+ {TypeOf(string("")), ""},
+ {TypeOf((*interface{})(nil)).Elem(), ""},
+ {TypeOf((*byte)(nil)), ""},
+ {TypeOf((*rune)(nil)), ""},
+ {TypeOf((*int64)(nil)), ""},
{TypeOf(map[string]int{}), ""},
{TypeOf((*error)(nil)).Elem(), ""},
}
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index a12fcb2668f..b25e5c73d1a 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -1705,10 +1705,11 @@ func ValueOf(i interface{}) Value {
return Value{typ, unsafe.Pointer(eface.word), fl}
}
-// Zero returns a Value representing a zero value for the specified type.
+// Zero returns a Value representing the zero value for the specified type.
// The result is different from the zero value of the Value struct,
// which represents no value at all.
// For example, Zero(TypeOf(42)) returns a Value with Kind Int and value 0.
+// The returned value is neither addressable nor settable.
func Zero(typ Type) Value {
if typ == nil {
panic("reflect: Zero(nil)")
diff --git a/libgo/go/regexp/regexp.go b/libgo/go/regexp/regexp.go
index 87e6b1c61e4..e4896a1c050 100644
--- a/libgo/go/regexp/regexp.go
+++ b/libgo/go/regexp/regexp.go
@@ -441,7 +441,7 @@ func (re *Regexp) ReplaceAllLiteralString(src, repl string) string {
}
// ReplaceAllStringFunc returns a copy of src in which all matches of the
-// Regexp have been replaced by the return value of of function repl applied
+// Regexp have been replaced by the return value of function repl applied
// to the matched substring. The replacement returned by repl is substituted
// directly, without using Expand.
func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string {
@@ -539,7 +539,7 @@ func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte {
}
// ReplaceAllFunc returns a copy of src in which all matches of the
-// Regexp have been replaced by the return value of of function repl applied
+// Regexp have been replaced by the return value of function repl applied
// to the matched byte slice. The replacement returned by repl is substituted
// directly, without using Expand.
func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
@@ -686,8 +686,9 @@ func (re *Regexp) FindStringIndex(s string) (loc []int) {
// FindReaderIndex returns a two-element slice of integers defining the
// location of the leftmost match of the regular expression in text read from
-// the RuneReader. The match itself is at s[loc[0]:loc[1]]. A return
-// value of nil indicates no match.
+// the RuneReader. The match text was found in the input stream at
+// byte offset loc[0] through loc[1]-1.
+// A return value of nil indicates no match.
func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int) {
a := re.doExecute(r, nil, "", 0, 2)
if a == nil {
diff --git a/libgo/go/runtime/pprof/pprof.go b/libgo/go/runtime/pprof/pprof.go
index 87f17d2db12..592c4a26960 100644
--- a/libgo/go/runtime/pprof/pprof.go
+++ b/libgo/go/runtime/pprof/pprof.go
@@ -357,7 +357,7 @@ func countHeap() int {
return n
}
-// writeHeapProfile writes the current runtime heap profile to w.
+// writeHeap writes the current runtime heap profile to w.
func writeHeap(w io.Writer, debug int) error {
// Find out how many records there are (MemProfile(nil, false)),
// allocate that many records, and get the data.
diff --git a/libgo/go/runtime/pprof/pprof_test.go b/libgo/go/runtime/pprof/pprof_test.go
index e933058e558..474011523e3 100644
--- a/libgo/go/runtime/pprof/pprof_test.go
+++ b/libgo/go/runtime/pprof/pprof_test.go
@@ -6,6 +6,7 @@ package pprof_test
import (
"bytes"
+ "fmt"
"hash/crc32"
"os/exec"
"runtime"
@@ -49,19 +50,27 @@ func TestCPUProfile(t *testing.T) {
// Convert []byte to []uintptr.
bytes := prof.Bytes()
+ l := len(bytes) / int(unsafe.Sizeof(uintptr(0)))
val := *(*[]uintptr)(unsafe.Pointer(&bytes))
- val = val[:len(bytes)/int(unsafe.Sizeof(uintptr(0)))]
+ val = val[:l]
- if len(val) < 10 {
+ if l < 13 {
t.Fatalf("profile too short: %#x", val)
}
- if val[0] != 0 || val[1] != 3 || val[2] != 0 || val[3] != 1e6/100 || val[4] != 0 {
- t.Fatalf("unexpected header %#x", val[:5])
+
+ fmt.Println(val, l)
+ hd, val, tl := val[:5], val[5:l-3], val[l-3:]
+ fmt.Println(hd, val, tl)
+ if hd[0] != 0 || hd[1] != 3 || hd[2] != 0 || hd[3] != 1e6/100 || hd[4] != 0 {
+ t.Fatalf("unexpected header %#x", hd)
+ }
+
+ if tl[0] != 0 || tl[1] != 1 || tl[2] != 0 {
+ t.Fatalf("malformed end-of-data marker %#x", tl)
}
// Check that profile is well formed and contains ChecksumIEEE.
found := false
- val = val[5:]
for len(val) > 0 {
if len(val) < 2 || val[0] < 1 || val[1] < 1 || uintptr(len(val)) < 2+val[1] {
t.Fatalf("malformed profile. leftover: %#x", val)
diff --git a/libgo/go/strconv/atoi.go b/libgo/go/strconv/atoi.go
index 59ef264d17c..bdd5d71f875 100644
--- a/libgo/go/strconv/atoi.go
+++ b/libgo/go/strconv/atoi.go
@@ -44,7 +44,7 @@ func cutoff64(base int) uint64 {
}
// ParseUint is like ParseInt but for unsigned numbers.
-func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
+func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
var cutoff, maxVal uint64
if bitSize == 0 {
@@ -57,32 +57,32 @@ func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
err = ErrSyntax
goto Error
- case 2 <= b && b <= 36:
+ case 2 <= base && base <= 36:
// valid base; nothing to do
- case b == 0:
+ case base == 0:
// Look for octal, hex prefix.
switch {
case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
- b = 16
+ base = 16
s = s[2:]
if len(s) < 1 {
err = ErrSyntax
goto Error
}
case s[0] == '0':
- b = 8
+ base = 8
default:
- b = 10
+ base = 10
}
default:
- err = errors.New("invalid base " + Itoa(b))
+ err = errors.New("invalid base " + Itoa(base))
goto Error
}
n = 0
- cutoff = cutoff64(b)
+ cutoff = cutoff64(base)
maxVal = 1<<uint(bitSize) - 1
for i := 0; i < len(s); i++ {
@@ -100,19 +100,19 @@ func ParseUint(s string, b int, bitSize int) (n uint64, err error) {
err = ErrSyntax
goto Error
}
- if int(v) >= b {
+ if int(v) >= base {
n = 0
err = ErrSyntax
goto Error
}
if n >= cutoff {
- // n*b overflows
+ // n*base overflows
n = 1<<64 - 1
err = ErrRange
goto Error
}
- n *= uint64(b)
+ n *= uint64(base)
n1 := n + uint64(v)
if n1 < n || n1 > maxVal {
diff --git a/libgo/go/sync/waitgroup.go b/libgo/go/sync/waitgroup.go
index 0165b1ffb2b..bc9e738e784 100644
--- a/libgo/go/sync/waitgroup.go
+++ b/libgo/go/sync/waitgroup.go
@@ -32,10 +32,11 @@ type WaitGroup struct {
// Add adds delta, which may be negative, to the WaitGroup counter.
// If the counter becomes zero, all goroutines blocked on Wait() are released.
+// If the counter goes negative, Add panics.
func (wg *WaitGroup) Add(delta int) {
v := atomic.AddInt32(&wg.counter, int32(delta))
if v < 0 {
- panic("sync: negative WaitGroup count")
+ panic("sync: negative WaitGroup counter")
}
if v > 0 || atomic.LoadInt32(&wg.waiters) == 0 {
return
diff --git a/libgo/go/sync/waitgroup_test.go b/libgo/go/sync/waitgroup_test.go
index 34430fc2158..84c4cfc37a3 100644
--- a/libgo/go/sync/waitgroup_test.go
+++ b/libgo/go/sync/waitgroup_test.go
@@ -50,7 +50,7 @@ func TestWaitGroup(t *testing.T) {
func TestWaitGroupMisuse(t *testing.T) {
defer func() {
err := recover()
- if err != "sync: negative WaitGroup count" {
+ if err != "sync: negative WaitGroup counter" {
t.Fatalf("Unexpected panic: %#v", err)
}
}()
diff --git a/libgo/go/syscall/env_windows.go b/libgo/go/syscall/env_windows.go
index 8308f10a2dc..3107ae5f415 100644
--- a/libgo/go/syscall/env_windows.go
+++ b/libgo/go/syscall/env_windows.go
@@ -12,14 +12,18 @@ import (
)
func Getenv(key string) (value string, found bool) {
+ keyp, err := utf16PtrFromString(key)
+ if err != nil {
+ return "", false
+ }
b := make([]uint16, 100)
- n, e := GetEnvironmentVariable(StringToUTF16Ptr(key), &b[0], uint32(len(b)))
+ n, e := GetEnvironmentVariable(keyp, &b[0], uint32(len(b)))
if n == 0 && e == ERROR_ENVVAR_NOT_FOUND {
return "", false
}
if n > uint32(len(b)) {
b = make([]uint16, n)
- n, e = GetEnvironmentVariable(StringToUTF16Ptr(key), &b[0], uint32(len(b)))
+ n, e = GetEnvironmentVariable(keyp, &b[0], uint32(len(b)))
if n > uint32(len(b)) {
n = 0
}
@@ -32,10 +36,18 @@ func Getenv(key string) (value string, found bool) {
func Setenv(key, value string) error {
var v *uint16
+ var err error
if len(value) > 0 {
- v = StringToUTF16Ptr(value)
+ v, err = utf16PtrFromString(value)
+ if err != nil {
+ return err
+ }
+ }
+ keyp, err := utf16PtrFromString(key)
+ if err != nil {
+ return err
}
- e := SetEnvironmentVariable(StringToUTF16Ptr(key), v)
+ e := SetEnvironmentVariable(keyp, v)
if e != nil {
return e
}
diff --git a/libgo/go/syscall/exec_unix.go b/libgo/go/syscall/exec_unix.go
index 664908d1310..b34ee1bf882 100644
--- a/libgo/go/syscall/exec_unix.go
+++ b/libgo/go/syscall/exec_unix.go
@@ -103,8 +103,9 @@ import (
var ForkLock sync.RWMutex
-// Convert array of string to array
-// of NUL-terminated byte pointer.
+// Convert array of string to array of NUL-terminated byte pointer.
+// If any string contains a NUL byte this function panics instead
+// of returning an error.
func StringSlicePtr(ss []string) []*byte {
bb := make([]*byte, len(ss)+1)
for i := 0; i < len(ss); i++ {
@@ -114,6 +115,22 @@ func StringSlicePtr(ss []string) []*byte {
return bb
}
+// slicePtrFromStrings converts a slice of strings to a slice of
+// pointers to NUL-terminated byte slices. If any string contains
+// a NUL byte, it returns (nil, EINVAL).
+func slicePtrFromStrings(ss []string) ([]*byte, error) {
+ var err error
+ bb := make([]*byte, len(ss)+1)
+ for i := 0; i < len(ss); i++ {
+ bb[i], err = bytePtrFromString(ss[i])
+ if err != nil {
+ return nil, err
+ }
+ }
+ bb[len(ss)] = nil
+ return bb, nil
+}
+
func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
func SetNonblock(fd int, nonblocking bool) (err error) {
@@ -168,9 +185,18 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
p[1] = -1
// Convert args to C form.
- argv0p := StringBytePtr(argv0)
- argvp := StringSlicePtr(argv)
- envvp := StringSlicePtr(attr.Env)
+ argv0p, err := bytePtrFromString(argv0)
+ if err != nil {
+ return 0, err
+ }
+ argvp, err := slicePtrFromStrings(argv)
+ if err != nil {
+ return 0, err
+ }
+ envvp, err := slicePtrFromStrings(attr.Env)
+ if err != nil {
+ return 0, err
+ }
if runtime.GOOS == "freebsd" && len(argv[0]) > len(argv0) {
argvp[0] = argv0p
@@ -178,11 +204,17 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
var chroot *byte
if sys.Chroot != "" {
- chroot = StringBytePtr(sys.Chroot)
+ chroot, err = bytePtrFromString(sys.Chroot)
+ if err != nil {
+ return 0, err
+ }
}
var dir *byte
if attr.Dir != "" {
- dir = StringBytePtr(attr.Dir)
+ dir, err = bytePtrFromString(attr.Dir)
+ if err != nil {
+ return 0, err
+ }
}
// Acquire the fork lock so that no other threads
@@ -254,8 +286,18 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
// Ordinary exec.
func Exec(argv0 string, argv []string, envv []string) (err error) {
- err1 := raw_execve(StringBytePtr(argv0),
- &StringSlicePtr(argv)[0],
- &StringSlicePtr(envv)[0])
+ argv0p, err := bytePtrFromString(argv0)
+ if err != nil {
+ return err
+ }
+ argvp, err := slicePtrFromStrings(argv)
+ if err != nil {
+ return err
+ }
+ envvp, err := slicePtrFromStrings(envv)
+ if err != nil {
+ return err
+ }
+ err1 := raw_execve(argv0p, &argvp[0], &envvp[0])
return Errno(err1)
}
diff --git a/libgo/go/syscall/exec_windows.go b/libgo/go/syscall/exec_windows.go
index 4dc4d059d7e..68779c461a0 100644
--- a/libgo/go/syscall/exec_windows.go
+++ b/libgo/go/syscall/exec_windows.go
@@ -132,7 +132,10 @@ func SetNonblock(fd Handle, nonblocking bool) (err error) {
// getFullPath retrieves the full path of the specified file.
// Just a wrapper for Windows GetFullPathName api.
func getFullPath(name string) (path string, err error) {
- p := StringToUTF16Ptr(name)
+ p, err := utf16PtrFromString(name)
+ if err != nil {
+ return "", err
+ }
buf := make([]uint16, 100)
n, err := GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
if err != nil {
@@ -261,7 +264,10 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
return 0, 0, err
}
}
- argv0p := StringToUTF16Ptr(argv0)
+ argv0p, err := utf16PtrFromString(argv0)
+ if err != nil {
+ return 0, 0, err
+ }
var cmdline string
// Windows CreateProcess takes the command line as a single string:
@@ -275,12 +281,18 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
var argvp *uint16
if len(cmdline) != 0 {
- argvp = StringToUTF16Ptr(cmdline)
+ argvp, err = utf16PtrFromString(cmdline)
+ if err != nil {
+ return 0, 0, err
+ }
}
var dirp *uint16
if len(attr.Dir) != 0 {
- dirp = StringToUTF16Ptr(attr.Dir)
+ dirp, err = utf16PtrFromString(attr.Dir)
+ if err != nil {
+ return 0, 0, err
+ }
}
// Acquire the fork lock so that no other threads
diff --git a/libgo/go/syscall/security_windows.go b/libgo/go/syscall/security_windows.go
index bd40fe58676..4353af4fb90 100644
--- a/libgo/go/syscall/security_windows.go
+++ b/libgo/go/syscall/security_windows.go
@@ -37,10 +37,13 @@ const (
// TranslateAccountName converts a directory service
// object name from one format to another.
func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
- u := StringToUTF16Ptr(username)
+ u, e := utf16PtrFromString(username)
+ if e != nil {
+ return "", e
+ }
b := make([]uint16, 50)
n := uint32(len(b))
- e := TranslateName(u, from, to, &b[0], &n)
+ e = TranslateName(u, from, to, &b[0], &n)
if e != nil {
if e != ERROR_INSUFFICIENT_BUFFER {
return "", e
@@ -94,7 +97,11 @@ type SID struct{}
// sid into a valid, functional sid.
func StringToSid(s string) (*SID, error) {
var sid *SID
- e := ConvertStringSidToSid(StringToUTF16Ptr(s), &sid)
+ p, e := utf16PtrFromString(s)
+ if e != nil {
+ return nil, e
+ }
+ e = ConvertStringSidToSid(p, &sid)
if e != nil {
return nil, e
}
@@ -109,17 +116,23 @@ func LookupSID(system, account string) (sid *SID, domain string, accType uint32,
if len(account) == 0 {
return nil, "", 0, EINVAL
}
- acc := StringToUTF16Ptr(account)
+ acc, e := utf16PtrFromString(account)
+ if e != nil {
+ return nil, "", 0, e
+ }
var sys *uint16
if len(system) > 0 {
- sys = StringToUTF16Ptr(system)
+ sys, e = utf16PtrFromString(system)
+ if e != nil {
+ return nil, "", 0, e
+ }
}
db := make([]uint16, 50)
dn := uint32(len(db))
b := make([]byte, 50)
n := uint32(len(b))
sid = (*SID)(unsafe.Pointer(&b[0]))
- e := LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
+ e = LookupAccountName(sys, acc, sid, &n, &db[0], &dn, &accType)
if e != nil {
if e != ERROR_INSUFFICIENT_BUFFER {
return nil, "", 0, e
@@ -170,7 +183,10 @@ func (sid *SID) Copy() (*SID, error) {
func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
var sys *uint16
if len(system) > 0 {
- sys = StringToUTF16Ptr(system)
+ sys, err = utf16PtrFromString(system)
+ if err != nil {
+ return "", "", 0, err
+ }
}
b := make([]uint16, 50)
n := uint32(len(b))
diff --git a/libgo/go/syscall/syscall.go b/libgo/go/syscall/syscall.go
index 4efaaec3bd2..3090a5ec697 100644
--- a/libgo/go/syscall/syscall.go
+++ b/libgo/go/syscall/syscall.go
@@ -16,18 +16,47 @@ package syscall
import "unsafe"
-// StringByteSlice returns a NUL-terminated slice of bytes
-// containing the text of s.
+// StringByteSlice returns a NUL-terminated slice of bytes containing the text of s.
+// If s contains a NUL byte this function panics instead of
+// returning an error.
func StringByteSlice(s string) []byte {
+ a, err := byteSliceFromString(s)
+ if err != nil {
+ panic("syscall: string with NUL passed to StringByteSlice")
+ }
+ return a
+}
+
+// byteSliceFromString returns a NUL-terminated slice of bytes
+// containing the text of s. If s contains a NUL byte at any
+// location, it returns (nil, EINVAL).
+func byteSliceFromString(s string) ([]byte, error) {
+ for i := 0; i < len(s); i++ {
+ if s[i] == 0 {
+ return nil, EINVAL
+ }
+ }
a := make([]byte, len(s)+1)
copy(a, s)
- return a
+ return a, nil
}
-// StringBytePtr returns a pointer to a NUL-terminated array of bytes
-// containing the text of s.
+// StringBytePtr returns a pointer to a NUL-terminated array of bytes containing the text of s.
+// If s contains a NUL byte this function panics instead of
+// returning an error.
func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }
+// bytePtrFromString returns a pointer to a NUL-terminated array of
+// bytes containing the text of s. If s contains a NUL byte at any
+// location, it returns (nil, EINVAL).
+func bytePtrFromString(s string) (*byte, error) {
+ a, err := byteSliceFromString(s)
+ if err != nil {
+ return nil, err
+ }
+ return &a[0], nil
+}
+
// Single-word zero for use when we need a valid pointer to 0 bytes.
// See mksyscall.pl.
var _zero uintptr
diff --git a/libgo/go/syscall/syscall_linux_386.go b/libgo/go/syscall/syscall_linux_386.go
index 9a988a5dca2..08422def375 100644
--- a/libgo/go/syscall/syscall_linux_386.go
+++ b/libgo/go/syscall/syscall_linux_386.go
@@ -8,13 +8,9 @@ package syscall
import "unsafe"
-func (r *PtraceRegs) PC() uint64 {
- return uint64(uint32(r.Eip))
-}
+func (r *PtraceRegs) PC() uint64 { return uint64(uint32(r.Eip)) }
-func (r *PtraceRegs) SetPC(pc uint64) {
- r.Eip = int32(pc)
-}
+func (r *PtraceRegs) SetPC(pc uint64) { r.Eip = int32(pc) }
func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) {
return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index 1cb8a078c6d..2d2f45e4df1 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -80,6 +80,7 @@ package testing
import (
_ "debug/elf"
+ "bytes"
"flag"
"fmt"
"os"
@@ -87,6 +88,7 @@ import (
"runtime/pprof"
"strconv"
"strings"
+ "sync"
"time"
)
@@ -116,8 +118,10 @@ var (
// common holds the elements common between T and B and
// captures common methods such as Errorf.
type common struct {
- output []byte // Output generated by test or benchmark.
- failed bool // Test or benchmark has failed.
+ mu sync.RWMutex // guards output and failed
+ output []byte // Output generated by test or benchmark.
+ failed bool // Test or benchmark has failed.
+
start time.Time // Time test or benchmark started
duration time.Duration
self interface{} // To be sent on signal channel when done.
@@ -129,37 +133,42 @@ func Short() bool {
return *short
}
-// decorate inserts the final newline if needed and indentation tabs for formatting.
-// If addFileLine is true, it also prefixes the string with the file and line of the call site.
-func decorate(s string, addFileLine bool) string {
- if addFileLine {
- _, file, line, ok := runtime.Caller(3) // decorate + log + public function.
- if ok {
- // Truncate file name at last file name separator.
- if index := strings.LastIndex(file, "/"); index >= 0 {
- file = file[index+1:]
- } else if index = strings.LastIndex(file, "\\"); index >= 0 {
- file = file[index+1:]
- }
- } else {
- file = "???"
- line = 1
+// decorate prefixes the string with the file and line of the call site
+// and inserts the final newline if needed and indentation tabs for formatting.
+func decorate(s string) string {
+ _, file, line, ok := runtime.Caller(3) // decorate + log + public function.
+ if ok {
+ // Truncate file name at last file name separator.
+ if index := strings.LastIndex(file, "/"); index >= 0 {
+ file = file[index+1:]
+ } else if index = strings.LastIndex(file, "\\"); index >= 0 {
+ file = file[index+1:]
}
- s = fmt.Sprintf("%s:%d: %s", file, line, s)
- }
- s = "\t" + s // Every line is indented at least one tab.
- n := len(s)
- if n > 0 && s[n-1] != '\n' {
- s += "\n"
- n++
+ } else {
+ file = "???"
+ line = 1
}
- for i := 0; i < n-1; i++ { // -1 to avoid final newline
- if s[i] == '\n' {
+ buf := new(bytes.Buffer)
+ fmt.Fprintf(buf, "%s:%d: ", file, line)
+
+ lines := strings.Split(s, "\n")
+ for i, line := range lines {
+ if i > 0 {
+ buf.WriteByte('\n')
+ }
+ // Every line is indented at least one tab.
+ buf.WriteByte('\t')
+ if i > 0 {
// Second and subsequent lines are indented an extra tab.
- return s[0:i+1] + "\t" + decorate(s[i+1:n], false)
+ buf.WriteByte('\t')
}
+ buf.WriteString(line)
+ }
+ if l := len(s); l > 0 && s[len(s)-1] != '\n' {
+ // Add final new line if needed.
+ buf.WriteByte('\n')
}
- return s
+ return buf.String()
}
// T is a type passed to Test functions to manage test state and support formatted test logs.
@@ -171,10 +180,18 @@ type T struct {
}
// Fail marks the function as having failed but continues execution.
-func (c *common) Fail() { c.failed = true }
+func (c *common) Fail() {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ c.failed = true
+}
// Failed returns whether the function has failed.
-func (c *common) Failed() bool { return c.failed }
+func (c *common) Failed() bool {
+ c.mu.RLock()
+ defer c.mu.RUnlock()
+ return c.failed
+}
// FailNow marks the function as having failed and stops its execution.
// Execution will continue at the next test or benchmark.
@@ -205,7 +222,9 @@ func (c *common) FailNow() {
// log generates the output. It's always at the same stack depth.
func (c *common) log(s string) {
- c.output = append(c.output, decorate(s, true)...)
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ c.output = append(c.output, decorate(s)...)
}
// Log formats its arguments using default formatting, analogous to Println(),
@@ -298,7 +317,7 @@ func Main(matchString func(pat, str string) (bool, error), tests []InternalTest,
func (t *T) report() {
tstr := fmt.Sprintf("(%.2f seconds)", t.duration.Seconds())
format := "--- %s: %s %s\n%s"
- if t.failed {
+ if t.Failed() {
fmt.Printf(format, "FAIL", t.name, tstr, t.output)
} else if *chatty {
fmt.Printf(format, "PASS", t.name, tstr, t.output)
@@ -357,7 +376,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
continue
}
t.report()
- ok = ok && !out.failed
+ ok = ok && !out.Failed()
}
running := 0
@@ -370,7 +389,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
}
t := (<-collector).(*T)
t.report()
- ok = ok && !t.failed
+ ok = ok && !t.Failed()
running--
}
}
diff --git a/libgo/go/text/tabwriter/tabwriter.go b/libgo/go/text/tabwriter/tabwriter.go
index ce84600d604..722ac8d877a 100644
--- a/libgo/go/text/tabwriter/tabwriter.go
+++ b/libgo/go/text/tabwriter/tabwriter.go
@@ -547,7 +547,7 @@ func (b *Writer) Write(buf []byte) (n int, err error) {
}
// NewWriter allocates and initializes a new tabwriter.Writer.
-// The parameters are the same as for the the Init function.
+// The parameters are the same as for the Init function.
//
func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer {
return new(Writer).Init(output, minwidth, tabwidth, padding, padchar, flags)
diff --git a/libgo/go/text/template/doc.go b/libgo/go/text/template/doc.go
index aa50ab97f6f..4a1682d97a3 100644
--- a/libgo/go/text/template/doc.go
+++ b/libgo/go/text/template/doc.go
@@ -198,7 +198,7 @@ If a "range" action initializes a variable, the variable is set to the
successive elements of the iteration. Also, a "range" may declare two
variables, separated by a comma:
- $index, $element := pipeline
+ range $index, $element := pipeline
in which case $index and $element are set to the successive values of the
array/slice index or map key and element, respectively. Note that if there is
diff --git a/libgo/go/text/template/exec_test.go b/libgo/go/text/template/exec_test.go
index f4ae50f0ee9..64149533b3e 100644
--- a/libgo/go/text/template/exec_test.go
+++ b/libgo/go/text/template/exec_test.go
@@ -387,7 +387,7 @@ var execTests = []execTest{
{"slice[WRONG]", "{{index .SI `hello`}}", "", tVal, false},
{"map[one]", "{{index .MSI `one`}}", "1", tVal, true},
{"map[two]", "{{index .MSI `two`}}", "2", tVal, true},
- {"map[NO]", "{{index .MSI `XXX`}}", "", tVal, true},
+ {"map[NO]", "{{index .MSI `XXX`}}", "0", tVal, true},
{"map[WRONG]", "{{index .MSI 10}}", "", tVal, false},
{"double index", "{{index .SMSI 1 `eleven`}}", "11", tVal, true},
diff --git a/libgo/go/text/template/funcs.go b/libgo/go/text/template/funcs.go
index 8fbf0ef50a7..e6fa0fb5f2a 100644
--- a/libgo/go/text/template/funcs.go
+++ b/libgo/go/text/template/funcs.go
@@ -128,7 +128,7 @@ func index(item interface{}, indices ...interface{}) (interface{}, error) {
if x := v.MapIndex(index); x.IsValid() {
v = x
} else {
- v = reflect.Zero(v.Type().Key())
+ v = reflect.Zero(v.Type().Elem())
}
default:
return nil, fmt.Errorf("can't index item of type %s", index.Type())
@@ -154,7 +154,7 @@ func length(item interface{}) (int, error) {
// Function invocation
-// call returns the result of evaluating the the first argument as a function.
+// call returns the result of evaluating the first argument as a function.
// The function must return 1 result, or 2 results, the second of which is an error.
func call(fn interface{}, args ...interface{}) (interface{}, error) {
v := reflect.ValueOf(fn)
diff --git a/libgo/go/text/template/parse/lex.go b/libgo/go/text/template/parse/lex.go
index 7705c0b88ff..c4e1a56a8d4 100644
--- a/libgo/go/text/template/parse/lex.go
+++ b/libgo/go/text/template/parse/lex.go
@@ -257,16 +257,17 @@ func lexText(l *lexer) stateFn {
// lexLeftDelim scans the left delimiter, which is known to be present.
func lexLeftDelim(l *lexer) stateFn {
- if strings.HasPrefix(l.input[l.pos:], l.leftDelim+leftComment) {
+ l.pos += len(l.leftDelim)
+ if strings.HasPrefix(l.input[l.pos:], leftComment) {
return lexComment
}
- l.pos += len(l.leftDelim)
l.emit(itemLeftDelim)
return lexInsideAction
}
// lexComment scans a comment. The left comment marker is known to be present.
func lexComment(l *lexer) stateFn {
+ l.pos += len(leftComment)
i := strings.Index(l.input[l.pos:], rightComment+l.rightDelim)
if i < 0 {
return l.errorf("unclosed comment")
diff --git a/libgo/go/text/template/parse/lex_test.go b/libgo/go/text/template/parse/lex_test.go
index 6ee1b470102..f3b23c91e43 100644
--- a/libgo/go/text/template/parse/lex_test.go
+++ b/libgo/go/text/template/parse/lex_test.go
@@ -198,6 +198,10 @@ var lexTests = []lexTest{
tRight,
tEOF,
}},
+ {"text with bad comment", "hello-{{/*/}}-world", []item{
+ {itemText, "hello-"},
+ {itemError, `unclosed comment`},
+ }},
}
// collect gathers the emitted items into a slice.
diff --git a/libgo/go/time/time.go b/libgo/go/time/time.go
index 2461dac06f5..d48ca0c269e 100644
--- a/libgo/go/time/time.go
+++ b/libgo/go/time/time.go
@@ -241,10 +241,10 @@ func (t Time) IsZero() bool {
// It is called when computing a presentation property like Month or Hour.
func (t Time) abs() uint64 {
l := t.loc
- if l == nil {
- l = &utcLoc
+ // Avoid function calls when possible.
+ if l == nil || l == &localLoc {
+ l = l.get()
}
- // Avoid function call if we hit the local time cache.
sec := t.sec + internalToUnix
if l != &utcLoc {
if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh
index 315d60cc39d..12e0310bb43 100755
--- a/libgo/mksysinfo.sh
+++ b/libgo/mksysinfo.sh
@@ -225,6 +225,16 @@ done
grep '^const _SIG[^_]' gen-sysinfo.go | \
grep -v '^const _SIGEV_' | \
sed -e 's/^\(const \)_\(SIG[^= ]*\)\(.*\)$/\1\2 = Signal(_\2)/' >> ${OUT}
+if ! grep '^const SIGPOLL ' ${OUT} >/dev/null 2>&1; then
+ if grep '^const SIGIO ' ${OUT} > /dev/null 2>&1; then
+ echo "const SIGPOLL = SIGIO" >> ${OUT}
+ fi
+fi
+if ! grep '^const SIGCLD ' ${OUT} >/dev/null 2>&1; then
+ if grep '^const SIGCHLD ' ${OUT} >/dev/null 2>&1; then
+ echo "const SIGCLD = SIGCHLD" >> ${OUT}
+ fi
+fi
# The syscall numbers. We force the names to upper case.
grep '^const _SYS_' gen-sysinfo.go | \
diff --git a/libgo/runtime/chan.c b/libgo/runtime/chan.c
index d0a1612ad2a..1e389a218de 100644
--- a/libgo/runtime/chan.c
+++ b/libgo/runtime/chan.c
@@ -87,7 +87,7 @@ runtime_makechan_c(ChanType *t, int64 hint)
Hchan *c;
int32 n;
const Type *elem;
-
+
elem = t->__element_type;
if(hint < 0 || (int32)hint != hint || (elem->__size > 0 && (uintptr)hint > MaxMem / elem->__size))
@@ -191,7 +191,7 @@ runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
sg = dequeue(&c->recvq);
if(sg != nil) {
runtime_unlock(c);
-
+
gp = sg->g;
gp->param = sg;
if(sg->elem != nil)
@@ -530,7 +530,7 @@ runtime_selectnbrecv(ChanType *t, byte *v, Hchan *c)
runtime_chanrecv(t, c, v, &selected, nil);
return selected;
-}
+}
// func selectnbrecv2(elem *any, ok *bool, c chan any) bool
//
@@ -562,7 +562,7 @@ runtime_selectnbrecv2(ChanType *t, byte *v, _Bool *received, Hchan *c)
if(received != nil)
*received = r;
return selected;
-}
+}
// For reflect:
// func chansend(c chan, val iword, nb bool) (selected bool)
@@ -578,7 +578,7 @@ reflect_chansend(ChanType *t, Hchan *c, uintptr val, _Bool nb)
bool selected;
bool *sp;
byte *vp;
-
+
if(nb) {
selected = false;
sp = (bool*)&selected;
@@ -697,7 +697,7 @@ runtime_selectsend(Select *sel, Hchan *c, void *elem, int index)
// nil cases do not compete
if(c == nil)
return;
-
+
selectsend(sel, c, index, elem);
}
@@ -706,7 +706,7 @@ selectsend(Select *sel, Hchan *c, int index, void *elem)
{
int32 i;
Scase *cas;
-
+
i = sel->ncase;
if(i >= sel->tcase)
runtime_throw("selectsend: too many cases");
@@ -977,7 +977,7 @@ loop:
case CaseRecv:
enqueue(&c->recvq, sg);
break;
-
+
case CaseSend:
enqueue(&c->sendq, sg);
break;
diff --git a/libgo/runtime/cpuprof.c b/libgo/runtime/cpuprof.c
index 252948d6659..9bf5d11e687 100644
--- a/libgo/runtime/cpuprof.c
+++ b/libgo/runtime/cpuprof.c
@@ -105,6 +105,7 @@ struct Profile {
uint32 wtoggle;
bool wholding; // holding & need to release a log half
bool flushing; // flushing hash table - profile is over
+ bool eod_sent; // special end-of-data record sent; => flushing
};
static Lock lk;
@@ -115,6 +116,8 @@ static void add(Profile*, uintptr*, int32);
static bool evict(Profile*, Entry*);
static bool flushlog(Profile*);
+static uintptr eod[3] = {0, 1, 0};
+
// LostProfileData is a no-op function used in profiles
// to mark the number of profiling stack traces that were
// discarded due to slow data writers.
@@ -168,6 +171,7 @@ runtime_SetCPUProfileRate(int32 hz)
prof->wholding = false;
prof->wtoggle = 0;
prof->flushing = false;
+ prof->eod_sent = false;
runtime_noteclear(&prof->wait);
runtime_setcpuprofilerate(tick, hz);
@@ -414,6 +418,16 @@ breakflush:
}
// Made it through the table without finding anything to log.
+ if(!p->eod_sent) {
+ // We may not have space to append this to the partial log buf,
+ // so we always return a new slice for the end-of-data marker.
+ p->eod_sent = true;
+ ret.array = (byte*)eod;
+ ret.len = sizeof eod;
+ ret.cap = ret.len;
+ return ret;
+ }
+
// Finally done. Clean up and return nil.
p->flushing = false;
if(!runtime_cas(&p->handoff, p->handoff, 0))
diff --git a/libgo/runtime/print.c b/libgo/runtime/print.c
index c24304e2487..5a8e47e5373 100644
--- a/libgo/runtime/print.c
+++ b/libgo/runtime/print.c
@@ -20,10 +20,10 @@ gwrite(const void *v, int32 n)
runtime_write(2, v, n);
return;
}
-
+
if(g->writenbuf == 0)
return;
-
+
if(n > g->writenbuf)
n = g->writenbuf;
runtime_memmove(g->writebuf, v, n);
diff --git a/libgo/runtime/runtime.c b/libgo/runtime/runtime.c
index 72875fd53f7..e0a7925aed1 100644
--- a/libgo/runtime/runtime.c
+++ b/libgo/runtime/runtime.c
@@ -106,11 +106,15 @@ static byte** argv;
extern Slice os_Args asm ("os.Args");
extern Slice syscall_Envs asm ("syscall.Envs");
+void (*runtime_sysargs)(int32, uint8**);
+
void
runtime_args(int32 c, byte **v)
{
argc = c;
argv = v;
+ if(runtime_sysargs != nil)
+ runtime_sysargs(c, v);
}
void
@@ -234,7 +238,7 @@ runtime_showframe(const unsigned char *s)
if(traceback < 0)
traceback = runtime_gotraceback();
- return traceback > 1 || (__builtin_strchr((const char*)s, '.') != nil && __builtin_memcmp(s, "runtime.", 7) != 0);
+ return traceback > 1 || (s != nil && __builtin_strchr((const char*)s, '.') != nil && __builtin_memcmp(s, "runtime.", 7) != 0);
}
bool
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 4652d5c53c4..11cf39b26e6 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,97 @@
+2012-11-05 Benjamin Kosnik <bkoz@redhat.com>
+
+ PR libstdc++/28811
+ PR libstdc++/54482
+ * configure.ac (glibcxx_lt_pic_flag,
+ glibcxx_compiler_pic_flag,
+ glibcxx_compiler_shared_flag): New. Use them.
+ (lt_prog_compiler_pic_CXX): Set via glibcxx_*_flag(s) above.
+ (pic_mode): Set to default.
+ (PIC_CXXFLAGS): Remove.
+ * Makefile.am (PICFLAG, PICFLAG_FOR_TARGET): Remove. Comment.
+ * libsupc++/Makefile.am: Use glibcxx_ld_pic_flag and
+ glibcxx_compiler_shared_flag. Comment.
+ * src/c++11/Makefile.am: Same.
+ * src/c++98/Makefile.am: Same.
+ * src/Makefile.am: Use glibcxx_compiler_pic_flag.
+
+ * Makefile.in: Regenerated.
+ * aclocal.m4: Same.
+ * configure: Same.
+ * doc/Makefile.in: Same.
+ * include/Makefile.in: Same.
+ * libsupc++/Makefile.in: Same.
+ * po/Makefile.in: Same.
+ * python/Makefile.in: Same.
+ * src/Makefile.in: Same.
+ * src/c++11/Makefile.in: Same.
+ * src/c++98/Makefile.in: Same.
+ * testsuite/Makefile.in: Same.
+
+ * src/c++11/compatibility-atomic-c++0x.cc: Use
+ _GLIBCXX_SHARED instead of PIC to designate shared-only
+ code blocks.
+ * src/c++11/compatibility-c++0x.cc: Same.
+ * src/c++11/compatibility-thread-c++0x.cc: Same.
+ * src/c++98/compatibility-list-2.cc: Same.
+ * src/c++98/compatibility.cc: : Same.
+
+ * testsuite/17_intro/shared_with_static_deps.cc: New.
+
+ * doc/xml/manual/build_hacking.xml: Separate configure from
+ make/build issues, add build details.
+
+2012-11-05 Benjamin Kosnik <bkoz@redhat.com>
+ Oleg Smolsky <oleg@smolsky.net>
+
+ PR libstdc++/55028
+ * config/abi/pre/gnu-versioned-namespace.ver: Add symbols.
+ * testsuite/23_containers/unordered_multimap/insert/55028-debug.cc: New.
+
+2012-11-05 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/55215
+ * include/bits/random.tcc (mersenne_twister_engine<>::seed(_Sseq&)):
+ Assign state_size to _M_p.
+ * testsuite/26_numerics/random/mersenne_twister_engine/cons/55215.cc:
+ New.
+ * testsuite/26_numerics/random/independent_bits_engine/cons/55215.cc:
+ Likewise.
+ * testsuite/26_numerics/random/shuffle_order_engine/cons/55215.cc:
+ Likewise.
+ * testsuite/26_numerics/random/subtract_with_carry_engine/cons/
+ 55215.cc: Likewise.
+ * testsuite/26_numerics/random/discard_block_engine/cons/55215.cc:
+ Likewise.
+ * testsuite/26_numerics/random/linear_congruential_engine/cons/
+ 55215.cc: Likewise.
+
+2012-11-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/55169
+ * include/bits/random.h: Remove all uses of param().
+
+2012-11-01 Haakan Younes <hyounes@google.com>
+ Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/55047
+ * include/bits/random.h (exponential_distribution<>::operator):
+ Fix formula to std::log(result_type(1) - __aurng()).
+ * include/bits/random.tcc: Likewise, everywhere.
+
+2012-10-29 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/55123
+ * include/bits/shared_ptr_base.h (__shared_count::_S_create_from_up):
+ Do not instantiate allocator with element_type.
+ * testsuite/20_util/shared_ptr/cons/55123.cc: New.
+
+2012-10-10 Andrew MacLeod <amacleod@redhat.com>
+
+ PR libstdc++/54861
+ * include/bits/atomic_base.h (atomic_signal_fence): Call
+ __atomic_signal_fence instead of __atomic_thread_fence.
+
2012-09-20 Benjamin Kosnik <bkoz@redhat.com>
PR libstdc++/54102, part 2
diff --git a/libstdc++-v3/Makefile.am b/libstdc++-v3/Makefile.am
index 76ff04396ea..8be4f6c3c43 100644
--- a/libstdc++-v3/Makefile.am
+++ b/libstdc++-v3/Makefile.am
@@ -152,8 +152,6 @@ AM_MAKEFLAGS = \
"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
"MAKE=$(MAKE)" \
"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
- "PICFLAG=$(PICFLAG)" \
- "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
"SHELL=$(SHELL)" \
"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
"exec_prefix=$(exec_prefix)" \
diff --git a/libstdc++-v3/Makefile.in b/libstdc++-v3/Makefile.in
index 5089d0a63d9..afc698fea1e 100644
--- a/libstdc++-v3/Makefile.in
+++ b/libstdc++-v3/Makefile.in
@@ -188,7 +188,6 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PDFLATEX = @PDFLATEX@
-PIC_CXXFLAGS = @PIC_CXXFLAGS@
RANLIB = @RANLIB@
SECTION_FLAGS = @SECTION_FLAGS@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
@@ -236,7 +235,10 @@ glibcxx_MOFILES = @glibcxx_MOFILES@
glibcxx_PCHFLAGS = @glibcxx_PCHFLAGS@
glibcxx_POFILES = @glibcxx_POFILES@
glibcxx_builddir = @glibcxx_builddir@
+glibcxx_compiler_pic_flag = @glibcxx_compiler_pic_flag@
+glibcxx_compiler_shared_flag = @glibcxx_compiler_shared_flag@
glibcxx_localedir = @glibcxx_localedir@
+glibcxx_lt_pic_flag = @glibcxx_lt_pic_flag@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
@@ -353,8 +355,6 @@ AM_MAKEFLAGS = \
"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
"MAKE=$(MAKE)" \
"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
- "PICFLAG=$(PICFLAG)" \
- "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
"SHELL=$(SHELL)" \
"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
"exec_prefix=$(exec_prefix)" \
diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
index e7e91624759..bc90e0706fa 100644
--- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
+++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
@@ -131,6 +131,14 @@ GLIBCXX_7.0 {
_ZNK11__gnu_debug16_Error_formatter8_M_error*;
_ZNK11__gnu_debug16_Error_formatter17_M_get_max_lengthEv;
+ # __gnu_debug::_Safe_unordered_container_base
+ # __gnu_debug::_Safe_local_iterator_base
+ _ZN11__gnu_debug30_Safe_unordered_container_base7_M_swapERS0_;
+ _ZN11__gnu_debug30_Safe_unordered_container_base13_M_detach_allEv;
+ _ZN11__gnu_debug25_Safe_local_iterator_base9_M_attachEPNS_19_Safe_sequence_baseEb;
+ _ZN11__gnu_debug25_Safe_local_iterator_base9_M_detachEv;
+
+
# parallel mode
_ZN14__gnu_parallel9_Settings3getEv;
_ZN14__gnu_parallel9_Settings3setERS0_;
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index f5aefe2c1c4..b6424958200 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -602,7 +602,6 @@ ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
-PIC_CXXFLAGS
WARN_FLAGS
OPTIMIZE_CXXFLAGS
TOPLEVEL_INCLUDES
@@ -713,6 +712,9 @@ GLIBCXX_BUILD_PCH_FALSE
GLIBCXX_BUILD_PCH_TRUE
GLIBCXX_HOSTED_FALSE
GLIBCXX_HOSTED_TRUE
+glibcxx_compiler_shared_flag
+glibcxx_compiler_pic_flag
+glibcxx_lt_pic_flag
enable_static
enable_shared
lt_host_flags
@@ -5280,6 +5282,7 @@ $as_echo "$as_me: OS config directory is $os_include_dir" >&6;}
+# Libtool setup.
if test "x${with_newlib}" != "xyes"; then
enable_dlopen=yes
@@ -11497,7 +11500,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11500 "configure"
+#line 11503 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11603,7 +11606,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11606 "configure"
+#line 11609 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -14889,6 +14892,38 @@ esac
+# libtool variables for C++ shared and position-independent compiles.
+#
+# Use glibcxx_lt_pic_flag to designate the automake variable
+# used to encapsulate the default libtool approach to creating objects
+# with position-independent code. Default: -prefer-pic.
+#
+# Use glibcxx_compiler_shared_flag to designate a compile-time flags for
+# creating shared objects. Default: -D_GLIBCXX_SHARED.
+#
+# Use glibcxx_compiler_pic_flag to designate a compile-time flags for
+# creating position-independent objects. This varies with the target
+# hardware and operating system, but is often: -DPIC -fPIC.
+if test "$enable_shared" = yes; then
+ glibcxx_lt_pic_flag="-prefer-pic"
+ glibcxx_compiler_pic_flag="$lt_prog_compiler_pic_CXX"
+ glibcxx_compiler_shared_flag="-D_GLIBCXX_SHARED"
+
+else
+ glibcxx_lt_pic_flag=
+ glibcxx_compiler_pic_flag=
+ glibcxx_compiler_shared_flag=
+fi
+
+
+
+
+# Override the libtool's pic_flag and pic_mode.
+# Do this step after AM_PROG_LIBTOOL, but before AC_OUTPUT.
+# NB: this impacts --with-pic and --without-pic.
+lt_prog_compiler_pic_CXX="$glibcxx_compiler_pic_flag $glibcxx_compiler_shared_flag"
+pic_mode='default'
+
# Eliminate -lstdc++ addition to postdeps for cross compiles.
postdeps_CXX=`echo " $postdeps_CXX " | sed 's, -lstdc++ ,,g'`
@@ -14961,7 +14996,7 @@ fi
#
# Fake what AC_TRY_COMPILE does. XXX Look at redoing this new-style.
cat > conftest.$ac_ext << EOF
-#line 14964 "configure"
+#line 14999 "configure"
struct S { ~S(); };
void bar();
void foo()
@@ -15296,7 +15331,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; }
# Fake what AC_TRY_COMPILE does.
cat > conftest.$ac_ext << EOF
-#line 15299 "configure"
+#line 15334 "configure"
int main()
{
typedef bool atomic_type;
@@ -15331,7 +15366,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15334 "configure"
+#line 15369 "configure"
int main()
{
typedef short atomic_type;
@@ -15366,7 +15401,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15369 "configure"
+#line 15404 "configure"
int main()
{
// NB: _Atomic_word not necessarily int.
@@ -15402,7 +15437,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15405 "configure"
+#line 15440 "configure"
int main()
{
typedef long long atomic_type;
@@ -15481,7 +15516,7 @@ $as_echo "$as_me: WARNING: Performance of certain classes will degrade as a resu
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 15484 "configure"
+#line 15519 "configure"
int main()
{
_Decimal32 d1;
@@ -15523,7 +15558,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 15526 "configure"
+#line 15561 "configure"
template<typename T1, typename T2>
struct same
{ typedef T2 type; };
@@ -15557,7 +15592,7 @@ $as_echo "$enable_int128" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15560 "configure"
+#line 15595 "configure"
template<typename T1, typename T2>
struct same
{ typedef T2 type; };
@@ -66471,13 +66506,6 @@ $as_echo "$gxx_include_dir" >&6; }
-if test "$enable_shared" = yes; then
- PIC_CXXFLAGS="-prefer-pic"
-else
- PIC_CXXFLAGS=
-fi
-
-
ac_config_files="$ac_config_files Makefile"
ac_config_files="$ac_config_files scripts/testsuite_flags"
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index 6a3db060508..ce1f6c48165 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -88,6 +88,7 @@ CXXFLAGS="$save_CXXFLAGS"
# up critical shell variables.
GLIBCXX_CONFIGURE
+# Libtool setup.
if test "x${with_newlib}" != "xyes"; then
AC_LIBTOOL_DLOPEN
fi
@@ -96,6 +97,38 @@ ACX_LT_HOST_FLAGS
AC_SUBST(enable_shared)
AC_SUBST(enable_static)
+# libtool variables for C++ shared and position-independent compiles.
+#
+# Use glibcxx_lt_pic_flag to designate the automake variable
+# used to encapsulate the default libtool approach to creating objects
+# with position-independent code. Default: -prefer-pic.
+#
+# Use glibcxx_compiler_shared_flag to designate a compile-time flags for
+# creating shared objects. Default: -D_GLIBCXX_SHARED.
+#
+# Use glibcxx_compiler_pic_flag to designate a compile-time flags for
+# creating position-independent objects. This varies with the target
+# hardware and operating system, but is often: -DPIC -fPIC.
+if test "$enable_shared" = yes; then
+ glibcxx_lt_pic_flag="-prefer-pic"
+ glibcxx_compiler_pic_flag="$lt_prog_compiler_pic_CXX"
+ glibcxx_compiler_shared_flag="-D_GLIBCXX_SHARED"
+
+else
+ glibcxx_lt_pic_flag=
+ glibcxx_compiler_pic_flag=
+ glibcxx_compiler_shared_flag=
+fi
+AC_SUBST(glibcxx_lt_pic_flag)
+AC_SUBST(glibcxx_compiler_pic_flag)
+AC_SUBST(glibcxx_compiler_shared_flag)
+
+# Override the libtool's pic_flag and pic_mode.
+# Do this step after AM_PROG_LIBTOOL, but before AC_OUTPUT.
+# NB: this impacts --with-pic and --without-pic.
+lt_prog_compiler_pic_CXX="$glibcxx_compiler_pic_flag $glibcxx_compiler_shared_flag"
+pic_mode='default'
+
# Eliminate -lstdc++ addition to postdeps for cross compiles.
postdeps_CXX=`echo " $postdeps_CXX " | sed 's, -lstdc++ ,,g'`
@@ -421,13 +454,6 @@ GLIBCXX_EXPORT_INSTALL_INFO
GLIBCXX_EXPORT_INCLUDES
GLIBCXX_EXPORT_FLAGS
-if test "$enable_shared" = yes; then
- PIC_CXXFLAGS="-prefer-pic"
-else
- PIC_CXXFLAGS=
-fi
-AC_SUBST(PIC_CXXFLAGS)
-
dnl In autoconf 2.5x, AC_OUTPUT is replaced by four AC_CONFIG_* macros,
dnl which can all be called multiple times as needed, plus one (different)
dnl AC_OUTPUT macro. This one lists the files to be created:
diff --git a/libstdc++-v3/doc/Makefile.in b/libstdc++-v3/doc/Makefile.in
index 58407ba7278..db265e962c2 100644
--- a/libstdc++-v3/doc/Makefile.in
+++ b/libstdc++-v3/doc/Makefile.in
@@ -160,7 +160,6 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PDFLATEX = @PDFLATEX@
-PIC_CXXFLAGS = @PIC_CXXFLAGS@
RANLIB = @RANLIB@
SECTION_FLAGS = @SECTION_FLAGS@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
@@ -210,7 +209,10 @@ glibcxx_MOFILES = @glibcxx_MOFILES@
glibcxx_PCHFLAGS = @glibcxx_PCHFLAGS@
glibcxx_POFILES = @glibcxx_POFILES@
glibcxx_builddir = @glibcxx_builddir@
+glibcxx_compiler_pic_flag = @glibcxx_compiler_pic_flag@
+glibcxx_compiler_shared_flag = @glibcxx_compiler_shared_flag@
glibcxx_localedir = @glibcxx_localedir@
+glibcxx_lt_pic_flag = @glibcxx_lt_pic_flag@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
diff --git a/libstdc++-v3/doc/xml/manual/build_hacking.xml b/libstdc++-v3/doc/xml/manual/build_hacking.xml
index daac8c0e2f0..771d005e71b 100644
--- a/libstdc++-v3/doc/xml/manual/build_hacking.xml
+++ b/libstdc++-v3/doc/xml/manual/build_hacking.xml
@@ -8,7 +8,13 @@
C++
</keyword>
<keyword>
- BUILD_HACKING
+ build
+ </keyword>
+ <keyword>
+ configure
+ </keyword>
+ <keyword>
+ hacking
</keyword>
<keyword>
version
@@ -38,7 +44,50 @@
</para>
</section>
-<section xml:id="build_hacking.map"><info><title>Overview: What Comes from Where</title></info>
+<section xml:id="build_hacking.overview">
+<info><title>Overview</title></info>
+
+<section xml:id="build_hacking.overview.basic">
+<info><title>General Process</title></info>
+
+<para>
+ The configure process begins the act of building libstdc++, and is
+ started via:
+</para>
+
+<screen>
+<computeroutput>
+configure
+</computeroutput>
+</screen>
+
+<para>
+The <filename>configure</filename> file is a script generated (via
+<command>autoconf</command>) from the file
+<filename>configure.ac</filename>.
+</para>
+
+
+<para>
+ After the configure process is complete,
+</para>
+
+<screen>
+<computeroutput>
+make all
+</computeroutput>
+</screen>
+
+<para>
+in the build directory starts the build process. The <literal>all</literal> target comes from the <filename>Makefile</filename> file, which is generated via <command>configure</command> from the <filename>Makefile.in</filename> file, which is in turn generated (via
+<command>automake</command>) from the file
+<filename>Makefile.am</filename>.
+</para>
+
+</section>
+
+
+<section xml:id="build_hacking.overview.map"><info><title>What Comes from Where</title></info>
<figure>
@@ -57,19 +106,19 @@
</figure>
<para>
- Regenerate all generated files by using the command sequence
- <code>"autoreconf"</code> at the top level of the libstdc++ source
- directory. The following will also work, but is much more complex:
- <code>"aclocal-1.11 &amp;&amp; autoconf-2.64 &amp;&amp;
- autoheader-2.64 &amp;&amp; automake-1.11"</code> The version
- numbers may be absent entirely or otherwise vary depending on
- <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://gcc.gnu.org/install/prerequisites.html">the
- current requirements</link> and your vendor's choice of
- installation names.
+ Regenerate all generated files by using the command
+ <code>autoreconf</code> at the top level of the libstdc++ source
+ directory.
</para>
</section>
-<section xml:id="build_hacking.scripts"><info><title>Storing Information in non-AC files (like configure.host)</title></info>
+</section> <!-- overview -->
+
+
+<section xml:id="build_hacking.configure">
+<info><title>Configure</title></info>
+
+<section xml:id="build_hacking.configure.scripts"><info><title>Storing Information in non-AC files (like configure.host)</title></info>
<para>
@@ -101,7 +150,7 @@
</para>
</section>
-<section xml:id="build_hacking.conventions"><info><title>Coding and Commenting Conventions</title></info>
+<section xml:id="build_hacking.configure.conventions"><info><title>Coding and Commenting Conventions</title></info>
<para>
@@ -126,7 +175,7 @@
</para>
</section>
-<section xml:id="build_hacking.acinclude"><info><title>The acinclude.m4 layout</title></info>
+<section xml:id="build_hacking.configure.acinclude"><info><title>The acinclude.m4 layout</title></info>
<para>
The nice thing about acinclude.m4/aclocal.m4 is that macros aren't
@@ -217,7 +266,7 @@
</section>
-<section xml:id="build_hacking.enable"><info><title><constant>GLIBCXX_ENABLE</constant>, the <literal>--enable</literal> maker</title></info>
+<section xml:id="build_hacking.configure.enable"><info><title><constant>GLIBCXX_ENABLE</constant>, the <literal>--enable</literal> maker</title></info>
<para>
@@ -351,5 +400,86 @@
</para>
</section>
+</section> <!-- configure -->
+
+<section xml:id="build_hacking.make"><info><title>Make</title></info>
+
+ <para>
+ The build process has to make all of object files needed for
+ static or shared libraries, but first it has to generate some
+ include files. The general order is as follows:
+ </para>
+
+<orderedlist>
+ <listitem>
+ <para>
+ make include files, make pre-compiled headers
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ make libsupc++
+ </para>
+ <para>
+ Generates a libtool convenience library,
+ <filename>libsupc++convenience</filename> with language-support
+ routines. Also generates a freestanding static library,
+ <filename>libsupc++.a</filename>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ make src
+ </para>
+ <para>
+ Generates two convenience libraries, one for C++98 and one for
+ C++11, various compability files for shared and static
+ libraries, and then collects all the generated bits and creates
+ the final libstdc++ libraries.
+ </para>
+<orderedlist>
+ <listitem>
+ <para>
+ make src/c++98
+ </para>
+ <para>
+ Generates a libtool convenience library,
+ <filename>libc++98convenience</filename> with language-support
+ routines. Uses the <literal>-std=gnu++98</literal> dialect.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ make src/c++11
+ </para>
+ <para>
+ Generates a libtool convenience library,
+ <filename>libc++11convenience</filename> with language-support
+ routines. Uses the <literal>-std=gnu++11</literal> dialect.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ make src
+ </para>
+ <para>
+ Generates needed compatibility objects for shared and static
+ libraries. Shared-only code is seggregated at compile-time via
+ the macro <literal>_GLIBCXX_SHARED</literal>.
+ </para>
+
+ <para>
+ Then, collects all the generated convenience libraries, adds in
+ any required compatibility objects, and creates the final shared
+ and static libraries: <filename>libstdc++.so</filename> and
+ <filename>libstdc++.a</filename>.
+ </para>
+
+ </listitem>
+</orderedlist>
+ </listitem>
+</orderedlist>
+
+</section> <!-- make -->
</section>
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 9344d467082..0b6205c1543 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -160,7 +160,6 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PDFLATEX = @PDFLATEX@
-PIC_CXXFLAGS = @PIC_CXXFLAGS@
RANLIB = @RANLIB@
SECTION_FLAGS = @SECTION_FLAGS@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
@@ -208,7 +207,10 @@ glibcxx_MOFILES = @glibcxx_MOFILES@
glibcxx_PCHFLAGS = @glibcxx_PCHFLAGS@
glibcxx_POFILES = @glibcxx_POFILES@
glibcxx_builddir = @glibcxx_builddir@
+glibcxx_compiler_pic_flag = @glibcxx_compiler_pic_flag@
+glibcxx_compiler_shared_flag = @glibcxx_compiler_shared_flag@
glibcxx_localedir = @glibcxx_localedir@
+glibcxx_lt_pic_flag = @glibcxx_lt_pic_flag@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index 9d5f4eb6ff0..bd14e35cd5a 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -73,7 +73,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline void
atomic_signal_fence(memory_order __m) noexcept
- { __atomic_thread_fence(__m); }
+ { __atomic_signal_fence(__m); }
/// kill_dependency
template<typename _Tp>
diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h
index aa4ce3e8209..1e8caa023b3 100644
--- a/libstdc++-v3/include/bits/random.h
+++ b/libstdc++-v3/include/bits/random.h
@@ -1,6 +1,6 @@
// random number generation -*- C++ -*-
-// Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+// Copyright (C) 2009-2012 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
@@ -1719,28 +1719,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng,
const param_type& __p);
+ /**
+ * @brief Return true if two uniform integer distributions have
+ * the same parameters.
+ */
+ friend bool
+ operator==(const uniform_int_distribution& __d1,
+ const uniform_int_distribution& __d2)
+ { return __d1._M_param == __d2._M_param; }
+
+ private:
param_type _M_param;
};
/**
* @brief Return true if two uniform integer distributions have
- * the same parameters.
- */
- template<typename _IntType>
- inline bool
- operator==(const std::uniform_int_distribution<_IntType>& __d1,
- const std::uniform_int_distribution<_IntType>& __d2)
- { return __d1.param() == __d2.param(); }
-
- /**
- * @brief Return true if two uniform integer distributions have
* different parameters.
*/
template<typename _IntType>
@@ -1894,7 +1894,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
@@ -1906,22 +1906,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return (__aurng() * (__p.b() - __p.a())) + __p.a();
}
+ /**
+ * @brief Return true if two uniform real distributions have
+ * the same parameters.
+ */
+ friend bool
+ operator==(const uniform_real_distribution& __d1,
+ const uniform_real_distribution& __d2)
+ { return __d1._M_param == __d2._M_param; }
+
private:
param_type _M_param;
};
/**
* @brief Return true if two uniform real distributions have
- * the same parameters.
- */
- template<typename _IntType>
- inline bool
- operator==(const std::uniform_real_distribution<_IntType>& __d1,
- const std::uniform_real_distribution<_IntType>& __d2)
- { return __d1.param() == __d2.param(); }
-
- /**
- * @brief Return true if two uniform real distributions have
* different parameters.
*/
template<typename _IntType>
@@ -2088,7 +2087,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
@@ -2261,7 +2260,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
@@ -2277,7 +2276,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend bool
operator==(const lognormal_distribution& __d1,
const lognormal_distribution& __d2)
- { return (__d1.param() == __d2.param()
+ { return (__d1._M_param == __d2._M_param
&& __d1._M_nd == __d2._M_nd); }
/**
@@ -2454,7 +2453,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
@@ -2469,7 +2468,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend bool
operator==(const gamma_distribution& __d1,
const gamma_distribution& __d2)
- { return (__d1.param() == __d2.param()
+ { return (__d1._M_param == __d2._M_param
&& __d1._M_nd == __d2._M_nd); }
/**
@@ -2633,7 +2632,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend bool
operator==(const chi_squared_distribution& __d1,
const chi_squared_distribution& __d2)
- { return __d1.param() == __d2.param() && __d1._M_gd == __d2._M_gd; }
+ { return __d1._M_param == __d2._M_param && __d1._M_gd == __d2._M_gd; }
/**
* @brief Inserts a %chi_squared_distribution random number distribution
@@ -2788,29 +2787,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng,
const param_type& __p);
+ /**
+ * @brief Return true if two Cauchy distributions have
+ * the same parameters.
+ */
+ friend bool
+ operator==(const cauchy_distribution& __d1,
+ const cauchy_distribution& __d2)
+ { return __d1._M_param == __d2._M_param; }
+
private:
param_type _M_param;
};
/**
* @brief Return true if two Cauchy distributions have
- * the same parameters.
- */
- template<typename _RealType>
- inline bool
- operator==(const std::cauchy_distribution<_RealType>& __d1,
- const std::cauchy_distribution<_RealType>& __d2)
- { return __d1.param() == __d2.param(); }
-
- /**
- * @brief Return true if two Cauchy distributions have
* different parameters.
*/
template<typename _RealType>
@@ -2985,7 +2983,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend bool
operator==(const fisher_f_distribution& __d1,
const fisher_f_distribution& __d2)
- { return (__d1.param() == __d2.param()
+ { return (__d1._M_param == __d2._M_param
&& __d1._M_gd_x == __d2._M_gd_x
&& __d1._M_gd_y == __d2._M_gd_y); }
@@ -3158,7 +3156,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend bool
operator==(const student_t_distribution& __d1,
const student_t_distribution& __d2)
- { return (__d1.param() == __d2.param()
+ { return (__d1._M_param == __d2._M_param
&& __d1._M_nd == __d2._M_nd && __d1._M_gd == __d2._M_gd); }
/**
@@ -3318,7 +3316,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
@@ -3333,21 +3331,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return false;
}
+ /**
+ * @brief Return true if two Bernoulli distributions have
+ * the same parameters.
+ */
+ friend bool
+ operator==(const bernoulli_distribution& __d1,
+ const bernoulli_distribution& __d2)
+ { return __d1._M_param == __d2._M_param; }
+
private:
param_type _M_param;
};
/**
* @brief Return true if two Bernoulli distributions have
- * the same parameters.
- */
- inline bool
- operator==(const std::bernoulli_distribution& __d1,
- const std::bernoulli_distribution& __d2)
- { return __d1.param() == __d2.param(); }
-
- /**
- * @brief Return true if two Bernoulli distributions have
* different parameters.
*/
inline bool
@@ -3518,7 +3516,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
@@ -3534,9 +3532,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator==(const binomial_distribution& __d1,
const binomial_distribution& __d2)
#ifdef _GLIBCXX_USE_C99_MATH_TR1
- { return __d1.param() == __d2.param() && __d1._M_nd == __d2._M_nd; }
+ { return __d1._M_param == __d2._M_param && __d1._M_nd == __d2._M_nd; }
#else
- { return __d1.param() == __d2.param(); }
+ { return __d1._M_param == __d2._M_param; }
#endif
/**
@@ -3701,29 +3699,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng,
const param_type& __p);
+ /**
+ * @brief Return true if two geometric distributions have
+ * the same parameters.
+ */
+ friend bool
+ operator==(const geometric_distribution& __d1,
+ const geometric_distribution& __d2)
+ { return __d1._M_param == __d2._M_param; }
+
private:
param_type _M_param;
};
/**
* @brief Return true if two geometric distributions have
- * the same parameters.
- */
- template<typename _IntType>
- inline bool
- operator==(const std::geometric_distribution<_IntType>& __d1,
- const std::geometric_distribution<_IntType>& __d2)
- { return __d1.param() == __d2.param(); }
-
- /**
- * @brief Return true if two geometric distributions have
* different parameters.
*/
template<typename _IntType>
@@ -3889,7 +3886,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend bool
operator==(const negative_binomial_distribution& __d1,
const negative_binomial_distribution& __d2)
- { return __d1.param() == __d2.param() && __d1._M_gd == __d2._M_gd; }
+ { return __d1._M_param == __d2._M_param && __d1._M_gd == __d2._M_gd; }
/**
* @brief Inserts a %negative_binomial_distribution random
@@ -4057,7 +4054,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
@@ -4073,9 +4070,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator==(const poisson_distribution& __d1,
const poisson_distribution& __d2)
#ifdef _GLIBCXX_USE_C99_MATH_TR1
- { return __d1.param() == __d2.param() && __d1._M_nd == __d2._M_nd; }
+ { return __d1._M_param == __d2._M_param && __d1._M_nd == __d2._M_nd; }
#else
- { return __d1.param() == __d2.param(); }
+ { return __d1._M_param == __d2._M_param; }
#endif
/**
@@ -4238,7 +4235,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
@@ -4247,24 +4244,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
__detail::_Adaptor<_UniformRandomNumberGenerator, result_type>
__aurng(__urng);
- return -std::log(__aurng()) / __p.lambda();
+ return -std::log(result_type(1) - __aurng()) / __p.lambda();
}
+ /**
+ * @brief Return true if two exponential distributions have the same
+ * parameters.
+ */
+ friend bool
+ operator==(const exponential_distribution& __d1,
+ const exponential_distribution& __d2)
+ { return __d1._M_param == __d2._M_param; }
+
private:
param_type _M_param;
};
/**
- * @brief Return true if two exponential distributions have the same
- * parameters.
- */
- template<typename _RealType>
- inline bool
- operator==(const std::exponential_distribution<_RealType>& __d1,
- const std::exponential_distribution<_RealType>& __d2)
- { return __d1.param() == __d2.param(); }
-
- /**
* @brief Return true if two exponential distributions have different
* parameters.
*/
@@ -4418,28 +4414,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng,
const param_type& __p);
+ /**
+ * @brief Return true if two Weibull distributions have the same
+ * parameters.
+ */
+ friend bool
+ operator==(const weibull_distribution& __d1,
+ const weibull_distribution& __d2)
+ { return __d1._M_param == __d2._M_param; }
+
private:
param_type _M_param;
};
/**
- * @brief Return true if two Weibull distributions have the same
- * parameters.
- */
- template<typename _RealType>
- inline bool
- operator==(const std::weibull_distribution<_RealType>& __d1,
- const std::weibull_distribution<_RealType>& __d2)
- { return __d1.param() == __d2.param(); }
-
- /**
* @brief Return true if two Weibull distributions have different
* parameters.
*/
@@ -4593,28 +4588,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng,
const param_type& __p);
+ /**
+ * @brief Return true if two extreme value distributions have the same
+ * parameters.
+ */
+ friend bool
+ operator==(const extreme_value_distribution& __d1,
+ const extreme_value_distribution& __d2)
+ { return __d1._M_param == __d2._M_param; }
+
private:
param_type _M_param;
};
/**
- * @brief Return true if two extreme value distributions have the same
- * parameters.
- */
- template<typename _RealType>
- inline bool
- operator==(const std::extreme_value_distribution<_RealType>& __d1,
- const std::extreme_value_distribution<_RealType>& __d2)
- { return __d1.param() == __d2.param(); }
-
- /**
* @brief Return true if two extreme value distributions have different
* parameters.
*/
@@ -4794,7 +4788,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
@@ -4802,6 +4796,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const param_type& __p);
/**
+ * @brief Return true if two discrete distributions have the same
+ * parameters.
+ */
+ friend bool
+ operator==(const discrete_distribution& __d1,
+ const discrete_distribution& __d2)
+ { return __d1._M_param == __d2._M_param; }
+
+ /**
* @brief Inserts a %discrete_distribution random number distribution
* @p __x into the output stream @p __os.
*
@@ -4837,16 +4840,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
/**
- * @brief Return true if two discrete distributions have the same
- * parameters.
- */
- template<typename _IntType>
- inline bool
- operator==(const std::discrete_distribution<_IntType>& __d1,
- const std::discrete_distribution<_IntType>& __d2)
- { return __d1.param() == __d2.param(); }
-
- /**
* @brief Return true if two discrete distributions have different
* parameters.
*/
@@ -5032,7 +5025,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
@@ -5040,6 +5033,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const param_type& __p);
/**
+ * @brief Return true if two piecewise constant distributions have the
+ * same parameters.
+ */
+ friend bool
+ operator==(const piecewise_constant_distribution& __d1,
+ const piecewise_constant_distribution& __d2)
+ { return __d1._M_param == __d2._M_param; }
+
+ /**
* @brief Inserts a %piecewise_constan_distribution random
* number distribution @p __x into the output stream @p __os.
*
@@ -5076,16 +5078,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
/**
- * @brief Return true if two piecewise constant distributions have the
- * same parameters.
- */
- template<typename _RealType>
- inline bool
- operator==(const std::piecewise_constant_distribution<_RealType>& __d1,
- const std::piecewise_constant_distribution<_RealType>& __d2)
- { return __d1.param() == __d2.param(); }
-
- /**
* @brief Return true if two piecewise constant distributions have
* different parameters.
*/
@@ -5274,7 +5266,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _UniformRandomNumberGenerator>
result_type
operator()(_UniformRandomNumberGenerator& __urng)
- { return this->operator()(__urng, this->param()); }
+ { return this->operator()(__urng, _M_param); }
template<typename _UniformRandomNumberGenerator>
result_type
@@ -5282,6 +5274,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const param_type& __p);
/**
+ * @brief Return true if two piecewise linear distributions have the
+ * same parameters.
+ */
+ friend bool
+ operator==(const piecewise_linear_distribution& __d1,
+ const piecewise_linear_distribution& __d2)
+ { return __d1._M_param == __d2._M_param; }
+
+ /**
* @brief Inserts a %piecewise_linear_distribution random number
* distribution @p __x into the output stream @p __os.
*
@@ -5318,16 +5319,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
/**
- * @brief Return true if two piecewise linear distributions have the
- * same parameters.
- */
- template<typename _RealType>
- inline bool
- operator==(const std::piecewise_linear_distribution<_RealType>& __d1,
- const std::piecewise_linear_distribution<_RealType>& __d2)
- { return __d1.param() == __d2.param(); }
-
- /**
* @brief Return true if two piecewise linear distributions have
* different parameters.
*/
diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc
index 5b90e5a6157..a182dfb838a 100644
--- a/libstdc++-v3/include/bits/random.tcc
+++ b/libstdc++-v3/include/bits/random.tcc
@@ -1,6 +1,6 @@
// random number generation (out of line) -*- C++ -*-
-// Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+// Copyright (C) 2009-2012 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
@@ -401,6 +401,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
if (__zero)
_M_x[0] = __detail::_Shift<_UIntType, __w - 1>::__value;
+ _M_p = state_size;
}
template<typename _UIntType, size_t __w,
@@ -1053,7 +1054,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
double __cand;
do
- __cand = std::floor(std::log(__aurng()) / __param._M_log_1_p);
+ __cand = std::floor(std::log(1.0 - __aurng()) / __param._M_log_1_p);
while (__cand >= __thr);
return result_type(__cand + __naf);
@@ -1258,7 +1259,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
do
{
const double __u = __c * __aurng();
- const double __e = -std::log(__aurng());
+ const double __e = -std::log(1.0 - __aurng());
double __w = 0.0;
@@ -1290,7 +1291,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__x = 1;
else
{
- const double __v = -std::log(__aurng());
+ const double __v = -std::log(1.0 - __aurng());
const double __y = __param._M_d
+ __v * __2cx / __param._M_d;
__x = std::ceil(__y);
@@ -1434,7 +1435,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
do
{
- const double __e = -std::log(__aurng());
+ const double __e = -std::log(1.0 - __aurng());
__sum += __e / (__t - __x);
__x += 1;
}
@@ -1502,7 +1503,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__reject = __y >= __param._M_d1;
if (!__reject)
{
- const double __e = -std::log(__aurng());
+ const double __e = -std::log(1.0 - __aurng());
__x = std::floor(__y);
__v = -__e - __n * __n / 2 + __param._M_c;
}
@@ -1514,15 +1515,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__reject = __y >= __param._M_d2;
if (!__reject)
{
- const double __e = -std::log(__aurng());
+ const double __e = -std::log(1.0 - __aurng());
__x = std::floor(-__y);
__v = -__e - __n * __n / 2;
}
}
else if (__u <= __a123)
{
- const double __e1 = -std::log(__aurng());
- const double __e2 = -std::log(__aurng());
+ const double __e1 = -std::log(1.0 - __aurng());
+ const double __e2 = -std::log(1.0 - __aurng());
const double __y = __param._M_d1
+ 2 * __s1s * __e1 / __param._M_d1;
@@ -1533,8 +1534,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
else
{
- const double __e1 = -std::log(__aurng());
- const double __e2 = -std::log(__aurng());
+ const double __e1 = -std::log(1.0 - __aurng());
+ const double __e2 = -std::log(1.0 - __aurng());
const double __y = __param._M_d2
+ 2 * __s2s * __e1 / __param._M_d2;
@@ -2136,7 +2137,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
__detail::_Adaptor<_UniformRandomNumberGenerator, result_type>
__aurng(__urng);
- return __p.b() * std::pow(-std::log(__aurng()),
+ return __p.b() * std::pow(-std::log(result_type(1) - __aurng()),
result_type(1) / __p.a());
}
@@ -2194,7 +2195,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
__detail::_Adaptor<_UniformRandomNumberGenerator, result_type>
__aurng(__urng);
- return __p.a() - __p.b() * std::log(-std::log(__aurng()));
+ return __p.a() - __p.b() * std::log(-std::log(result_type(1)
+ - __aurng()));
}
template<typename _RealType, typename _CharT, typename _Traits>
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index 39449f1b4bb..0d60eeffa5b 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -621,7 +621,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r,
typename std::enable_if<!std::is_reference<_Del>::value>::type* = 0)
{
- return new _Sp_counted_deleter<_Tp*, _Del, std::allocator<_Tp>,
+ return new _Sp_counted_deleter<_Tp*, _Del, std::allocator<void>,
_Lp>(__r.get(), __r.get_deleter());
}
@@ -632,7 +632,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typedef typename std::remove_reference<_Del>::type _Del1;
typedef std::reference_wrapper<_Del1> _Del2;
- return new _Sp_counted_deleter<_Tp*, _Del2, std::allocator<_Tp>,
+ return new _Sp_counted_deleter<_Tp*, _Del2, std::allocator<void>,
_Lp>(__r.get(), std::ref(__r.get_deleter()));
}
diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am
index eaf109e7309..7c72f58df85 100644
--- a/libstdc++-v3/libsupc++/Makefile.am
+++ b/libstdc++-v3/libsupc++/Makefile.am
@@ -98,33 +98,6 @@ sources = \
libsupc___la_SOURCES = $(sources) $(c_sources)
libsupc__convenience_la_SOURCES = $(sources) $(c_sources)
-# AM_CXXFLAGS needs to be in each subdirectory so that it can be
-# modified in a per-library or per-sub-library way. Need to manually
-# set this option because CONFIG_CXXFLAGS has to be after
-# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden
-# as the occasion call for it.
-AM_CXXFLAGS = \
- $(PIC_CXXFLAGS) \
- $(XTEMPLATE_FLAGS) \
- $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
-
-AM_MAKEFLAGS = \
- "gxx_include_dir=$(gxx_include_dir)"
-
-
-# Use special rules for pulling things out of libiberty. These
-# objects should be compiled with the "C" compiler, not the C++
-# compiler, and also should not use the C++ includes.
-C_INCLUDES = -I.. -I$(toplevel_srcdir)/libiberty -I$(toplevel_srcdir)/include
-C_COMPILE = \
- $(CC) $(DEFS) $(C_INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-
-# LTCOMPILE is copied from LTCXXCOMPILE below.
-LTCOMPILE = $(LIBTOOL) --tag CC --tag disable-shared $(LIBTOOLFLAGS) --mode=compile \
- $(CC) $(DEFS) $(C_INCLUDES) $(PIC_CXXFLAGS) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-
cp-demangle.c:
rm -f $@
$(LN_S) $(toplevel_srcdir)/libiberty/cp-demangle.c $@
@@ -155,13 +128,37 @@ nested_exception.lo: nested_exception.cc
nested_exception.o: nested_exception.cc
$(CXXCOMPILE) -std=gnu++0x -c $<
-# Libtool notes
+# AM_CXXFLAGS needs to be in each subdirectory so that it can be
+# modified in a per-library or per-sub-library way. Need to manually
+# set this option because CONFIG_CXXFLAGS has to be after
+# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden
+# as the occasion call for it.
+AM_CXXFLAGS = \
+ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
+ $(XTEMPLATE_FLAGS) \
+ $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
+
+AM_MAKEFLAGS = \
+ "gxx_include_dir=$(gxx_include_dir)"
-# 1) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
-# last. (That way, things like -O2 passed down from the toplevel can
-# be overridden by --enable-debug.)
-# 2) In general, libtool expects an argument such as `--tag=CXX' when
+# Use special rules for pulling things out of libiberty. These
+# objects should be compiled with the "C" compiler, not the C++
+# compiler, and also should not use the C++ includes.
+C_INCLUDES = -I.. -I$(toplevel_srcdir)/libiberty -I$(toplevel_srcdir)/include
+C_COMPILE = \
+ $(CC) $(DEFS) $(C_INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+
+# LTCOMPILE is copied from LTCXXCOMPILE below.
+LTCOMPILE = $(LIBTOOL) --tag CC --tag disable-shared $(LIBTOOLFLAGS) --mode=compile \
+ $(CC) $(DEFS) $(C_INCLUDES) \
+ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+
+# Libtool notes
+
+# 1) In general, libtool expects an argument such as `--tag=CXX' when
# using the C++ compiler, because that will enable the settings
# detected when C++ support was being configured. However, when no
# such flag is given in the command line, libtool attempts to figure
@@ -173,9 +170,18 @@ nested_exception.o: nested_exception.cc
# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe
# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to
# attempt to infer which configuration to use.
-#
-# We have to put --tag disable-shared after --tag CXX lest things
-# CXX undo the affect of disable-shared.
+#
+# The second tag argument, `--tag disable-shared` means that libtool
+# only compiles each source once, for static objects. In actuality,
+# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to
+# the libtool command that is used create the object, which is
+# suitable for shared libraries. The `--tag disable-shared` must be
+# placed after --tag CXX lest things CXX undo the affect of
+# disable-shared.
+
+# 2) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
+# last. (That way, things like -O2 passed down from the toplevel can
+# be overridden by --enable-debug.)
LTCXXCOMPILE = \
$(LIBTOOL) --tag CXX --tag disable-shared \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in
index 831f22be933..a75d543028a 100644
--- a/libstdc++-v3/libsupc++/Makefile.in
+++ b/libstdc++-v3/libsupc++/Makefile.in
@@ -220,7 +220,6 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PDFLATEX = @PDFLATEX@
-PIC_CXXFLAGS = @PIC_CXXFLAGS@
RANLIB = @RANLIB@
SECTION_FLAGS = @SECTION_FLAGS@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
@@ -268,7 +267,10 @@ glibcxx_MOFILES = @glibcxx_MOFILES@
glibcxx_PCHFLAGS = @glibcxx_PCHFLAGS@
glibcxx_POFILES = @glibcxx_POFILES@
glibcxx_builddir = @glibcxx_builddir@
+glibcxx_compiler_pic_flag = @glibcxx_compiler_pic_flag@
+glibcxx_compiler_shared_flag = @glibcxx_compiler_shared_flag@
glibcxx_localedir = @glibcxx_localedir@
+glibcxx_lt_pic_flag = @glibcxx_lt_pic_flag@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
@@ -413,7 +415,7 @@ libsupc__convenience_la_SOURCES = $(sources) $(c_sources)
# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden
# as the occasion call for it.
AM_CXXFLAGS = \
- $(PIC_CXXFLAGS) \
+ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
$(XTEMPLATE_FLAGS) \
$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
@@ -432,17 +434,14 @@ C_COMPILE = \
# LTCOMPILE is copied from LTCXXCOMPILE below.
LTCOMPILE = $(LIBTOOL) --tag CC --tag disable-shared $(LIBTOOLFLAGS) --mode=compile \
- $(CC) $(DEFS) $(C_INCLUDES) $(PIC_CXXFLAGS) \
+ $(CC) $(DEFS) $(C_INCLUDES) \
+ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
# Libtool notes
-# 1) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
-# last. (That way, things like -O2 passed down from the toplevel can
-# be overridden by --enable-debug.)
-
-# 2) In general, libtool expects an argument such as `--tag=CXX' when
+# 1) In general, libtool expects an argument such as `--tag=CXX' when
# using the C++ compiler, because that will enable the settings
# detected when C++ support was being configured. However, when no
# such flag is given in the command line, libtool attempts to figure
@@ -454,9 +453,18 @@ LTCOMPILE = $(LIBTOOL) --tag CC --tag disable-shared $(LIBTOOLFLAGS) --mode=comp
# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe
# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to
# attempt to infer which configuration to use.
-#
-# We have to put --tag disable-shared after --tag CXX lest things
-# CXX undo the affect of disable-shared.
+#
+# The second tag argument, `--tag disable-shared` means that libtool
+# only compiles each source once, for static objects. In actuality,
+# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to
+# the libtool command that is used create the object, which is
+# suitable for shared libraries. The `--tag disable-shared` must be
+# placed after --tag CXX lest things CXX undo the affect of
+# disable-shared.
+
+# 2) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
+# last. (That way, things like -O2 passed down from the toplevel can
+# be overridden by --enable-debug.)
LTCXXCOMPILE = \
$(LIBTOOL) --tag CXX --tag disable-shared \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
diff --git a/libstdc++-v3/po/Makefile.in b/libstdc++-v3/po/Makefile.in
index 4392d89d118..a3076505847 100644
--- a/libstdc++-v3/po/Makefile.in
+++ b/libstdc++-v3/po/Makefile.in
@@ -160,7 +160,6 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PDFLATEX = @PDFLATEX@
-PIC_CXXFLAGS = @PIC_CXXFLAGS@
RANLIB = @RANLIB@
SECTION_FLAGS = @SECTION_FLAGS@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
@@ -208,7 +207,10 @@ glibcxx_MOFILES = @glibcxx_MOFILES@
glibcxx_PCHFLAGS = @glibcxx_PCHFLAGS@
glibcxx_POFILES = @glibcxx_POFILES@
glibcxx_builddir = @glibcxx_builddir@
+glibcxx_compiler_pic_flag = @glibcxx_compiler_pic_flag@
+glibcxx_compiler_shared_flag = @glibcxx_compiler_shared_flag@
glibcxx_localedir = @glibcxx_localedir@
+glibcxx_lt_pic_flag = @glibcxx_lt_pic_flag@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
diff --git a/libstdc++-v3/python/Makefile.in b/libstdc++-v3/python/Makefile.in
index f83fac87a09..249d56f5e52 100644
--- a/libstdc++-v3/python/Makefile.in
+++ b/libstdc++-v3/python/Makefile.in
@@ -184,7 +184,6 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PDFLATEX = @PDFLATEX@
-PIC_CXXFLAGS = @PIC_CXXFLAGS@
RANLIB = @RANLIB@
SECTION_FLAGS = @SECTION_FLAGS@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
@@ -232,7 +231,10 @@ glibcxx_MOFILES = @glibcxx_MOFILES@
glibcxx_PCHFLAGS = @glibcxx_PCHFLAGS@
glibcxx_POFILES = @glibcxx_POFILES@
glibcxx_builddir = @glibcxx_builddir@
+glibcxx_compiler_pic_flag = @glibcxx_compiler_pic_flag@
+glibcxx_compiler_shared_flag = @glibcxx_compiler_shared_flag@
glibcxx_localedir = @glibcxx_localedir@
+glibcxx_lt_pic_flag = @glibcxx_lt_pic_flag@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
diff --git a/libstdc++-v3/src/Makefile.am b/libstdc++-v3/src/Makefile.am
index a1eb04dabf3..254b8d55974 100644
--- a/libstdc++-v3/src/Makefile.am
+++ b/libstdc++-v3/src/Makefile.am
@@ -116,22 +116,41 @@ compatibility-thread-c++0x.lo: compatibility-thread-c++0x.cc
compatibility-thread-c++0x.o: compatibility-thread-c++0x.cc
$(CXXCOMPILE) -std=gnu++11 -c $<
-# AM_CXXFLAGS needs to be in each subdirectory so that it can be
+# A note on compatibility and static libraries.
+#
+# static lib == linked against only this version, should not need compat
+# shared lib == linked against potentially all compat versions
+#
+# Thus, the shared libs have more compat symbols, which can be found
+# segregated in the sources with -D_GLIBCXX_SHARED.
+#
+# In the sub-directories of libsupc++, src/c++98, src/c++11, only
+# -prefer-pic objects are generated for the convenience libraries.
+#
+# In the main src directory, make shared and static objects just for
+# the compat libraries. Shared objects are compiled with -prefer-pic
+# -D_GLIBCXX_SHARED and in the .libs sub-directory, static objects are
+# compiled with -prefer-pic (ie, -fPIC but not -D_GLIBCXX_SHARED) and
+# the main src directory.
+#
+# Why are objects destined for libstdc++.a compiled with -fPIC? First,
+# because -fPIC is not harmful to use for objects destined for static
+# libraries. In addition, using -fPIC will allow the use of static
+# libstdc++.a in the creation of other C++ shared libraries.
+
+# AM_CXXFLAGS needs to be in each sub-directory so that it can be
# modified in a per-library or per-sub-library way. Need to manually
# set this option because CONFIG_CXXFLAGS has to be after
# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden
# as the occasion calls for it.
AM_CXXFLAGS = \
+ $(glibcxx_compiler_pic_flag) \
$(XTEMPLATE_FLAGS) \
$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
# Libtool notes
-# 1) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
-# last. (That way, things like -O2 passed down from the toplevel can
-# be overridden by --enable-debug.)
-
-# 2) In general, libtool expects an argument such as `--tag=CXX' when
+# 1) In general, libtool expects an argument such as `--tag=CXX' when
# using the C++ compiler, because that will enable the settings
# detected when C++ support was being configured. However, when no
# such flag is given in the command line, libtool attempts to figure
@@ -142,7 +161,19 @@ AM_CXXFLAGS = \
# can't decide which configuration to use, and it gives up. The
# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe
# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to
-# attempt to infer which configuration to use
+# attempt to infer which configuration to use.
+#
+# The second tag argument, `--tag disable-shared` means that libtool
+# only compiles each source once, for static objects. In actuality,
+# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to
+# the libtool command that is used create the object, which is
+# suitable for shared libraries. The `--tag disable-shared` must be
+# placed after --tag CXX lest things CXX undo the affect of
+# disable-shared.
+
+# 2) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
+# last. (That way, things like -O2 passed down from the toplevel can
+# be overridden by --enable-debug.)
LTCXXCOMPILE = \
$(LIBTOOL) --tag CXX \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
diff --git a/libstdc++-v3/src/Makefile.in b/libstdc++-v3/src/Makefile.in
index b10d853af49..53208102018 100644
--- a/libstdc++-v3/src/Makefile.in
+++ b/libstdc++-v3/src/Makefile.in
@@ -213,7 +213,6 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PDFLATEX = @PDFLATEX@
-PIC_CXXFLAGS = @PIC_CXXFLAGS@
RANLIB = @RANLIB@
SECTION_FLAGS = @SECTION_FLAGS@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
@@ -261,7 +260,10 @@ glibcxx_MOFILES = @glibcxx_MOFILES@
glibcxx_PCHFLAGS = @glibcxx_PCHFLAGS@
glibcxx_POFILES = @glibcxx_POFILES@
glibcxx_builddir = @glibcxx_builddir@
+glibcxx_compiler_pic_flag = @glibcxx_compiler_pic_flag@
+glibcxx_compiler_shared_flag = @glibcxx_compiler_shared_flag@
glibcxx_localedir = @glibcxx_localedir@
+glibcxx_lt_pic_flag = @glibcxx_lt_pic_flag@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
@@ -374,23 +376,42 @@ libstdc___la_LINK = $(CXXLINK) $(libstdc___la_LDFLAGS)
# Use special rules for parallel mode compilation.
PARALLEL_FLAGS = -fopenmp -D_GLIBCXX_PARALLEL -I$(glibcxx_builddir)/../libgomp
-# AM_CXXFLAGS needs to be in each subdirectory so that it can be
+# A note on compatibility and static libraries.
+#
+# static lib == linked against only this version, should not need compat
+# shared lib == linked against potentially all compat versions
+#
+# Thus, the shared libs have more compat symbols, which can be found
+# segregated in the sources with -D_GLIBCXX_SHARED.
+#
+# In the sub-directories of libsupc++, src/c++98, src/c++11, only
+# -prefer-pic objects are generated for the convenience libraries.
+#
+# In the main src directory, make shared and static objects just for
+# the compat libraries. Shared objects are compiled with -prefer-pic
+# -D_GLIBCXX_SHARED and in the .libs sub-directory, static objects are
+# compiled with -prefer-pic (ie, -fPIC but not -D_GLIBCXX_SHARED) and
+# the main src directory.
+#
+# Why are objects destined for libstdc++.a compiled with -fPIC? First,
+# because -fPIC is not harmful to use for objects destined for static
+# libraries. In addition, using -fPIC will allow the use of static
+# libstdc++.a in the creation of other C++ shared libraries.
+
+# AM_CXXFLAGS needs to be in each sub-directory so that it can be
# modified in a per-library or per-sub-library way. Need to manually
# set this option because CONFIG_CXXFLAGS has to be after
# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden
# as the occasion calls for it.
AM_CXXFLAGS = \
+ $(glibcxx_compiler_pic_flag) \
$(XTEMPLATE_FLAGS) \
$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
# Libtool notes
-# 1) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
-# last. (That way, things like -O2 passed down from the toplevel can
-# be overridden by --enable-debug.)
-
-# 2) In general, libtool expects an argument such as `--tag=CXX' when
+# 1) In general, libtool expects an argument such as `--tag=CXX' when
# using the C++ compiler, because that will enable the settings
# detected when C++ support was being configured. However, when no
# such flag is given in the command line, libtool attempts to figure
@@ -401,7 +422,19 @@ AM_CXXFLAGS = \
# can't decide which configuration to use, and it gives up. The
# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe
# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to
-# attempt to infer which configuration to use
+# attempt to infer which configuration to use.
+#
+# The second tag argument, `--tag disable-shared` means that libtool
+# only compiles each source once, for static objects. In actuality,
+# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to
+# the libtool command that is used create the object, which is
+# suitable for shared libraries. The `--tag disable-shared` must be
+# placed after --tag CXX lest things CXX undo the affect of
+# disable-shared.
+
+# 2) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
+# last. (That way, things like -O2 passed down from the toplevel can
+# be overridden by --enable-debug.)
LTCXXCOMPILE = \
$(LIBTOOL) --tag CXX \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am
index e8a4d3a66f9..f6502700080 100644
--- a/libstdc++-v3/src/c++11/Makefile.am
+++ b/libstdc++-v3/src/c++11/Makefile.am
@@ -68,7 +68,7 @@ libc__11convenience_la_SOURCES = $(sources) $(inst_sources)
# as the occasion calls for it.
AM_CXXFLAGS = \
-std=gnu++11 \
- $(PIC_CXXFLAGS) \
+ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
$(XTEMPLATE_FLAGS) \
$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
@@ -77,11 +77,7 @@ AM_MAKEFLAGS = \
# Libtool notes
-# 1) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
-# last. (That way, things like -O2 passed down from the toplevel can
-# be overridden by --enable-debug.)
-
-# 2) In general, libtool expects an argument such as `--tag=CXX' when
+# 1) In general, libtool expects an argument such as `--tag=CXX' when
# using the C++ compiler, because that will enable the settings
# detected when C++ support was being configured. However, when no
# such flag is given in the command line, libtool attempts to figure
@@ -93,8 +89,18 @@ AM_MAKEFLAGS = \
# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe
# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to
# attempt to infer which configuration to use.
-# We have to put --tag disable-shared after --tag CXX lest things
-# CXX undo the affect of disable-shared.
+#
+# The second tag argument, `--tag disable-shared` means that libtool
+# only compiles each source once, for static objects. In actuality,
+# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to
+# the libtool command that is used create the object, which is
+# suitable for shared libraries. The `--tag disable-shared` must be
+# placed after --tag CXX lest things CXX undo the affect of
+# disable-shared.
+
+# 2) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
+# last. (That way, things like -O2 passed down from the toplevel can
+# be overridden by --enable-debug.)
LTCXXCOMPILE = \
$(LIBTOOL) --tag CXX --tag disable-shared \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
diff --git a/libstdc++-v3/src/c++11/Makefile.in b/libstdc++-v3/src/c++11/Makefile.in
index 0c63c514741..d725d260d5c 100644
--- a/libstdc++-v3/src/c++11/Makefile.in
+++ b/libstdc++-v3/src/c++11/Makefile.in
@@ -177,7 +177,6 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PDFLATEX = @PDFLATEX@
-PIC_CXXFLAGS = @PIC_CXXFLAGS@
RANLIB = @RANLIB@
SECTION_FLAGS = @SECTION_FLAGS@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
@@ -225,7 +224,10 @@ glibcxx_MOFILES = @glibcxx_MOFILES@
glibcxx_PCHFLAGS = @glibcxx_PCHFLAGS@
glibcxx_POFILES = @glibcxx_POFILES@
glibcxx_builddir = @glibcxx_builddir@
+glibcxx_compiler_pic_flag = @glibcxx_compiler_pic_flag@
+glibcxx_compiler_shared_flag = @glibcxx_compiler_shared_flag@
glibcxx_localedir = @glibcxx_localedir@
+glibcxx_lt_pic_flag = @glibcxx_lt_pic_flag@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
@@ -331,7 +333,7 @@ libc__11convenience_la_SOURCES = $(sources) $(inst_sources)
# as the occasion calls for it.
AM_CXXFLAGS = \
-std=gnu++11 \
- $(PIC_CXXFLAGS) \
+ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
$(XTEMPLATE_FLAGS) \
$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
@@ -341,11 +343,7 @@ AM_MAKEFLAGS = \
# Libtool notes
-# 1) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
-# last. (That way, things like -O2 passed down from the toplevel can
-# be overridden by --enable-debug.)
-
-# 2) In general, libtool expects an argument such as `--tag=CXX' when
+# 1) In general, libtool expects an argument such as `--tag=CXX' when
# using the C++ compiler, because that will enable the settings
# detected when C++ support was being configured. However, when no
# such flag is given in the command line, libtool attempts to figure
@@ -357,8 +355,18 @@ AM_MAKEFLAGS = \
# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe
# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to
# attempt to infer which configuration to use.
-# We have to put --tag disable-shared after --tag CXX lest things
-# CXX undo the affect of disable-shared.
+#
+# The second tag argument, `--tag disable-shared` means that libtool
+# only compiles each source once, for static objects. In actuality,
+# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to
+# the libtool command that is used create the object, which is
+# suitable for shared libraries. The `--tag disable-shared` must be
+# placed after --tag CXX lest things CXX undo the affect of
+# disable-shared.
+
+# 2) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
+# last. (That way, things like -O2 passed down from the toplevel can
+# be overridden by --enable-debug.)
LTCXXCOMPILE = \
$(LIBTOOL) --tag CXX --tag disable-shared \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
diff --git a/libstdc++-v3/src/c++11/compatibility-atomic-c++0x.cc b/libstdc++-v3/src/c++11/compatibility-atomic-c++0x.cc
index 8ccad9330ed..3ad0b93974e 100644
--- a/libstdc++-v3/src/c++11/compatibility-atomic-c++0x.cc
+++ b/libstdc++-v3/src/c++11/compatibility-atomic-c++0x.cc
@@ -30,7 +30,7 @@
// XXX GLIBCXX_ABI Deprecated
// gcc-4.7.0
-#ifdef PIC
+#ifdef _GLIBCXX_SHARED
#define LOGSIZE 4
@@ -147,7 +147,7 @@ _GLIBCXX_END_NAMESPACE_VERSION
// In the future, GLIBCXX_ABI > 6 should remove all uses of
// _GLIBCXX_*_SYMVER macros in this file.
-#if defined(_GLIBCXX_SYMVER_GNU) && defined(PIC) \
+#if defined(_GLIBCXX_SYMVER_GNU) && defined(_GLIBCXX_SHARED) \
&& defined(_GLIBCXX_HAVE_AS_SYMVER_DIRECTIVE) \
&& defined(_GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT)
diff --git a/libstdc++-v3/src/c++11/compatibility-c++0x.cc b/libstdc++-v3/src/c++11/compatibility-c++0x.cc
index bd5dbe0ff06..306bad55faf 100644
--- a/libstdc++-v3/src/c++11/compatibility-c++0x.cc
+++ b/libstdc++-v3/src/c++11/compatibility-c++0x.cc
@@ -30,7 +30,7 @@
# error "compatibility-c++0x.cc must be compiled with -std=gnu++0x"
#endif
-#ifdef PIC
+#ifdef _GLIBCXX_SHARED
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc b/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc
index e5c7eec419e..5e87b531923 100644
--- a/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc
+++ b/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc
@@ -23,7 +23,7 @@
// <http://www.gnu.org/licenses/>.
#include <bits/c++config.h>
-#if defined(_GLIBCXX_HAVE_TLS) && defined(PIC)
+#if defined(_GLIBCXX_HAVE_TLS) && defined(_GLIBCXX_SHARED)
#define _GLIBCXX_ASYNC_ABI_COMPAT
#endif
@@ -40,7 +40,7 @@
// XXX GLIBCXX_ABI Deprecated
// gcc-4.6.0
// <future> export changes
-#if defined(_GLIBCXX_SYMVER_GNU) && defined(PIC) \
+#if defined(_GLIBCXX_SYMVER_GNU) && defined(_GLIBCXX_SHARED) \
&& defined(_GLIBCXX_HAVE_AS_SYMVER_DIRECTIVE) \
&& defined(_GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT)
@@ -57,7 +57,7 @@ _GLIBCXX_ASM_SYMVER(_ZN9__gnu_cxx15future_categoryE, _ZSt15future_category, GLIB
// gcc-4.6.0
// <mutex> export changes
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
-#if defined(_GLIBCXX_SYMVER_GNU) && defined(PIC) \
+#if defined(_GLIBCXX_SYMVER_GNU) && defined(_GLIBCXX_SHARED) \
&& defined(_GLIBCXX_HAVE_AS_SYMVER_DIRECTIVE) \
&& defined(_GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT)
@@ -82,7 +82,7 @@ _GLIBCXX_ASM_SYMVER(_ZN9__gnu_cxx11try_to_lockE, _ZSt11try_to_lock, GLIBCXX_3.4.
// <future> export changes
#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \
&& (ATOMIC_INT_LOCK_FREE > 1)
-#if defined(_GLIBCXX_HAVE_TLS) && defined(PIC)
+#if defined(_GLIBCXX_HAVE_TLS) && defined(_GLIBCXX_SHARED)
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
diff --git a/libstdc++-v3/src/c++98/Makefile.am b/libstdc++-v3/src/c++98/Makefile.am
index 05767e9ff23..c153a59336d 100644
--- a/libstdc++-v3/src/c++98/Makefile.am
+++ b/libstdc++-v3/src/c++98/Makefile.am
@@ -172,7 +172,7 @@ parallel_settings.o: parallel_settings.cc
# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden
# as the occasion calls for it.
AM_CXXFLAGS = \
- $(PIC_CXXFLAGS) \
+ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
$(XTEMPLATE_FLAGS) \
$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
@@ -181,11 +181,7 @@ AM_MAKEFLAGS = \
# Libtool notes
-# 1) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
-# last. (That way, things like -O2 passed down from the toplevel can
-# be overridden by --enable-debug.)
-
-# 2) In general, libtool expects an argument such as `--tag=CXX' when
+# 1) In general, libtool expects an argument such as `--tag=CXX' when
# using the C++ compiler, because that will enable the settings
# detected when C++ support was being configured. However, when no
# such flag is given in the command line, libtool attempts to figure
@@ -197,8 +193,18 @@ AM_MAKEFLAGS = \
# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe
# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to
# attempt to infer which configuration to use.
-# We have to put --tag disable-shared after --tag CXX lest things
-# CXX undo the affect of disable-shared.
+#
+# The second tag argument, `--tag disable-shared` means that libtool
+# only compiles each source once, for static objects. In actuality,
+# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to
+# the libtool command that is used create the object, which is
+# suitable for shared libraries. The `--tag disable-shared` must be
+# placed after --tag CXX lest things CXX undo the affect of
+# disable-shared.
+
+# 2) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
+# last. (That way, things like -O2 passed down from the toplevel can
+# be overridden by --enable-debug.)
LTCXXCOMPILE = \
$(LIBTOOL) --tag CXX --tag disable-shared \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
diff --git a/libstdc++-v3/src/c++98/Makefile.in b/libstdc++-v3/src/c++98/Makefile.in
index f36742ba021..c3173bc91f2 100644
--- a/libstdc++-v3/src/c++98/Makefile.in
+++ b/libstdc++-v3/src/c++98/Makefile.in
@@ -192,7 +192,6 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PDFLATEX = @PDFLATEX@
-PIC_CXXFLAGS = @PIC_CXXFLAGS@
RANLIB = @RANLIB@
SECTION_FLAGS = @SECTION_FLAGS@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
@@ -240,7 +239,10 @@ glibcxx_MOFILES = @glibcxx_MOFILES@
glibcxx_PCHFLAGS = @glibcxx_PCHFLAGS@
glibcxx_POFILES = @glibcxx_POFILES@
glibcxx_builddir = @glibcxx_builddir@
+glibcxx_compiler_pic_flag = @glibcxx_compiler_pic_flag@
+glibcxx_compiler_shared_flag = @glibcxx_compiler_shared_flag@
glibcxx_localedir = @glibcxx_localedir@
+glibcxx_lt_pic_flag = @glibcxx_lt_pic_flag@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
@@ -400,7 +402,7 @@ PARALLEL_FLAGS = -fopenmp -D_GLIBCXX_PARALLEL -I$(glibcxx_builddir)/../libgomp
# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden
# as the occasion calls for it.
AM_CXXFLAGS = \
- $(PIC_CXXFLAGS) \
+ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \
$(XTEMPLATE_FLAGS) \
$(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS)
@@ -410,11 +412,7 @@ AM_MAKEFLAGS = \
# Libtool notes
-# 1) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
-# last. (That way, things like -O2 passed down from the toplevel can
-# be overridden by --enable-debug.)
-
-# 2) In general, libtool expects an argument such as `--tag=CXX' when
+# 1) In general, libtool expects an argument such as `--tag=CXX' when
# using the C++ compiler, because that will enable the settings
# detected when C++ support was being configured. However, when no
# such flag is given in the command line, libtool attempts to figure
@@ -426,8 +424,18 @@ AM_MAKEFLAGS = \
# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe
# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to
# attempt to infer which configuration to use.
-# We have to put --tag disable-shared after --tag CXX lest things
-# CXX undo the affect of disable-shared.
+#
+# The second tag argument, `--tag disable-shared` means that libtool
+# only compiles each source once, for static objects. In actuality,
+# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to
+# the libtool command that is used create the object, which is
+# suitable for shared libraries. The `--tag disable-shared` must be
+# placed after --tag CXX lest things CXX undo the affect of
+# disable-shared.
+
+# 2) Need to explicitly set LTCXXCOMPILE so that AM_CXXFLAGS is
+# last. (That way, things like -O2 passed down from the toplevel can
+# be overridden by --enable-debug.)
LTCXXCOMPILE = \
$(LIBTOOL) --tag CXX --tag disable-shared \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
diff --git a/libstdc++-v3/src/c++98/compatibility-list-2.cc b/libstdc++-v3/src/c++98/compatibility-list-2.cc
index 975450cb100..0e118ff4371 100644
--- a/libstdc++-v3/src/c++98/compatibility-list-2.cc
+++ b/libstdc++-v3/src/c++98/compatibility-list-2.cc
@@ -24,7 +24,7 @@
#include <bits/move.h>
-#ifdef PIC
+#ifdef _GLIBCXX_SHARED
#ifndef _GLIBCXX_BEGIN_NAMESPACE_COMPAT
# define _GLIBCXX_BEGIN_NAMESPACE_COMPAT
diff --git a/libstdc++-v3/src/c++98/compatibility.cc b/libstdc++-v3/src/c++98/compatibility.cc
index 38d9e4b6743..9f423d0e821 100644
--- a/libstdc++-v3/src/c++98/compatibility.cc
+++ b/libstdc++-v3/src/c++98/compatibility.cc
@@ -25,7 +25,7 @@
#include <bits/c++config.h>
-#if defined(_GLIBCXX_SYMVER_GNU) && defined(PIC) \
+#if defined(_GLIBCXX_SYMVER_GNU) && defined(_GLIBCXX_SHARED) \
&& defined(_GLIBCXX_HAVE_AS_SYMVER_DIRECTIVE)\
&& defined(_GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT)
#define istreambuf_iterator istreambuf_iteratorXX
@@ -204,7 +204,7 @@ _GLIBCXX_END_NAMESPACE_VERSION
// NB: These symbols renames should go into the shared library only,
// and only those shared libraries that support versioning.
-#if defined(_GLIBCXX_SYMVER_GNU) && defined(PIC) \
+#if defined(_GLIBCXX_SYMVER_GNU) && defined(_GLIBCXX_SHARED) \
&& defined(_GLIBCXX_HAVE_AS_SYMVER_DIRECTIVE) \
&& defined(_GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT)
@@ -529,7 +529,7 @@ extern __attribute__((used, weak)) const void * const _ZTIPKe[4]
#endif // _GLIBCXX_LONG_DOUBLE_COMPAT
#ifdef _GLIBCXX_SYMVER_DARWIN
-#if (defined(__ppc__) || defined(__ppc64__)) && defined(PIC)
+#if (defined(__ppc__) || defined(__ppc64__)) && defined(_GLIBCXX_SHARED)
/* __eprintf shouldn't have been made visible from libstdc++, or
anywhere, but on Mac OS X 10.4 it was defined in
libstdc++.6.0.3.dylib; so on that platform we have to keep defining
diff --git a/libstdc++-v3/testsuite/17_intro/shared_with_static_deps.cc b/libstdc++-v3/testsuite/17_intro/shared_with_static_deps.cc
new file mode 100644
index 00000000000..7feac92cce1
--- /dev/null
+++ b/libstdc++-v3/testsuite/17_intro/shared_with_static_deps.cc
@@ -0,0 +1,33 @@
+// { dg-do link }
+// { dg-require-static-libstdcxx }
+// { dg-require-sharedlib "" }
+// { dg-require-effective-target fpic }
+// { dg-options "-shared -fPIC -static-libgcc -static-libstdc++" }
+
+// Copyright (C) 2012 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/>
+
+// libstdc++/28811 --with-pic vs. static linking
+#include <iostream>
+#include <locale>
+
+int main()
+{
+ std::locale c __attribute__((unused)) = std::locale::classic();
+ std::cout << "i am old-skool\n";
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/55123.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/55123.cc
new file mode 100644
index 00000000000..35b517e8863
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/55123.cc
@@ -0,0 +1,30 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2012 Free Software Foundation
+//
+// 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 <memory>
+
+// libstdc++/55123
+
+#include <memory>
+
+void f() {
+ std::unique_ptr<const int> y;
+ std::shared_ptr<const int> x = std::move(y);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/55028-debug.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/55028-debug.cc
new file mode 100644
index 00000000000..fc17256f4bb
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/insert/55028-debug.cc
@@ -0,0 +1,40 @@
+// { dg-options "-std=gnu++0x -D_GLIBCXX_DEBUG" }
+//
+// Copyright (C) 2012 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/>.
+
+// libstdc++/55028
+#include <string>
+#include <unordered_map>
+#include <testsuite_hooks.h>
+
+struct MyType
+{ };
+
+void test()
+{
+ // using MyMap = std::multimap<std::string, MyType *>; // works
+ using MyMap = std::unordered_multimap<std::string, MyType*>; // fails to link
+ MyMap m;
+ m.insert(std::make_pair(std::string("blah"), new MyType));
+}
+
+int main()
+{
+ test();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/cons/55215.cc b/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/cons/55215.cc
new file mode 100644
index 00000000000..c655b262062
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/cons/55215.cc
@@ -0,0 +1,58 @@
+// { dg-options "-std=gnu++11" }
+// { dg-require-cstdint "" }
+//
+// Copyright (C) 2012 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 <random>
+#include <testsuite_hooks.h>
+
+int f(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::ranlux24(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+int g(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::ranlux24();
+ rnd.seed(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ const int f1 = f(0);
+ const int f2 = f(0);
+
+ const int g1 = g(0);
+ const int g2 = g(0);
+
+ VERIFY( f1 == f2 );
+ VERIFY( g1 == g2 );
+ VERIFY( f1 == g1 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/cons/55215.cc b/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/cons/55215.cc
new file mode 100644
index 00000000000..4b502b7d7c0
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/cons/55215.cc
@@ -0,0 +1,60 @@
+// { dg-options "-std=gnu++11" }
+// { dg-require-cstdint "" }
+//
+// Copyright (C) 2012 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 <random>
+#include <testsuite_hooks.h>
+
+int f(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::independent_bits_engine<std::mt19937, 9,
+ std::uint_fast32_t>(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+int g(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::independent_bits_engine<std::mt19937, 9,
+ std::uint_fast32_t>();
+ rnd.seed(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ const int f1 = f(0);
+ const int f2 = f(0);
+
+ const int g1 = g(0);
+ const int g2 = g(0);
+
+ VERIFY( f1 == f2 );
+ VERIFY( g1 == g2 );
+ VERIFY( f1 == g1 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/cons/55215.cc b/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/cons/55215.cc
new file mode 100644
index 00000000000..21333fba97d
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/cons/55215.cc
@@ -0,0 +1,58 @@
+// { dg-options "-std=gnu++11" }
+// { dg-require-cstdint "" }
+//
+// Copyright (C) 2012 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 <random>
+#include <testsuite_hooks.h>
+
+int f(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::minstd_rand(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+int g(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::minstd_rand();
+ rnd.seed(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ const int f1 = f(0);
+ const int f2 = f(0);
+
+ const int g1 = g(0);
+ const int g2 = g(0);
+
+ VERIFY( f1 == f2 );
+ VERIFY( g1 == g2 );
+ VERIFY( f1 == g1 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/cons/55215.cc b/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/cons/55215.cc
new file mode 100644
index 00000000000..3453d9f727a
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/cons/55215.cc
@@ -0,0 +1,58 @@
+// { dg-options "-std=gnu++11" }
+// { dg-require-cstdint "" }
+//
+// Copyright (C) 2012 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 <random>
+#include <testsuite_hooks.h>
+
+int f(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::mt19937(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+int g(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::mt19937();
+ rnd.seed(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ const int f1 = f(0);
+ const int f2 = f(0);
+
+ const int g1 = g(0);
+ const int g2 = g(0);
+
+ VERIFY( f1 == f2 );
+ VERIFY( g1 == g2 );
+ VERIFY( f1 == g1 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/cons/55215.cc b/libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/cons/55215.cc
new file mode 100644
index 00000000000..d7db635d8ef
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/cons/55215.cc
@@ -0,0 +1,58 @@
+// { dg-options "-std=gnu++11" }
+// { dg-require-cstdint "" }
+//
+// Copyright (C) 2012 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 <random>
+#include <testsuite_hooks.h>
+
+int f(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::knuth_b(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+int g(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::knuth_b();
+ rnd.seed(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ const int f1 = f(0);
+ const int f2 = f(0);
+
+ const int g1 = g(0);
+ const int g2 = g(0);
+
+ VERIFY( f1 == f2 );
+ VERIFY( g1 == g2 );
+ VERIFY( f1 == g1 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/cons/55215.cc b/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/cons/55215.cc
new file mode 100644
index 00000000000..4927d771667
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/cons/55215.cc
@@ -0,0 +1,58 @@
+// { dg-options "-std=gnu++11" }
+// { dg-require-cstdint "" }
+//
+// Copyright (C) 2012 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 <random>
+#include <testsuite_hooks.h>
+
+int f(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::ranlux24_base(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+int g(int x)
+{
+ std::seed_seq sq(&x, &x + 1);
+ auto rnd = std::ranlux24_base();
+ rnd.seed(sq);
+ return std::uniform_int_distribution<int>()(rnd);
+}
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ const int f1 = f(0);
+ const int f2 = f(0);
+
+ const int g1 = g(0);
+ const int g2 = g(0);
+
+ VERIFY( f1 == f2 );
+ VERIFY( g1 == g2 );
+ VERIFY( f1 == g1 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/Makefile.in b/libstdc++-v3/testsuite/Makefile.in
index bb077d148a6..3c4f39ec32d 100644
--- a/libstdc++-v3/testsuite/Makefile.in
+++ b/libstdc++-v3/testsuite/Makefile.in
@@ -160,7 +160,6 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PDFLATEX = @PDFLATEX@
-PIC_CXXFLAGS = @PIC_CXXFLAGS@
RANLIB = @RANLIB@
SECTION_FLAGS = @SECTION_FLAGS@
SECTION_LDFLAGS = @SECTION_LDFLAGS@
@@ -208,7 +207,10 @@ glibcxx_MOFILES = @glibcxx_MOFILES@
glibcxx_PCHFLAGS = @glibcxx_PCHFLAGS@
glibcxx_POFILES = @glibcxx_POFILES@
glibcxx_builddir = @glibcxx_builddir@
+glibcxx_compiler_pic_flag = @glibcxx_compiler_pic_flag@
+glibcxx_compiler_shared_flag = @glibcxx_compiler_shared_flag@
glibcxx_localedir = @glibcxx_localedir@
+glibcxx_lt_pic_flag = @glibcxx_lt_pic_flag@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
glibcxx_toolexecdir = @glibcxx_toolexecdir@