aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2008-08-14 17:24:50 +0000
committerhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2008-08-14 17:24:50 +0000
commit88a09daa59a002a27998d5a1043e064fdd58c436 (patch)
tree14225345b79f5b12c30d08a5b44f233420107b8f
parentd5b4e28e9c8ec97cb8f9c2ba0c6d16971ddeb261 (diff)
Merged with trunk at revision 139098.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/ix86/avx@139102 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog66
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/c-parser.c2
-rw-r--r--gcc/config/i386/sse.md41
-rw-r--r--gcc/config/rs6000/rs6000-c.c2
-rw-r--r--gcc/config/sparc/sparc.c4
-rw-r--r--gcc/fold-const.c4
-rw-r--r--gcc/testsuite/ChangeLog37
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20080813-1.c30
-rw-r--r--gcc/testsuite/gcc.dg/arm-g2.c1
-rw-r--r--gcc/testsuite/gcc.dg/arm-mmx-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/arm-scd42-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/parser-pr28152-2.c11
-rw-r--r--gcc/testsuite/gcc.dg/parser-pr28152.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-outer-4a.c9
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-outer-4b.c9
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-outer-4f.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-outer-4g.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-outer-4i.c29
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-outer-4j.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-outer-4k.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-outer-4l.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/incoming-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/incoming-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/incoming-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/incoming-4.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/incoming-5.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr37101.c64
-rw-r--r--gcc/tree-vect-transform.c222
-rw-r--r--libstdc++-v3/ChangeLog5
-rw-r--r--libstdc++-v3/config/abi/pre/gnu.ver29
-rw-r--r--libstdc++-v3/libsupc++/Makefile.am3
-rw-r--r--libstdc++-v3/libsupc++/Makefile.in9
-rw-r--r--libstdc++-v3/libsupc++/eh_alloc.cc68
-rw-r--r--libstdc++-v3/libsupc++/eh_arm.cc8
-rw-r--r--libstdc++-v3/libsupc++/eh_call.cc4
-rw-r--r--libstdc++-v3/libsupc++/eh_personality.cc22
-rw-r--r--libstdc++-v3/libsupc++/eh_ptr.cc236
-rw-r--r--libstdc++-v3/libsupc++/eh_throw.cc21
-rw-r--r--libstdc++-v3/libsupc++/eh_type.cc12
-rw-r--r--libstdc++-v3/libsupc++/exception7
-rw-r--r--libstdc++-v3/libsupc++/exception_ptr.h169
-rw-r--r--libstdc++-v3/libsupc++/unwind-cxx.h143
-rw-r--r--libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc90
-rw-r--r--libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc188
-rw-r--r--libstdc++-v3/testsuite/18_support/exception_ptr/rethrow_exception.cc113
46 files changed, 1499 insertions, 201 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c6cf33c20f2..73b478e6558 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,60 @@
+2008-08-14 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
+
+ PR c/28152
+ * c-parser.c (c_lex_one_token): Do not store the canonical spelling
+ for keywords.
+
+2008-08-14 Dorit Nuzman <dorit@il.ibm.com>
+
+ * tree-vect-transform.c (vect_create_epilog_for_reduction): Takes an
+ additional argument. Support reduction when duplication is needed due
+ to data-types of different sizes in the loop.
+ (get_initial_def_for_induction): Fix printout.
+ (vect_get_vec_def_for_stmt_copy): Support case where the
+ vec_stmt_for_operand is a phi node.
+ (vectorizable_reduction): Support reduction when duplication is needed
+ due to data-types of different sizes in the loop.
+ (vectorizable_call): Remove restriction to not vectorize in case we
+ have data-types of different sizes in the loop.
+ (vectorizable_conversion): Likewise.
+ (vectorizable_operation): Likewise.
+ (vectorizable_type_demotion): Likewise.
+ (vectorizable_type_promotion): Likewise.
+ (vectorizable_induction): Add restriction to not vectorize in case
+ we have data-types of different sizes in the loop.
+
+2008-08-14 Christophe Saout <christophe@saout.de>
+ Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/37101
+ * config/i386/sse.md (vec_concatv2di): Remove movlps alternative.
+ (*vec_concatv2di_rex64_sse4_1): Ditto.
+ (*vec_concatv2di_rex64_sse): Ditto.
+
+2008-08-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/37103
+ * fold-const.c (fold_widened_comparison): Do not allow
+ sign changes that change the result even if shorter type
+ is wider than arg1_unw's type.
+
+2008-08-13 Kazu Hirata <kazu@codesourcery.com>
+
+ * gcc.dg/arm-g2.c, gcc.dg/arm-mmx-1.c, gcc.dg/arm-scd42-2.c:
+ Skip if the multilib testing specifies -march that does not
+ agree with the one specified in the testcase.
+
+2008-08-13 Joseph Myers <joseph@codesourcery.com>
+
+ * config/sparc/sparc.c (emit_soft_tfmode_cvt): Explicitly sign or
+ zero extend SImode values being converted to TFmode before passing
+ to libcalls.
+
+2008-08-13 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Predefine
+ __PPU__ when targeting the Cell/B.E. PPU processor.
+
2008-08-13 Eric Botcazou <ebotcazou@adacore.com>
* gimple.h (gimple_call_set_chain): Accept SSA variables.
@@ -115,7 +172,6 @@
2008-08-12 Nathan Froyd <froydnj@codesourcery.com>
PR libgomp/26165
-
* gcc.c (include_spec_function): Tweak call to find_a_file.
2008-08-12 Jakub Jelinek <jakub@redhat.com>
@@ -131,7 +187,7 @@
2008-08-12 Anatoly Sokolov <aesok@post.ru>
- * final.c (final_scan_insn): Use app_enable/app_disable functions.
+ * final.c (final_scan_insn): Use app_enable/app_disable functions.
2008-08-12 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
@@ -661,8 +717,8 @@
2008-08-07 Bob Wilson <bob.wilson@acm.org>
- * config/xtensa/xtensa.c (xtensa_copy_incoming_a7): Copy incoming value
- in a6 after the set_frame_ptr insn.
+ * config/xtensa/xtensa.c (xtensa_copy_incoming_a7): Copy incoming
+ value in a6 after the set_frame_ptr insn.
2008-08-07 Richard Henderson <rth@redhat.com>
@@ -750,7 +806,7 @@
* matrix-reorg.c (compute_offset): Avoid C++ keywords.
2008-08-06 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
-
+
PR 26785
* diagnostic.c (permerror_at): New.
* toplev.h (permerror_at): Declare.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index c60f7bba8a6..657795f131f 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20080813
+20080814
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 6617145a6cb..1ea9d07fcdf 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -241,8 +241,6 @@ c_lex_one_token (c_parser *parser, c_token *token)
}
else
{
- /* Return the canonical spelling for this keyword. */
- token->value = ridpointers[(int) rid_code];
token->type = CPP_KEYWORD;
token->keyword = rid_code;
break;
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index d1ec9ea829d..141c3a26ece 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -7177,20 +7177,19 @@
(set_attr "mode" "TI,TI,TI,V2SF,V2SF")])
(define_insn "vec_concatv2di"
- [(set (match_operand:V2DI 0 "register_operand" "=Y2 ,?Y2,Y2,x,x,x")
+ [(set (match_operand:V2DI 0 "register_operand" "=Y2 ,?Y2,Y2,x,x")
(vec_concat:V2DI
- (match_operand:DI 1 "nonimmediate_operand" " mY2,*y ,0 ,0,0,m")
- (match_operand:DI 2 "vector_move_operand" " C , C,Y2,x,m,0")))]
+ (match_operand:DI 1 "nonimmediate_operand" " mY2,*y ,0 ,0,0")
+ (match_operand:DI 2 "vector_move_operand" " C , C,Y2,x,m")))]
"!TARGET_64BIT && TARGET_SSE"
"@
movq\t{%1, %0|%0, %1}
movq2dq\t{%1, %0|%0, %1}
punpcklqdq\t{%2, %0|%0, %2}
movlhps\t{%2, %0|%0, %2}
- movhps\t{%2, %0|%0, %2}
- movlps\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov,ssemov,sselog,ssemov,ssemov,ssemov")
- (set_attr "mode" "TI,TI,TI,V4SF,V2SF,V2SF")])
+ movhps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemov,ssemov,sselog,ssemov,ssemov")
+ (set_attr "mode" "TI,TI,TI,V4SF,V2SF")])
(define_insn "*vec_concatv2di_rex64_avx"
[(set (match_operand:V2DI 0 "register_operand" "=x,x,Yi,!x,x,x,x")
@@ -7214,10 +7213,10 @@
(set_attr "mode" "TI,TI,TI,TI,TI,V2SF,V2SF")])
(define_insn "*vec_concatv2di_rex64_sse4_1"
- [(set (match_operand:V2DI 0 "register_operand" "=x ,x ,Yi,!x,x,x,x,x")
+ [(set (match_operand:V2DI 0 "register_operand" "=x ,x ,Yi,!x,x,x,x")
(vec_concat:V2DI
- (match_operand:DI 1 "nonimmediate_operand" " 0 ,mx,r ,*y,0,0,0,m")
- (match_operand:DI 2 "vector_move_operand" " rm,C ,C ,C ,x,x,m,0")))]
+ (match_operand:DI 1 "nonimmediate_operand" " 0 ,mx,r ,*y,0,0,0")
+ (match_operand:DI 2 "vector_move_operand" " rm,C ,C ,C ,x,x,m")))]
"TARGET_64BIT && TARGET_SSE4_1"
"@
pinsrq\t{$0x1, %2, %0|%0, %2, 0x1}
@@ -7226,17 +7225,16 @@
movq2dq\t{%1, %0|%0, %1}
punpcklqdq\t{%2, %0|%0, %2}
movlhps\t{%2, %0|%0, %2}
- movhps\t{%2, %0|%0, %2}
- movlps\t{%1, %0|%0, %1}"
- [(set_attr "type" "sselog,ssemov,ssemov,ssemov,sselog,ssemov,ssemov,ssemov")
- (set_attr "prefix_extra" "1,*,*,*,*,*,*,*")
- (set_attr "mode" "TI,TI,TI,TI,TI,V4SF,V2SF,V2SF")])
+ movhps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog,ssemov,ssemov,ssemov,sselog,ssemov,ssemov")
+ (set_attr "prefix_extra" "1,*,*,*,*,*,*")
+ (set_attr "mode" "TI,TI,TI,TI,TI,V4SF,V2SF")])
(define_insn "*vec_concatv2di_rex64_sse"
- [(set (match_operand:V2DI 0 "register_operand" "=Y2 ,Yi,!Y2,Y2,x,x,x")
+ [(set (match_operand:V2DI 0 "register_operand" "=Y2 ,Yi,!Y2,Y2,x,x")
(vec_concat:V2DI
- (match_operand:DI 1 "nonimmediate_operand" " mY2,r ,*y ,0 ,0,0,m")
- (match_operand:DI 2 "vector_move_operand" " C ,C ,C ,Y2,x,m,0")))]
+ (match_operand:DI 1 "nonimmediate_operand" " mY2,r ,*y ,0 ,0,0")
+ (match_operand:DI 2 "vector_move_operand" " C ,C ,C ,Y2,x,m")))]
"TARGET_64BIT && TARGET_SSE"
"@
movq\t{%1, %0|%0, %1}
@@ -7244,10 +7242,9 @@
movq2dq\t{%1, %0|%0, %1}
punpcklqdq\t{%2, %0|%0, %2}
movlhps\t{%2, %0|%0, %2}
- movhps\t{%2, %0|%0, %2}
- movlps\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,ssemov,ssemov")
- (set_attr "mode" "TI,TI,TI,TI,V4SF,V2SF,V2SF")])
+ movhps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,ssemov")
+ (set_attr "mode" "TI,TI,TI,TI,V4SF,V2SF")])
(define_expand "vec_unpacku_hi_v16qi"
[(match_operand:V8HI 0 "register_operand" "")
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index 76c92352b57..8cbace8a795 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -278,6 +278,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
cpp_get_callbacks (pfile)->macro_to_expand = rs6000_macro_to_expand;
}
}
+ if (rs6000_cpu == PROCESSOR_CELL)
+ builtin_define ("__PPU__");
if (TARGET_SPE)
builtin_define ("__SPE__");
if (TARGET_PAIRED_FLOAT)
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 045735f208c..58667a2cb19 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -2371,6 +2371,8 @@ emit_soft_tfmode_cvt (enum rtx_code code, rtx *operands)
{
case SImode:
func = "_Qp_itoq";
+ if (TARGET_ARCH64)
+ operands[1] = gen_rtx_SIGN_EXTEND (DImode, operands[1]);
break;
case DImode:
func = "_Qp_xtoq";
@@ -2385,6 +2387,8 @@ emit_soft_tfmode_cvt (enum rtx_code code, rtx *operands)
{
case SImode:
func = "_Qp_uitoq";
+ if (TARGET_ARCH64)
+ operands[1] = gen_rtx_ZERO_EXTEND (DImode, operands[1]);
break;
case DImode:
func = "_Qp_uxtoq";
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index cae45b5a658..eac31ef1a79 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -6733,10 +6733,8 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
if ((code == EQ_EXPR || code == NE_EXPR
|| TYPE_UNSIGNED (TREE_TYPE (arg0)) == TYPE_UNSIGNED (shorter_type))
&& (TREE_TYPE (arg1_unw) == shorter_type
- || (TYPE_PRECISION (shorter_type)
- > TYPE_PRECISION (TREE_TYPE (arg1_unw)))
|| ((TYPE_PRECISION (shorter_type)
- == TYPE_PRECISION (TREE_TYPE (arg1_unw)))
+ >= TYPE_PRECISION (TREE_TYPE (arg1_unw)))
&& (TYPE_UNSIGNED (shorter_type)
== TYPE_UNSIGNED (TREE_TYPE (arg1_unw))))
|| (TREE_CODE (arg1_unw) == INTEGER_CST
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1f1890a1435..bdbc3542e9e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,38 @@
+2008-08-14 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
+
+ PR c/28152
+ * gcc.dg/parser-pr28152.c: New.
+ * gcc.dg/parser-pr28152-2.c: New.
+
+2008-08-14 Dorit Nuzman <dorit@il.ibm.com>
+
+ * gcc.dg/vect/vect-outer-4g.c: Change loop bound.
+ * gcc.dg/vect/vect-outer-4k.c: Likewise.
+ * gcc.dg/vect/vect-outer-4l.c: Likewise.
+ * gcc.dg/vect/vect-outer-4f.c: Likewise.
+ * gcc.dg/vect/vect-outer-4a.c: Vectorizable. Remove obsolete comment.
+ * gcc.dg/vect/vect-outer-4i.c: Likewise.
+ * gcc.dg/vect/vect-outer-4b.c: Likewise.
+ * gcc.dg/vect/vect-outer-4j.c: Likewise.
+
+2008-08-14 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/37101
+ * gcc.target/i386/pr37101.c: New test.
+
+2008-08-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/37103
+ * gcc.c-torture/execute/20080813-1.c: New test.
+
+2008-08-13 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/incoming-1.c: Skip *-*-darwin*.
+ * gcc.target/i386/incoming-2.c: Likewise.
+ * gcc.target/i386/incoming-3.c: Likewise.
+ * gcc.target/i386/incoming-4.c: Likewise.
+ * gcc.target/i386/incoming-5.c: Likewise.
+
2008-08-13 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR 30551
@@ -113,7 +148,7 @@
loop.
Should be vectorizable on targets that support vector unpack.
* gcc.dg/vect/vect-widen-mult-u8.c,
- gcc.dg/vect/wrapv-vect-reduc-dot-s8b.c,.
+ gcc.dg/vect/wrapv-vect-reduc-dot-s8b.c,
gcc.dg/vect/wrapv-vect-reduc-dot-s8b.c: Likewise.
* gcc.dg/vect/vect-35.c: Should be vectorizable on targets that
support vector pack. Avoid vectorization of the init loop.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20080813-1.c b/gcc/testsuite/gcc.c-torture/execute/20080813-1.c
new file mode 100644
index 00000000000..9ef6bc2e2c5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20080813-1.c
@@ -0,0 +1,30 @@
+/* PR middle-end/37103 */
+
+extern void abort (void);
+
+void
+foo (unsigned short x)
+{
+ signed char y = -1;
+ if (x == y)
+ abort ();
+}
+
+void
+bar (unsigned short x)
+{
+ unsigned char y = -1;
+ if (x == y)
+ abort ();
+}
+
+int
+main (void)
+{
+ if (sizeof (int) == sizeof (short))
+ return 0;
+ foo (-1);
+ if (sizeof (short) > 1)
+ bar (-1);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/arm-g2.c b/gcc/testsuite/gcc.dg/arm-g2.c
index a15b280cc10..031b93657da 100644
--- a/gcc/testsuite/gcc.dg/arm-g2.c
+++ b/gcc/testsuite/gcc.dg/arm-g2.c
@@ -1,6 +1,7 @@
/* Verify that hardware multiply is preferred on XScale. */
/* { dg-do compile } */
/* { dg-options "-mcpu=xscale -O2" } */
+/* { dg-skip-if "Test is specific to the Xscale" { arm*-*-* } { "-march=*" } { "-march=xscale" } } */
/* { dg-require-effective-target arm32 } */
/* Brett Gaines' test case. */
diff --git a/gcc/testsuite/gcc.dg/arm-mmx-1.c b/gcc/testsuite/gcc.dg/arm-mmx-1.c
index e4535eebefd..21cc47912c0 100644
--- a/gcc/testsuite/gcc.dg/arm-mmx-1.c
+++ b/gcc/testsuite/gcc.dg/arm-mmx-1.c
@@ -1,8 +1,11 @@
/* Verify that if IP is saved to ensure stack alignment, we don't load
it into sp. */
/* { dg-do compile } */
+/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-mcpu=*" } { "-mcpu=iwmmxt" } } */
+/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-mabi=*" } { "-mabi=iwmmxt" } } */
+/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-mfloat-abi=softfp" } { "" } } */
+/* { dg-skip-if "Test is specific to the iWMMXt" { arm*-*-* } { "-march=*" } { "-march=iwmmxt" } } */
/* { dg-options "-O -mno-apcs-frame -mcpu=iwmmxt -mabi=iwmmxt" } */
-/* { dg-skip-if "" { *-*-* } { "-mfloat-abi=softfp" } { "" } } */
/* { dg-require-effective-target arm32 } */
/* { dg-final { scan-assembler "ldmfd\[ ]sp!.*ip,\[ ]*pc" } } */
diff --git a/gcc/testsuite/gcc.dg/arm-scd42-2.c b/gcc/testsuite/gcc.dg/arm-scd42-2.c
index 1c257c173b6..0c372983a54 100644
--- a/gcc/testsuite/gcc.dg/arm-scd42-2.c
+++ b/gcc/testsuite/gcc.dg/arm-scd42-2.c
@@ -1,6 +1,7 @@
/* Verify that mov is preferred on XScale for loading a 2 byte constant. */
/* { dg-do compile } */
/* { dg-options "-mcpu=xscale -O" } */
+/* { dg-skip-if "Test is specific to the Xscale" { arm*-*-* } { "-march=*" } { "-march=xscale" } } */
/* { dg-require-effective-target arm32 } */
unsigned load2(void) __attribute__ ((naked));
diff --git a/gcc/testsuite/gcc.dg/parser-pr28152-2.c b/gcc/testsuite/gcc.dg/parser-pr28152-2.c
new file mode 100644
index 00000000000..18dc1e63dec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/parser-pr28152-2.c
@@ -0,0 +1,11 @@
+/* PR 28152: error messages should mention __complex__ */
+/* { dg-do compile } */
+/* { dg-options "" } */
+int
+main (void)
+{
+ __complex__ float z;
+
+ z = __complex__ (1.90000007326203904e+19, 0.0); /* { dg-error "__complex__" } */
+ z = __complex__ (1.0e+0, 0.0) / z; /* { dg-error "__complex__" } */
+ /* { dg-error "at end of input" "" { target *-*-* } 10 } */
diff --git a/gcc/testsuite/gcc.dg/parser-pr28152.c b/gcc/testsuite/gcc.dg/parser-pr28152.c
new file mode 100644
index 00000000000..99534c10bfe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/parser-pr28152.c
@@ -0,0 +1,11 @@
+/* PR 28152: error messages should mention _Complex */
+/* { dg-do compile } */
+/* { dg-options "" } */
+int
+main (void)
+{
+ _Complex float z;
+
+ z = _Complex (1.90000007326203904e+19, 0.0); /* { dg-error "_Complex" } */
+ z = _Complex (1.0e+0, 0.0) / z; /* { dg-error "_Complex" } */
+ /* { dg-error "at end of input" "" { target *-*-* } 10 } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-4a.c b/gcc/testsuite/gcc.dg/vect/vect-outer-4a.c
index 8fd1a03db14..d7bcc9a2e8c 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-outer-4a.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-outer-4a.c
@@ -6,8 +6,7 @@ signed short in[N+M];
signed short coeff[M];
signed short out[N];
-/* Outer-loop vectorization.
- Currently not vectorized because of multiple-data-types in the inner-loop. */
+/* Outer-loop vectorization. */
void
foo (){
@@ -23,9 +22,5 @@ foo (){
}
}
-/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail *-*-* } } } */
-/* FORNOW. not vectorized until we support 0-stride acceses like coeff[j]. should be:
- { scan-tree-dump-not "multiple types in nested loop." "vect" { xfail *-*-* } } } */
-
-/* { dg-final { scan-tree-dump-times "zero step in outer loop." 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { target { vect_widen_mult_hi_to_si && vect_pack_trunc } } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-4b.c b/gcc/testsuite/gcc.dg/vect/vect-outer-4b.c
index ba2f7b4d0df..407315a8dc3 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-outer-4b.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-outer-4b.c
@@ -6,8 +6,7 @@ signed short in[N+M];
signed short coeff[M];
int out[N];
-/* Outer-loop vectorization.
- Currently not vectorized because of multiple-data-types in the inner-loop. */
+/* Outer-loop vectorization. */
void
foo (){
@@ -23,9 +22,5 @@ foo (){
}
}
-/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail *-*-* } } } */
-/* FORNOW. not vectorized until we support 0-stride acceses like coeff[j]. should be:
- { scan-tree-dump-not "multiple types in nested loop." "vect" { xfail *-*-* } } } */
-
-/* { dg-final { scan-tree-dump-times "zero step in outer loop." 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { target vect_widen_mult_hi_to_si } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-4f.c b/gcc/testsuite/gcc.dg/vect/vect-outer-4f.c
index cef37c42321..88d6b7abccd 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-outer-4f.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-outer-4f.c
@@ -2,7 +2,7 @@
#include <stdarg.h>
#include "tree-vect.h"
-#define N 40
+#define N 96
#define M 128
unsigned short in[N+M];
unsigned int out[N];
diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-4g.c b/gcc/testsuite/gcc.dg/vect/vect-outer-4g.c
index cef37c42321..88d6b7abccd 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-outer-4g.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-outer-4g.c
@@ -2,7 +2,7 @@
#include <stdarg.h>
#include "tree-vect.h"
-#define N 40
+#define N 96
#define M 128
unsigned short in[N+M];
unsigned int out[N];
diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-4i.c b/gcc/testsuite/gcc.dg/vect/vect-outer-4i.c
index bc43c5bc6d5..a244ac20ac2 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-outer-4i.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-outer-4i.c
@@ -1,13 +1,17 @@
-/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
-#define N 40
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 96
#define M 128
unsigned char in[N+M];
unsigned short out[N];
/* Outer-loop vectorization. */
-/* Not vectorized due to multiple-types in the inner-loop. */
+/* Multiple-types in the inner-loop. */
+__attribute__ ((noinline))
unsigned short
foo (){
int i,j;
@@ -24,5 +28,22 @@ foo (){
return s;
}
-/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail *-*-* } } } */
+int main (void)
+{
+ check_vect ();
+ int i;
+ unsigned short s;
+
+ for (i = 0; i < N+M; i++)
+ in[i] = (unsigned char)i;
+
+ s = foo ();
+
+ if (s != 34048)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { target vect_unpack } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-4j.c b/gcc/testsuite/gcc.dg/vect/vect-outer-4j.c
index 7e1b7ec81ee..db8f61c5e37 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-outer-4j.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-outer-4j.c
@@ -1,12 +1,11 @@
/* { dg-do compile } */
-#define N 40
+#define N 96
#define M 128
unsigned char in[N+M];
unsigned short out[N];
/* Outer-loop vectorization. */
-/* Not vectorized due to multiple-types in the inner-loop. */
void
foo (){
@@ -22,5 +21,5 @@ foo (){
}
}
-/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { target vect_unpack } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-4k.c b/gcc/testsuite/gcc.dg/vect/vect-outer-4k.c
index cef37c42321..88d6b7abccd 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-outer-4k.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-outer-4k.c
@@ -2,7 +2,7 @@
#include <stdarg.h>
#include "tree-vect.h"
-#define N 40
+#define N 96
#define M 128
unsigned short in[N+M];
unsigned int out[N];
diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-4l.c b/gcc/testsuite/gcc.dg/vect/vect-outer-4l.c
index cef37c42321..88d6b7abccd 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-outer-4l.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-outer-4l.c
@@ -2,7 +2,7 @@
#include <stdarg.h>
#include "tree-vect.h"
-#define N 40
+#define N 96
#define M 128
unsigned short in[N+M];
unsigned int out[N];
diff --git a/gcc/testsuite/gcc.target/i386/incoming-1.c b/gcc/testsuite/gcc.target/i386/incoming-1.c
index fcc80f1ec2a..86e98a79b47 100644
--- a/gcc/testsuite/gcc.target/i386/incoming-1.c
+++ b/gcc/testsuite/gcc.target/i386/incoming-1.c
@@ -1,5 +1,5 @@
/* PR middle-end/37009 */
-/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
/* { dg-options "-w -msse2 -mpreferred-stack-boundary=2" } */
#include <emmintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/incoming-2.c b/gcc/testsuite/gcc.target/i386/incoming-2.c
index cc6c3934253..2947d3347cd 100644
--- a/gcc/testsuite/gcc.target/i386/incoming-2.c
+++ b/gcc/testsuite/gcc.target/i386/incoming-2.c
@@ -1,5 +1,5 @@
/* PR middle-end/37009 */
-/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
/* { dg-options "-w -msse2 -mpreferred-stack-boundary=2" } */
#include <emmintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/incoming-3.c b/gcc/testsuite/gcc.target/i386/incoming-3.c
index aad38b53ab4..1edbfda0b39 100644
--- a/gcc/testsuite/gcc.target/i386/incoming-3.c
+++ b/gcc/testsuite/gcc.target/i386/incoming-3.c
@@ -1,5 +1,5 @@
/* PR middle-end/37009 */
-/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
/* { dg-options "-w -msse2 -mpreferred-stack-boundary=2" } */
#include <emmintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/incoming-4.c b/gcc/testsuite/gcc.target/i386/incoming-4.c
index 270024bc15c..80c169c2469 100644
--- a/gcc/testsuite/gcc.target/i386/incoming-4.c
+++ b/gcc/testsuite/gcc.target/i386/incoming-4.c
@@ -1,5 +1,5 @@
/* PR middle-end/37009 */
-/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
/* { dg-options "-w -msse2 -mpreferred-stack-boundary=2" } */
#include <stdarg.h>
diff --git a/gcc/testsuite/gcc.target/i386/incoming-5.c b/gcc/testsuite/gcc.target/i386/incoming-5.c
index 38620bfc938..f083d403116 100644
--- a/gcc/testsuite/gcc.target/i386/incoming-5.c
+++ b/gcc/testsuite/gcc.target/i386/incoming-5.c
@@ -1,5 +1,5 @@
/* PR middle-end/37009 */
-/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-do compile { target { { ! *-*-darwin* } && ilp32 } } } */
/* { dg-options "-m32 -mincoming-stack-boundary=2 -mpreferred-stack-boundary=2" } */
extern void bar (double *);
diff --git a/gcc/testsuite/gcc.target/i386/pr37101.c b/gcc/testsuite/gcc.target/i386/pr37101.c
new file mode 100644
index 00000000000..8fd3bfc5f85
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr37101.c
@@ -0,0 +1,64 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -ftree-vectorize -march=nocona" } */
+
+typedef __SIZE_TYPE__ size_t;
+extern void *malloc (size_t);
+extern void free (void *);
+
+typedef struct _Resource
+{
+ struct _Resource *next;
+ unsigned int id;
+} ResourceRec, *ResourcePtr;
+
+typedef struct _ClientResource
+{
+ ResourcePtr *resources;
+ int elements;
+ int buckets;
+ int hashsize;
+} ClientResourceRec;
+
+static ClientResourceRec clientTable[256];
+
+void
+RebuildTable (int client)
+{
+ int j;
+ ResourcePtr res, next;
+ ResourcePtr **tails, *resources;
+ ResourcePtr **tptr, *rptr;
+
+ j = 2 * clientTable[client].buckets;
+
+ tails =
+ (ResourcePtr **) malloc ((unsigned long) (j * sizeof (ResourcePtr *)));
+ resources =
+ (ResourcePtr *) malloc ((unsigned long) (j * sizeof (ResourcePtr)));
+
+ for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++)
+ {
+ *rptr = ((ResourcePtr) ((void *) 0));
+ *tptr = rptr;
+ }
+
+ clientTable[client].hashsize++;
+ for (j = clientTable[client].buckets,
+ rptr = clientTable[client].resources; --j >= 0; rptr++)
+ {
+ for (res = *rptr; res; res = next)
+ {
+ next = res->next;
+ res->next = ((ResourcePtr) ((void *) 0));
+ tptr = &tails[Hash (client, res->id)];
+ **tptr = res;
+ *tptr = &res->next;
+ }
+ }
+ free ((void *) tails);
+ clientTable[client].buckets *= 2;
+ free ((void *) clientTable[client].resources);
+ clientTable[client].resources = resources;
+}
+
+/* { dg-final { scan-assembler-not "movlps" } } */
diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c
index a1bc2b1bd08..eb370775cba 100644
--- a/gcc/tree-vect-transform.c
+++ b/gcc/tree-vect-transform.c
@@ -59,8 +59,8 @@ static tree vect_init_vector (gimple, tree, tree, gimple_stmt_iterator *);
static void vect_finish_stmt_generation
(gimple stmt, gimple vec_stmt, gimple_stmt_iterator *);
static bool vect_is_simple_cond (tree, loop_vec_info);
-static void vect_create_epilog_for_reduction (tree, gimple, enum tree_code,
- gimple);
+static void vect_create_epilog_for_reduction
+ (tree, gimple, int, enum tree_code, gimple);
static tree get_initial_def_for_reduction (gimple, tree, tree *);
/* Utility function dealing with loop peeling (not peeling itself). */
@@ -1824,7 +1824,7 @@ get_initial_def_for_induction (gimple iv_phi)
if (vect_print_dump_info (REPORT_DETAILS))
{
- fprintf (vect_dump, "transform induction: created def-use cycle:");
+ fprintf (vect_dump, "transform induction: created def-use cycle: ");
print_gimple_stmt (vect_dump, induction_phi, 0, TDF_SLIM);
fprintf (vect_dump, "\n");
print_gimple_stmt (vect_dump, SSA_NAME_DEF_STMT (vec_def), 0, TDF_SLIM);
@@ -2056,6 +2056,10 @@ vect_get_vec_def_for_stmt_copy (enum vect_def_type dt, tree vec_oprnd)
vec_stmt_for_operand = STMT_VINFO_RELATED_STMT (def_stmt_info);
gcc_assert (vec_stmt_for_operand);
vec_oprnd = gimple_get_lhs (vec_stmt_for_operand);
+ if (gimple_code (vec_stmt_for_operand) == GIMPLE_PHI)
+ vec_oprnd = PHI_RESULT (vec_stmt_for_operand);
+ else
+ vec_oprnd = gimple_get_lhs (vec_stmt_for_operand);
return vec_oprnd;
}
@@ -2251,6 +2255,11 @@ get_initial_def_for_reduction (gimple stmt, tree init_val, tree *adjustment_def)
VECT_DEF is a vector of partial results.
REDUC_CODE is the tree-code for the epilog reduction.
+ NCOPIES is > 1 in case the vectorization factor (VF) is bigger than the
+ number of elements that we can fit in a vectype (nunits). In this case
+ we have to generate more than one vector stmt - i.e - we need to "unroll"
+ the vector stmt by a factor VF/nunits. For more details see documentation
+ in vectorizable_operation.
STMT is the scalar reduction stmt that is being vectorized.
REDUCTION_PHI is the phi-node that carries the reduction computation.
@@ -2294,10 +2303,12 @@ get_initial_def_for_reduction (gimple stmt, tree init_val, tree *adjustment_def)
static void
vect_create_epilog_for_reduction (tree vect_def, gimple stmt,
+ int ncopies,
enum tree_code reduc_code,
gimple reduction_phi)
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ stmt_vec_info prev_phi_info;
tree vectype;
enum machine_mode mode;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
@@ -2305,7 +2316,7 @@ vect_create_epilog_for_reduction (tree vect_def, gimple stmt,
basic_block exit_bb;
tree scalar_dest;
tree scalar_type;
- gimple new_phi;
+ gimple new_phi = NULL, phi;
gimple_stmt_iterator exit_gsi;
tree vec_dest;
tree new_temp = NULL_TREE;
@@ -2316,7 +2327,7 @@ vect_create_epilog_for_reduction (tree vect_def, gimple stmt,
tree bitsize, bitpos, bytesize;
enum tree_code code = gimple_assign_rhs_code (stmt);
tree adjustment_def;
- tree vec_initial_def;
+ tree vec_initial_def, def;
tree orig_name;
imm_use_iterator imm_iter;
use_operand_p use_p;
@@ -2326,7 +2337,8 @@ vect_create_epilog_for_reduction (tree vect_def, gimple stmt,
gimple use_stmt;
bool nested_in_vect_loop = false;
VEC(gimple,heap) *phis = NULL;
- int i;
+ enum vect_def_type dt = vect_unknown_def_type;
+ int j, i;
if (nested_in_vect_loop_p (loop, stmt))
{
@@ -2356,25 +2368,34 @@ vect_create_epilog_for_reduction (tree vect_def, gimple stmt,
/*** 1. Create the reduction def-use cycle ***/
- /* 1.1 set the loop-entry arg of the reduction-phi: */
/* For the case of reduction, vect_get_vec_def_for_operand returns
the scalar def before the loop, that defines the initial value
of the reduction variable. */
vec_initial_def = vect_get_vec_def_for_operand (reduction_op, stmt,
&adjustment_def);
- add_phi_arg (reduction_phi, vec_initial_def, loop_preheader_edge (loop));
-
- /* 1.2 set the loop-latch arg for the reduction-phi: */
- add_phi_arg (reduction_phi, vect_def, loop_latch_edge (loop));
- if (vect_print_dump_info (REPORT_DETAILS))
+ phi = reduction_phi;
+ def = vect_def;
+ for (j = 0; j < ncopies; j++)
{
- fprintf (vect_dump, "transform reduction: created def-use cycle:");
- print_gimple_stmt (vect_dump, reduction_phi, 0, TDF_SLIM);
- fprintf (vect_dump, "\n");
- print_gimple_stmt (vect_dump, SSA_NAME_DEF_STMT (vect_def), 0, TDF_SLIM);
- }
+ /* 1.1 set the loop-entry arg of the reduction-phi: */
+ add_phi_arg (phi, vec_initial_def, loop_preheader_edge (loop));
+
+ /* 1.2 set the loop-latch arg for the reduction-phi: */
+ if (j > 0)
+ def = vect_get_vec_def_for_stmt_copy (dt, def);
+ add_phi_arg (phi, def, loop_latch_edge (loop));
+ if (vect_print_dump_info (REPORT_DETAILS))
+ {
+ fprintf (vect_dump, "transform reduction: created def-use cycle: ");
+ print_gimple_stmt (vect_dump, phi, 0, TDF_SLIM);
+ fprintf (vect_dump, "\n");
+ print_gimple_stmt (vect_dump, SSA_NAME_DEF_STMT (def), 0, TDF_SLIM);
+ }
+
+ phi = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (phi));
+ }
/*** 2. Create epilog code
The reduction epilog code operates across the elements of the vector
@@ -2398,7 +2419,7 @@ vect_create_epilog_for_reduction (tree vect_def, gimple stmt,
s_out3 = extract_field <v_out2, 0> # step 2
s_out4 = adjust_result <s_out3> # step 3
- (step 3 is optional, and step2 1 and 2 may be combined).
+ (step 3 is optional, and steps 1 and 2 may be combined).
Lastly, the uses of s_out0 are replaced by s_out4.
***/
@@ -2407,8 +2428,22 @@ vect_create_epilog_for_reduction (tree vect_def, gimple stmt,
v_out1 = phi <v_loop> */
exit_bb = single_exit (loop)->dest;
- new_phi = create_phi_node (SSA_NAME_VAR (vect_def), exit_bb);
- SET_PHI_ARG_DEF (new_phi, single_exit (loop)->dest_idx, vect_def);
+ def = vect_def;
+ prev_phi_info = NULL;
+ for (j = 0; j < ncopies; j++)
+ {
+ phi = create_phi_node (SSA_NAME_VAR (vect_def), exit_bb);
+ set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, loop_vinfo));
+ if (j == 0)
+ new_phi = phi;
+ else
+ {
+ def = vect_get_vec_def_for_stmt_copy (dt, def);
+ STMT_VINFO_RELATED_STMT (prev_phi_info) = phi;
+ }
+ SET_PHI_ARG_DEF (phi, single_exit (loop)->dest_idx, def);
+ prev_phi_info = vinfo_for_stmt (phi);
+ }
exit_gsi = gsi_after_labels (exit_bb);
/* 2.2 Get the relevant tree-code to use in the epilog for schemes 2,3
@@ -2449,6 +2484,9 @@ vect_create_epilog_for_reduction (tree vect_def, gimple stmt,
if (nested_in_vect_loop)
goto vect_finalize_reduction;
+ /* FORNOW */
+ gcc_assert (ncopies = 1);
+
/* 2.3 Create the reduction code, using one of the three schemes described
above. */
@@ -2664,15 +2702,19 @@ vect_finalize_reduction:
{
stmt_vec_info stmt_vinfo = vinfo_for_stmt (exit_phi);
- /* FORNOW. Currently not supporting the case that an inner-loop reduction
- is not used in the outer-loop (but only outside the outer-loop). */
+ /* FORNOW. Currently not supporting the case that an inner-loop
+ reduction is not used in the outer-loop (but only outside the
+ outer-loop). */
gcc_assert (STMT_VINFO_RELEVANT_P (stmt_vinfo)
&& !STMT_VINFO_LIVE_P (stmt_vinfo));
- epilog_stmt = adjustment_def ? epilog_stmt : new_phi;
+ epilog_stmt = adjustment_def ? epilog_stmt : new_phi;
STMT_VINFO_VEC_STMT (stmt_vinfo) = epilog_stmt;
- set_vinfo_for_stmt (epilog_stmt,
+ set_vinfo_for_stmt (epilog_stmt,
new_stmt_vec_info (epilog_stmt, loop_vinfo));
+ if (adjustment_def)
+ STMT_VINFO_RELATED_STMT (vinfo_for_stmt (epilog_stmt)) =
+ STMT_VINFO_RELATED_STMT (vinfo_for_stmt (new_phi));
continue;
}
@@ -2745,7 +2787,7 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
tree def;
gimple def_stmt;
enum vect_def_type dt;
- gimple new_phi;
+ gimple new_phi = NULL;
tree scalar_type;
bool is_simple_use;
gimple orig_stmt;
@@ -2754,23 +2796,17 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
int i;
int nunits = TYPE_VECTOR_SUBPARTS (vectype);
int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
- stmt_vec_info prev_stmt_info;
+ int epilog_copies;
+ stmt_vec_info prev_stmt_info, prev_phi_info;
+ gimple first_phi = NULL;
+ bool single_defuse_cycle = false;
tree reduc_def;
gimple new_stmt = NULL;
int j;
tree ops[3];
if (nested_in_vect_loop_p (loop, stmt))
- {
- loop = loop->inner;
- /* FORNOW. This restriction should be relaxed. */
- if (ncopies > 1)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "multiple types in nested loop.");
- return false;
- }
- }
+ loop = loop->inner;
gcc_assert (ncopies >= 1);
@@ -3004,18 +3040,52 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
/* Create the destination vector */
vec_dest = vect_create_destination_var (scalar_dest, vectype);
- /* Create the reduction-phi that defines the reduction-operand. */
- new_phi = create_phi_node (vec_dest, loop->header);
-
/* In case the vectorization factor (VF) is bigger than the number
of elements that we can fit in a vectype (nunits), we have to generate
more than one vector stmt - i.e - we need to "unroll" the
vector stmt by a factor VF/nunits. For more details see documentation
in vectorizable_operation. */
+ /* If the reduction is used in an outer loop we need to generate
+ VF intermediate results, like so (e.g. for ncopies=2):
+ r0 = phi (init, r0)
+ r1 = phi (init, r1)
+ r0 = x0 + r0;
+ r1 = x1 + r1;
+ (i.e. we generate VF results in 2 registers).
+ In this case we have a separate def-use cycle for each copy, and therefore
+ for each copy we get the vector def for the reduction variable from the
+ respective phi node created for this copy.
+
+ Otherwise (the reduction is unused in the loop nest), we can combine
+ together intermediate results, like so (e.g. for ncopies=2):
+ r = phi (init, r)
+ r = x0 + r;
+ r = x1 + r;
+ (i.e. we generate VF/2 results in a single register).
+ In this case for each copy we get the vector def for the reduction variable
+ from the vectorized reduction operation generated in the previous iteration.
+ */
+
+ if (STMT_VINFO_RELEVANT (stmt_info) == vect_unused_in_loop)
+ {
+ single_defuse_cycle = true;
+ epilog_copies = 1;
+ }
+ else
+ epilog_copies = ncopies;
+
prev_stmt_info = NULL;
+ prev_phi_info = NULL;
for (j = 0; j < ncopies; j++)
{
+ if (j == 0 || !single_defuse_cycle)
+ {
+ /* Create the reduction-phi that defines the reduction-operand. */
+ new_phi = create_phi_node (vec_dest, loop->header);
+ set_vinfo_for_stmt (new_phi, new_stmt_vec_info (new_phi, loop_vinfo));
+ }
+
/* Handle uses. */
if (j == 0)
{
@@ -3027,6 +3097,7 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
/* Get the vector def for the reduction variable from the phi node */
reduc_def = PHI_RESULT (new_phi);
+ first_phi = new_phi;
}
else
{
@@ -3035,9 +3106,12 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
if (op_type == ternary_op)
loop_vec_def1 = vect_get_vec_def_for_stmt_copy (dt, loop_vec_def1);
- /* Get the vector def for the reduction variable from the vectorized
- reduction operation generated in the previous iteration (j-1) */
- reduc_def = gimple_assign_lhs (new_stmt);
+ if (single_defuse_cycle)
+ reduc_def = gimple_assign_lhs (new_stmt);
+ else
+ reduc_def = PHI_RESULT (new_phi);
+
+ STMT_VINFO_RELATED_STMT (prev_phi_info) = new_phi;
}
/* Arguments are ready. create the new vector stmt. */
@@ -3056,11 +3130,15 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
else
STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
prev_stmt_info = vinfo_for_stmt (new_stmt);
+ prev_phi_info = vinfo_for_stmt (new_phi);
}
/* Finalize the reduction-phi (set it's arguments) and create the
epilog reduction code. */
- vect_create_epilog_for_reduction (new_temp, stmt, epilog_reduc_code, new_phi);
+ if (!single_defuse_cycle)
+ new_temp = gimple_assign_lhs (*vec_stmt);
+ vect_create_epilog_for_reduction (new_temp, stmt, epilog_copies,
+ epilog_reduc_code, first_phi);
return true;
}
@@ -3108,7 +3186,6 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
int nunits_in;
int nunits_out;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree fndecl, new_temp, def, rhs_type, lhs_type;
gimple def_stmt;
enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
@@ -3212,14 +3289,6 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
needs to be generated. */
gcc_assert (ncopies >= 1);
- /* FORNOW. This restriction should be relaxed. */
- if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "multiple types in nested loop.");
- return false;
- }
-
if (!vec_stmt) /* transformation not required. */
{
STMT_VINFO_TYPE (stmt_info) = call_vec_info_type;
@@ -3234,14 +3303,6 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "transform operation.");
- /* FORNOW. This restriction should be relaxed. */
- if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "multiple types in nested loop.");
- return false;
- }
-
/* Handle def. */
scalar_dest = gimple_call_lhs (stmt);
vec_dest = vect_create_destination_var (scalar_dest, vectype_out);
@@ -3436,7 +3497,6 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
enum tree_code code, code1 = ERROR_MARK, code2 = ERROR_MARK;
tree decl1 = NULL_TREE, decl2 = NULL_TREE;
tree new_temp;
@@ -3527,14 +3587,6 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
needs to be generated. */
gcc_assert (ncopies >= 1);
- /* FORNOW. This restriction should be relaxed. */
- if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "multiple types in nested loop.");
- return false;
- }
-
/* Check the operands of the operation. */
if (!vect_is_simple_use (op0, loop_vinfo, &def_stmt, &def, &dt[0]))
{
@@ -3847,11 +3899,19 @@ vectorizable_induction (gimple phi, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
stmt_vec_info stmt_info = vinfo_for_stmt (phi);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
int nunits = TYPE_VECTOR_SUBPARTS (vectype);
int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
tree vec_def;
gcc_assert (ncopies >= 1);
+ /* FORNOW. This restriction should be relaxed. */
+ if (nested_in_vect_loop_p (loop, phi) && ncopies > 1)
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "multiple types in nested loop.");
+ return false;
+ }
if (!STMT_VINFO_RELEVANT_P (stmt_info))
return false;
@@ -3903,7 +3963,6 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
enum tree_code code;
enum machine_mode vec_mode;
tree new_temp;
@@ -3932,13 +3991,6 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
if (slp_node)
ncopies = 1;
gcc_assert (ncopies >= 1);
- /* FORNOW. This restriction should be relaxed. */
- if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "multiple types in nested loop.");
- return false;
- }
if (!STMT_VINFO_RELEVANT_P (stmt_info))
return false;
@@ -4257,7 +4309,6 @@ vectorizable_type_demotion (gimple stmt, gimple_stmt_iterator *gsi,
tree vec_oprnd0=NULL, vec_oprnd1=NULL;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
enum tree_code code, code1 = ERROR_MARK;
tree new_temp;
tree def;
@@ -4310,13 +4361,6 @@ vectorizable_type_demotion (gimple stmt, gimple_stmt_iterator *gsi,
ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
gcc_assert (ncopies >= 1);
- /* FORNOW. This restriction should be relaxed. */
- if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "multiple types in nested loop.");
- return false;
- }
if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
&& INTEGRAL_TYPE_P (TREE_TYPE (op0)))
@@ -4458,7 +4502,6 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
tree vec_oprnd0=NULL, vec_oprnd1=NULL;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
enum tree_code code, code1 = ERROR_MARK, code2 = ERROR_MARK;
tree decl1 = NULL_TREE, decl2 = NULL_TREE;
int op_type;
@@ -4511,13 +4554,6 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
gcc_assert (ncopies >= 1);
- /* FORNOW. This restriction should be relaxed. */
- if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "multiple types in nested loop.");
- return false;
- }
if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
&& INTEGRAL_TYPE_P (TREE_TYPE (op0)))
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 2edf9f9d2ea..11269e69388 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,10 @@
2008-08-13 Paolo Carlini <paolo.carlini@oracle.com>
+ Re-instate last patch, amended to use __exchange_and_add_dispatch
+ and __atomic_add_dispatch in eh_ptr.cc and eh_throw.cc.
+
+2008-08-13 Paolo Carlini <paolo.carlini@oracle.com>
+
Revert the last patch.
2008-08-13 Sebastian Redl <sebastian.redl@getdesigned.at>
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 7b31a1cfa47..0ec4879ffd4 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -66,7 +66,9 @@ GLIBCXX_3.4 {
# std::condition_variable;
std::co[^n]*;
std::c[p-s]*;
- std::c[u-z]*;
+ std::cu[^r]*;
+# std::current_exception
+ std::c[v-z]*;
# std::[d-g]*;
std::d[a-d]*;
std::d[f-z]*;
@@ -112,10 +114,13 @@ GLIBCXX_3.4 {
std::n[^au]*;
std::nu[^m]*;
std::num[^e]*;
- std::[p-r]*;
std::ostrstream*;
std::out_of_range*;
std::overflow_error*;
+ std::[p-q]*;
+ std::r[^e]*;
+ std::re[^t]*;
+# std::rethrow_exception
std::set_new_handler*;
std::set_terminate*;
std::set_unexpected*;
@@ -1047,4 +1052,24 @@ CXXABI_1.3.3 {
_ZTIPu8char32_t;
_ZTIPKu8char32_t;
+ # exception_ptr
+ _ZNSt15__exception_ptr13exception_ptrC1Ev;
+ _ZNSt15__exception_ptr13exception_ptrC2Ev;
+ _ZNSt15__exception_ptr13exception_ptrC1ERKS0_;
+ _ZNSt15__exception_ptr13exception_ptrC2ERKS0_;
+ _ZNSt15__exception_ptr13exception_ptrC1EMS0_FvvE;
+ _ZNSt15__exception_ptr13exception_ptrC2EMS0_FvvE;
+ _ZNSt15__exception_ptr13exception_ptrD1Ev;
+ _ZNSt15__exception_ptr13exception_ptrD2Ev;
+ _ZNSt15__exception_ptr13exception_ptraSERKS0_;
+ _ZNKSt15__exception_ptr13exception_ptrcvMS0_FvvEEv;
+ _ZNKSt15__exception_ptr13exception_ptrntEv;
+ _ZNKSt15__exception_ptr13exception_ptr20__cxa_exception_typeEv;
+ _ZNSt15__exception_ptr13exception_ptr4swapERS0_;
+ _ZNSt15__exception_ptreqERKNS_13exception_ptrES2_;
+ _ZNSt15__exception_ptrneERKNS_13exception_ptrES2_;
+
+ _ZSt17current_exceptionv;
+ _ZSt17rethrow_exceptionNSt15__exception_ptr13exception_ptrE;
+
} CXXABI_1.3.2;
diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am
index c0412f0b8ed..680005fbf83 100644
--- a/libstdc++-v3/libsupc++/Makefile.am
+++ b/libstdc++-v3/libsupc++/Makefile.am
@@ -34,7 +34,7 @@ noinst_LTLIBRARIES = libsupc++convenience.la
headers = \
exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
- initializer_list
+ initializer_list exception_ptr.h
if GLIBCXX_HOSTED
c_sources = \
@@ -60,6 +60,7 @@ sources = \
eh_exception.cc \
eh_globals.cc \
eh_personality.cc \
+ eh_ptr.cc \
eh_term_handler.cc \
eh_terminate.cc \
eh_throw.cc \
diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in
index 105aec63d8d..c3d1c6c6b43 100644
--- a/libstdc++-v3/libsupc++/Makefile.in
+++ b/libstdc++-v3/libsupc++/Makefile.in
@@ -79,7 +79,7 @@ am__libsupc___la_SOURCES_DIST = array_type_info.cc atexit_arm.cc \
bad_cast.cc bad_typeid.cc class_type_info.cc del_op.cc \
del_opnt.cc del_opv.cc del_opvnt.cc dyncast.cc eh_alloc.cc \
eh_arm.cc eh_aux_runtime.cc eh_call.cc eh_catch.cc \
- eh_exception.cc eh_globals.cc eh_personality.cc \
+ eh_exception.cc eh_globals.cc eh_personality.cc eh_ptr.cc \
eh_term_handler.cc eh_terminate.cc eh_throw.cc eh_type.cc \
eh_unex_handler.cc enum_type_info.cc function_type_info.cc \
fundamental_type_info.cc guard.cc new_handler.cc new_op.cc \
@@ -91,7 +91,7 @@ am__objects_1 = array_type_info.lo atexit_arm.lo bad_cast.lo \
bad_typeid.lo class_type_info.lo del_op.lo del_opnt.lo \
del_opv.lo del_opvnt.lo dyncast.lo eh_alloc.lo eh_arm.lo \
eh_aux_runtime.lo eh_call.lo eh_catch.lo eh_exception.lo \
- eh_globals.lo eh_personality.lo eh_term_handler.lo \
+ eh_globals.lo eh_personality.lo eh_ptr.lo eh_term_handler.lo \
eh_terminate.lo eh_throw.lo eh_type.lo eh_unex_handler.lo \
enum_type_info.lo function_type_info.lo \
fundamental_type_info.lo guard.lo new_handler.lo new_op.lo \
@@ -107,7 +107,7 @@ am__libsupc__convenience_la_SOURCES_DIST = array_type_info.cc \
atexit_arm.cc bad_cast.cc bad_typeid.cc class_type_info.cc \
del_op.cc del_opnt.cc del_opv.cc del_opvnt.cc dyncast.cc \
eh_alloc.cc eh_arm.cc eh_aux_runtime.cc eh_call.cc eh_catch.cc \
- eh_exception.cc eh_globals.cc eh_personality.cc \
+ eh_exception.cc eh_globals.cc eh_personality.cc eh_ptr.cc \
eh_term_handler.cc eh_terminate.cc eh_throw.cc eh_type.cc \
eh_unex_handler.cc enum_type_info.cc function_type_info.cc \
fundamental_type_info.cc guard.cc new_handler.cc new_op.cc \
@@ -356,7 +356,7 @@ toolexeclib_LTLIBRARIES = libsupc++.la
noinst_LTLIBRARIES = libsupc++convenience.la
headers = \
exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \
- initializer_list
+ initializer_list exception_ptr.h
@GLIBCXX_HOSTED_TRUE@c_sources = \
@GLIBCXX_HOSTED_TRUE@ cp-demangle.c
@@ -380,6 +380,7 @@ sources = \
eh_exception.cc \
eh_globals.cc \
eh_personality.cc \
+ eh_ptr.cc \
eh_term_handler.cc \
eh_terminate.cc \
eh_throw.cc \
diff --git a/libstdc++-v3/libsupc++/eh_alloc.cc b/libstdc++-v3/libsupc++/eh_alloc.cc
index 553c1c1e858..6bc46fc9a91 100644
--- a/libstdc++-v3/libsupc++/eh_alloc.cc
+++ b/libstdc++-v3/libsupc++/eh_alloc.cc
@@ -1,5 +1,5 @@
// -*- C++ -*- Allocate exception objects.
-// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008
// Free Software Foundation, Inc.
//
// This file is part of GCC.
@@ -89,6 +89,9 @@ typedef char one_buffer[EMERGENCY_OBJ_SIZE] __attribute__((aligned));
static one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT];
static bitmask_type emergency_used;
+static __cxa_dependent_exception dependents_buffer[EMERGENCY_OBJ_COUNT];
+static bitmask_type dependents_used;
+
namespace
{
// A single mutex controlling emergency allocations.
@@ -157,3 +160,66 @@ __cxxabiv1::__cxa_free_exception(void *vptr) throw()
else
free (ptr - sizeof (__cxa_exception));
}
+
+
+extern "C" __cxa_dependent_exception*
+__cxxabiv1::__cxa_allocate_dependent_exception() throw()
+{
+ __cxa_dependent_exception *ret;
+
+ ret = static_cast<__cxa_dependent_exception*>
+ (malloc (sizeof (__cxa_dependent_exception)));
+
+ if (!ret)
+ {
+ __gnu_cxx::__scoped_lock sentry(emergency_mutex);
+
+ bitmask_type used = dependents_used;
+ unsigned int which = 0;
+
+ while (used & 1)
+ {
+ used >>= 1;
+ if (++which >= EMERGENCY_OBJ_COUNT)
+ goto failed;
+ }
+
+ dependents_used |= (bitmask_type)1 << which;
+ ret = &dependents_buffer[which];
+
+ failed:;
+
+ if (!ret)
+ std::terminate ();
+ }
+
+ // We have an uncaught exception as soon as we allocate memory. This
+ // yields uncaught_exception() true during the copy-constructor that
+ // initializes the exception object. See Issue 475.
+ __cxa_eh_globals *globals = __cxa_get_globals ();
+ globals->uncaughtExceptions += 1;
+
+ memset (ret, 0, sizeof (__cxa_dependent_exception));
+
+ return ret;
+}
+
+
+extern "C" void
+__cxxabiv1::__cxa_free_dependent_exception
+ (__cxa_dependent_exception *vptr) throw()
+{
+ char *base = (char *) dependents_buffer;
+ char *ptr = (char *) vptr;
+ if (ptr >= base
+ && ptr < base + sizeof (dependents_buffer))
+ {
+ const unsigned int which
+ = (unsigned) (ptr - base) / sizeof (__cxa_dependent_exception);
+
+ __gnu_cxx::__scoped_lock sentry(emergency_mutex);
+ dependents_used &= ~((bitmask_type)1 << which);
+ }
+ else
+ free (vptr);
+}
diff --git a/libstdc++-v3/libsupc++/eh_arm.cc b/libstdc++-v3/libsupc++/eh_arm.cc
index 6f770e95663..f10bb41e5c0 100644
--- a/libstdc++-v3/libsupc++/eh_arm.cc
+++ b/libstdc++-v3/libsupc++/eh_arm.cc
@@ -1,5 +1,5 @@
// -*- C++ -*- ARM specific Exception handling support routines.
-// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
@@ -48,13 +48,19 @@ __cxa_type_match(_Unwind_Exception* ue_header,
{
bool forced_unwind = __is_gxx_forced_unwind_class(ue_header->exception_class);
bool foreign_exception = !forced_unwind && !__is_gxx_exception_class(ue_header->exception_class);
+ bool dependent_exception =
+ __is_dependent_exception(ue_header->exception_class);
__cxa_exception* xh = __get_exception_header_from_ue(ue_header);
+ __cxa_dependent_exception *dx = __get_dependent_exception_from_ue(ue_header);
const std::type_info* throw_type;
if (forced_unwind)
throw_type = &typeid(abi::__forced_unwind);
else if (foreign_exception)
throw_type = &typeid(abi::__foreign_exception);
+ else if (dependent_exception)
+ throw_type = __get_exception_header_from_obj
+ (dx->primaryException)->exceptionType;
else
throw_type = xh->exceptionType;
diff --git a/libstdc++-v3/libsupc++/eh_call.cc b/libstdc++-v3/libsupc++/eh_call.cc
index edf62188a6b..c0bced99533 100644
--- a/libstdc++-v3/libsupc++/eh_call.cc
+++ b/libstdc++-v3/libsupc++/eh_call.cc
@@ -1,5 +1,5 @@
// -*- C++ -*- Helpers for calling unextected and terminate
-// Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
@@ -125,7 +125,7 @@ __cxa_call_unexpected(void* exc_obj_in)
__cxa_eh_globals* globals = __cxa_get_globals_fast();
__cxa_exception* new_xh = globals->caughtExceptions;
- void* new_ptr = new_xh + 1;
+ void* new_ptr = __gxx_get_object_from_ambiguous_exception (new_xh);
const std::type_info* catch_type;
int n;
bool bad_exception_allowed = false;
diff --git a/libstdc++-v3/libsupc++/eh_personality.cc b/libstdc++-v3/libsupc++/eh_personality.cc
index b7d957c4d37..12b54c16587 100644
--- a/libstdc++-v3/libsupc++/eh_personality.cc
+++ b/libstdc++-v3/libsupc++/eh_personality.cc
@@ -377,7 +377,7 @@ PERSONALITY_FUNCTION (int version,
const unsigned char *p;
_Unwind_Ptr landing_pad, ip;
int handler_switch_value;
- void* thrown_ptr = ue_header + 1;
+ void* thrown_ptr = 0;
bool foreign_exception;
int ip_before_insn = 0;
@@ -543,30 +543,33 @@ PERSONALITY_FUNCTION (int version,
bool saw_handler = false;
#ifdef __ARM_EABI_UNWINDER__
+ // ??? How does this work - more importantly, how does it interact with
+ // dependent exceptions?
throw_type = ue_header;
if (actions & _UA_FORCE_UNWIND)
{
__GXX_INIT_FORCED_UNWIND_CLASS(ue_header->exception_class);
- thrown_ptr = 0;
}
- else if (foreign_exception)
- thrown_ptr = 0;
+ else if (!foreign_exception)
+ thrown_ptr = __get_object_from_ue (ue_header);
#else
// During forced unwinding, match a magic exception type.
if (actions & _UA_FORCE_UNWIND)
{
throw_type = &typeid(abi::__forced_unwind);
- thrown_ptr = 0;
}
// With a foreign exception class, there's no exception type.
// ??? What to do about GNU Java and GNU Ada exceptions?
else if (foreign_exception)
{
throw_type = &typeid(abi::__foreign_exception);
- thrown_ptr = 0;
}
else
- throw_type = xh->exceptionType;
+ {
+ thrown_ptr = __get_object_from_ue (ue_header);
+ throw_type = __get_exception_header_from_obj
+ (thrown_ptr)->exceptionType;
+ }
#endif
while (1)
@@ -758,13 +761,14 @@ __cxa_call_unexpected (void *exc_obj_in)
__cxa_eh_globals *globals = __cxa_get_globals_fast ();
__cxa_exception *new_xh = globals->caughtExceptions;
- void *new_ptr = new_xh + 1;
+ void *new_ptr = __get_object_from_ambiguous_exception (new_xh);
// We don't quite have enough stuff cached; re-parse the LSDA.
parse_lsda_header (0, xh_lsda, &info);
// If this new exception meets the exception spec, allow it.
- if (check_exception_spec (&info, new_xh->exceptionType,
+ if (check_exception_spec (&info, __get_exception_header_from_obj
+ (new_ptr)->exceptionType,
new_ptr, xh_switch_value))
__throw_exception_again;
diff --git a/libstdc++-v3/libsupc++/eh_ptr.cc b/libstdc++-v3/libsupc++/eh_ptr.cc
new file mode 100644
index 00000000000..35ba5f90b87
--- /dev/null
+++ b/libstdc++-v3/libsupc++/eh_ptr.cc
@@ -0,0 +1,236 @@
+// -*- C++ -*- Implement the members of exception_ptr.
+// Copyright (C) 2008 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 2, 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 COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#include <bits/c++config.h>
+#include <exception>
+#include <exception_ptr.h>
+#include "unwind-cxx.h"
+
+using namespace __cxxabiv1;
+
+
+std::__exception_ptr::exception_ptr::exception_ptr() throw()
+ : _M_exception_object(0)
+{
+}
+
+
+std::__exception_ptr::exception_ptr::exception_ptr(void* obj) throw()
+ : _M_exception_object(obj)
+{
+ _M_addref();
+}
+
+
+std::__exception_ptr::exception_ptr::exception_ptr(__safe_bool) throw()
+ : _M_exception_object(0)
+{
+}
+
+
+std::__exception_ptr::exception_ptr::exception_ptr(
+ const exception_ptr& other) throw()
+ : _M_exception_object(other._M_exception_object)
+{
+ _M_addref();
+}
+
+
+std::__exception_ptr::exception_ptr::~exception_ptr() throw()
+{
+ _M_release();
+}
+
+
+std::__exception_ptr::exception_ptr&
+std::__exception_ptr::exception_ptr::operator=(
+ const exception_ptr& other) throw()
+{
+ exception_ptr(other).swap(*this);
+ return *this;
+}
+
+
+void
+std::__exception_ptr::exception_ptr::_M_addref() throw()
+{
+ if (_M_exception_object)
+ {
+ __cxa_exception *eh =
+ __get_exception_header_from_obj (_M_exception_object);
+ __gnu_cxx::__atomic_add_dispatch (&eh->referenceCount, 1);
+ }
+}
+
+
+void
+std::__exception_ptr::exception_ptr::_M_release() throw()
+{
+ if (_M_exception_object)
+ {
+ __cxa_exception *eh =
+ __get_exception_header_from_obj (_M_exception_object);
+ if (__gnu_cxx::__exchange_and_add_dispatch (&eh->referenceCount, -1) == 0)
+ {
+ if (eh->exceptionDestructor)
+ eh->exceptionDestructor (_M_exception_object);
+
+ __cxa_free_exception (_M_exception_object);
+ _M_exception_object = 0;
+ }
+ }
+}
+
+
+void*
+std::__exception_ptr::exception_ptr::_M_get() const throw()
+{
+ return _M_exception_object;
+}
+
+
+void
+std::__exception_ptr::exception_ptr::_M_safe_bool_dummy()
+{
+}
+
+
+void
+std::__exception_ptr::exception_ptr::swap(exception_ptr &other) throw()
+{
+ void *tmp = _M_exception_object;
+ _M_exception_object = other._M_exception_object;
+ other._M_exception_object = tmp;
+}
+
+
+bool
+std::__exception_ptr::exception_ptr::operator!() const throw()
+{
+ return _M_exception_object == 0;
+}
+
+
+std::__exception_ptr::exception_ptr::operator __safe_bool() const throw()
+{
+ return _M_exception_object ? &exception_ptr::_M_safe_bool_dummy : 0;
+}
+
+
+const std::type_info*
+std::__exception_ptr::exception_ptr::__cxa_exception_type() const throw()
+{
+ __cxa_exception *eh = __get_exception_header_from_obj (_M_exception_object);
+ return eh->exceptionType;
+}
+
+
+bool std::__exception_ptr::operator==(const exception_ptr& lhs,
+ const exception_ptr& rhs) throw()
+{
+ return lhs._M_exception_object == rhs._M_exception_object;
+}
+
+
+bool std::__exception_ptr::operator!=(const exception_ptr& lhs,
+ const exception_ptr& rhs) throw()
+{
+ return !(lhs == rhs);
+}
+
+
+std::exception_ptr
+std::current_exception() throw()
+{
+ __cxa_eh_globals *globals = __cxa_get_globals ();
+ __cxa_exception *header = globals->caughtExceptions;
+
+ if (!header)
+ return std::exception_ptr();
+
+ // Since foreign exceptions can't be counted, we can't return them.
+ if (!__is_gxx_exception_class (header->unwindHeader.exception_class))
+ return std::exception_ptr();
+
+ return std::exception_ptr(
+ __get_object_from_ambiguous_exception (header));
+}
+
+
+static void
+__gxx_dependent_exception_cleanup (_Unwind_Reason_Code code,
+ _Unwind_Exception *exc)
+{
+ // This cleanup is set only for dependents.
+ __cxa_dependent_exception *dep = __get_dependent_exception_from_ue (exc);
+ __cxa_exception *header =
+ __get_exception_header_from_obj (dep->primaryException);
+
+ // We only want to be called through _Unwind_DeleteException.
+ // _Unwind_DeleteException in the HP-UX IA64 libunwind library
+ // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
+ // like the GCC _Unwind_DeleteException function does.
+ if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
+ __terminate (header->terminateHandler);
+
+ if (__gnu_cxx::__exchange_and_add_dispatch (&header->referenceCount, -1) == 0)
+ {
+ if (header->exceptionDestructor)
+ header->exceptionDestructor (header + 1);
+
+ __cxa_free_exception (header + 1);
+ }
+}
+
+
+void
+std::rethrow_exception(std::exception_ptr ep)
+{
+ void *obj = ep._M_get();
+ __cxa_exception *eh = __get_exception_header_from_obj (obj);
+
+ __cxa_dependent_exception *dep = __cxa_allocate_dependent_exception ();
+ dep->primaryException = obj;
+ __gnu_cxx::__atomic_add_dispatch (&eh->referenceCount, 1);
+
+ dep->unexpectedHandler = __unexpected_handler;
+ dep->terminateHandler = __terminate_handler;
+ __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(dep->unwindHeader.exception_class);
+ dep->unwindHeader.exception_cleanup = __gxx_dependent_exception_cleanup;
+
+#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
+ _Unwind_SjLj_RaiseException (&dep->unwindHeader);
+#else
+ _Unwind_RaiseException (&dep->unwindHeader);
+#endif
+
+ // Some sort of unwinding error. Note that terminate is a handler.
+ __cxa_begin_catch (&dep->unwindHeader);
+ std::terminate ();
+}
diff --git a/libstdc++-v3/libsupc++/eh_throw.cc b/libstdc++-v3/libsupc++/eh_throw.cc
index b405f8f7c64..198ff181035 100644
--- a/libstdc++-v3/libsupc++/eh_throw.cc
+++ b/libstdc++-v3/libsupc++/eh_throw.cc
@@ -1,5 +1,5 @@
// -*- C++ -*- Exception handling routines for throwing.
-// Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2003, 2008 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
@@ -36,20 +36,23 @@ using namespace __cxxabiv1;
static void
__gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
{
+ // This cleanup is set only for primaries.
__cxa_exception *header = __get_exception_header_from_ue (exc);
- // If we haven't been caught by a foreign handler, then this is
- // some sort of unwind error. In that case just die immediately.
+ // We only want to be called through _Unwind_DeleteException.
// _Unwind_DeleteException in the HP-UX IA64 libunwind library
- // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
+ // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
// like the GCC _Unwind_DeleteException function does.
if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
__terminate (header->terminateHandler);
- if (header->exceptionDestructor)
- header->exceptionDestructor (header + 1);
+ if (__gnu_cxx::__exchange_and_add_dispatch (&header->referenceCount, -1) == 0)
+ {
+ if (header->exceptionDestructor)
+ header->exceptionDestructor (header + 1);
- __cxa_free_exception (header + 1);
+ __cxa_free_exception (header + 1);
+ }
}
@@ -57,12 +60,14 @@ extern "C" void
__cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo,
void (*dest) (void *))
{
+ // Definitely a primary.
__cxa_exception *header = __get_exception_header_from_obj (obj);
+ header->referenceCount = 0;
header->exceptionType = tinfo;
header->exceptionDestructor = dest;
header->unexpectedHandler = __unexpected_handler;
header->terminateHandler = __terminate_handler;
- __GXX_INIT_EXCEPTION_CLASS(header->unwindHeader.exception_class);
+ __GXX_INIT_PRIMARY_EXCEPTION_CLASS(header->unwindHeader.exception_class);
header->unwindHeader.exception_cleanup = __gxx_exception_cleanup;
#ifdef _GLIBCXX_SJLJ_EXCEPTIONS
diff --git a/libstdc++-v3/libsupc++/eh_type.cc b/libstdc++-v3/libsupc++/eh_type.cc
index 99627efdd97..03432976714 100644
--- a/libstdc++-v3/libsupc++/eh_type.cc
+++ b/libstdc++-v3/libsupc++/eh_type.cc
@@ -1,5 +1,5 @@
// -*- C++ -*- Exception handling routines for catching.
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2008 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
@@ -43,7 +43,15 @@ std::type_info *__cxa_current_exception_type ()
__cxa_eh_globals *globals = __cxa_get_globals ();
__cxa_exception *header = globals->caughtExceptions;
if (header)
- return header->exceptionType;
+ {
+ if (__is_dependent_exception (header->unwindHeader.exception_class))
+ {
+ __cxa_dependent_exception *de =
+ __get_dependent_exception_from_ue (&header->unwindHeader);
+ header = __get_exception_header_from_obj (de->primaryException);
+ }
+ return header->exceptionType;
+ }
else
return 0;
}
diff --git a/libstdc++-v3/libsupc++/exception b/libstdc++-v3/libsupc++/exception
index a7e2db78dd1..f1288211e98 100644
--- a/libstdc++-v3/libsupc++/exception
+++ b/libstdc++-v3/libsupc++/exception
@@ -1,7 +1,7 @@
// Exception Handling support header for -*- C++ -*-
// Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-// 2004, 2005, 2006, 2007
+// 2004, 2005, 2006, 2007, 2008
// Free Software Foundation
//
// This file is part of GCC.
@@ -110,6 +110,7 @@ namespace std
* result in a call of @c terminate() (15.5.1)."
*/
bool uncaught_exception() throw();
+
} // namespace std
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
@@ -132,4 +133,8 @@ _GLIBCXX_END_NAMESPACE
#pragma GCC visibility pop
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <exception_ptr.h>
+#endif
+
#endif
diff --git a/libstdc++-v3/libsupc++/exception_ptr.h b/libstdc++-v3/libsupc++/exception_ptr.h
new file mode 100644
index 00000000000..77b0431c42f
--- /dev/null
+++ b/libstdc++-v3/libsupc++/exception_ptr.h
@@ -0,0 +1,169 @@
+// Exception Handling support header (exception_ptr class) for -*- C++ -*-
+
+// Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+// 2004, 2005, 2006, 2007, 2008
+// Free Software Foundation
+//
+// 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 2, 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 COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+/** @file exception_ptr.h
+ * This is an internal header file, included by other headers and the
+ * implementation. You should not attempt to use it directly.
+ */
+
+#ifndef __EXCEPTION_PTR_H__
+#define __EXCEPTION_PTR_H__
+
+#pragma GCC visibility push(default)
+
+#include <bits/c++config.h>
+
+extern "C++" {
+
+namespace std
+{
+ // Hide the free operators from other types
+ namespace __exception_ptr
+ {
+ /**
+ * @brief An opaque pointer to an arbitrary exception.
+ */
+ class exception_ptr;
+ }
+
+ using __exception_ptr::exception_ptr;
+
+ /** Obtain an %exception_ptr to the currently handled exception. If there
+ * is none, or the currently handled exception is foreign, return the null
+ * value.
+ */
+ exception_ptr current_exception() throw();
+
+ /// Throw the object pointed to by the %exception_ptr.
+ void rethrow_exception(exception_ptr) __attribute__ ((__noreturn__));
+
+ /// Obtain an %exception_ptr pointing to a copy of the supplied object.
+ template <class _Ex>
+ exception_ptr copy_exception(_Ex __ex) throw();
+
+
+ namespace __exception_ptr
+ {
+ bool operator==(const exception_ptr&,
+ const exception_ptr&) throw();
+ bool operator!=(const exception_ptr&,
+ const exception_ptr&) throw();
+
+ class exception_ptr
+ {
+ void* _M_exception_object;
+
+ explicit exception_ptr(void* __e) throw();
+
+ void _M_addref() throw();
+ void _M_release() throw();
+
+ void *_M_get() const throw();
+
+ void _M_safe_bool_dummy();
+
+ friend exception_ptr std::current_exception() throw();
+ friend void std::rethrow_exception(exception_ptr);
+
+ public:
+ exception_ptr() throw();
+
+ typedef void (exception_ptr::*__safe_bool)();
+
+ // For construction from nullptr or 0.
+ exception_ptr(__safe_bool) throw();
+
+ exception_ptr(const exception_ptr&) throw();
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ exception_ptr(exception_ptr&& __o) throw()
+ : _M_exception_object(__o._M_exception_object)
+ {
+ __o._M_exception_object = 0;
+ }
+#endif
+
+ exception_ptr& operator=(const exception_ptr&) throw();
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ exception_ptr& operator=(exception_ptr&& __o) throw()
+ {
+ exception_ptr(__o).swap(*this);
+ return *this;
+ }
+#endif
+
+ ~exception_ptr() throw();
+
+ void swap(exception_ptr&) throw();
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ void swap(exception_ptr &&__o) throw()
+ {
+ void *__tmp = _M_exception_object;
+ _M_exception_object = __o._M_exception_object;
+ __o._M_exception_object = __tmp;
+ }
+#endif
+
+ bool operator!() const throw();
+ operator __safe_bool() const throw();
+
+ friend bool operator==(const exception_ptr&,
+ const exception_ptr&) throw();
+
+ const type_info *__cxa_exception_type() const throw();
+ };
+
+ } // namespace __exception_ptr
+
+
+ template <class _Ex>
+ exception_ptr copy_exception(_Ex __ex) throw()
+ {
+ try
+ {
+ throw __ex;
+ }
+ catch(...)
+ {
+ return current_exception ();
+ }
+ }
+
+} // namespace std
+
+} // extern "C++"
+
+#pragma GCC visibility pop
+
+#endif
diff --git a/libstdc++-v3/libsupc++/unwind-cxx.h b/libstdc++-v3/libsupc++/unwind-cxx.h
index 75874fc5da4..9697498026d 100644
--- a/libstdc++-v3/libsupc++/unwind-cxx.h
+++ b/libstdc++-v3/libsupc++/unwind-cxx.h
@@ -1,5 +1,5 @@
// -*- C++ -*- Exception handling and frame unwind runtime interface routines.
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2008 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
@@ -39,18 +39,22 @@
#include <exception>
#include <cstddef>
#include "unwind.h"
+#include <ext/atomicity.h>
#pragma GCC visibility push(default)
namespace __cxxabiv1
{
-// A C++ exception object consists of a header, which is a wrapper around
-// an unwind object header with additional C++ specific information,
+// A primary C++ exception object consists of a header, which is a wrapper
+// around an unwind object header with additional C++ specific information,
// followed by the exception object itself.
struct __cxa_exception
-{
+{
+ // Manage this header.
+ _Atomic_word referenceCount;
+
// Manage the exception object itself.
std::type_info *exceptionType;
void (*exceptionDestructor)(void *);
@@ -87,6 +91,47 @@ struct __cxa_exception
_Unwind_Exception unwindHeader;
};
+// A dependent C++ exception object consists of a wrapper around an unwind
+// object header with additional C++ specific information, containing a pointer
+// to a primary exception object.
+
+struct __cxa_dependent_exception
+{
+ // The primary exception this thing depends on.
+ void *primaryException;
+
+ // The C++ standard has entertaining rules wrt calling set_terminate
+ // and set_unexpected in the middle of the exception cleanup process.
+ std::unexpected_handler unexpectedHandler;
+ std::terminate_handler terminateHandler;
+
+ // The caught exception stack threads through here.
+ __cxa_exception *nextException;
+
+ // How many nested handlers have caught this exception. A negated
+ // value is a signal that this object has been rethrown.
+ int handlerCount;
+
+#ifdef __ARM_EABI_UNWINDER__
+ // Stack of exceptions in cleanups.
+ __cxa_exception* nextPropagatingException;
+
+ // The nuber of active cleanup handlers for this exception.
+ int propagationCount;
+#else
+ // Cache parsed handler data from the personality routine Phase 1
+ // for Phase 2 and __cxa_call_unexpected.
+ int handlerSwitchValue;
+ const unsigned char *actionRecord;
+ const unsigned char *languageSpecificData;
+ _Unwind_Ptr catchTemp;
+ void *adjustedPtr;
+#endif
+
+ // The generic exception header. Must be last.
+ _Unwind_Exception unwindHeader;
+};
+
// Each thread in a C++ program has access to a __cxa_eh_globals object.
struct __cxa_eh_globals
{
@@ -105,12 +150,20 @@ struct __cxa_eh_globals
extern "C" __cxa_eh_globals *__cxa_get_globals () throw();
extern "C" __cxa_eh_globals *__cxa_get_globals_fast () throw();
-// Allocate memory for the exception plus the thown object.
+// Allocate memory for the primary exception plus the thrown object.
extern "C" void *__cxa_allocate_exception(std::size_t thrown_size) throw();
-// Free the space allocated for the exception.
+// Free the space allocated for the primary exception.
extern "C" void __cxa_free_exception(void *thrown_exception) throw();
+// Allocate memory for a dependent exception.
+extern "C" __cxa_dependent_exception*
+__cxa_allocate_dependent_exception() throw();
+
+// Free the space allocated for the dependent exception.
+extern "C" void
+__cxa_free_dependent_exception(__cxa_dependent_exception *ex) throw();
+
// Throw the exception.
extern "C" void __cxa_throw (void *thrown_exception,
std::type_info *tinfo,
@@ -173,6 +226,12 @@ __get_exception_header_from_ue (_Unwind_Exception *exc)
return reinterpret_cast<__cxa_exception *>(exc + 1) - 1;
}
+static inline __cxa_dependent_exception *
+__get_dependent_exception_from_ue (_Unwind_Exception *exc)
+{
+ return reinterpret_cast<__cxa_dependent_exception *>(exc + 1) - 1;
+}
+
#ifdef __ARM_EABI_UNWINDER__
static inline bool
__is_gxx_exception_class(_Unwind_Exception_Class c)
@@ -185,11 +244,19 @@ __is_gxx_exception_class(_Unwind_Exception_Class c)
&& c[4] == 'C'
&& c[5] == '+'
&& c[6] == '+'
- && c[7] == '\0';
+ && (c[7] == '\0' || c[7] == '\x01');
+}
+
+// Only checks for primary or dependent, but not that it is a C++ exception at
+// all.
+static inline bool
+__is_dependent_exception(_Unwind_Exception_Class c)
+{
+ return c[7] == '\x01';
}
static inline void
-__GXX_INIT_EXCEPTION_CLASS(_Unwind_Exception_Class c)
+__GXX_INIT_PRIMARY_EXCEPTION_CLASS(_Unwind_Exception_Class c)
{
c[0] = 'G';
c[1] = 'N';
@@ -201,6 +268,19 @@ __GXX_INIT_EXCEPTION_CLASS(_Unwind_Exception_Class c)
c[7] = '\0';
}
+static inline void
+__GXX_INIT_DEPENDENT_EXCEPTION_CLASS(_Unwind_Exception_Class c)
+{
+ c[0] = 'G';
+ c[1] = 'N';
+ c[2] = 'U';
+ c[3] = 'C';
+ c[4] = 'C';
+ c[5] = '+';
+ c[6] = '+';
+ c[7] = '\x01';
+}
+
static inline bool
__is_gxx_forced_unwind_class(_Unwind_Exception_Class c)
{
@@ -233,8 +313,8 @@ __gxx_caught_object(_Unwind_Exception* eo)
return (void*)eo->barrier_cache.bitpattern[0];
}
#else // !__ARM_EABI_UNWINDER__
-// This is the exception class we report -- "GNUCC++\0".
-const _Unwind_Exception_Class __gxx_exception_class
+// This is the primary exception class we report -- "GNUCC++\0".
+const _Unwind_Exception_Class __gxx_primary_exception_class
= ((((((((_Unwind_Exception_Class) 'G'
<< 8 | (_Unwind_Exception_Class) 'N')
<< 8 | (_Unwind_Exception_Class) 'U')
@@ -244,13 +324,36 @@ const _Unwind_Exception_Class __gxx_exception_class
<< 8 | (_Unwind_Exception_Class) '+')
<< 8 | (_Unwind_Exception_Class) '\0');
+// This is the dependent (from std::rethrow_exception) exception class we report
+// "GNUCC++\x01"
+const _Unwind_Exception_Class __gxx_dependent_exception_class
+= ((((((((_Unwind_Exception_Class) 'G'
+ << 8 | (_Unwind_Exception_Class) 'N')
+ << 8 | (_Unwind_Exception_Class) 'U')
+ << 8 | (_Unwind_Exception_Class) 'C')
+ << 8 | (_Unwind_Exception_Class) 'C')
+ << 8 | (_Unwind_Exception_Class) '+')
+ << 8 | (_Unwind_Exception_Class) '+')
+ << 8 | (_Unwind_Exception_Class) '\x01');
+
static inline bool
__is_gxx_exception_class(_Unwind_Exception_Class c)
{
- return c == __gxx_exception_class;
+ return c == __gxx_primary_exception_class
+ || c == __gxx_dependent_exception_class;
}
-#define __GXX_INIT_EXCEPTION_CLASS(c) c = __gxx_exception_class
+// Only checks for primary or dependent, but not that it is a C++ exception at
+// all.
+static inline bool
+__is_dependent_exception(_Unwind_Exception_Class c)
+{
+ return (c & 1);
+}
+
+#define __GXX_INIT_PRIMARY_EXCEPTION_CLASS(c) c = __gxx_primary_exception_class
+#define __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(c) \
+ c = __gxx_dependent_exception_class
// GNU C++ personality routine, Version 0.
extern "C" _Unwind_Reason_Code __gxx_personality_v0
@@ -265,11 +368,27 @@ extern "C" _Unwind_Reason_Code __gxx_personality_sj0
static inline void*
__gxx_caught_object(_Unwind_Exception* eo)
{
+ // Bad as it looks, this actually works for dependent exceptions too.
__cxa_exception* header = __get_exception_header_from_ue (eo);
return header->adjustedPtr;
}
#endif // !__ARM_EABI_UNWINDER__
+static inline void*
+__get_object_from_ue(_Unwind_Exception* eo) throw()
+{
+ return __is_dependent_exception (eo->exception_class) ?
+ __get_dependent_exception_from_ue (eo)->primaryException :
+ eo + 1;
+}
+
+static inline void *
+__get_object_from_ambiguous_exception(__cxa_exception *p_or_d) throw()
+{
+ return __get_object_from_ue (&p_or_d->unwindHeader);
+}
+
+
} /* namespace __cxxabiv1 */
#pragma GCC visibility pop
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc
new file mode 100644
index 00000000000..d4a63e4b001
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc
@@ -0,0 +1,90 @@
+// { dg-options "-std=gnu++0x" }
+// 2008-05-25 Sebastian Redl <sebastian.redl@getdesigned.at>
+
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// current_exception() under various conditions.
+
+#include <exception>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ exception_ptr ep = current_exception();
+ VERIFY( !ep );
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ try {
+ throw 0;
+ } catch(...) {
+ exception_ptr ep = current_exception();
+ VERIFY( ep );
+ }
+}
+
+void test03()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ try {
+ throw exception();
+ } catch(std::exception&) {
+ exception_ptr ep = current_exception();
+ VERIFY( ep );
+ }
+}
+
+void test04()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ try {
+ throw 0;
+ } catch(...) {
+ exception_ptr ep1 = current_exception();
+ try {
+ throw 0;
+ } catch(...) {
+ exception_ptr ep2 = current_exception();
+ VERIFY( ep1 != ep2 );
+ }
+ exception_ptr ep3 = current_exception();
+ // Not guaranteed by standard, but by this implementation.
+ VERIFY( ep1 == ep3 );
+ }
+}
+
+int main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc
new file mode 100644
index 00000000000..1107a2ece60
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc
@@ -0,0 +1,188 @@
+// { dg-options "-std=gnu++0x" }
+// 2008-05-25 Sebastian Redl <sebastian.redl@getdesigned.at>
+
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// Tests the life span of the exception object.
+
+#include <exception>
+#include <testsuite_hooks.h>
+
+bool may_destruct = false;
+
+class destructing
+{
+ mutable bool copied;
+
+public:
+ destructing() : copied(false) { }
+ destructing(const destructing &o) : copied(false) { o.copied = true; }
+ ~destructing() { VERIFY( copied || may_destruct ); }
+};
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ may_destruct = false;
+
+ // Test the destructing class.
+ {
+ destructing *d = new destructing;
+ destructing d2(*d);
+ delete d;
+ may_destruct = true;
+ }
+ may_destruct = false;
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ may_destruct = false;
+
+ try {
+ throw destructing();
+ } catch(...) {
+ may_destruct = true;
+ }
+ may_destruct = false;
+}
+
+void test03()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ may_destruct = false;
+
+ try {
+ throw destructing();
+ } catch(...) {
+ {
+ exception_ptr ep = current_exception();
+ }
+ may_destruct = true;
+ }
+ may_destruct = false;
+}
+
+void test04()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ may_destruct = false;
+
+ {
+ exception_ptr ep;
+ try {
+ throw destructing();
+ } catch(...) {
+ ep = current_exception();
+ }
+ may_destruct = true;
+ }
+ may_destruct = false;
+}
+
+void test05_helper()
+{
+ using namespace std;
+ try {
+ throw destructing();
+ } catch(...) {
+ exception_ptr ep = current_exception();
+ rethrow_exception(ep);
+ }
+}
+
+void test05()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ may_destruct = false;
+
+ try {
+ test05_helper();
+ } catch(...) {
+ may_destruct = true;
+ }
+ may_destruct = false;
+}
+
+void test06_helper()
+{
+ using namespace std;
+ try {
+ throw destructing();
+ } catch(...) {
+ exception_ptr ep = current_exception();
+ throw;
+ }
+}
+
+void test06()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ may_destruct = false;
+
+ try {
+ test06_helper();
+ } catch(...) {
+ may_destruct = true;
+ }
+ may_destruct = false;
+}
+
+std::exception_ptr gep;
+
+void test99()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ may_destruct = false;
+
+ try {
+ throw destructing();
+ } catch(...) {
+ gep = current_exception();
+ }
+}
+
+int main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ test05();
+ test06();
+
+ test99();
+ may_destruct = true;
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/rethrow_exception.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/rethrow_exception.cc
new file mode 100644
index 00000000000..96d38d5eba3
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/rethrow_exception.cc
@@ -0,0 +1,113 @@
+// { dg-options "-std=gnu++0x" }
+// 2008-05-25 Sebastian Redl <sebastian.redl@getdesigned.at>
+
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// rethrow_exception() and preservation of data
+
+#include <exception>
+#include <typeinfo>
+#include <cstring>
+#include <stdexcept>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ try {
+ rethrow_exception(copy_exception(0));
+ } catch(...) {
+ }
+}
+
+void test02()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ try {
+ rethrow_exception(copy_exception(runtime_error("test")));
+ } catch(exception &e) {
+ VERIFY( typeid(e) == typeid(runtime_error) );
+ VERIFY( strcmp(e.what(), "test") == 0 );
+ }
+}
+
+void test03()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ exception_ptr ep;
+ try {
+ throw 0;
+ } catch(...) {
+ ep = current_exception();
+ }
+ try {
+ rethrow_exception(ep);
+ } catch(...) {
+ }
+}
+
+void test04()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ // Weave the exceptions in an attempt to confuse the machinery.
+ try {
+ throw 0;
+ } catch(...) {
+ exception_ptr ep1 = current_exception();
+ try {
+ throw 1;
+ } catch(...) {
+ exception_ptr ep2 = current_exception();
+ try {
+ rethrow_exception(ep1);
+ } catch(...) {
+ try {
+ rethrow_exception(ep2);
+ } catch(...) {
+ try {
+ rethrow_exception(ep1);
+ } catch(...) {
+ }
+ try {
+ rethrow_exception(ep2);
+ } catch(...) {
+ }
+ }
+ }
+ }
+ }
+}
+
+int main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+
+ return 0;
+}