diff options
author | hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-08-14 17:24:50 +0000 |
---|---|---|
committer | hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-08-14 17:24:50 +0000 |
commit | 88a09daa59a002a27998d5a1043e064fdd58c436 (patch) | |
tree | 14225345b79f5b12c30d08a5b44f233420107b8f | |
parent | d5b4e28e9c8ec97cb8f9c2ba0c6d16971ddeb261 (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
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; +} |