diff options
258 files changed, 8721 insertions, 1880 deletions
diff --git a/ChangeLog b/ChangeLog index 6da8b90ca30..eb44ef69457 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2012-10-04 Lawrence Crowl <crowl@google.com> + + * MAINTAINERS (Write After Approval): Add myself. + 2012-10-01 Cary Coutant <ccoutant@google.com> * MAINTAINERS: Add myself as dwarf debugging code maintainer. diff --git a/ChangeLog.MELT b/ChangeLog.MELT index e035c8546e8..262f76e6942 100644 --- a/ChangeLog.MELT +++ b/ChangeLog.MELT @@ -1,4 +1,8 @@ +2012-10-08 Basile Starynkevitch <basile@starynkevitch.net> + + MELT branch merged with trunk rev 192205 using svnmerge.py + 2012-10-04 Basile Starynkevitch <basile@starynkevitch.net> MELT branch merged with trunk rev 192095 using svnmerge.py diff --git a/MAINTAINERS b/MAINTAINERS index 3b9b959022f..8d816b1b5f0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -343,6 +343,7 @@ R. Kelley Cook kcook@gcc.gnu.org Christian Cornelssen ccorn@cs.tu-berlin.de François-Xavier Coudert fxcoudert@gcc.gnu.org Cary Coutant ccoutant@google.com +Lawrence Crowl crowl@google.com Ian Dall ian@beware.dropbear.id.au David Daney david.daney@caviumnetworks.com Bud Davis jmdavis@link.com diff --git a/contrib/ChangeLog b/contrib/ChangeLog index 6e4cab402e1..d5ec0bab401 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,7 @@ +2012-10-06 Diego Novillo <dnovillo@google.com> + + * testsuite-management/x86_64-unknown-linux-gnu.xfail: Update. + 2012-10-02 Christophe Lyon <christophe.lyon@linaro.org> * check_GNU_style.sh: Remove temporay file upon exit. diff --git a/contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail b/contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail index b4e59872235..59b3f912b19 100644 --- a/contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail +++ b/contrib/testsuite-management/x86_64-unknown-linux-gnu.xfail @@ -1,6 +1,7 @@ XPASS: gcc.dg/Wstrict-overflow-18.c (test for bogus messages, line 20) UNRESOLVED: gcc.dg/attr-weakref-1.c compilation failed to produce executable FAIL: gcc.dg/attr-weakref-1.c (test for excess errors) +FAIL: gcc.dg/builtin-object-size-8.c execution test XPASS: gcc.dg/guality/example.c -O2 -flto -fno-use-linker-plugin -flto-partition=none execution test XPASS: gcc.dg/guality/example.c -O2 execution test XPASS: gcc.dg/guality/example.c -O0 execution test @@ -16,59 +17,38 @@ XPASS: gcc.dg/guality/inline-params.c -O2 execution test XPASS: gcc.dg/guality/inline-params.c -O3 -g execution test XPASS: gcc.dg/guality/inline-params.c -O2 -flto -fno-use-linker-plugin -flto-partition=none execution test XPASS: gcc.dg/guality/inline-params.c -O3 -fomit-frame-pointer execution test -XPASS: gcc.dg/guality/inline-params.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects execution test XPASS: gcc.dg/guality/inline-params.c -Os execution test XPASS: gcc.dg/guality/pr41447-1.c -O2 execution test -XPASS: gcc.dg/guality/pr41447-1.c -O2 -flto -fno-use-linker-plugin -flto-partition=none execution test -XPASS: gcc.dg/guality/pr41447-1.c -O0 execution test XPASS: gcc.dg/guality/pr41447-1.c -O1 execution test XPASS: gcc.dg/guality/pr41447-1.c -O3 -fomit-frame-pointer execution test XPASS: gcc.dg/guality/pr41447-1.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects execution test +XPASS: gcc.dg/guality/pr41447-1.c -O0 execution test XPASS: gcc.dg/guality/pr41447-1.c -O3 -g execution test XPASS: gcc.dg/guality/pr41447-1.c -Os execution test -XPASS: gcc.dg/guality/pr41616-1.c -O1 execution test XPASS: gcc.dg/guality/pr41616-1.c -O3 -fomit-frame-pointer execution test +XPASS: gcc.dg/guality/pr41616-1.c -O1 execution test XPASS: gcc.dg/guality/pr41616-1.c -O2 execution test -XPASS: gcc.dg/guality/pr41616-1.c -O2 -flto -fno-use-linker-plugin -flto-partition=none execution test XPASS: gcc.dg/guality/pr41616-1.c -O0 execution test XPASS: gcc.dg/guality/pr41616-1.c -Os execution test +XPASS: gcc.dg/guality/pr41616-1.c -O2 -flto -fno-use-linker-plugin -flto-partition=none execution test XPASS: gcc.dg/guality/pr41616-1.c -O3 -g execution test XPASS: gcc.dg/inline_3.c (test for excess errors) XPASS: gcc.dg/inline_4.c (test for excess errors) -FAIL: gcc.dg/pr52558-2.c scan-tree-dump-times lim1 "MEM.*g_2_lsm_flag" 1 -FAIL: gcc.dg/tm/reg-promotion.c scan-tree-dump-times lim1 "MEM count_lsm.. count_lsm_flag" 1 FAIL: gcc.dg/torture/pr51106-2.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (test for excess errors) FAIL: gcc.dg/torture/pr51106-2.c -O3 -g (test for excess errors) -FAIL: gcc.dg/torture/pr51106-2.c -O0 (internal compiler error) -FAIL: gcc.dg/torture/pr51106-2.c -O2 (internal compiler error) -FAIL: gcc.dg/torture/pr51106-2.c -O1 (internal compiler error) FAIL: gcc.dg/torture/pr51106-2.c -O0 (test for excess errors) -FAIL: gcc.dg/torture/pr51106-2.c -O2 (test for excess errors) -FAIL: gcc.dg/torture/pr51106-2.c -O3 -g (internal compiler error) FAIL: gcc.dg/torture/pr51106-2.c -O1 (test for excess errors) -FAIL: gcc.dg/torture/pr51106-2.c -Os (internal compiler error) -FAIL: gcc.dg/torture/pr51106-2.c -O3 -fomit-frame-pointer (internal compiler error) -FAIL: gcc.dg/torture/pr51106-2.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (internal compiler error) FAIL: gcc.dg/torture/pr51106-2.c -Os (test for excess errors) FAIL: gcc.dg/torture/pr51106-2.c -O3 -fomit-frame-pointer (test for excess errors) +FAIL: gcc.dg/torture/pr51106-2.c -O2 (test for excess errors) XPASS: gcc.dg/unroll_2.c (test for excess errors) XPASS: gcc.dg/unroll_3.c (test for excess errors) XPASS: gcc.dg/unroll_4.c (test for excess errors) -FAIL: gcc.target/i386/pad-10.c scan-assembler-not nop -FAIL: gfortran.dg/lto/pr45586 f_lto_pr45586_0.o-f_lto_pr45586_0.o link, -O0 -flto -flto-partition=1to1 -fno-use-linker-plugin (internal compiler error) -UNRESOLVED: gfortran.dg/lto/pr45586 f_lto_pr45586_0.o-f_lto_pr45586_0.o execute -O0 -flto -fuse-linker-plugin -fno-fat-lto-objects -FAIL: gfortran.dg/lto/pr45586 f_lto_pr45586_0.o-f_lto_pr45586_0.o link, -O0 -flto -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) -UNRESOLVED: gfortran.dg/lto/pr45586 f_lto_pr45586_0.o-f_lto_pr45586_0.o execute -O0 -flto -flto-partition=1to1 -fno-use-linker-plugin -FAIL: gfortran.dg/lto/pr45586 f_lto_pr45586_0.o-f_lto_pr45586_0.o link, -O0 -flto -flto-partition=none -fuse-linker-plugin (internal compiler error) -UNRESOLVED: gfortran.dg/lto/pr45586 f_lto_pr45586_0.o-f_lto_pr45586_0.o execute -O0 -flto -flto-partition=none -fuse-linker-plugin -UNRESOLVED: gfortran.dg/lto/pr45586-2 f_lto_pr45586-2_0.o-f_lto_pr45586-2_0.o execute -O0 -flto -flto-partition=none -fuse-linker-plugin -UNRESOLVED: gfortran.dg/lto/pr45586-2 f_lto_pr45586-2_0.o-f_lto_pr45586-2_0.o execute -O0 -flto -flto-partition=1to1 -fno-use-linker-plugin -FAIL: gfortran.dg/lto/pr45586-2 f_lto_pr45586-2_0.o-f_lto_pr45586-2_0.o link, -O0 -flto -flto-partition=1to1 -fno-use-linker-plugin (internal compiler error) -UNRESOLVED: gfortran.dg/lto/pr45586-2 f_lto_pr45586-2_0.o-f_lto_pr45586-2_0.o execute -O0 -flto -fuse-linker-plugin -fno-fat-lto-objects -FAIL: gfortran.dg/lto/pr45586-2 f_lto_pr45586-2_0.o-f_lto_pr45586-2_0.o link, -O0 -flto -flto-partition=none -fuse-linker-plugin (internal compiler error) -FAIL: gfortran.dg/lto/pr45586-2 f_lto_pr45586-2_0.o-f_lto_pr45586-2_0.o link, -O0 -flto -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) FAIL: gnat.dg/array11.adb (test for warnings, line 12) FAIL: gnat.dg/object_overflow.adb (test for warnings, line 8) FAIL: libmudflap.c++/pass55-frag.cxx (-O2) execution test FAIL: libmudflap.c++/pass55-frag.cxx ( -O) execution test FAIL: libmudflap.c++/pass55-frag.cxx (-O3) execution test +FAIL: sourcelocation output - source compiled test +FAIL: sourcelocation -findirect-dispatch output - source compiled test +FAIL: sourcelocation -O3 output - source compiled test diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2a7913557ef..b9eb340befd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,327 @@ +2012-10-08 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/54825 + * tree-ssa-sccvn.c (vn_nary_length_from_stmt): Handle BIT_FIELD_REF. + (init_vn_nary_op_from_stmt): Likewise. + * tree-ssa-pre.c (compute_avail): Use vn_nary_op_lookup_stmt. + * tree-ssa-sccvn.h (sizeof_vn_nary_op): Avoid overflow. + +2012-10-08 Richard Guenther <rguenther@suse.de> + + * tree-ssa-pre.c (postorder_num): New global. + (compute_antic): Initialize all blocks and adjust for + generic postorder. + (my_rev_post_order_compute): Remove. + (init_pre): Use inverted_post_order_compute. + +2012-10-08 Bernd Schmidt <bernds@codesourcery.com> + + * sched-int.h (schedule_block): Adjust declaration. + * sched-rgn.c (bb_state_array, bb_state): New static variables. + (sched_rgn_init): Initialize them. + (sched_rgn_free): Free them. + (schedule_region): Save scheduling state for future blocks, and + pass such state to schedule_block. + * params.def (PARAM_SCHED_STATE_EDGE_PROB_CUTOFF): New. + * doc/invoke.texi (--param): Document it. + * haifa-sched.c (schedule_block): New arg init_state. Use it to + initialize state if nonnull. All callers changed. + Call advance_one_cycle after scheduling. + +2012-10-08 Georg-Johann Lay <avr@gjlay.de> + + PR target/54854 + * doc/invoke.texi (AVR Options): Remove -mshort-calls. + * config/avr/avr.opt (-mshort-calls): Remove option. + * config/avr/avr.h (AVR_HAVE_JMP_CALL): Don't depend on + TARGET_SHORT_CALLS. + +2012-10-08 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/54685 + * config/sh/sh.md (one_cmplsi2): Make insn_and_split. Add manual + combine matching for an insn sequence where a ge:SI pattern can be used. + +2012-10-08 Dodji Seketeli <dodji@redhat.com> + + PR c++/53528 C++11 attribute support + * plugin.h (register_scoped_attributes): Declare new function. + * tree.h (enu attribute_flags::ATTR_FLAG_CXX_11): New flag. + (lookup_scoped_attribute_spec, cxx_11_attribute_p) + (get_attribute_name, get_attribute_namespace): Declare new functions. + (struct attribute_spec): Remove const qualifier from the members. + * tree.c (comp_type_attributes, private_lookup_attribute) + (lookup_ident_attribute, remove_attribute, merge_attribute) + (attribute_hash_list, attribute_list_contained): Use + get_attribute_name. + * attribs.c (decl_attributes): Don't crash on error_mark_node. + Forbid c++11 attributes appertaining to type-specifiers. + (attribute_hash): Remove global variable. + (attributes_table): New global variable. + (find_attribute_namespace, register_scoped_attribute): New static + functions. + (register_scoped_attributes, lookup_scoped_attribute_spec) + (cxx11_attribute_p, get_attribute_name, get_attribute_namespace): + New public functions. + (init_attributes): Register all the GNU attributes into the "gnu" + namespace. + (register_attribute): Use register_scoped_attribute to register + the attribute into the "gnu" namespace. + (lookup_attribute_spec): Use lookup_scoped_attribute_spec to + lookup the attribute in the "gnu" namespace. + (decl_attributes): Use new get_attribute_namespace and + lookup_scoped_attribute_spec to consider attribute namespaces when + looking up attributes. When operating in c++-11 mode, pass flag + ATTR_FLAG_CXX11 to the spec handler. + +2012-10-08 Georg-Johann Lay <avr@gjlay.de> + + PR target/54815 + * config/avr/avr.md (*add<mode>3, add<mode>3, addpsi3): Make + constraint alternative "r,0,r" slighly more expensive. + (sub<mode>3, + (andqi3, andhi3, andpsi3, andsi3): Ditto. + (iorqi3, iorhi3, iorpsi3, iorsi3): Ditto. + (xorhi3, xorpsi3, xorsi3): Ditto. + +2012-10-08 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/54760 + * config/sh/sh.md (*mov<mode>_gbr_load, *mov<mode>_gbr_store): New + insns and accompanying unnamed splits. + * config/sh/predicates.md (general_movsrc_operand, + general_movdst_operand): Reject GBR addresses. + * config/sh/sh-protos.h (sh_find_equiv_gbr_addr): New declaration. + * config/sh/sh.c (sh_address_cost, sh_legitimate_address_p, + sh_secondary_reload): Handle GBR addresses. + (base_reg_disp): New class. + (sh_find_base_reg_disp, sh_find_equiv_gbr_addr): New functions. + +2012-10-08 Hans-Peter Nilsson <hp@bitrange.com> + + * config/mmix/mmix.c (mmix_output_octa): Don't assume + HOST_WIDEST_INT_PRINT_HEX starts with "0x". Instead use + HOST_WIDE_INT_PRINT_HEX_PURE, falling back to + HOST_WIDEST_INT_PRINT_UNSIGNED. + +2012-10-07 Richard Sandiford <rdsandiford@googlemail.com> + + * machmode.h (GET_MODE_UNIT_PRECISION): New macro. + * simplify-rtx.c (simplify_truncation): New function, + extracted from simplify_subreg and (in small part) from + simplify_unary_operation_1. + (simplify_unary_operation_1) <TRUNCATE>: Use it. Remove sign bit + test for !TRULY_NOOP_TRUNCATION_MODES_P. + (simplify_subreg): Use simplify_truncate for lowpart subregs + where both the inner and outer modes are scalar integers. + * config/mips/mips.c (mips_truncated_op_cost): New function. + (mips_rtx_costs): Adjust test for BADDU. + * config/mips/mips.md (*baddu_di<mode>): Push truncates to operands. + +2012-10-07 Jan Hubicka <jh@suse.cz> + + * ipa-inline-analysis.c (do_estimate_edge_time): Return actual + time spent by the inlined sequence. + (do_estimate_edge_growth): Rename to ... + (do_estimate_edge_time): ... this one; return size of inlined sequence. + * ipa-inline.h (do_estimate_edge_size): New. + (do_estimate_edge_growth): Remove. + (estimate_edge_size): New function. + (estimate_edge_growth): Use it. + +2012-10-07 Jan Hubicka <jh@suse.cz> + + * lto-cgraph.c (lto_symtab_encoder_new): New parameter FOR_INPUT. + (lto_symtab_encoder_delete): Update. + (lto_symtab_encoder_encode): Update. + (compute_ltrans_boundary): Update. + (input_symtab): Update. + * lto-streamer.h (lto_symtab_encoder_new): Update. + +2012-10-07 Richard Sandiford <rdsandiford@googlemail.com> + + * config/mips/mips-protos.h (mips_split_type): New enum. + (mips_split_64bit_move_p, mips_split_doubleword_move): Delete. + (mips_split_move_p, mips_split_move, mips_split_move_insn_p) + (mips_split_move_insn): Declare. + * config/mips/mips.c (mips_tuning_info): New variable. + (mips_load_store_insns): Use mips_split_move_insn_p instead of + mips_split_64bit_move_p. + (mips_emit_move_or_split, mips_mult_move_p): New functions. + (mips_split_64bit_move_p): Rename to... + (mips_split_move_p): ...this and take a mips_split_type argument. + Generalize to all moves. Call mips_mult_move_p. + (mips_split_doubleword_move): Rename to... + (mips_split_move): ...this and take a mips_split_type argument. + Assert that mips_split_move_p holds. + (mips_insn_split_type, mips_split_move_insn_p, mips_split_move_insn): + New functions. + (mips_output_move): Use mips_split_move_p instead of + mips_split_64bit_move_p. Handle MULT $0, $0 moves. + (mips_save_reg): Use mips_emit_move_or_split. + (mips_sim_reset): Assign to curr_state. Call targetm.sched.init + and advance_state. + (mips_sim_init): Call targetm.sched.init_dfa_pre_cycle_insn and + targetm.sched.init_dfa_post_cycle_insn, if defined. + (mips_sim_next_cycle): Assign to curr_state. Use advance_state + instead of state_transition. + (mips_sim_issue_insn): Assign to curr_state. Use + targetm.sched.variable_issue to see how many more insns can be issued. + (mips_seq_time, mips_mult_zero_zero_cost) + (mips_set_fast_mult_zero_zero_p, mips_set_tuning_info) + (mips_expand_to_rtl_hook): New functions. + (TARGET_EXPAND_TO_RTL_HOOK): Define. + * config/mips/mips.md (move_type): Add imul. + (type): Map imul move_types to imul. + (*movdi_32bit, *movti): Add imul alternatives. + Use mips_split_move_insn_p and mips_split_move_insn instead of + mips_split_64bit_move_p and mips_split_doubleword_move in move + splitters. + +2012-10-06 Segher Boessenkool <segher@kernel.crashing.org> + + * config/rs6000/rs6000.c (print_operand) ['A']: Delete. + +2012-10-06 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/52764 + * ginclude/stdint-wrap.h: In C++11 if __STDC_HOSTED__ define + __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS. + * ginclude/stdint-gcc.h: In C++11 unconditionally define + limit and constant macros. + +2012-10-06 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/54249 + * ginclude/stddef.h: In C++11 mode declare nullptr_t in the global + namespace. + +2012-10-06 Jan Hubicka <jh@suse.cz> + + PR lto/53831 + PR lto/54776 + * lto-streamer-out.c (produce_symtab): Cleanup; drop v1 API hack. + +2012-10-06 Dehao Chen <dehao@google.com> + + PR debug/54826 + * gimple-low.c (lower_stmt): Set the block for call args. + +2012-10-06 Jan Hubicka <jh@suse.cz> + + * doc/invoke.texi (-fprofile-report): Document. + * common.opt (-fprofile-report): New option. + * toplev.c (finalize): Call dump_profile_report. + * toplev.h (profile_report): Declare. + * passes.c (profile_record): New static var. + (check_profile_consistency): New function. + (dump_profile_record): New function. + (execute_one_ipa_transform_pass): Call check_profile_consistency. + (execute_one_pass): Likewise. + +2012-10-06 Jan Hubicka <jh@suse.cz> + + PR lto/54790 + * lto-streamer.h (lto_symtab_register_decl, lto_symtab_get_resolution, + lto_mark_nothrow_fndecl, lto_fixup_nothrow_decls): Remove. + * lto-symtab.c (lto_symtab_register_decl): Remove. + +2012-10-06 Andreas Schwab <schwab@linux-m68k.org> + + PR rtl-optimization/54739 + * config/m68k/m68k.md (anddi3, iordi3, xordi3, one_cmpldi2): Remove. + +2012-10-06 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/54760 + * config/sh/sh.md (define_constants): Add UNSPECV_GBR. + (get_thread_pointer, set_thread_pointer): New expanders. + (load_gbr): Rename to store_gbr. Remove GBR_REG use. + (store_gbr): New insn. + * config/sh/sh.c (prepare_move_operands): Use gen_store_gbr instead of + gen_load_gbr in TLS_MODEL_LOCAL_EXEC case. + (sh1_builtin_p): New function. + (signature_args): Add SH_BLTIN_VP. + (bdesc): Add __builtin_thread_pointer and __builtin_set_thread_pointer. + +2012-10-05 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> + + PR rtl-optimization/54739 + * config/pa/pa.md: Remove DImode and, not and, ior and xor patterns + for 32-bit targets. Adjust expanders. + + * config/pa/pa.md: Adjust unamed HImode add insn pattern. + +2012-10-05 Oleg Endo <olegendo@gcc.gnu.org> + + * config/sh/sh.c (builtin_description): Add is_enabled member. + (shmedia_builtin_p): New function. + (bdesc): Use shmedia_builtin_p for existing built-ins. + (sh_media_init_builtins, sh_init_builtins): Merge into single function + sh_init_builtins. Add is_enabled checking. Move variable declarations + to where they are actually used. + (sh_media_builtin_decl, sh_builtin_decl): Merge into single function + sh_builtin_decl. Add is_enabled checking. + (sh_expand_builtin): Move variable declarations to where they are + actually used. + +2012-10-05 Jakub Jelinek <jakub@redhat.com> + + * tree-inline.c (expand_call_inline): Move VAR_DECLs with + PARM_DECL origins from remapped DECL_INITIAL's BLOCK_VARS + into id->block's BLOCK_VARS. + + PR debug/54519 + * ipa-split.c (split_function): Add debug args and debug source + and normal stmts for args_to_skip which are gimple regs. + * tree-inline.c (copy_debug_stmt): When inlining, adjust source + debug bind stmts to debug binds of corresponding DEBUG_EXPR_DECL. + +2012-10-05 Georg-Johann Lay <avr@gjlay.de> + + * config/avr/avr.md: Fix indentations of insn C snippets. + +2012-10-05 Richard Guenther <rguenther@suse.de> + + PR middle-end/54811 + * tree-ssa-live.c (clear_unused_block_pointer_1): Look at + DECL_DEBUG_EXPR again. + +2012-10-05 Jan Hubicka <jh@suse.cz> + Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/33763 + * tree-inline.c (expand_call_inline): Silently ignore always_inline + attribute for redefined extern inline functions. + +2012-10-04 Jan Hubicka <jh@suse.cz> + + * tree-vectorizer.h (vect_estimate_min_profitable_iters): Remove. + * tree-vect-loop.c (vect_estimate_min_profitable_iters): Declare here. + (vect_analyze_loop_operations): Use loop count estimate to rule out + unprofitable vectorization. + (vect_estimate_min_profitable_iters): Return + ret_min_profitable_estimate. + +2012-10-05 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/54810 + * tree-vrp.c (register_edge_assert_for_2): Handle + NAME = (unsigned) NAME2; if (NAME cmp CST) for + narrowing casts to unsigned integral type like + NAME = NAME2 & CST2; if (NAME cmp CST) where CST2 + is the max value of the unsigned integral type. + +2012-10-04 Jeff Law <law@redhat.com> + + * PR target/50356 + * config/h8300/h8300.c (h8300_rtx_costs): Fix typo in CONST_INT case. + +2012-10-04 Jason Merrill <jason@redhat.com> + + * config/rs6000/rs6000.c (rs6000_code_end): Protect the use of + ASM_WEAKEN_DECL with #if RS6000_WEAK. + 2012-10-04 Basile Starynkevitch <basile@starynkevitch.net> * gengtype.c (walk_type): Emit mark_hook when inside a @@ -55,10 +379,10 @@ * config/i386/i386.c (ix86_dep_by_shift_count_body) : Add check on reload_completed since it can be invoked before register allocation phase in pre-reload schedule. - (ia32_multipass_dfa_lookahead) : Do not use dfa_lookahead for pre-reload - schedule to save compile time. - (ix86_sched_reorder) : Do not perform ready list reordering for pre-reload - schedule to save compile time. + (ia32_multipass_dfa_lookahead) : Do not use dfa_lookahead for + pre-reload schedule to save compile time. + (ix86_sched_reorder) : Do not perform ready list reordering for + pre-reload schedule to save compile time. (insn_is_function_arg) : New function. Returns true if lhs of insn is HW function argument register. (add_parameter_dependencies) : New function. Add output dependencies @@ -70,14 +394,14 @@ (add_dependee_for_func_arg) : New function. Avoid cross block motion of function argument through adding dependency from the first non-jump insn in bb. - (ix86_dependencies_evaluation_hook) : New function. Hook for pre-reload schedule: - avoid motion of function arguments passed in passed in likely spilled - HW registers. - (ix86_adjust_priority) : New function. Hook for pre-reload schedule: set priority - of moves from likely spilled HW registers to maximum to schedule them - as soon as possible. - (ix86_sched_init_global): Do not perform multipass scheduling for pre-reload - schedule to save compile time. + (ix86_dependencies_evaluation_hook) : New function. Hook for + pre-reload schedule: avoid motion of function arguments passed in + likely spilled HW registers. + (ix86_adjust_priority) : New function. Hook for pre-reload schedule: + set priority of moves from likely spilled HW registers to maximum to + schedule them as soon as possible. + (ix86_sched_init_global): Do not perform multipass scheduling for + pre-reload schedule to save compile time. 2012-10-04 Uros Bizjak <ubizjak@gmail.com> @@ -141,7 +465,7 @@ * config/rx/rx.opt (mwarn-multiple-fast-interrupts): New option. * doc/invoke.texi: Document the option. -2012-09-03 Mark Kettenis <kettenis@openbsd.org> +2012-10-03 Mark Kettenis <kettenis@openbsd.org> * config.gcc (*-*-openbsd4.[3-9]|*-*-openbsd[5-9]*): Set default_use_cxa_atexit to yes. @@ -4295,7 +4619,7 @@ 2012-08-17 Nick Clifton <nickc@redhat.com> - * config/fr30/fr30.md (cbranchsi4): Remove mode from comparison. + * config/fr30/fr30.md (cbranchsi4): Remove mode from comparison. (branch_true): Likewise. (branch_false): Likewise. @@ -17919,7 +18243,7 @@ * config/arm/linux-eabi.h (GLIBC_DYNAMIC_LINKER_SOFT_FLOAT): Define. (GLIBC_DYNAMIC_LINKER_HARD_FLOAT): Define. (GLIBC_DYNAMIC_LINKER_DEFAULT): Define. - (GLIBC_DYNAMIC_LINKER): Redefine to use the hard float path. + (GLIBC_DYNAMIC_LINKER): Redefine to use the hard float path. 2012-04-25 Sriraman Tallam <tmsriram@google.com> diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 392af5d642f..3bda1e32d7f 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20121004 +20121008 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 8196e94e8ad..1a9ff91cf3f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,106 @@ +2012-10-05 Robert Dewar <dewar@adacore.com> + + * sem_ch7.adb: Minor reformatting. + +2012-10-05 Ed Schonberg <schonberg@adacore.com> + + * sem_prag.adb (Analyze_Pragma, case Persistent_BSS): check for + a duplicate pragma before Rep_Item_Too_Late to prevent spurious + messages about duplicate pragmas. + +2012-10-05 Ed Schonberg <schonberg@adacore.com> + + * exp_util.adb (Find_Init_Call): If the successor of the + object declaration is a block, check whether it contains the + initialization call, because it may have been created by actuals + that use the secondary stack. + +2012-10-05 Thomas Quinot <quinot@adacore.com> + + * sem_dim.adb, errout.adb, errout.ads (Analyze_Dimension_Call): Add + guard against abnormal tree resulting from a previously diagnosed + illegality. + +2012-10-05 Hristian Kirtchev <kirtchev@adacore.com> + + * freeze.adb (Freeze_Expression): Rename local variable Cspc to Spec + and update all refs to it. Do not freeze an entity outside a subprogram + body when the original context is an expression function. + +2012-10-05 Robert Dewar <dewar@adacore.com> + + * gnat1drv.adb (Adjust_Global_Switches): Default for overflow checking + is suppressed, even if backend overflow/divide checks are enabled. + +2012-10-05 Ed Schonberg <schonberg@adacore.com> + + * einfo.adb (Set_Invariant_Procedure, Set_Predicate_Function): + chain properly subprograms on Subprograms_For_Type list. + * sem_ch13.ads; (Build_Invariant_Procedure_Declaration): new + procedure, to create declaration for invariant procedure + independently of the construction of the body, so that it can + be called within expression functions. + * sem_ch13.adb (Build_Invariant_Procedure): code cleanup. The + declaration may already have been generated at the point an + explicit invariant aspect is encountered. + * sem_prag.adb; (Analyze_Pragma, case Invariant): create declaration + for invariant procedure. + * sem_ch7.adb (Analyze_Package_Specification): clean up call to + build invariant procedure. + (Preserve_Full_Attributes): propagate information about invariants + if they appear on a completion, + +2012-10-05 Pascal Obry <obry@adacore.com> + + * gnat_ugn.texi: Update documentation to lift Microsoft C + restriction. + +2012-10-05 Robert Dewar <dewar@adacore.com> + + * sem_util.adb (Has_One_Matching_Field): Handle case of lone + discriminant. + +2012-10-05 Yannick Moy <moy@adacore.com> + + * checks.adb (Minimize_Eliminate_Overflow_Checks): Correct code + for the division operation and exponent operation. Adjust bound + for the mod and rem operations. + +2012-10-05 Robert Dewar <dewar@adacore.com> + + * checks.adb, checks.ads, s-tassta.adb, s-stposu.adb, s-spsufi.adb, + s-spsufi.ads, exp_ch4.adb: Minor reformatting. + +2012-10-05 Yannick Moy <moy@adacore.com> + + * switch-c.adb, checks.adb, checks.ads, sem_prag.adb, exp_ch4.adb, + osint.adb: Minor correction of typos, and special case for Alfa mode. + +2012-10-05 Hristian Kirtchev <kirtchev@adacore.com> + + * s-spsufi.adb: Add with clause for Ada.Unchecked_Deallocation. + Add with and use clauses for System.Finalization_Masters. + (Finalize_And_Deallocate): Add an instance of + Ada.Unchecked_Deallocation. Merge the code from the now obsolete + Finalize_Subpool into this routine. + * s-spsufi.ads: Add pragma Preelaborate. + * s-stposu.adb: Remove with clause for + Ada.Unchecked_Deallocation; Add with and use clauses for + System.Storage_Pools.Subpools.Finalization; (Finalize_Pool): + Update the comment on all actions takes with respect to a subpool + finalization. Finalize and deallocate each individual subpool. + (Finalize_Subpool): Removed. + (Free): Removed; + (Detach): Move from package body to spec. + * s-stposu.ads (Detach): Move from package body to spec. + (Finalize_Subpool): Removed. + +2012-10-05 Arnaud Charlet <charlet@adacore.com> + + * s-tassta.adb: Update comments. + (Vulnerable_Complete_Master): If Free_On_Termination is set, do + nothing, and let the task free itself if not already done. + 2012-10-04 Robert Dewar <dewar@adacore.com> * sem_res.adb (Resolve_Set_Membership): Warn on duplicates. diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index 075eb14caeb..061f9796f2a 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -765,9 +765,9 @@ package body Checks is procedure Apply_Arithmetic_Overflow_Check (N : Node_Id) is begin -- Use old routine in almost all cases (the only case we are treating - -- specially is the case of an signed integer arithmetic op with the + -- specially is the case of a signed integer arithmetic op with the -- Do_Overflow_Check flag set on the node, and the overflow checking - -- mode is either Minimized_Or_Eliminated. + -- mode is MINIMIZED or ELIMINATED). if Overflow_Check_Mode (Etype (N)) not in Minimized_Or_Eliminated or else not Do_Overflow_Check (N) @@ -775,9 +775,9 @@ package body Checks is then Apply_Arithmetic_Overflow_Checked_Suppressed (N); - -- Otherwise use the new routine for MINIMIZED/ELIMINATED modes for - -- the case of a signed integer arithmetic op, with Do_Overflow_Check - -- set True, and the checking mode is Minimized_Or_Eliminated. + -- Otherwise use the new routine for the case of a signed integer + -- arithmetic op, with Do_Overflow_Check set to True, and the checking + -- mode is MINIMIZED or ELIMINATED. else Apply_Arithmetic_Overflow_Minimized_Eliminated (N); @@ -797,7 +797,7 @@ package body Checks is -- This is used in SUPPRESSED/CHECKED modes. It is identical to the -- code for these cases before the big overflow earthquake, thus ensuring - -- that in these modes we have compatible behavior (and realibility) to + -- that in these modes we have compatible behavior (and reliability) to -- what was there before. It is also called for types other than signed -- integers, and if the Do_Overflow_Check flag is off. @@ -805,9 +805,9 @@ package body Checks is -- to give up and just generate an overflow check without any fuss. procedure Apply_Arithmetic_Overflow_Checked_Suppressed (N : Node_Id) is - Loc : constant Source_Ptr := Sloc (N); - Typ : constant Entity_Id := Etype (N); - Rtyp : constant Entity_Id := Root_Type (Typ); + Loc : constant Source_Ptr := Sloc (N); + Typ : constant Entity_Id := Etype (N); + Rtyp : constant Entity_Id := Root_Type (Typ); begin -- An interesting special case. If the arithmetic operation appears as @@ -1117,10 +1117,11 @@ package body Checks is end if; -- Otherwise, we have a top level arithmetic operation node, and this - -- is where we commence the special processing for minimize/eliminate. - -- This is the case where we tell the machinery not to move into Bignum - -- mode at this top level (of course the top level operation will still - -- be in Bignum mode if either of its operands are of type Bignum). + -- is where we commence the special processing for MINIMIZED/ELIMINATED + -- modes. This is the case where we tell the machinery not to move into + -- Bignum mode at this top level (of course the top level operation + -- will still be in Bignum mode if either of its operands are of type + -- Bignum). Minimize_Eliminate_Overflow_Checks (Op, Lo, Hi, Top_Level => True); @@ -1164,8 +1165,8 @@ package body Checks is -- X := Long_Long_Integer'Base (A * (B ** C)); -- Now the product may fit in Long_Long_Integer but not in Integer. - -- In Minimize/Eliminate mode, we don't want to introduce an overflow - -- exception for this intermediate value. + -- In MINIMIZED/ELIMINATED mode, we don't want to introduce an + -- overflow exception for this intermediate value. declare Blk : constant Node_Id := Make_Bignum_Block (Loc); @@ -1206,9 +1207,9 @@ package body Checks is Analyze_And_Resolve (Op); end; - -- Here we know the result is Long_Long_Integer'Base, or that it - -- has been rewritten because the parent is a conversion (see - -- Apply_Arithmetic_Overflow_Check.Conversion_Optimization). + -- Here we know the result is Long_Long_Integer'Base, of that it has + -- been rewritten because the parent operation is a conversion. See + -- Apply_Arithmetic_Overflow_Checked_Suppressed.Conversion_Optimization. else pragma Assert @@ -3813,8 +3814,8 @@ package body Checks is if Is_RTE (Etype (N), RE_Bignum) then return Relocate_Node (N); - -- Otherwise construct call to To_Bignum, converting the operand to - -- the required Long_Long_Integer form. + -- Otherwise construct call to To_Bignum, converting the operand to the + -- required Long_Long_Integer form. else pragma Assert (Is_Signed_Integer_Type (Etype (N))); @@ -4442,13 +4443,14 @@ package body Checks is return; end if; - -- This is the point at which processing for CHECKED mode diverges from - -- processing for MINIMIZED/ELIMINATED mode. This divergence is probably - -- more extreme that it needs to be, but what is going on here is that - -- when we introduced MINIMIZED/ELININATED modes, we wanted to leave the - -- processing for CHECKED mode untouched. There were two reasons for - -- this. First it avoided any incomptible change of behavior. Second, - -- it guaranteed that CHECKED mode continued to be legacy reliable. + -- This is the point at which processing for CHECKED mode diverges + -- from processing for MINIMIZED/ELIMINATED modes. This divergence is + -- probably more extreme that it needs to be, but what is going on here + -- is that when we introduced MINIMIZED/ELIMINATED modes, we wanted + -- to leave the processing for CHECKED mode untouched. There were + -- two reasons for this. First it avoided any incompatible change of + -- behavior. Second, it guaranteed that CHECKED mode continued to be + -- legacy reliable. -- The big difference is that in CHECKED mode there is a fair amount of -- circuitry to try to avoid setting the Do_Overflow_Check flag if we @@ -6691,9 +6693,9 @@ package body Checks is -- recursive calls to process operands. This processing may involve the use -- of bignum or long long integer arithmetic, which will change the types -- of operands and results. That's why we can't do this bottom up (since - -- it would intefere with semantic analysis). + -- it would interfere with semantic analysis). - -- What happens is that if Minimized/Eliminated mode is in effect then + -- What happens is that if MINIMIZED/ELIMINATED mode is in effect then -- the operator expansion routines, as well as the expansion routines -- for if/case expression test the Do_Overflow_Check flag and if it is -- set they (for the moment) do nothing except call the routine to apply @@ -6710,12 +6712,12 @@ package body Checks is -- After possible rewriting of a constituent subexpression node, a call is -- made to either reexpand the node (if nothing has changed) or reanalyze - -- the node (if it has been modified by the overflow check processing). - -- The Analyzed_flag is set False before the reexpand/reanalyze. To avoid - -- a recursive call into the whole overflow apparatus, and important rule + -- the node (if it has been modified by the overflow check processing). The + -- Analyzed_Flag is set to False before the reexpand/reanalyze. To avoid + -- a recursive call into the whole overflow apparatus, an important rule -- for this call is that either Do_Overflow_Check must be False, or if -- it is set, then the overflow checking mode must be temporarily set - -- to Checked/Suppressed. Either step will avoid the unwanted recursion. + -- to CHECKED/SUPPRESSED. Either step will avoid the unwanted recursion. procedure Minimize_Eliminate_Overflow_Checks (N : Node_Id; @@ -6755,33 +6757,33 @@ package body Checks is -- Set True if one or more operands is already of type Bignum, meaning -- that for sure (regardless of Top_Level setting) we are committed to -- doing the operation in Bignum mode (or in the case of a case or if - -- expression, converting all the dependent expressions to bignum). + -- expression, converting all the dependent expressions to Bignum). Long_Long_Integer_Operands : Boolean; - -- Set True if one r more operands is already of type Long_Loong_Integer + -- Set True if one or more operands is already of type Long_Long_Integer -- which means that if the result is known to be in the result type -- range, then we must convert such operands back to the result type. -- This switch is properly set only when Bignum_Operands is False. procedure Reexpand (C : Suppressed_Or_Checked); - -- This is called when we have not modifed the node, so we do not need - -- to reanalyze it. But we do want to reexpand it in either CHECKED - -- or SUPPRESSED mode (as indicated by the argument C) to get proper + -- This is called when we have not modified the node, so we do not need + -- to reanalyze it. But we do want to reexpand it in either SUPPRESSED + -- or CHECKED mode (as indicated by the argument C) to get proper -- expansion. It is important that we reset the mode to SUPPRESSED or -- CHECKED, since if we leave it in MINIMIZED or ELIMINATED mode we -- would reenter this routine recursively which would not be good! -- Note that this is not just an optimization, testing has showed up - -- several complex cases in which renalyzing an already analyzed node + -- several complex cases in which reanalyzing an already analyzed node -- causes incorrect behavior. function In_Result_Range return Boolean; -- Returns True iff Lo .. Hi are within range of the result type procedure Max (A : in out Uint; B : Uint); - -- If A is No_Uint, sets A to B, else to UI_Max (A, B); + -- If A is No_Uint, sets A to B, else to UI_Max (A, B) procedure Min (A : in out Uint; B : Uint); - -- If A is No_Uint, sets A to B, else to UI_Min (A, B); + -- If A is No_Uint, sets A to B, else to UI_Min (A, B) --------------------- -- In_Result_Range -- @@ -6858,7 +6860,7 @@ package body Checks is Determine_Range (N, OK, Lo, Hi, Assume_Valid => False); - -- If Deterine_Range did not work (can this in fact happen? Not + -- If Determine_Range did not work (can this in fact happen? Not -- clear but might as well protect), use type bounds. if not OK then @@ -6901,8 +6903,8 @@ package body Checks is Max (Hi, Rhi); end if; - -- If at least one of our operands is now bignum, we must rebuild - -- the if expression to use bignum operands. We will analyze the + -- If at least one of our operands is now Bignum, we must rebuild + -- the if expression to use Bignum operands. We will analyze the -- rebuilt if expression with overflow checks off, since once we -- are in bignum mode, we are all done with overflow checks! @@ -6952,8 +6954,6 @@ package body Checks is elsif Nkind (N) = N_Case_Expression then Bignum_Operands := False; Long_Long_Integer_Operands := False; - Lo := No_Uint; - Hi := No_Uint; declare Alt : Node_Id; @@ -6986,7 +6986,7 @@ package body Checks is -- resetting the overflow flag, since we are done with overflow -- checks for this node. We will reexpand to get the needed -- expansion for the case expression, but we do not need to - -- renalyze, since nothing has changed. + -- reanalyze, since nothing has changed. if not (Bignum_Operands or Long_Long_Integer_Operands) then Set_Do_Overflow_Check (N, False); @@ -7057,7 +7057,7 @@ package body Checks is -- don't need to do any range analysis. As previously discussed we could -- do range analysis in such cases, but it could mean working with giant -- numbers at compile time for very little gain (the number of cases - -- in which we could slip back from bignum mode are small). + -- in which we could slip back from bignum mode is small). if Rlo = No_Uint or else (Binary and then Llo = No_Uint) then Lo := No_Uint; @@ -7069,10 +7069,6 @@ package body Checks is else Bignum_Operands := False; - Long_Long_Integer_Operands := - Etype (Right_Opnd (N)) = LLIB - or else (Binary and then Etype (Left_Opnd (N)) = LLIB); - case Nkind (N) is -- Absolute value @@ -7091,147 +7087,80 @@ package body Checks is when N_Op_Divide => - -- Following seems awfully complex, can it be simplified ??? - - Hi := No_Uint; - Lo := No_Uint; - - declare - S : Uint; - - begin - -- First work on finding big absolute result values. These - -- come from dividing large numbers (which we have in Llo - -- and Lhi) by small values, which we need to figure out. - - -- Case where right operand can be positive - - if Rhi > 0 then - - -- Find smallest positive divisor - - if Rlo > 0 then - S := Rlo; - else - S := Uint_1; - end if; + -- If the right operand can only be zero, set 0..0 - -- Big negative value divided by small positive value - -- generates a candidate for lowest possible result. - - if Llo < 0 then - Min (Lo, Llo / S); - end if; - - -- Big positive value divided by small positive value - -- generates a candidate for highest possible result. - - if Lhi > 0 then - Max (Hi, Lhi / S); - end if; - end if; - - -- Case where right operand can be negative - - if Rlo < 0 then - - -- Find smallest absolute value negative divisor - - if Rhi < 0 then - S := Rhi; - else - S := -Uint_1; - end if; - - -- Big negative value divided by small negative value - -- generates a candidate for largest possible result. - - if Llo < 0 then - Max (Hi, Llo / S); - end if; - - -- Big positive value divided by small negative value - -- generates a candidate for lowest possible result. - - if Lhi > 0 then - Min (Lo, Lhi / S); - end if; - end if; - - -- Now work on finding small absolute result values. These - -- come from dividing small numbers, which we need to figure - -- out, by large values (which we have in Rlo, Rhi). - - -- Case where left operand can be positive - - if Lhi > 0 then - - -- Find smallest positive dividend + if Rlo = 0 and then Rhi = 0 then + Lo := Uint_0; + Hi := Uint_0; - if Llo > 0 then - S := Llo; - else - S := Uint_1; - end if; + -- Possible bounds of division must come from dividing end + -- values of the input ranges (four possibilities), provided + -- zero is not included in the possible values of the right + -- operand. + + -- Otherwise, we just consider two intervals of values for + -- the right operand: the interval of negative values (up to + -- -1) and the interval of positive values (starting at 1). + -- Since division by 1 is the identity, and division by -1 + -- is negation, we get all possible bounds of division in that + -- case by considering: + -- - all values from the division of end values of input + -- ranges; + -- - the end values of the left operand; + -- - the negation of the end values of the left operand. - -- Small positive values divided by large negative values - -- generate candidates for low results. + else + declare + Mrk : constant Uintp.Save_Mark := Mark; + -- Mark so we can release the RR and Ev values - if Rlo < 0 then - Min (Lo, S / Rlo); - end if; + Ev1 : Uint; + Ev2 : Uint; + Ev3 : Uint; + Ev4 : Uint; - -- Small positive values divided by large positive values - -- generate candidates for high results. + begin + -- Discard extreme values of zero for the divisor, since + -- they will simply result in an exception in any case. - if Rhi > 0 then - Max (Hi, S / Rhi); + if Rlo = 0 then + Rlo := Uint_1; + elsif Rhi = 0 then + Rhi := -Uint_1; end if; - end if; - -- Case where left operand can be negative + -- Compute possible bounds coming from dividing end + -- values of the input ranges. - if Llo < 0 then - - -- Find smallest absolute value negative dividend - - if Lhi < 0 then - S := Lhi; - else - S := -Uint_1; - end if; + Ev1 := Llo / Rlo; + Ev2 := Llo / Rhi; + Ev3 := Lhi / Rlo; + Ev4 := Lhi / Rhi; - -- Small negative value divided by large negative value - -- generates a candidate for highest possible result. + Lo := UI_Min (UI_Min (Ev1, Ev2), UI_Min (Ev3, Ev4)); + Hi := UI_Max (UI_Max (Ev1, Ev2), UI_Max (Ev3, Ev4)); - if Rlo < 0 then - Max (Hi, Rlo / S); - end if; + -- If the right operand can be both negative or positive, + -- include the end values of the left operand in the + -- extreme values, as well as their negation. - -- Small negative value divided by large positive value - -- generates a candidate for lowest possible result. + if Rlo < 0 and then Rhi > 0 then + Ev1 := Llo; + Ev2 := -Llo; + Ev3 := Lhi; + Ev4 := -Lhi; - if Rhi > 0 then - Min (Lo, Rhi / S); + Min (Lo, + UI_Min (UI_Min (Ev1, Ev2), UI_Min (Ev3, Ev4))); + Max (Hi, + UI_Max (UI_Max (Ev1, Ev2), UI_Max (Ev3, Ev4))); end if; - end if; - - -- Finally, if neither Lo or Hi set (happens if the right - -- operand is always zero for example), then set 0 .. 0. - - if Lo = No_Uint and then Hi = No_Uint then - Lo := Uint_0; - Hi := Uint_0; - - -- If one bound set and not the other copy - elsif Lo = No_Uint then - Lo := Hi; + -- Release the RR and Ev values - elsif Hi = No_Uint then - Hi := Lo; - end if; - end; + Release_And_Save (Mrk, Lo, Hi); + end; + end if; -- Exponentiation @@ -7268,14 +7197,15 @@ package body Checks is else -- High bound comes either from exponentiation of largest - -- positive value to largest exponent value, or from the - -- exponentiation of most negative value to an odd exponent. + -- positive value to largest exponent value, or from + -- the exponentiation of most negative value to an + -- even exponent. declare Hi1, Hi2 : Uint; begin - if Lhi >= 0 then + if Lhi > 0 then Hi1 := Lhi ** Rhi; else Hi1 := Uint_0; @@ -7283,9 +7213,9 @@ package body Checks is if Llo < 0 then if Rhi mod 2 = 0 then - Hi2 := Llo ** (Rhi - 1); - else Hi2 := Llo ** Rhi; + else + Hi2 := Llo ** (Rhi - 1); end if; else Hi2 := Uint_0; @@ -7297,13 +7227,13 @@ package body Checks is -- Result can only be negative if base can be negative if Llo < 0 then - if UI_Mod (Rhi, 2) = 0 then + if Rhi mod 2 = 0 then Lo := Llo ** (Rhi - 1); else Lo := Llo ** Rhi; end if; - -- Otherwise low bound is minimium ** minimum + -- Otherwise low bound is minimum ** minimum else Lo := Llo ** Rlo; @@ -7320,7 +7250,7 @@ package body Checks is when N_Op_Mod => declare - Maxabs : constant Uint := UI_Max (abs Rlo, abs Rhi); + Maxabs : constant Uint := UI_Max (abs Rlo, abs Rhi) - 1; -- This is the maximum absolute value of the result begin @@ -7375,9 +7305,10 @@ package body Checks is when N_Op_Rem => declare - Maxabs : constant Uint := UI_Max (abs Rlo, abs Rhi); + Maxabs : constant Uint := UI_Max (abs Rlo, abs Rhi) - 1; -- This is the maximum absolute value of the result. Note - -- that the result range does not depend on the sign of B. + -- that the result range does not depend on the sign of the + -- right operand. begin Lo := Uint_0; @@ -7412,13 +7343,13 @@ package body Checks is end if; -- Here for the case where we have not rewritten anything (no bignum - -- operands or long long integer operands), and we know the result If we - -- know we are in the result range, and we do not have Bignum operands - -- or Long_Long_Integer operands, we can just reexpand with overflow - -- checks turned off (since we know we cannot have overflow). As always - -- the reexpansion is required to complete expansion of the operator, - -- but we do not need to reanalyze, and we prevent recursion by - -- suppressing the check, + -- operands or long long integer operands), and we know the result. + -- If we know we are in the result range, and we do not have Bignum + -- operands or Long_Long_Integer operands, we can just reexpand with + -- overflow checks turned off (since we know we cannot have overflow). + -- As always the reexpansion is required to complete expansion of the + -- operator, but we do not need to reanalyze, and we prevent recursion + -- by suppressing the check. if not (Bignum_Operands or Long_Long_Integer_Operands) and then In_Result_Range @@ -7428,11 +7359,12 @@ package body Checks is return; -- Here we know that we are not in the result range, and in the general - -- we will move into either the Bignum or Long_Long_Integer domain to - -- compute the result. However, there is one exception. If we are at the - -- top level, and we do not have Bignum or Long_Long_Integer operands, - -- we will have to immediately convert the result back to the result - -- type, so there is no point in Bignum/Long_Long_Integer fiddling. + -- case we will move into either the Bignum or Long_Long_Integer domain + -- to compute the result. However, there is one exception. If we are + -- at the top level, and we do not have Bignum or Long_Long_Integer + -- operands, we will have to immediately convert the result back to + -- the result type, so there is no point in Bignum/Long_Long_Integer + -- fiddling. elsif Top_Level and then not (Bignum_Operands or Long_Long_Integer_Operands) @@ -7455,8 +7387,8 @@ package body Checks is Set_Analyzed (N, False); -- One subtlety. We can't just go ahead and do an analyze operation - -- here because it will cause recursion into the whole minimized/ - -- eliminated overflow processing which is not what we want. Here + -- here because it will cause recursion into the whole MINIMIZED/ + -- ELIMINATED overflow processing which is not what we want. Here -- we are at the top level, and we need a check against the result -- mode (i.e. we want to use Checked mode). So do exactly that! -- Also, we have not modified the node, so this is a case where diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads index 8efaecef780..f7a4399386d 100644 --- a/gcc/ada/checks.ads +++ b/gcc/ada/checks.ads @@ -223,7 +223,7 @@ package Checks is -- Returns result of converting node N to Bignum. The returned value is not -- analyzed, the caller takes responsibility for this. Node N must be a -- subexpression node of a signed integer type or Bignum type (if it is - -- already a Bignnum, the returned value is Relocate_Node (N). + -- already a Bignum, the returned value is Relocate_Node (N)). procedure Determine_Range (N : Node_Id; @@ -273,7 +273,7 @@ package Checks is Top_Level : Boolean); -- This is the main routine for handling MINIMIZED and ELIMINATED overflow -- checks. On entry N is a node whose result is a signed integer subtype. - -- If the node is an artihmetic operation, then a range analysis is carried + -- If the node is an arithmetic operation, then a range analysis is carried -- out, and there are three possibilities: -- -- The node is left unchanged (apart from expansion of an exponentiation @@ -289,13 +289,13 @@ package Checks is -- -- In the first two cases, Lo and Hi are set to the bounds of the possible -- range of results, computed as accurately as possible. In the third case - -- Lo and Hi are set to No_Uint (there are some cases where we cold get an + -- Lo and Hi are set to No_Uint (there are some cases where we could get an -- advantage from keeping result ranges for Bignum values, but it could use -- a lot of space and is very unlikely to be valuable). -- -- If the node is not an arithmetic operation, then it is unchanged but -- Lo and Hi are still set (to the bounds of the result subtype if nothing - -- better can be determined. + -- better can be determined). -- -- Note: this function is recursive, if called with an arithmetic operator, -- recursive calls are made to process the operands using this procedure. @@ -310,8 +310,8 @@ package Checks is -- with a Long_Long_Integer left operand and an Integer right operand, and -- we would get a semantic error. -- - -- The routine is called in three situations if we are operating in - -- either MINIMIZED or ELIMINATED modes. + -- The routine is called in three situations if we are operating in either + -- MINIMIZED or ELIMINATED modes. -- -- Overflow checks applied to the top node of an expression tree when -- that node is an arithmetic operator. In this case the result is @@ -328,7 +328,7 @@ package Checks is -- just that the result of IN is false in that case). -- -- Note that if Bignum values appear, the caller must take care of doing - -- the appropriate mark/release operation on the secondary stack. + -- the appropriate mark/release operations on the secondary stack. -- -- Top_Level is used to avoid inefficient unnecessary transitions into the -- Bignum domain. If Top_Level is True, it means that the caller will have diff --git a/gcc/ada/einfo.adb b/gcc/ada/einfo.adb index e7c9146d6f0..bfa7593dc5d 100644 --- a/gcc/ada/einfo.adb +++ b/gcc/ada/einfo.adb @@ -7113,6 +7113,7 @@ package body Einfo is S := Subprograms_For_Type (Id); Set_Subprograms_For_Type (Id, V); + Set_Subprograms_For_Type (V, S); while Present (S) loop if Has_Invariants (S) then @@ -7121,8 +7122,6 @@ package body Einfo is S := Subprograms_For_Type (S); end if; end loop; - - Set_Subprograms_For_Type (Id, V); end Set_Invariant_Procedure; ---------------------------- @@ -7137,6 +7136,7 @@ package body Einfo is S := Subprograms_For_Type (Id); Set_Subprograms_For_Type (Id, V); + Set_Subprograms_For_Type (V, S); while Present (S) loop if Has_Predicates (S) then @@ -7145,8 +7145,6 @@ package body Einfo is S := Subprograms_For_Type (S); end if; end loop; - - Set_Subprograms_For_Type (Id, V); end Set_Predicate_Function; ----------------- diff --git a/gcc/ada/errout.adb b/gcc/ada/errout.adb index 6f450200ef9..64062b29e9c 100644 --- a/gcc/ada/errout.adb +++ b/gcc/ada/errout.adb @@ -198,6 +198,21 @@ package body Errout is -- spec for precise definition of the conversion that is performed by this -- routine in OpenVMS mode. + -------------------- + -- Cascaded_Error -- + -------------------- + + procedure Cascaded_Error is + begin + -- An anomaly has been detected which is assumed to be a consequence of + -- a previous error. Raise an exception if no serious error has been + -- found so far. + + if Serious_Errors_Detected = 0 then + raise Program_Error; + end if; + end Cascaded_Error; + ----------------------- -- Change_Error_Text -- ----------------------- diff --git a/gcc/ada/errout.ads b/gcc/ada/errout.ads index 212eea4a116..7da6493e453 100644 --- a/gcc/ada/errout.ads +++ b/gcc/ada/errout.ads @@ -727,6 +727,13 @@ package Errout is -- This routine can only be called during semantic analysis. It may not -- be called during parsing. + procedure Cascaded_Error; + -- When an anomaly is detected, many semantic routines silently bail out, + -- assuming that the anomaly was caused by a previously detected error. + -- This routine should be called in these cases, and will raise an + -- exception if no serious error has been detected. This ensure that the + -- anomaly is never allowed to go unnoticed. + procedure Change_Error_Text (Error_Id : Error_Msg_Id; New_Msg : String); -- The error message text of the message identified by Id is replaced by -- the given text. This text may contain insertion characters in the diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index f47bae4b918..ee9ce0c50f2 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -141,8 +141,8 @@ package body Exp_Ch4 is -- Common expansion processing for short-circuit boolean operators procedure Expand_Compare_Minimize_Eliminate_Overflow (N : Node_Id); - -- Deal with comparison in Minimize/Eliminate overflow mode. This is where - -- we allow comparison of "out of range" values. + -- Deal with comparison in MINIMIZED/ELIMINATED overflow mode. This is + -- where we allow comparison of "out of range" values. function Expand_Composite_Equality (Nod : Node_Id; @@ -165,10 +165,10 @@ package body Exp_Ch4 is -- include both arrays and singleton elements. procedure Expand_Membership_Minimize_Eliminate_Overflow (N : Node_Id); - -- N is an N_In membership test mode, with the overflow check mode - -- set to Minimized or Eliminated, and the type of the left operand - -- is a signed integer type. This is a case where top level processing - -- is required to handle overflow checks in subtrees. + -- N is an N_In membership test mode, with the overflow check mode set to + -- MINIMIZED or ELIMINATED, and the type of the left operand is a signed + -- integer type. This is a case where top level processing is required to + -- handle overflow checks in subtrees. procedure Fixup_Universal_Fixed_Operation (N : Node_Id); -- N is a N_Op_Divide or N_Op_Multiply node whose result is universal @@ -5524,7 +5524,7 @@ package body Exp_Ch4 is Ltyp := Etype (Left_Opnd (N)); Rtyp := Etype (Right_Opnd (N)); - -- If Minimize/Eliminate overflow mode and type is a signed integer + -- If MINIMIZED/ELIMINATED overflow mode and type is a signed integer -- type, then expand with a separate procedure. Note the use of the -- flag No_Minimize_Eliminate to prevent infinite recursion. @@ -7084,7 +7084,7 @@ package body Exp_Ch4 is Typl := Base_Type (Typl); -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that - -- results in not having a comparison operation any more, we are done. + -- means we no longer have a comparison operation, we are all done. Expand_Compare_Minimize_Eliminate_Overflow (N); @@ -7678,7 +7678,7 @@ package body Exp_Ch4 is Binary_Op_Validity_Checks (N); -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that - -- results in not having a comparison operation any more, we are done. + -- means we no longer have a comparison operation, we are all done. Expand_Compare_Minimize_Eliminate_Overflow (N); @@ -7728,7 +7728,7 @@ package body Exp_Ch4 is Binary_Op_Validity_Checks (N); -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that - -- results in not having a comparison operation any more, we are done. + -- means we no longer have a comparison operation, we are all done. Expand_Compare_Minimize_Eliminate_Overflow (N); @@ -7778,7 +7778,7 @@ package body Exp_Ch4 is Binary_Op_Validity_Checks (N); -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that - -- results in not having a comparison operation any more, we are done. + -- means we no longer have a comparison operation, we are all done. Expand_Compare_Minimize_Eliminate_Overflow (N); @@ -7828,7 +7828,7 @@ package body Exp_Ch4 is Binary_Op_Validity_Checks (N); -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that - -- results in not having a comparison operation any more, we are done. + -- means we no longer have a comparison operation, we are all done. Expand_Compare_Minimize_Eliminate_Overflow (N); @@ -8263,7 +8263,7 @@ package body Exp_Ch4 is Binary_Op_Validity_Checks (N); -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if - -- that results in not having a /= opertion any more, we are done. + -- means we no longer have a /= operation, we are all done. Expand_Compare_Minimize_Eliminate_Overflow (N); diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 82b054adfce..cc3213d03da 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -2166,6 +2166,7 @@ package body Exp_Util is (Var : Entity_Id; Rep_Clause : Node_Id) return Node_Id is + Par : constant Node_Id := Parent (Var); Typ : constant Entity_Id := Etype (Var); Init_Proc : Entity_Id; @@ -2204,6 +2205,7 @@ package body Exp_Util is begin if not Has_Non_Null_Base_Init_Proc (Typ) then + -- No init proc for the type, so obviously no call to be found return Empty; @@ -2213,7 +2215,7 @@ package body Exp_Util is -- First scan the list containing the declaration of Var - Init_Call := Find_Init_Call_In_List (From => Next (Parent (Var))); + Init_Call := Find_Init_Call_In_List (From => Next (Par)); -- If not found, also look on Var's freeze actions list, if any, since -- the init call may have been moved there (case of an address clause @@ -2224,6 +2226,23 @@ package body Exp_Util is Find_Init_Call_In_List (First (Actions (Freeze_Node (Var)))); end if; + -- If the initialization call has actuals that use the secondary stack, + -- the call may have been wrapped into a temporary block, in which case + -- the block itself has to be removed. + + if No (Init_Call) and then Nkind (Next (Par)) = N_Block_Statement then + declare + Blk : constant Node_Id := Next (Par); + begin + if Present + (Find_Init_Call_In_List + (First (Statements (Handled_Statement_Sequence (Blk))))) + then + Init_Call := Blk; + end if; + end; + end if; + return Init_Call; end Find_Init_Call; diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index 039325afbcf..9e0cbcacf80 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -5156,43 +5156,63 @@ package body Freeze is -- subprogram body that we are inside. if In_Exp_Body (Parent_P) then - - -- However, we *do* want to freeze at this point if we have - -- an entity to freeze, and that entity is declared *inside* - -- the body of the expander generated procedure. This case - -- is recognized by the scope of the type, which is either - -- the spec for some enclosing body, or (in the case of - -- init_procs, for which there are no separate specs) the - -- current scope. - declare Subp : constant Node_Id := Parent (Parent_P); - Cspc : Entity_Id; + Spec : Entity_Id; begin + -- Freeze the entity only when it is declared inside the + -- body of the expander generated procedure. This case + -- is recognized by the scope of the entity or its type, + -- which is either the spec for some enclosing body, or + -- (in the case of init_procs, for which there are no + -- separate specs) the current scope. + if Nkind (Subp) = N_Subprogram_Body then - Cspc := Corresponding_Spec (Subp); + Spec := Corresponding_Spec (Subp); - if (Present (Typ) and then Scope (Typ) = Cspc) + if (Present (Typ) and then Scope (Typ) = Spec) or else - (Present (Nam) and then Scope (Nam) = Cspc) + (Present (Nam) and then Scope (Nam) = Spec) then exit; elsif Present (Typ) and then Scope (Typ) = Current_Scope - and then Current_Scope = Defining_Entity (Subp) + and then Defining_Entity (Subp) = Current_Scope then exit; end if; end if; - end; - -- If not that exception to the exception, then this is - -- where we delay the freeze till outside the body. + -- An expression function may act as a completion of + -- a function declaration. As such, it can reference + -- entities declared between the two views: - Parent_P := Parent (Parent_P); - Freeze_Outside := True; + -- Hidden []; -- 1 + -- function F return ...; + -- private + -- function Hidden return ...; + -- function F return ... is (Hidden); -- 2 + + -- Refering to the example above, freezing the expression + -- of F (2) would place Hidden's freeze node (1) in the + -- wrong place. Avoid explicit freezing and let the usual + -- scenarios do the job - for example, reaching the end + -- of the private declarations. + + if Nkind (Original_Node (Subp)) = + N_Expression_Function + then + null; + + -- Freeze outside the body + + else + Parent_P := Parent (Parent_P); + Freeze_Outside := True; + end if; + end; -- Here if normal case where we are in handled statement -- sequence and want to do the insertion right there. diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb index 2d79edfeca9..a4d01c9f8ba 100644 --- a/gcc/ada/gnat1drv.adb +++ b/gcc/ada/gnat1drv.adb @@ -328,12 +328,17 @@ procedure Gnat1drv is Exception_Mechanism := Back_End_Exceptions; end if; - -- Set proper status for overflow checks. If already set (by -gnato or - -- -gnatp) then we have nothing to do. + -- Set proper status for overflow checks + + -- If already set (by - gnato or -gnatp) then we have nothing to do if Opt.Suppress_Options.Overflow_Checks_General /= Not_Set then null; + -- Otherwise set appropriate default mode. Note: at present we set + -- SUPPRESSED in all three of the following cases. They are separated + -- because in the future we may make different choices. + -- By default suppress overflow checks in -gnatg mode elsif GNAT_Mode then @@ -341,16 +346,18 @@ procedure Gnat1drv is Suppress_Options.Overflow_Checks_Assertions := Suppressed; -- If we have backend divide and overflow checks, then by default - -- overflow checks are minimized, which is a reasonable setting. + -- overflow checks are suppressed. Historically this code used to + -- activate overflow checks, although no target currently has these + -- flags set, so this was dead code anyway. elsif Targparm.Backend_Divide_Checks_On_Target and Targparm.Backend_Overflow_Checks_On_Target then - Suppress_Options.Overflow_Checks_General := Minimized; - Suppress_Options.Overflow_Checks_Assertions := Minimized; + Suppress_Options.Overflow_Checks_General := Suppressed; + Suppress_Options.Overflow_Checks_Assertions := Suppressed; - -- Otherwise for now, default is checks are suppressed. This is likely + -- Otherwise for now, default is checks are suppressed. This is subject -- to change in the future, but for now this is the compatible behavior -- with previous versions of GNAT. diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 45c02d84b18..b94f035ba91 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -28212,10 +28212,16 @@ success. It should be possible to use @code{GetLastError} and features are not used, but it is not guaranteed to work. @item -It is not possible to link against Microsoft libraries except for +It is not possible to link against Microsoft C++ libraries except for import libraries. Interfacing must be done by the mean of DLLs. @item +It is possible to link against Microsoft C libraries. Yet the preferred +solution is to use C/C++ compiler that comes with @value{EDITION}, since it +doesn't require having two different development environments and makes the +inter-language debugging experience smoother. + +@item When the compilation environment is located on FAT32 drives, users may experience recompilations of the source files that have not changed if Daylight Saving Time (DST) state has changed since the last time files @@ -28302,14 +28308,14 @@ application that contains a mix of Ada and C/C++, the choice of your Windows C/C++ development environment conditions your overall interoperability strategy. -If you use @command{gcc} to compile the non-Ada part of your application, -there are no Windows-specific restrictions that affect the overall -interoperability with your Ada code. If you do want to use the -Microsoft tools for your non-Ada code, you have two choices: +If you use @command{gcc} or Microsoft C to compile the non-Ada part of +your application, there are no Windows-specific restrictions that +affect the overall interoperability with your Ada code. If you do want +to use the Microsoft tools for your C++ code, you have two choices: @enumerate @item -Encapsulate your non-Ada code in a DLL to be linked with your Ada +Encapsulate your C++ code in a DLL to be linked with your Ada application. In this case, use the Microsoft or whatever environment to build the DLL and use GNAT to build your executable (@pxref{Using DLLs with GNAT}). diff --git a/gcc/ada/osint.adb b/gcc/ada/osint.adb index af355a16a26..8765b4cb60e 100644 --- a/gcc/ada/osint.adb +++ b/gcc/ada/osint.adb @@ -1658,7 +1658,7 @@ package body Osint is -- Start off by setting all suppress options, to False. The special -- overflow fields are set to Not_Set (they will be set by -gnatp, or -- by -gnato, or, if neither of these appear, in Adjust_Global_Switches - -- in Gnat1drv. + -- in Gnat1drv). Suppress_Options := ((others => False), Not_Set, Not_Set); diff --git a/gcc/ada/s-spsufi.adb b/gcc/ada/s-spsufi.adb index 86b18aad7df..ef2c935f341 100644 --- a/gcc/ada/s-spsufi.adb +++ b/gcc/ada/s-spsufi.adb @@ -2,12 +2,11 @@ -- -- -- GNAT COMPILER COMPONENTS -- -- -- --- S Y S T E M . S T O R A G E _ P O O L S . S U B P O O L S . -- --- F I N A L I Z A T I O N -- +-- SYSTEM.STORAGE_POOLS.SUBPOOLS.FINALIZATION -- -- -- -- B o d y -- -- -- --- Copyright (C) 2011, Free Software Foundation, Inc. -- +-- Copyright (C) 2011-2012, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -30,6 +29,10 @@ -- -- ------------------------------------------------------------------------------ +with Ada.Unchecked_Deallocation; + +with System.Finalization_Masters; use System.Finalization_Masters; + package body System.Storage_Pools.Subpools.Finalization is ----------------------------- @@ -37,6 +40,8 @@ package body System.Storage_Pools.Subpools.Finalization is ----------------------------- procedure Finalize_And_Deallocate (Subpool : in out Subpool_Handle) is + procedure Free is new Ada.Unchecked_Deallocation (SP_Node, SP_Node_Ptr); + begin -- Do nothing if the subpool was never created or never used. The latter -- case may arise with an array of subpool implementations. @@ -48,9 +53,18 @@ package body System.Storage_Pools.Subpools.Finalization is return; end if; - -- Clean up all controlled objects allocated through the subpool + -- Clean up all controlled objects chained on the subpool's master + + Finalize (Subpool.Master); + + -- Remove the subpool from its owner's list of subpools + + Detach (Subpool.Node); + + -- Destroy the associated doubly linked list node which was created in + -- Set_Pool_Of_Subpools. - Finalize_Subpool (Subpool); + Free (Subpool.Node); -- Dispatch to the user-defined implementation of Deallocate_Subpool diff --git a/gcc/ada/s-spsufi.ads b/gcc/ada/s-spsufi.ads index 66aac4b07a9..1de738b6f84 100644 --- a/gcc/ada/s-spsufi.ads +++ b/gcc/ada/s-spsufi.ads @@ -2,12 +2,11 @@ -- -- -- GNAT COMPILER COMPONENTS -- -- -- --- S Y S T E M . S T O R A G E _ P O O L S . S U B P O O L S . -- --- F I N A L I Z A T I O N -- +-- SYSTEM.STORAGE_POOLS.SUBPOOLS.FINALIZATION -- -- -- -- S p e c -- -- -- --- Copyright (C) 2011, Free Software Foundation, Inc. -- +-- Copyright (C) 2011-2012, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -34,6 +33,11 @@ pragma Compiler_Unit; package System.Storage_Pools.Subpools.Finalization is + -- The pragma is needed because package System.Storage_Pools.Subpools which + -- is already preelaborated now depends on this unit. + + pragma Preelaborate; + procedure Finalize_And_Deallocate (Subpool : in out Subpool_Handle); -- This routine performs the following actions: -- 1) Finalize all objects chained on the subpool's master diff --git a/gcc/ada/s-stposu.adb b/gcc/ada/s-stposu.adb index 7838e48d8e8..cf43f2232d3 100644 --- a/gcc/ada/s-stposu.adb +++ b/gcc/ada/s-stposu.adb @@ -29,15 +29,18 @@ -- -- ------------------------------------------------------------------------------ -with Ada.Exceptions; use Ada.Exceptions; +with Ada.Exceptions; use Ada.Exceptions; with Ada.Unchecked_Conversion; -with Ada.Unchecked_Deallocation; + with System.Address_Image; with System.Finalization_Masters; use System.Finalization_Masters; with System.IO; use System.IO; with System.Soft_Links; use System.Soft_Links; with System.Storage_Elements; use System.Storage_Elements; +with System.Storage_Pools.Subpools.Finalization; +use System.Storage_Pools.Subpools.Finalization; + package body System.Storage_Pools.Subpools is Finalize_Address_Table_In_Use : Boolean := False; @@ -51,11 +54,6 @@ package body System.Storage_Pools.Subpools is procedure Attach (N : not null SP_Node_Ptr; L : not null SP_Node_Ptr); -- Attach a subpool node to a pool - procedure Free is new Ada.Unchecked_Deallocation (SP_Node, SP_Node_Ptr); - - procedure Detach (N : not null SP_Node_Ptr); - -- Unhook a subpool node from an arbitrary subpool list - ----------------------------------- -- Adjust_Controlled_Dereference -- ----------------------------------- @@ -544,9 +542,10 @@ package body System.Storage_Pools.Subpools is -- 2) Remove the the subpool from the owner's list of subpools -- 3) Deallocate the doubly linked list node associated with the -- subpool. + -- 4) Call Deallocate_Subpool begin - Finalize_Subpool (Curr_Ptr.Subpool); + Finalize_And_Deallocate (Curr_Ptr.Subpool); exception when Fin_Occur : others => @@ -565,32 +564,6 @@ package body System.Storage_Pools.Subpools is end if; end Finalize_Pool; - ---------------------- - -- Finalize_Subpool -- - ---------------------- - - procedure Finalize_Subpool (Subpool : not null Subpool_Handle) is - begin - -- Do nothing if the subpool was never used - - if Subpool.Owner = null or else Subpool.Node = null then - return; - end if; - - -- Clean up all controlled objects chained on the subpool's master - - Finalize (Subpool.Master); - - -- Remove the subpool from its owner's list of subpools - - Detach (Subpool.Node); - - -- Destroy the associated doubly linked list node which was created in - -- Set_Pool_Of_Subpool. - - Free (Subpool.Node); - end Finalize_Subpool; - ------------------------------ -- Header_Size_With_Padding -- ------------------------------ diff --git a/gcc/ada/s-stposu.ads b/gcc/ada/s-stposu.ads index 40fe676bdaf..c80dd9e3446 100644 --- a/gcc/ada/s-stposu.ads +++ b/gcc/ada/s-stposu.ads @@ -325,6 +325,9 @@ private -- is controlled. When set to True, the machinery generates additional -- data. + procedure Detach (N : not null SP_Node_Ptr); + -- Unhook a subpool node from an arbitrary subpool list + overriding procedure Finalize (Controller : in out Pool_Controller); -- Buffer routine, calls Finalize_Pool @@ -333,11 +336,6 @@ private -- their masters. This action first detaches a controlled object from a -- particular master, then invokes its Finalize_Address primitive. - procedure Finalize_Subpool (Subpool : not null Subpool_Handle); - -- Finalize all controlled objects chained on Subpool's master. Remove the - -- subpool from its owner's list. Deallocate the associated doubly linked - -- list node. - function Header_Size_With_Padding (Alignment : System.Storage_Elements.Storage_Count) return System.Storage_Elements.Storage_Count; diff --git a/gcc/ada/s-tassta.adb b/gcc/ada/s-tassta.adb index 57c28be4ee5..08886c157bb 100644 --- a/gcc/ada/s-tassta.adb +++ b/gcc/ada/s-tassta.adb @@ -1905,7 +1905,16 @@ package body System.Tasking.Stages is C := All_Tasks_List; P := null; while C /= null loop - if C.Common.Parent = Self_ID and then C.Master_of_Task >= CM then + + -- If Free_On_Termination is set, do nothing here, and let the + -- task free itself if not already done, otherwise we risk a race + -- condition where Vulnerable_Free_Task is called in the loop below, + -- while the task calls Free_Task itself, in Terminate_Task. + + if C.Common.Parent = Self_ID + and then C.Master_of_Task >= CM + and then not C.Free_On_Termination + then if P /= null then P.Common.All_Tasks_Link := C.Common.All_Tasks_Link; else @@ -2088,9 +2097,7 @@ package body System.Tasking.Stages is -- is called from Expunge_Unactivated_Tasks. -- For tasks created by elaboration of task object declarations it is - -- called from the finalization code of the Task_Wrapper procedure. It is - -- also called from Ada.Unchecked_Deallocation, for objects that are or - -- contain tasks. + -- called from the finalization code of the Task_Wrapper procedure. procedure Vulnerable_Free_Task (T : Task_Id) is begin diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index d75b70b68d2..521eb80b174 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -4902,6 +4902,48 @@ package body Sem_Ch13 is end if; end Analyze_Record_Representation_Clause; + ------------------------------------------- + -- Build_Invariant_Procedure_Declaration -- + ------------------------------------------- + + function Build_Invariant_Procedure_Declaration + (Typ : Entity_Id) return Node_Id + is + Loc : constant Source_Ptr := Sloc (Typ); + Object_Entity : constant Entity_Id := + Make_Defining_Identifier (Loc, New_Internal_Name ('I')); + Spec : Node_Id; + SId : Entity_Id; + + begin + Set_Etype (Object_Entity, Typ); + + -- Check for duplicate definiations. + + if Has_Invariants (Typ) + and then Present (Invariant_Procedure (Typ)) + then + return Empty; + end if; + + SId := Make_Defining_Identifier (Loc, + Chars => New_External_Name (Chars (Typ), "Invariant")); + Set_Has_Invariants (SId); + Set_Has_Invariants (Typ); + Set_Ekind (SId, E_Procedure); + Set_Invariant_Procedure (Typ, SId); + + Spec := + Make_Procedure_Specification (Loc, + Defining_Unit_Name => SId, + Parameter_Specifications => New_List ( + Make_Parameter_Specification (Loc, + Defining_Identifier => Object_Entity, + Parameter_Type => New_Occurrence_Of (Typ, Loc)))); + + return Make_Subprogram_Declaration (Loc, Specification => Spec); + end Build_Invariant_Procedure_Declaration; + ------------------------------- -- Build_Invariant_Procedure -- ------------------------------- @@ -4936,12 +4978,11 @@ package body Sem_Ch13 is -- "inherited" to the exception message and generating an informational -- message about the inheritance of an invariant. - Object_Name : constant Name_Id := New_Internal_Name ('I'); + Object_Name : Name_Id; -- Name for argument of invariant procedure - Object_Entity : constant Node_Id := - Make_Defining_Identifier (Loc, Object_Name); - -- The procedure declaration entity for the argument + Object_Entity : Node_Id; + -- The entity of the formal for the procedure -------------------- -- Add_Invariants -- @@ -5140,7 +5181,29 @@ package body Sem_Ch13 is Stmts := No_List; PDecl := Empty; PBody := Empty; - Set_Etype (Object_Entity, Typ); + SId := Empty; + + -- If the aspect specification exists for some view of the type, the + -- declaration for the procedure has been created. + + if Has_Invariants (Typ) then + SId := Invariant_Procedure (Typ); + end if; + + if Present (SId) then + PDecl := Unit_Declaration_Node (SId); + + else + PDecl := Build_Invariant_Procedure_Declaration (Typ); + end if; + + -- Recover formal of procedure, for use in the calls to invariant + -- functions (including inherited ones). + + Object_Entity := + Defining_Identifier + (First (Parameter_Specifications (Specification (PDecl)))); + Object_Name := Chars (Object_Entity); -- Add invariants for the current type @@ -5174,38 +5237,7 @@ package body Sem_Ch13 is if Stmts /= No_List then - -- Build procedure declaration - - SId := - Make_Defining_Identifier (Loc, - Chars => New_External_Name (Chars (Typ), "Invariant")); - Set_Has_Invariants (SId); - Set_Invariant_Procedure (Typ, SId); - - Spec := - Make_Procedure_Specification (Loc, - Defining_Unit_Name => SId, - Parameter_Specifications => New_List ( - Make_Parameter_Specification (Loc, - Defining_Identifier => Object_Entity, - Parameter_Type => New_Occurrence_Of (Typ, Loc)))); - - PDecl := Make_Subprogram_Declaration (Loc, Specification => Spec); - - -- Build procedure body - - SId := - Make_Defining_Identifier (Loc, - Chars => New_External_Name (Chars (Typ), "Invariant")); - - Spec := - Make_Procedure_Specification (Loc, - Defining_Unit_Name => SId, - Parameter_Specifications => New_List ( - Make_Parameter_Specification (Loc, - Defining_Identifier => - Make_Defining_Identifier (Loc, Object_Name), - Parameter_Type => New_Occurrence_Of (Typ, Loc)))); + Spec := Copy_Separate_Tree (Specification (PDecl)); PBody := Make_Subprogram_Body (Loc, @@ -5216,14 +5248,18 @@ package body Sem_Ch13 is Statements => Stmts)); -- Insert procedure declaration and spec at the appropriate points. + -- If declaration is already analyzed, it was processed by the + -- generated pragma. if Present (Private_Decls) then -- The spec goes at the end of visible declarations, but they have -- already been analyzed, so we need to explicitly do the analyze. - Append_To (Visible_Decls, PDecl); - Analyze (PDecl); + if not Analyzed (PDecl) then + Append_To (Visible_Decls, PDecl); + Analyze (PDecl); + end if; -- The body goes at the end of the private declarations, which we -- have not analyzed yet, so we do not need to perform an explicit @@ -5523,6 +5559,7 @@ package body Sem_Ch13 is Make_Defining_Identifier (Loc, Chars => New_External_Name (Chars (Typ), "Predicate")); Set_Has_Predicates (SId); + Set_Ekind (SId, E_Function); Set_Predicate_Function (Typ, SId); -- The predicate function is shared between views of a type. diff --git a/gcc/ada/sem_ch13.ads b/gcc/ada/sem_ch13.ads index 0ac7386e878..611f3f1c617 100644 --- a/gcc/ada/sem_ch13.ads +++ b/gcc/ada/sem_ch13.ads @@ -46,6 +46,14 @@ package Sem_Ch13 is -- order is specified and there is at least one component clause. Adjusts -- component positions according to either Ada 95 or Ada 2005 (AI-133). + function Build_Invariant_Procedure_Declaration + (Typ : Entity_Id) return Node_Id; + -- If a type declaration has a specified invariant aspect, build the + -- declaration for the procedure at once, so that calls to it can be + -- generated before the body of the invariant procedure is built. This + -- is needed in the presence of public expression functions that return + -- the type in question. + procedure Build_Invariant_Procedure (Typ : Entity_Id; N : Node_Id); -- Typ is a private type with invariants (indicated by Has_Invariants being -- set for Typ, indicating the presence of pragma Invariant entries on the diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb index 326219d1fc6..a25e3283338 100644 --- a/gcc/ada/sem_ch7.adb +++ b/gcc/ada/sem_ch7.adb @@ -28,6 +28,7 @@ -- handling of private and full declarations, and the construction of dispatch -- tables for tagged types. +with Aspects; use Aspects; with Atree; use Atree; with Debug; use Debug; with Einfo; use Einfo; @@ -1387,7 +1388,23 @@ package body Sem_Ch7 is and then Nkind (Parent (E)) = N_Full_Type_Declaration and then Has_Aspects (Parent (E)) then - Build_Invariant_Procedure (E, N); + declare + ASN : Node_Id; + + begin + ASN := First (Aspect_Specifications (Parent (E))); + while Present (ASN) loop + if Chars (Identifier (ASN)) = Name_Invariant + or else + Chars (Identifier (ASN)) = Name_Type_Invariant + then + Build_Invariant_Procedure (E, N); + exit; + end if; + + Next (ASN); + end loop; + end; end if; Next_Entity (E); @@ -2143,6 +2160,14 @@ package body Sem_Ch7 is Set_Freeze_Node (Priv, Freeze_Node (Full)); + -- Propagate information of type invariants, which may be specified + -- for the full view. + + if Has_Invariants (Full) and not Has_Invariants (Priv) then + Set_Has_Invariants (Priv); + Set_Subprograms_For_Type (Priv, Subprograms_For_Type (Full)); + end if; + if Is_Tagged_Type (Priv) and then Is_Tagged_Type (Full) and then not Error_Posted (Full) diff --git a/gcc/ada/sem_dim.adb b/gcc/ada/sem_dim.adb index afe7d85ae6a..9b9de0a102b 100644 --- a/gcc/ada/sem_dim.adb +++ b/gcc/ada/sem_dim.adb @@ -1629,6 +1629,15 @@ package body Sem_Dim is Formal := First_Formal (Nam); while Present (Formal) loop + + -- A missing corresponding actual indicates that the analysis of + -- the call was aborted due to a previous error. + + if No (Actual) then + Cascaded_Error; + return; + end if; + Formal_Typ := Etype (Formal); Dims_Of_Formal := Dimensions_Of (Formal_Typ); diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index 258ec5b1685..2c9d518f670 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -10329,6 +10329,7 @@ package body Sem_Prag is when Pragma_Invariant => Invariant : declare Type_Id : Node_Id; Typ : Entity_Id; + PDecl : Node_Id; Discard : Boolean; pragma Unreferenced (Discard); @@ -10380,8 +10381,13 @@ package body Sem_Prag is -- Note that the type has at least one invariant, and also that -- it has inheritable invariants if we have Invariant'Class. + -- Build the corresponding invariant procedure declaration, so + -- that calls to it can be generated before the body is built + -- (for example wihin an expression function). - Set_Has_Invariants (Typ); + PDecl := Build_Invariant_Procedure_Declaration (Typ); + Insert_After (N, PDecl); + Analyze (PDecl); if Class_Present (N) then Set_Has_Inheritable_Invariants (Typ); @@ -11798,8 +11804,16 @@ package body Sem_Prag is Check_Optional_Identifier (Arg, Name); Check_Arg_Is_Identifier (Argx); + -- Do not suppress overflow checks for formal verification. + -- Instead, require that a check is inserted so that formal + -- verification can detect wraparound errors. + if Chars (Argx) = Name_Suppressed then - return Suppressed; + if Alfa_Mode then + return Checked; + else + return Suppressed; + end if; elsif Chars (Argx) = Name_Checked then return Checked; @@ -12116,6 +12130,11 @@ package body Sem_Prag is Ent := Entity (Get_Pragma_Arg (Arg1)); Decl := Parent (Ent); + -- Check for duplication before inserting in list of + -- representation items. + + Check_Duplicate_Pragma (Ent); + if Rep_Item_Too_Late (Ent, N) then return; end if; @@ -12131,8 +12150,6 @@ package body Sem_Prag is Arg1); end if; - Check_Duplicate_Pragma (Ent); - Prag := Make_Linker_Section_Pragma (Ent, Sloc (N), ".persistent.bss"); diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 2202c886766..1c9eb645555 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -13622,7 +13622,9 @@ package body Sem_Util is function Has_One_Matching_Field return Boolean; -- Determines if Expec_Type is a record type with a single component or -- discriminant whose type matches the found type or is one dimensional - -- array whose component type matches the found type. + -- array whose component type matches the found type. In the case of + -- one discriminant, we ignore the variant parts. That's not accurate, + -- but good enough for the warning. ---------------------------- -- Has_One_Matching_Field -- @@ -13664,10 +13666,10 @@ package body Sem_Util is if No (E) then return False; - elsif (Ekind (E) /= E_Discriminant - and then Ekind (E) /= E_Component) + elsif not Ekind_In (E, E_Discriminant, E_Component) or else (Chars (E) = Name_uTag - or else Chars (E) = Name_uParent) + or else + Chars (E) = Name_uParent) then Next_Entity (E); @@ -13679,7 +13681,10 @@ package body Sem_Util is if not Covers (Etype (E), Found_Type) then return False; - elsif Present (Next_Entity (E)) then + elsif Present (Next_Entity (E)) + and then (Ekind (E) = E_Component + or else Ekind (Next_Entity (E)) = E_Discriminant) + then return False; else diff --git a/gcc/ada/switch-c.adb b/gcc/ada/switch-c.adb index 7dbbd8a86b6..2a96c06d11a 100644 --- a/gcc/ada/switch-c.adb +++ b/gcc/ada/switch-c.adb @@ -53,7 +53,7 @@ package body Switch.C is function Get_Overflow_Mode (C : Character) return Overflow_Check_Type; -- Given a digit in the range 0 .. 3, returns the corresponding value of - -- Overflow_Check_Type. Raises program error if C is outside this range. + -- Overflow_Check_Type. Raises Program_Error if C is outside this range. function Switch_Subsequently_Cancelled (C : String; @@ -867,11 +867,11 @@ package body Switch.C is then Suppress_Options.Suppress (J) := True; end if; - - Suppress_Options.Overflow_Checks_General := Suppressed; - Suppress_Options.Overflow_Checks_Assertions := Suppressed; end loop; + Suppress_Options.Overflow_Checks_General := Suppressed; + Suppress_Options.Overflow_Checks_Assertions := Suppressed; + Validity_Checks_On := False; Opt.Suppress_Checks := True; end if; diff --git a/gcc/attribs.c b/gcc/attribs.c index d3af4141f4e..b330f27d89d 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -38,9 +38,6 @@ along with GCC; see the file COPYING3. If not see searched. */ static const struct attribute_spec *attribute_tables[4]; -/* Hashtable mapping names (represented as substrings) to attribute specs. */ -static htab_t attribute_hash; - /* Substring representation. */ struct substring @@ -49,6 +46,28 @@ struct substring int length; }; +DEF_VEC_O (attribute_spec); +DEF_VEC_ALLOC_O (attribute_spec, heap); + +/* Scoped attribute name representation. */ + +struct scoped_attributes +{ + const char *ns; + VEC (attribute_spec, heap) *attributes; + htab_t attribute_hash; +}; + +DEF_VEC_O (scoped_attributes); +DEF_VEC_ALLOC_O (scoped_attributes, heap); + +/* The table of scope attributes. */ +static VEC(scoped_attributes, heap) *attributes_table; + +static scoped_attributes* find_attribute_namespace (const char*); +static void register_scoped_attribute (const struct attribute_spec *, + scoped_attributes *); + static bool attributes_initialized = false; /* Default empty table of attributes. */ @@ -102,6 +121,64 @@ eq_attr (const void *p, const void *q) return (!strncmp (spec->name, str->str, str->length) && !spec->name[str->length]); } +/* Insert an array of attributes ATTRIBUTES into a namespace. This + array must be NULL terminated. NS is the name of attribute + namespace. The function returns the namespace into which the + attributes have been registered. */ + +scoped_attributes* +register_scoped_attributes (const struct attribute_spec * attributes, + const char* ns) +{ + scoped_attributes *result = NULL; + + /* See if we already have attributes in the namespace NS. */ + result = find_attribute_namespace (ns); + + if (result == NULL) + { + /* We don't have any namespace NS yet. Create one. */ + scoped_attributes sa; + + if (attributes_table == NULL) + attributes_table = VEC_alloc (scoped_attributes, heap, 64); + + memset (&sa, 0, sizeof (sa)); + sa.ns = ns; + sa.attributes = VEC_alloc (attribute_spec, heap, 64); + result = VEC_safe_push (scoped_attributes, heap, attributes_table, sa); + } + + /* Really add the attributes to their namespace now. */ + for (unsigned i = 0; attributes[i].name != NULL; ++i) + { + VEC_safe_push (attribute_spec, heap, + result->attributes, attributes[i]); + register_scoped_attribute (&attributes[i], result); + } + + gcc_assert (result != NULL); + + return result; +} + +/* Return the namespace which name is NS, NULL if none exist. */ + +static scoped_attributes* +find_attribute_namespace (const char* ns) +{ + unsigned ix; + scoped_attributes *iter; + + FOR_EACH_VEC_ELT (scoped_attributes, attributes_table, ix, iter) + if (ns == iter->ns + || (iter->ns != NULL + && ns != NULL + && !strcmp (iter->ns, ns))) + return iter; + return NULL; +} + /* Initialize attribute tables, and make some sanity checks if --enable-checking. */ @@ -109,7 +186,6 @@ void init_attributes (void) { size_t i; - int k; if (attributes_initialized) return; @@ -181,12 +257,10 @@ init_attributes (void) } #endif - attribute_hash = htab_create (200, hash_attr, eq_attr, NULL); - for (i = 0; i < ARRAY_SIZE (attribute_tables); i++) - for (k = 0; attribute_tables[i][k].name != NULL; k++) - { - register_attribute (&attribute_tables[i][k]); - } + for (i = 0; i < ARRAY_SIZE (attribute_tables); ++i) + /* Put all the GNU attributes into the "gnu" namespace. */ + register_scoped_attributes (attribute_tables[i], "gnu"); + invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL); attributes_initialized = true; } @@ -196,9 +270,23 @@ init_attributes (void) void register_attribute (const struct attribute_spec *attr) { + register_scoped_attribute (attr, find_attribute_namespace ("gnu")); +} + +/* Insert a single attribute ATTR into a namespace of attributes. */ + +static void +register_scoped_attribute (const struct attribute_spec *attr, + scoped_attributes *name_space) +{ struct substring str; void **slot; + gcc_assert (attr != NULL && name_space != NULL); + + if (name_space->attribute_hash == NULL) + name_space->attribute_hash = htab_create (200, hash_attr, eq_attr, NULL); + str.str = attr->name; str.length = strlen (str.str); @@ -206,27 +294,45 @@ register_attribute (const struct attribute_spec *attr) in the form '__text__'. */ gcc_assert (str.length > 0 && str.str[0] != '_'); - slot = htab_find_slot_with_hash (attribute_hash, &str, + slot = htab_find_slot_with_hash (name_space->attribute_hash, &str, substring_hash (str.str, str.length), INSERT); gcc_assert (!*slot || attr->name[0] == '*'); *slot = (void *) CONST_CAST (struct attribute_spec *, attr); } -/* Return the spec for the attribute named NAME. */ +/* Return the spec for the scoped attribute with namespace NS and + name NAME. */ const struct attribute_spec * -lookup_attribute_spec (const_tree name) +lookup_scoped_attribute_spec (const_tree ns, const_tree name) { struct substring attr; + scoped_attributes *attrs; + + const char *ns_str = (ns != NULL_TREE) ? IDENTIFIER_POINTER (ns): NULL; + + attrs = find_attribute_namespace (ns_str); + + if (attrs == NULL) + return NULL; attr.str = IDENTIFIER_POINTER (name); attr.length = IDENTIFIER_LENGTH (name); extract_attribute_substring (&attr); return (const struct attribute_spec *) - htab_find_with_hash (attribute_hash, &attr, + htab_find_with_hash (attrs->attribute_hash, &attr, substring_hash (attr.str, attr.length)); } + +/* Return the spec for the attribute named NAME. */ + +const struct attribute_spec * +lookup_attribute_spec (const_tree name) +{ + return lookup_scoped_attribute_spec (get_identifier ("gnu"), name); +} + /* Process the attributes listed in ATTRIBUTES and install them in *NODE, which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL, @@ -243,7 +349,7 @@ decl_attributes (tree *node, tree attributes, int flags) tree a; tree returned_attrs = NULL_TREE; - if (TREE_TYPE (*node) == error_mark_node) + if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node) return NULL_TREE; if (!attributes_initialized) @@ -302,10 +408,12 @@ decl_attributes (tree *node, tree attributes, int flags) for (a = attributes; a; a = TREE_CHAIN (a)) { - tree name = TREE_PURPOSE (a); + tree ns = get_attribute_namespace (a); + tree name = get_attribute_name (a); tree args = TREE_VALUE (a); tree *anode = node; - const struct attribute_spec *spec = lookup_attribute_spec (name); + const struct attribute_spec *spec = + lookup_scoped_attribute_spec (ns, name); bool no_add_attrs = 0; int fn_ptr_quals = 0; tree fn_ptr_tmp = NULL_TREE; @@ -313,8 +421,15 @@ decl_attributes (tree *node, tree attributes, int flags) if (spec == NULL) { if (!(flags & (int) ATTR_FLAG_BUILT_IN)) - warning (OPT_Wattributes, "%qE attribute directive ignored", - name); + { + if (ns == NULL_TREE || !cxx11_attribute_p (a)) + warning (OPT_Wattributes, "%qE attribute directive ignored", + name); + else + warning (OPT_Wattributes, + "%<%E::%E%> scoped attribute directive ignored", + ns, name); + } continue; } else if (list_length (args) < spec->min_length @@ -327,6 +442,20 @@ decl_attributes (tree *node, tree attributes, int flags) } gcc_assert (is_attribute_p (spec->name, name)); + if (TYPE_P (*node) + && cxx11_attribute_p (a) + && !(flags & ATTR_FLAG_TYPE_IN_PLACE)) + { + /* This is a c++11 attribute that appertains to a + type-specifier, outside of the definition of, a class + type. Ignore it. */ + warning (OPT_Wattributes, "attribute ignored"); + inform (input_location, + "an attribute that appertains to a type-specifier " + "is ignored"); + continue; + } + if (spec->decl_required && !DECL_P (*anode)) { if (flags & ((int) ATTR_FLAG_DECL_NEXT @@ -406,9 +535,15 @@ decl_attributes (tree *node, tree attributes, int flags) } if (spec->handler != NULL) - returned_attrs = chainon ((*spec->handler) (anode, name, args, - flags, &no_add_attrs), - returned_attrs); + { + int cxx11_flag = + cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0; + + returned_attrs = chainon ((*spec->handler) (anode, name, args, + flags|cxx11_flag, + &no_add_attrs), + returned_attrs); + } /* Layout the decl in case anything changed. */ if (spec->type_required && DECL_P (*node) @@ -488,6 +623,56 @@ decl_attributes (tree *node, tree attributes, int flags) return returned_attrs; } +/* Return TRUE iff ATTR has been parsed by the front-end as a C++-11 + attribute. + + When G++ parses a C++11 attribute, it is represented as + a TREE_LIST which TREE_PURPOSE is itself a TREE_LIST. TREE_PURPOSE + (TREE_PURPOSE (ATTR)) is the namespace of the attribute, and the + TREE_VALUE (TREE_PURPOSE (ATTR)) is its non-qualified name. Please + use get_attribute_namespace and get_attribute_name to retrieve the + namespace and name of the attribute, as these accessors work with + GNU attributes as well. */ + +bool +cxx11_attribute_p (const_tree attr) +{ + if (attr == NULL_TREE + || TREE_CODE (attr) != TREE_LIST) + return false; + + return (TREE_CODE (TREE_PURPOSE (attr)) == TREE_LIST); +} + +/* Return the name of the attribute ATTR. This accessor works on GNU + and C++11 (scoped) attributes. + + Please read the comments of cxx11_attribute_p to understand the + format of attributes. */ + +tree +get_attribute_name (const_tree attr) +{ + if (cxx11_attribute_p (attr)) + return TREE_VALUE (TREE_PURPOSE (attr)); + return TREE_PURPOSE (attr); +} + +/* Return the namespace of the attribute ATTR. This accessor works on + GNU and C++11 (scoped) attributes. On GNU attributes, + it returns an identifier tree for the string "gnu". + + Please read the comments of cxx11_attribute_p to understand the + format of attributes. */ + +tree +get_attribute_namespace (const_tree attr) +{ + if (cxx11_attribute_p (attr)) + return TREE_PURPOSE (TREE_PURPOSE (attr)); + return get_identifier ("gnu"); +} + /* Subroutine of set_method_tm_attributes. Apply TM attribute ATTR to the method FNDECL. */ diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 0d112cfe7a7..b49388df86d 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,15 @@ +2012-10-08 Dodji Seketeli <dodji@redhat.com> + + PR c++/53528 C++11 attribute support + * c-common.h (bitfield_p, cxx_fundamental_alignment_p): Declare + new functions. + * c-common.c (check_cxx_fundamental_alignment_constraints): New + static function. + (handle_aligned_attribute): In choose strictest alignment + among many. Use new check_cxx_fundamental_alignment_constraints. + (handle_transparent_union_attribute): In c++11 attribute syntax, + don't look through typedefs. + 2012-10-04 Arnaud Charlet <charlet@adacore.com> * c-ada-spec.c (print_ada_declaration): Remove handling of TDF_RAW. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 6de2f1c81fd..e24278951da 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -484,6 +484,7 @@ const struct c_common_resword c_common_reswords[] = { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY }, { "__volatile", RID_VOLATILE, 0 }, { "__volatile__", RID_VOLATILE, 0 }, + { "alignas", RID_ALIGNAS, D_CXXONLY | D_CXX0X | D_CXXWARN }, { "alignof", RID_ALIGNOF, D_CXXONLY | D_CXX0X | D_CXXWARN }, { "asm", RID_ASM, D_ASM }, { "auto", RID_AUTO, 0 }, @@ -6665,7 +6666,9 @@ handle_transparent_union_attribute (tree *node, tree name, *no_add_attrs = true; - if (TREE_CODE (*node) == TYPE_DECL) + + if (TREE_CODE (*node) == TYPE_DECL + && ! (flags & ATTR_FLAG_CXX11)) node = &TREE_TYPE (*node); type = *node; @@ -7137,6 +7140,89 @@ check_user_alignment (const_tree align, bool allow_zero) return i; } +/* + If in c++-11, check if the c++-11 alignment constraint with respect + to fundamental alignment (in [dcl.align]) are satisfied. If not in + c++-11 mode, does nothing. + + [dcl.align]2/ says: + + [* if the constant expression evaluates to a fundamental alignment, + the alignment requirement of the declared entity shall be the + specified fundamental alignment. + + * if the constant expression evaluates to an extended alignment + and the implementation supports that alignment in the context + of the declaration, the alignment of the declared entity shall + be that alignment + + * if the constant expression evaluates to an extended alignment + and the implementation does not support that alignment in the + context of the declaration, the program is ill-formed]. */ + +static bool +check_cxx_fundamental_alignment_constraints (tree node, + unsigned align_log, + int flags) +{ + bool alignment_too_large_p = false; + unsigned requested_alignment = 1U << align_log; + unsigned max_align = 0; + + if ((!(flags & ATTR_FLAG_CXX11) && !warn_cxx_compat) + || (node == NULL_TREE || node == error_mark_node)) + return true; + + if (cxx_fundamental_alignment_p (requested_alignment)) + return true; + + if (DECL_P (node)) + { + if (TREE_STATIC (node)) + { + /* For file scope variables and static members, the target + supports alignments that are at most + MAX_OFILE_ALIGNMENT. */ + if (requested_alignment > (max_align = MAX_OFILE_ALIGNMENT)) + alignment_too_large_p = true; + } + else + { +#ifdef BIGGEST_FIELD_ALIGNMENT +#define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_FIELD_ALIGNMENT +#else +#define MAX_TARGET_FIELD_ALIGNMENT BIGGEST_ALIGNMENT +#endif + /* For non-static members, the target supports either + alignments that at most either BIGGEST_FIELD_ALIGNMENT + if it is defined or BIGGEST_ALIGNMENT. */ + max_align = MAX_TARGET_FIELD_ALIGNMENT; + if (TREE_CODE (node) == FIELD_DECL + && requested_alignment > (max_align = MAX_TARGET_FIELD_ALIGNMENT)) + alignment_too_large_p = true; +#undef MAX_TARGET_FIELD_ALIGNMENT + /* For stack variables, the target supports at most + MAX_STACK_ALIGNMENT. */ + else if (decl_function_context (node) != NULL + && requested_alignment > (max_align = MAX_STACK_ALIGNMENT)) + alignment_too_large_p = true; + } + } + else if (TYPE_P (node)) + { + /* Let's be liberal for types. */ + if (requested_alignment > (max_align = BIGGEST_ALIGNMENT)) + alignment_too_large_p = true; + } + + if (alignment_too_large_p) + pedwarn (input_location, OPT_Wattributes, + "requested alignment %d is larger than %d", + requested_alignment, max_align); + + return !alignment_too_large_p; +} + /* Handle a "aligned" attribute; arguments as in struct attribute_spec.handler. */ @@ -7160,7 +7246,8 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, else if (TYPE_P (*node)) type = node, is_type = 1; - if ((i = check_user_alignment (align_expr, false)) == -1) + if ((i = check_user_alignment (align_expr, false)) == -1 + || !check_cxx_fundamental_alignment_constraints (*node, i, flags)) *no_add_attrs = true; else if (is_type) { @@ -7190,6 +7277,17 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, error ("alignment may not be specified for %q+D", decl); *no_add_attrs = true; } + else if (DECL_USER_ALIGN (decl) + && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT) + /* C++-11 [dcl.align/4]: + + When multiple alignment-specifiers are specified for an + entity, the alignment requirement shall be set to the + strictest specified alignment. + + This formally comes from the c++11 specification but we are + doing it for the GNU attribute syntax as well. */ + *no_add_attrs = true; else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT) { @@ -11154,4 +11252,22 @@ convert_vector_to_pointer_for_subscript (location_t loc, } } +/* Return true iff ALIGN is an integral constant that is a fundamental + alignment, as defined by [basic.align] in the c++-11 + specifications. + + That is: + + [A fundamental alignment is represented by an alignment less than or + equal to the greatest alignment supported by the implementation + in all contexts, which is equal to + alignof(max_align_t)]. */ + +bool +cxx_fundamental_alignment_p (unsigned align) +{ + return (align <= MAX (TYPE_ALIGN (long_long_integer_type_node), + TYPE_ALIGN (long_double_type_node))); +} + #include "gt-c-family-c-common.h" diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index cefe92d9ee6..5b23bd3c2fa 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -789,6 +789,7 @@ extern bool keyword_begins_type_specifier (enum rid); extern bool keyword_is_storage_class_specifier (enum rid); extern bool keyword_is_type_qualifier (enum rid); extern bool keyword_is_decl_specifier (enum rid); +extern bool cxx_fundamental_alignment_p (unsigned); #define c_sizeof(LOC, T) c_sizeof_or_alignof_type (LOC, T, true, 1) #define c_alignof(LOC, T) c_sizeof_or_alignof_type (LOC, T, false, 1) diff --git a/gcc/common.opt b/gcc/common.opt index a427a1f68c6..5cd6b1a05bb 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1801,6 +1801,10 @@ fprofile-values Common Report Var(flag_profile_values) Insert code to profile values of expressions +fprofile-report +Common Report Var(profile_report) +Report on consistency of profile + frandom-seed Common Var(common_deferred_options) Defer diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index 8488ecd3e08..4925e0e1df0 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -57,7 +57,7 @@ enum #define TARGET_CPU_CPP_BUILTINS() avr_cpu_cpp_builtins (pfile) -#define AVR_HAVE_JMP_CALL (avr_current_arch->have_jmp_call && !TARGET_SHORT_CALLS) +#define AVR_HAVE_JMP_CALL (avr_current_arch->have_jmp_call) #define AVR_HAVE_MUL (avr_current_arch->have_mul) #define AVR_HAVE_MOVW (avr_current_arch->have_movw_lpmx) #define AVR_HAVE_LPMX (avr_current_arch->have_movw_lpmx) diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index d3ffd1aba41..8b071f02af1 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -1177,7 +1177,7 @@ ;; "*addhq3" "*adduhq3" ;; "*addha3" "*adduha3" (define_insn "*add<mode>3" - [(set (match_operand:ALL2 0 "register_operand" "=?r,d,!w ,d") + [(set (match_operand:ALL2 0 "register_operand" "=??r,d,!w ,d") (plus:ALL2 (match_operand:ALL2 1 "register_operand" "%0,0,0 ,0") (match_operand:ALL2 2 "nonmemory_or_const_operand" "r,s,IJ YIJ,n Ynn")))] "" @@ -1244,7 +1244,7 @@ ;; "addsq3" "addusq3" ;; "addsa3" "addusa3" (define_insn "add<mode>3" - [(set (match_operand:ALL4 0 "register_operand" "=r,d ,r") + [(set (match_operand:ALL4 0 "register_operand" "=??r,d ,r") (plus:ALL4 (match_operand:ALL4 1 "register_operand" "%0,0 ,0") (match_operand:ALL4 2 "nonmemory_operand" "r,i ,n Ynn"))) (clobber (match_scratch:QI 3 "=X,X ,&d"))] @@ -1302,7 +1302,7 @@ (set_attr "cc" "set_n")]) (define_insn "addpsi3" - [(set (match_operand:PSI 0 "register_operand" "=r,d ,d,r") + [(set (match_operand:PSI 0 "register_operand" "=??r,d ,d,r") (plus:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0,0") (match_operand:PSI 2 "nonmemory_operand" "r,s ,n,n"))) (clobber (match_scratch:QI 3 "=X,X ,X,&d"))] @@ -1356,7 +1356,7 @@ ;; "subqi3" ;; "subqq3" "subuqq3" (define_insn "sub<mode>3" - [(set (match_operand:ALL1 0 "register_operand" "=r,d ,r ,r ,r ,r") + [(set (match_operand:ALL1 0 "register_operand" "=??r,d ,r ,r ,r ,r") (minus:ALL1 (match_operand:ALL1 1 "register_operand" "0,0 ,0 ,0 ,0 ,0") (match_operand:ALL1 2 "nonmemory_or_const_operand" "r,n Ynn,Y01,Ym1,Y02,Ym2")))] "" @@ -1374,7 +1374,7 @@ ;; "subhq3" "subuhq3" ;; "subha3" "subuha3" (define_insn "sub<mode>3" - [(set (match_operand:ALL2 0 "register_operand" "=r,d ,*r") + [(set (match_operand:ALL2 0 "register_operand" "=??r,d ,*r") (minus:ALL2 (match_operand:ALL2 1 "register_operand" "0,0 ,0") (match_operand:ALL2 2 "nonmemory_or_const_operand" "r,i Ynn,Ynn"))) (clobber (match_scratch:QI 3 "=X,X ,&d"))] @@ -1411,7 +1411,7 @@ ;; "subsq3" "subusq3" ;; "subsa3" "subusa3" (define_insn "sub<mode>3" - [(set (match_operand:ALL4 0 "register_operand" "=r,d ,r") + [(set (match_operand:ALL4 0 "register_operand" "=??r,d ,r") (minus:ALL4 (match_operand:ALL4 1 "register_operand" "0,0 ,0") (match_operand:ALL4 2 "nonmemory_or_const_operand" "r,n Ynn,Ynn"))) (clobber (match_scratch:QI 3 "=X,X ,&d"))] @@ -2932,7 +2932,7 @@ ; and (define_insn "andqi3" - [(set (match_operand:QI 0 "register_operand" "=r,d") + [(set (match_operand:QI 0 "register_operand" "=??r,d") (and:QI (match_operand:QI 1 "register_operand" "%0,0") (match_operand:QI 2 "nonmemory_operand" "r,i")))] "" @@ -2943,7 +2943,7 @@ (set_attr "cc" "set_zn,set_zn")]) (define_insn "andhi3" - [(set (match_operand:HI 0 "register_operand" "=r,d,d,r ,r") + [(set (match_operand:HI 0 "register_operand" "=??r,d,d,r ,r") (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0 ,0") (match_operand:HI 2 "nonmemory_operand" "r,s,n,Ca2,n"))) (clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))] @@ -2961,7 +2961,7 @@ (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")]) (define_insn "andpsi3" - [(set (match_operand:PSI 0 "register_operand" "=r,d,r ,r") + [(set (match_operand:PSI 0 "register_operand" "=??r,d,r ,r") (and:PSI (match_operand:PSI 1 "register_operand" "%0,0,0 ,0") (match_operand:PSI 2 "nonmemory_operand" "r,n,Ca3,n"))) (clobber (match_scratch:QI 3 "=X,X,X ,&d"))] @@ -2979,7 +2979,7 @@ (set_attr "cc" "set_n,clobber,clobber,clobber")]) (define_insn "andsi3" - [(set (match_operand:SI 0 "register_operand" "=r,d,r ,r") + [(set (match_operand:SI 0 "register_operand" "=??r,d,r ,r") (and:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0") (match_operand:SI 2 "nonmemory_operand" "r,n,Ca4,n"))) (clobber (match_scratch:QI 3 "=X,X,X ,&d"))] @@ -3014,7 +3014,7 @@ ;; ior (define_insn "iorqi3" - [(set (match_operand:QI 0 "register_operand" "=r,d") + [(set (match_operand:QI 0 "register_operand" "=??r,d") (ior:QI (match_operand:QI 1 "register_operand" "%0,0") (match_operand:QI 2 "nonmemory_operand" "r,i")))] "" @@ -3025,7 +3025,7 @@ (set_attr "cc" "set_zn,set_zn")]) (define_insn "iorhi3" - [(set (match_operand:HI 0 "register_operand" "=r,d,d,r ,r") + [(set (match_operand:HI 0 "register_operand" "=??r,d,d,r ,r") (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0 ,0") (match_operand:HI 2 "nonmemory_operand" "r,s,n,Co2,n"))) (clobber (match_scratch:QI 3 "=X,X,X,X ,&d"))] @@ -3043,7 +3043,7 @@ (set_attr "cc" "set_n,set_n,clobber,clobber,clobber")]) (define_insn "iorpsi3" - [(set (match_operand:PSI 0 "register_operand" "=r,d,r ,r") + [(set (match_operand:PSI 0 "register_operand" "=??r,d,r ,r") (ior:PSI (match_operand:PSI 1 "register_operand" "%0,0,0 ,0") (match_operand:PSI 2 "nonmemory_operand" "r,n,Co3,n"))) (clobber (match_scratch:QI 3 "=X,X,X ,&d"))] @@ -3061,7 +3061,7 @@ (set_attr "cc" "set_n,clobber,clobber,clobber")]) (define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=r,d,r ,r") + [(set (match_operand:SI 0 "register_operand" "=??r,d,r ,r") (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0 ,0") (match_operand:SI 2 "nonmemory_operand" "r,n,Co4,n"))) (clobber (match_scratch:QI 3 "=X,X,X ,&d"))] @@ -3092,7 +3092,7 @@ (set_attr "cc" "set_zn")]) (define_insn "xorhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r ,r") + [(set (match_operand:HI 0 "register_operand" "=??r,r ,r") (xor:HI (match_operand:HI 1 "register_operand" "%0,0 ,0") (match_operand:HI 2 "nonmemory_operand" "r,Cx2,n"))) (clobber (match_scratch:QI 3 "=X,X ,&d"))] @@ -3108,7 +3108,7 @@ (set_attr "cc" "set_n,clobber,clobber")]) (define_insn "xorpsi3" - [(set (match_operand:PSI 0 "register_operand" "=r,r ,r") + [(set (match_operand:PSI 0 "register_operand" "=??r,r ,r") (xor:PSI (match_operand:PSI 1 "register_operand" "%0,0 ,0") (match_operand:PSI 2 "nonmemory_operand" "r,Cx3,n"))) (clobber (match_scratch:QI 3 "=X,X ,&d"))] @@ -3126,7 +3126,7 @@ (set_attr "cc" "set_n,clobber,clobber")]) (define_insn "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r ,r") + [(set (match_operand:SI 0 "register_operand" "=??r,r ,r") (xor:SI (match_operand:SI 1 "register_operand" "%0,0 ,0") (match_operand:SI 2 "nonmemory_operand" "r,Cx4,n"))) (clobber (match_scratch:QI 3 "=X,X ,&d"))] @@ -4167,13 +4167,13 @@ "reload_completed" [(set (match_dup 2) (match_dup 1)) (set (match_dup 3) (const_int 0))] -{ - unsigned int low_off = subreg_lowpart_offset (QImode, HImode); - unsigned int high_off = subreg_highpart_offset (QImode, HImode); + { + unsigned int low_off = subreg_lowpart_offset (QImode, HImode); + unsigned int high_off = subreg_highpart_offset (QImode, HImode); - operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, low_off); - operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, high_off); -}) + operands[2] = simplify_gen_subreg (QImode, operands[0], HImode, low_off); + operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, high_off); + }) (define_insn_and_split "zero_extendqipsi2" [(set (match_operand:PSI 0 "register_operand" "=r") @@ -4198,13 +4198,13 @@ "reload_completed" [(set (match_dup 2) (zero_extend:HI (match_dup 1))) (set (match_dup 3) (const_int 0))] -{ - unsigned int low_off = subreg_lowpart_offset (HImode, SImode); - unsigned int high_off = subreg_highpart_offset (HImode, SImode); + { + unsigned int low_off = subreg_lowpart_offset (HImode, SImode); + unsigned int high_off = subreg_highpart_offset (HImode, SImode); - operands[2] = simplify_gen_subreg (HImode, operands[0], SImode, low_off); - operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off); -}) + operands[2] = simplify_gen_subreg (HImode, operands[0], SImode, low_off); + operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off); + }) (define_insn_and_split "zero_extendhipsi2" [(set (match_operand:PSI 0 "register_operand" "=r") @@ -4248,13 +4248,13 @@ "reload_completed" [(set (match_dup 2) (match_dup 1)) (set (match_dup 3) (const_int 0))] -{ - unsigned int low_off = subreg_lowpart_offset (HImode, SImode); - unsigned int high_off = subreg_highpart_offset (HImode, SImode); + { + unsigned int low_off = subreg_lowpart_offset (HImode, SImode); + unsigned int high_off = subreg_highpart_offset (HImode, SImode); - operands[2] = simplify_gen_subreg (HImode, operands[0], SImode, low_off); - operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off); -}) + operands[2] = simplify_gen_subreg (HImode, operands[0], SImode, low_off); + operands[3] = simplify_gen_subreg (HImode, operands[0], SImode, high_off); + }) (define_insn_and_split "zero_extendpsisi2" [(set (match_operand:SI 0 "register_operand" "=r") @@ -4277,13 +4277,13 @@ "reload_completed" [(set (match_dup 2) (zero_extend:SI (match_dup 1))) (set (match_dup 3) (const_int 0))] -{ - unsigned int low_off = subreg_lowpart_offset (SImode, DImode); - unsigned int high_off = subreg_highpart_offset (SImode, DImode); + { + unsigned int low_off = subreg_lowpart_offset (SImode, DImode); + unsigned int high_off = subreg_highpart_offset (SImode, DImode); - operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off); - operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off); -}) + operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off); + operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off); + }) (define_insn_and_split "zero_extendhidi2" [(set (match_operand:DI 0 "register_operand" "=r") @@ -4293,13 +4293,13 @@ "reload_completed" [(set (match_dup 2) (zero_extend:SI (match_dup 1))) (set (match_dup 3) (const_int 0))] -{ - unsigned int low_off = subreg_lowpart_offset (SImode, DImode); - unsigned int high_off = subreg_highpart_offset (SImode, DImode); + { + unsigned int low_off = subreg_lowpart_offset (SImode, DImode); + unsigned int high_off = subreg_highpart_offset (SImode, DImode); - operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off); - operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off); -}) + operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off); + operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off); + }) (define_insn_and_split "zero_extendsidi2" [(set (match_operand:DI 0 "register_operand" "=r") @@ -4309,13 +4309,13 @@ "reload_completed" [(set (match_dup 2) (match_dup 1)) (set (match_dup 3) (const_int 0))] -{ - unsigned int low_off = subreg_lowpart_offset (SImode, DImode); - unsigned int high_off = subreg_highpart_offset (SImode, DImode); + { + unsigned int low_off = subreg_lowpart_offset (SImode, DImode); + unsigned int high_off = subreg_highpart_offset (SImode, DImode); - operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off); - operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off); -}) + operands[2] = simplify_gen_subreg (SImode, operands[0], DImode, low_off); + operands[3] = simplify_gen_subreg (SImode, operands[0], DImode, high_off); + }) ;;<=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=><=> ;; compare diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt index 10769e80e4c..35fca20c3a3 100644 --- a/gcc/config/avr/avr.opt +++ b/gcc/config/avr/avr.opt @@ -50,10 +50,6 @@ Target Report Undocumented Mask(ORDER_1) morder2 Target Report Undocumented Mask(ORDER_2) -mshort-calls -Target Report Mask(SHORT_CALLS) -Use rjmp/rcall (limited range) on >8K devices - mtiny-stack Target Report Mask(TINY_STACK) Change only the low 8 bits of the stack pointer diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index 38a922898e2..7ec13264a11 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -1,6 +1,6 @@ /* Subroutines for insn-output.c for Renesas H8/300. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Contributed by Steve Chamberlain (sac@cygnus.com), Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com). @@ -1244,7 +1244,7 @@ h8300_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED, *total = 0; return true; } - if (-4 <= n || n <= 4) + if (-4 <= n && n <= 4) { switch ((int) n) { diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 31be33edeb1..5f67831a8f5 100644 --- a/gcc/config/m68k/m68k.md +++ b/gcc/config/m68k/m68k.md @@ -3597,72 +3597,6 @@ ;; logical-and instructions -;; "anddi3" is mainly here to help combine(). -(define_insn "anddi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "=o,d") - (and:DI (match_operand:DI 1 "general_operand" "%0,0") - (match_operand:DI 2 "general_operand" "dn,don")))] - "!TARGET_COLDFIRE" -{ - CC_STATUS_INIT; - /* We can get CONST_DOUBLE, but also const1_rtx etc. */ - if (CONSTANT_P (operands[2])) - { - rtx hi, lo; - - split_double (operands[2], &hi, &lo); - - switch (INTVAL (hi)) - { - case 0 : - output_asm_insn ("clr%.l %0", operands); - break; - case -1 : - break; - default : - { - rtx xoperands[3]; - - xoperands[0] = operands[0]; - xoperands[2] = hi; - output_asm_insn (output_andsi3 (xoperands), xoperands); - } - } - if (GET_CODE (operands[0]) == REG) - operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); - else - operands[0] = adjust_address (operands[0], SImode, 4); - switch (INTVAL (lo)) - { - case 0 : - output_asm_insn ("clr%.l %0", operands); - break; - case -1 : - break; - default : - { - rtx xoperands[3]; - - xoperands[0] = operands[0]; - xoperands[2] = lo; - output_asm_insn (output_andsi3 (xoperands), xoperands); - } - } - return ""; - } - if (GET_CODE (operands[0]) != REG) - { - operands[1] = adjust_address (operands[0], SImode, 4); - return "and%.l %2,%0\;and%.l %R2,%1"; - } - if (GET_CODE (operands[2]) != REG) - { - operands[1] = adjust_address (operands[2], SImode, 4); - return "and%.l %2,%0\;and%.l %1,%R0"; - } - return "and%.l %2,%0\;and%.l %R2,%R0"; -}) - ;; Prevent AND from being made with sp. This doesn't exist in the machine ;; and reload will cause inefficient code. Since sp is a FIXED_REG, we ;; can't allocate pseudos into it. @@ -3780,76 +3714,6 @@ return "or%.w %1,%0"; }) -;; "iordi3" is mainly here to help combine(). -(define_insn "iordi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "=o,d") - (ior:DI (match_operand:DI 1 "general_operand" "%0,0") - (match_operand:DI 2 "general_operand" "dn,don")))] - "!TARGET_COLDFIRE" -{ - CC_STATUS_INIT; - /* We can get CONST_DOUBLE, but also const1_rtx etc. */ - if (CONSTANT_P (operands[2])) - { - rtx hi, lo; - - split_double (operands[2], &hi, &lo); - - switch (INTVAL (hi)) - { - case 0 : - break; - case -1 : - /* FIXME : a scratch register would be welcome here if operand[0] - is not a register */ - output_asm_insn ("move%.l #-1,%0", operands); - break; - default : - { - rtx xoperands[3]; - - xoperands[0] = operands[0]; - xoperands[2] = hi; - output_asm_insn (output_iorsi3 (xoperands), xoperands); - } - } - if (GET_CODE (operands[0]) == REG) - operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); - else - operands[0] = adjust_address (operands[0], SImode, 4); - switch (INTVAL (lo)) - { - case 0 : - break; - case -1 : - /* FIXME : a scratch register would be welcome here if operand[0] - is not a register */ - output_asm_insn ("move%.l #-1,%0", operands); - break; - default : - { - rtx xoperands[3]; - - xoperands[0] = operands[0]; - xoperands[2] = lo; - output_asm_insn (output_iorsi3 (xoperands), xoperands); - } - } - return ""; - } - if (GET_CODE (operands[0]) != REG) - { - operands[1] = adjust_address (operands[0], SImode, 4); - return "or%.l %2,%0\;or%.l %R2,%1"; - } - if (GET_CODE (operands[2]) != REG) - { - operands[1] = adjust_address (operands[2], SImode, 4); - return "or%.l %2,%0\;or%.l %1,%R0"; - } - return "or%.l %2,%0\;or%.l %R2,%R0"; -}) - (define_expand "iorsi3" [(set (match_operand:SI 0 "nonimmediate_operand" "") (ior:SI (match_operand:SI 1 "general_operand" "") @@ -3957,79 +3821,6 @@ ;; xor instructions -;; "xordi3" is mainly here to help combine(). -(define_insn "xordi3" - [(set (match_operand:DI 0 "nonimmediate_operand" "=od") - (xor:DI (match_operand:DI 1 "general_operand" "%0") - (match_operand:DI 2 "general_operand" "dn")))] - "!TARGET_COLDFIRE" -{ - CC_STATUS_INIT; - /* We can get CONST_DOUBLE, but also const1_rtx etc. */ - - if (CONSTANT_P (operands[2])) - { - rtx hi, lo; - - split_double (operands[2], &hi, &lo); - - switch (INTVAL (hi)) - { - case 0 : - break; - case -1 : - output_asm_insn ("not%.l %0", operands); - break; - default : - /* FIXME : a scratch register would be welcome here if - -128 <= INTVAL (hi) < -1 */ - { - rtx xoperands[3]; - - xoperands[0] = operands[0]; - xoperands[2] = hi; - output_asm_insn (output_xorsi3 (xoperands), xoperands); - } - } - if (GET_CODE (operands[0]) == REG) - operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); - else - operands[0] = adjust_address (operands[0], SImode, 4); - switch (INTVAL (lo)) - { - case 0 : - break; - case -1 : - output_asm_insn ("not%.l %0", operands); - break; - default : - /* FIXME : a scratch register would be welcome here if - -128 <= INTVAL (lo) < -1 */ - operands[2] = lo; - /* FIXME : this should be merged with xorsi3 */ - { - rtx xoperands[3]; - - xoperands[0] = operands[0]; - xoperands[2] = lo; - output_asm_insn (output_xorsi3 (xoperands), xoperands); - } - } - return ""; - } - if (GET_CODE (operands[0]) != REG) - { - operands[1] = adjust_address (operands[0], SImode, 4); - return "eor%.l %2,%0\;eor%.l %R2,%1"; - } - if (GET_CODE (operands[2]) != REG) - { - operands[1] = adjust_address (operands[2], SImode, 4); - return "eor%.l %2,%0\;eor%.l %1,%R0"; - } - return "eor%.l %2,%0\;eor%.l %R2,%R0"; -}) - (define_expand "xorsi3" [(set (match_operand:SI 0 "nonimmediate_operand" "") (xor:SI (match_operand:SI 1 "general_operand" "") @@ -4498,23 +4289,6 @@ ;; one complement instructions -;; "one_cmpldi2" is mainly here to help combine(). -(define_insn "one_cmpldi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=dm") - (not:DI (match_operand:DI 1 "general_operand" "0")))] - "!TARGET_COLDFIRE" -{ - CC_STATUS_INIT; - if (GET_CODE (operands[0]) == REG) - operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); - else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC - || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) - operands[1] = operands[0]; - else - operands[1] = adjust_address (operands[0], SImode, 4); - return "not%.l %1\;not%.l %0"; -}) - (define_expand "one_cmplsi2" [(set (match_operand:SI 0 "nonimmediate_operand" "") (not:SI (match_operand:SI 1 "general_operand" "")))] diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 2584bc76c8e..708d6bb9402 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -173,6 +173,25 @@ enum mips_call_type { MIPS_CALL_EPILOGUE }; +/* Controls the conditions under which certain instructions are split. + + SPLIT_IF_NECESSARY + Only perform splits that are necessary for correctness + (because no unsplit version exists). + + SPLIT_FOR_SPEED + Perform splits that are necessary for correctness or + beneficial for code speed. + + SPLIT_FOR_SIZE + Perform splits that are necessary for correctness or + beneficial for code size. */ +enum mips_split_type { + SPLIT_IF_NECESSARY, + SPLIT_FOR_SPEED, + SPLIT_FOR_SIZE +}; + extern bool mips_symbolic_constant_p (rtx, enum mips_symbol_context, enum mips_symbol_type *); extern int mips_regno_mode_ok_for_base_p (int, enum machine_mode, bool); @@ -212,8 +231,10 @@ extern int m16_simm8_8 (rtx, enum machine_mode); extern int m16_nsimm8_8 (rtx, enum machine_mode); extern rtx mips_subword (rtx, bool); -extern bool mips_split_64bit_move_p (rtx, rtx); -extern void mips_split_doubleword_move (rtx, rtx); +extern bool mips_split_move_p (rtx, rtx, enum mips_split_type); +extern void mips_split_move (rtx, rtx, enum mips_split_type); +extern bool mips_split_move_insn_p (rtx, rtx, rtx); +extern void mips_split_move_insn (rtx, rtx, rtx); extern const char *mips_output_move (rtx, rtx); extern bool mips_cfun_has_cprestore_slot_p (void); extern bool mips_cprestore_address_p (rtx, bool); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index d37a2f4328d..4073a15d05d 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -265,6 +265,24 @@ static const char *const mips_fp_conditions[] = { MIPS_FP_CONDITIONS (STRINGIFY) }; +/* Tuning information that is automatically derived from other sources + (such as the scheduler). */ +static struct { + /* The architecture and tuning settings that this structure describes. */ + enum processor arch; + enum processor tune; + + /* True if this structure describes MIPS16 settings. */ + bool mips16_p; + + /* True if the structure has been initialized. */ + bool initialized_p; + + /* True if "MULT $0, $0" is preferable to "MTLO $0; MTHI $0" + when optimizing for speed. */ + bool fast_mult_zero_zero_p; +} mips_tuning_info; + /* Information about a function's frame layout. */ struct GTY(()) mips_frame_info { /* The size of the frame in bytes. */ @@ -2395,11 +2413,11 @@ mips_load_store_insns (rtx mem, rtx insn) mode = GET_MODE (mem); /* Try to prove that INSN does not need to be split. */ - might_split_p = true; - if (GET_MODE_BITSIZE (mode) == 64) + might_split_p = GET_MODE_SIZE (mode) > UNITS_PER_WORD; + if (might_split_p) { set = single_set (insn); - if (set && !mips_split_64bit_move_p (SET_DEST (set), SET_SRC (set))) + if (set && !mips_split_move_insn_p (SET_DEST (set), SET_SRC (set), insn)) might_split_p = false; } @@ -2441,6 +2459,18 @@ mips_emit_move (rtx dest, rtx src) : emit_move_insn_1 (dest, src)); } +/* Emit a move from SRC to DEST, splitting compound moves into individual + instructions. SPLIT_TYPE is the type of split to perform. */ + +static void +mips_emit_move_or_split (rtx dest, rtx src, enum mips_split_type split_type) +{ + if (mips_split_move_p (dest, src, split_type)) + mips_split_move (dest, src, split_type); + else + mips_emit_move (dest, src); +} + /* Emit an instruction of the form (set TARGET (CODE OP0)). */ static void @@ -3527,6 +3557,17 @@ mips_set_reg_reg_cost (enum machine_mode mode) } } +/* Return the cost of an operand X that can be trucated for free. + SPEED says whether we're optimizing for size or speed. */ + +static int +mips_truncated_op_cost (rtx x, bool speed) +{ + if (GET_CODE (x) == TRUNCATE) + x = XEXP (x, 0); + return set_src_cost (x, speed); +} + /* Implement TARGET_RTX_COSTS. */ static bool @@ -3907,12 +3948,13 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED, case ZERO_EXTEND: if (outer_code == SET && ISA_HAS_BADDU - && (GET_CODE (XEXP (x, 0)) == TRUNCATE - || GET_CODE (XEXP (x, 0)) == SUBREG) && GET_MODE (XEXP (x, 0)) == QImode - && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS) + && GET_CODE (XEXP (x, 0)) == PLUS) { - *total = set_src_cost (XEXP (XEXP (x, 0), 0), speed); + rtx plus = XEXP (x, 0); + *total = (COSTS_N_INSNS (1) + + mips_truncated_op_cost (XEXP (plus, 0), speed) + + mips_truncated_op_cost (XEXP (plus, 1), speed)); return true; } *total = mips_zero_extend_cost (mode, XEXP (x, 0)); @@ -4107,39 +4149,60 @@ mips_subword (rtx op, bool high_p) return simplify_gen_subreg (word_mode, op, mode, byte); } -/* Return true if a 64-bit move from SRC to DEST should be split into two. */ +/* Return true if SRC should be moved into DEST using "MULT $0, $0". + SPLIT_TYPE is the condition under which moves should be split. */ + +static bool +mips_mult_move_p (rtx dest, rtx src, enum mips_split_type split_type) +{ + return ((split_type != SPLIT_FOR_SPEED + || mips_tuning_info.fast_mult_zero_zero_p) + && src == const0_rtx + && REG_P (dest) + && GET_MODE_SIZE (GET_MODE (dest)) == 2 * UNITS_PER_WORD + && (ISA_HAS_DSP_MULT + ? ACC_REG_P (REGNO (dest)) + : MD_REG_P (REGNO (dest)))); +} + +/* Return true if a move from SRC to DEST should be split into two. + SPLIT_TYPE describes the split condition. */ bool -mips_split_64bit_move_p (rtx dest, rtx src) +mips_split_move_p (rtx dest, rtx src, enum mips_split_type split_type) { - if (TARGET_64BIT) + /* Check whether the move can be done using some variant of MULT $0,$0. */ + if (mips_mult_move_p (dest, src, split_type)) return false; /* FPR-to-FPR moves can be done in a single instruction, if they're allowed at all. */ - if (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) + unsigned int size = GET_MODE_SIZE (GET_MODE (dest)); + if (size == 8 && FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) return false; /* Check for floating-point loads and stores. */ - if (ISA_HAS_LDC1_SDC1) + if (size == 8 && ISA_HAS_LDC1_SDC1) { if (FP_REG_RTX_P (dest) && MEM_P (src)) return false; if (FP_REG_RTX_P (src) && MEM_P (dest)) return false; } - return true; + + /* Otherwise split all multiword moves. */ + return size > UNITS_PER_WORD; } -/* Split a doubleword move from SRC to DEST. On 32-bit targets, - this function handles 64-bit moves for which mips_split_64bit_move_p - holds. For 64-bit targets, this function handles 128-bit moves. */ +/* Split a move from SRC to DEST, given that mips_split_move_p holds. + SPLIT_TYPE describes the split condition. */ void -mips_split_doubleword_move (rtx dest, rtx src) +mips_split_move (rtx dest, rtx src, enum mips_split_type split_type) { rtx low_dest; + gcc_checking_assert (mips_split_move_p (dest, src, split_type)); if (FP_REG_RTX_P (dest) || FP_REG_RTX_P (src)) { if (!TARGET_64BIT && GET_MODE (dest) == DImode) @@ -4194,6 +4257,41 @@ mips_split_doubleword_move (rtx dest, rtx src) } } } + +/* Return the split type for instruction INSN. */ + +static enum mips_split_type +mips_insn_split_type (rtx insn) +{ + basic_block bb = BLOCK_FOR_INSN (insn); + if (bb) + { + if (optimize_bb_for_speed_p (bb)) + return SPLIT_FOR_SPEED; + else + return SPLIT_FOR_SIZE; + } + /* Once CFG information has been removed, we should trust the optimization + decisions made by previous passes and only split where necessary. */ + return SPLIT_IF_NECESSARY; +} + +/* Return true if a move from SRC to DEST in INSN should be split. */ + +bool +mips_split_move_insn_p (rtx dest, rtx src, rtx insn) +{ + return mips_split_move_p (dest, src, mips_insn_split_type (insn)); +} + +/* Split a move from SRC to DEST in INSN, given that mips_split_move_insn_p + holds. */ + +void +mips_split_move_insn (rtx dest, rtx src, rtx insn) +{ + mips_split_move (dest, src, mips_insn_split_type (insn)); +} /* Return the appropriate instructions to move SRC into DEST. Assume that SRC is operand 1 and DEST is operand 0. */ @@ -4211,7 +4309,7 @@ mips_output_move (rtx dest, rtx src) mode = GET_MODE (dest); dbl_p = (GET_MODE_SIZE (mode) == 8); - if (dbl_p && mips_split_64bit_move_p (dest, src)) + if (mips_split_move_p (dest, src, SPLIT_IF_NECESSARY)) return "#"; if ((src_code == REG && GP_REG_P (REGNO (src))) @@ -4222,6 +4320,14 @@ mips_output_move (rtx dest, rtx src) if (GP_REG_P (REGNO (dest))) return "move\t%0,%z1"; + if (mips_mult_move_p (dest, src, SPLIT_IF_NECESSARY)) + { + if (ISA_HAS_DSP_MULT) + return "mult\t%q0,%.,%."; + else + return "mult\t%.,%."; + } + /* Moves to HI are handled by special .md insns. */ if (REGNO (dest) == LO_REGNUM) return "mtlo\t%z1"; @@ -10432,10 +10538,7 @@ mips_save_reg (rtx reg, rtx mem) { rtx x1, x2; - if (mips_split_64bit_move_p (mem, reg)) - mips_split_doubleword_move (mem, reg); - else - mips_emit_move (mem, reg); + mips_emit_move_or_split (mem, reg, SPLIT_IF_NECESSARY); x1 = mips_frame_set (mips_subword (mem, false), mips_subword (reg, false)); @@ -14895,10 +14998,15 @@ struct mips_sim { static void mips_sim_reset (struct mips_sim *state) { + curr_state = state->dfa_state; + state->time = 0; state->insns_left = state->issue_rate; memset (&state->last_set, 0, sizeof (state->last_set)); - state_reset (state->dfa_state); + state_reset (curr_state); + + targetm.sched.init (0, false, 0); + advance_state (curr_state); } /* Initialize STATE before its first use. DFA_STATE points to an @@ -14907,6 +15015,12 @@ mips_sim_reset (struct mips_sim *state) static void mips_sim_init (struct mips_sim *state, state_t dfa_state) { + if (targetm.sched.init_dfa_pre_cycle_insn) + targetm.sched.init_dfa_pre_cycle_insn (); + + if (targetm.sched.init_dfa_post_cycle_insn) + targetm.sched.init_dfa_post_cycle_insn (); + state->issue_rate = mips_issue_rate (); state->dfa_state = dfa_state; mips_sim_reset (state); @@ -14917,9 +15031,11 @@ mips_sim_init (struct mips_sim *state, state_t dfa_state) static void mips_sim_next_cycle (struct mips_sim *state) { + curr_state = state->dfa_state; + state->time++; state->insns_left = state->issue_rate; - state_transition (state->dfa_state, 0); + advance_state (curr_state); } /* Advance simulation state STATE until instruction INSN can read @@ -15025,8 +15141,11 @@ mips_sim_record_set (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data) static void mips_sim_issue_insn (struct mips_sim *state, rtx insn) { - state_transition (state->dfa_state, insn); - state->insns_left--; + curr_state = state->dfa_state; + + state_transition (curr_state, insn); + state->insns_left = targetm.sched.variable_issue (0, false, insn, + state->insns_left); mips_sim_insn = insn; note_stores (PATTERN (insn), mips_sim_record_set, state); @@ -15077,6 +15196,109 @@ mips_sim_finish_insn (struct mips_sim *state, rtx insn) break; } } + +/* Use simulator state STATE to calculate the execution time of + instruction sequence SEQ. */ + +static unsigned int +mips_seq_time (struct mips_sim *state, rtx seq) +{ + mips_sim_reset (state); + for (rtx insn = seq; insn; insn = NEXT_INSN (insn)) + { + mips_sim_wait_insn (state, insn); + mips_sim_issue_insn (state, insn); + } + return state->time; +} + +/* Return the execution-time cost of mips_tuning_info.fast_mult_zero_zero_p + setting SETTING, using STATE to simulate instruction sequences. */ + +static unsigned int +mips_mult_zero_zero_cost (struct mips_sim *state, bool setting) +{ + mips_tuning_info.fast_mult_zero_zero_p = setting; + start_sequence (); + + enum machine_mode dword_mode = TARGET_64BIT ? TImode : DImode; + rtx hilo = gen_rtx_REG (dword_mode, MD_REG_FIRST); + mips_emit_move_or_split (hilo, const0_rtx, SPLIT_FOR_SPEED); + + /* If the target provides mulsidi3_32bit then that's the most likely + consumer of the result. Test for bypasses. */ + if (dword_mode == DImode && HAVE_maddsidi4) + { + rtx gpr = gen_rtx_REG (SImode, GP_REG_FIRST + 4); + emit_insn (gen_maddsidi4 (hilo, gpr, gpr, hilo)); + } + + unsigned int time = mips_seq_time (state, get_insns ()); + end_sequence (); + return time; +} + +/* Check the relative speeds of "MULT $0,$0" and "MTLO $0; MTHI $0" + and set up mips_tuning_info.fast_mult_zero_zero_p accordingly. + Prefer MULT -- which is shorter -- in the event of a tie. */ + +static void +mips_set_fast_mult_zero_zero_p (struct mips_sim *state) +{ + if (TARGET_MIPS16) + /* No MTLO or MTHI available. */ + mips_tuning_info.fast_mult_zero_zero_p = true; + else + { + unsigned int true_time = mips_mult_zero_zero_cost (state, true); + unsigned int false_time = mips_mult_zero_zero_cost (state, false); + mips_tuning_info.fast_mult_zero_zero_p = (true_time <= false_time); + } +} + +/* Set up costs based on the current architecture and tuning settings. */ + +static void +mips_set_tuning_info (void) +{ + if (mips_tuning_info.initialized_p + && mips_tuning_info.arch == mips_arch + && mips_tuning_info.tune == mips_tune + && mips_tuning_info.mips16_p == TARGET_MIPS16) + return; + + mips_tuning_info.arch = mips_arch; + mips_tuning_info.tune = mips_tune; + mips_tuning_info.mips16_p = TARGET_MIPS16; + mips_tuning_info.initialized_p = true; + + dfa_start (); + + struct mips_sim state; + mips_sim_init (&state, alloca (state_size ())); + + mips_set_fast_mult_zero_zero_p (&state); + + dfa_finish (); +} + +/* Implement TARGET_EXPAND_TO_RTL_HOOK. */ + +static void +mips_expand_to_rtl_hook (void) +{ + /* We need to call this at a point where we can safely create sequences + of instructions, so TARGET_OVERRIDE_OPTIONS is too early. We also + need to call it at a point where the DFA infrastructure is not + already in use, so we can't just call it lazily on demand. + + At present, mips_tuning_info is only needed during post-expand + RTL passes such as split_insns, so this hook should be early enough. + We may need to move the call elsewhere if mips_tuning_info starts + to be used for other things (such as rtx_costs, or expanders that + could be called during gimple optimization). */ + mips_set_tuning_info (); +} /* The VR4130 pipeline issues aligned pairs of instructions together, but it stalls the second instruction if it depends on the first. @@ -17748,6 +17970,8 @@ mips_expand_vec_minmax (rtx target, rtx op0, rtx op1, #undef TARGET_PREFERRED_RELOAD_CLASS #define TARGET_PREFERRED_RELOAD_CLASS mips_preferred_reload_class +#undef TARGET_EXPAND_TO_RTL_HOOK +#define TARGET_EXPAND_TO_RTL_HOOK mips_expand_to_rtl_hook #undef TARGET_ASM_FILE_START #define TARGET_ASM_FILE_START mips_file_start #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 787852c2ded..570e7851096 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -204,7 +204,7 @@ ;; the split instructions; in some cases, it is more appropriate for the ;; scheduling type to be "multi" instead. (define_attr "move_type" - "unknown,load,fpload,store,fpstore,mtc,mfc,mtlo,mflo,move,fmove, + "unknown,load,fpload,store,fpstore,mtc,mfc,mtlo,mflo,imul,move,fmove, const,constN,signext,ext_ins,logical,arith,sll0,andi,loadpool, shift_shift" (const_string "unknown")) @@ -369,6 +369,7 @@ (eq_attr "move_type" "mflo") (const_string "mflo") ;; These types of move are always single insns. + (eq_attr "move_type" "imul") (const_string "imul") (eq_attr "move_type" "fmove") (const_string "fmove") (eq_attr "move_type" "loadpool") (const_string "load") (eq_attr "move_type" "signext") (const_string "signext") @@ -1305,9 +1306,8 @@ (define_insn "*baddu_di<mode>" [(set (match_operand:GPR 0 "register_operand" "=d") (zero_extend:GPR - (truncate:QI - (plus:DI (match_operand:DI 1 "register_operand" "d") - (match_operand:DI 2 "register_operand" "d")))))] + (plus:QI (truncate:QI (match_operand:DI 1 "register_operand" "d")) + (truncate:QI (match_operand:DI 2 "register_operand" "d")))))] "ISA_HAS_BADDU && TARGET_64BIT" "baddu\\t%0,%1,%2" [(set_attr "alu_type" "add")]) @@ -4243,14 +4243,17 @@ (set_attr "mode" "<MODE>")]) (define_insn "*movdi_32bit" - [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*f,*f,*d,*m,*B*C*D,*B*C*D,*d,*m") - (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*J*d,*m,*f,*f,*d,*m,*B*C*D,*B*C*D"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*a,*d,*f,*f,*d,*m,*B*C*D,*B*C*D,*d,*m") + (match_operand:DI 1 "move_operand" "d,i,m,d,*J,*d,*a,*J*d,*m,*f,*f,*d,*m,*B*C*D,*B*C*D"))] "!TARGET_64BIT && !TARGET_MIPS16 && (register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode))" { return mips_output_move (operands[0], operands[1]); } - [(set_attr "move_type" "move,const,load,store,mtlo,mflo,mtc,fpload,mfc,fpstore,mtc,fpload,mfc,fpstore") - (set_attr "mode" "DI")]) + [(set_attr "move_type" "move,const,load,store,imul,mtlo,mflo,mtc,fpload,mfc,fpstore,mtc,fpload,mfc,fpstore") + (set (attr "mode") + (if_then_else (eq_attr "move_type" "imul") + (const_string "SI") + (const_string "DI")))]) (define_insn "*movdi_32bit_mips16" [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d") @@ -4696,15 +4699,18 @@ }) (define_insn "*movti" - [(set (match_operand:TI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d") - (match_operand:TI 1 "move_operand" "d,i,m,dJ,*d*J,*a"))] + [(set (match_operand:TI 0 "nonimmediate_operand" "=d,d,d,m,*a,*a,*d") + (match_operand:TI 1 "move_operand" "d,i,m,dJ,*J,*d,*a"))] "TARGET_64BIT && !TARGET_MIPS16 && (register_operand (operands[0], TImode) || reg_or_0_operand (operands[1], TImode))" - "#" - [(set_attr "move_type" "move,const,load,store,mtlo,mflo") - (set_attr "mode" "TI")]) + { return mips_output_move (operands[0], operands[1]); } + [(set_attr "move_type" "move,const,load,store,imul,mtlo,mflo") + (set (attr "mode") + (if_then_else (eq_attr "move_type" "imul") + (const_string "SI") + (const_string "TI")))]) (define_insn "*movti_mips16" [(set (match_operand:TI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d") @@ -4754,21 +4760,20 @@ (define_split [(set (match_operand:MOVE64 0 "nonimmediate_operand") (match_operand:MOVE64 1 "move_operand"))] - "reload_completed && !TARGET_64BIT - && mips_split_64bit_move_p (operands[0], operands[1])" + "reload_completed && mips_split_move_insn_p (operands[0], operands[1], insn)" [(const_int 0)] { - mips_split_doubleword_move (operands[0], operands[1]); + mips_split_move_insn (operands[0], operands[1], curr_insn); DONE; }) (define_split [(set (match_operand:MOVE128 0 "nonimmediate_operand") (match_operand:MOVE128 1 "move_operand"))] - "TARGET_64BIT && reload_completed" + "reload_completed && mips_split_move_insn_p (operands[0], operands[1], insn)" [(const_int 0)] { - mips_split_doubleword_move (operands[0], operands[1]); + mips_split_move_insn (operands[0], operands[1], curr_insn); DONE; }) diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c index d5d72dfdcad..26668e76da8 100644 --- a/gcc/config/mmix/mmix.c +++ b/gcc/config/mmix/mmix.c @@ -2499,19 +2499,9 @@ mmix_output_shiftvalue_op_from_str (FILE *stream, static void mmix_output_octa (FILE *stream, HOST_WIDEST_INT value, int do_begin_end) { - /* Snipped from final.c:output_addr_const. We need to avoid the - presumed universal "0x" prefix. We can do it by replacing "0x" with - "#0" here; we must avoid a space in the operands and no, the zero - won't cause the number to be assumed in octal format. */ - char hex_format[sizeof (HOST_WIDEST_INT_PRINT_HEX)]; - if (do_begin_end) fprintf (stream, "\tOCTA "); - strcpy (hex_format, HOST_WIDEST_INT_PRINT_HEX); - hex_format[0] = '#'; - hex_format[1] = '0'; - /* Provide a few alternative output formats depending on the number, to improve legibility of assembler output. */ if ((value < (HOST_WIDEST_INT) 0 && value > (HOST_WIDEST_INT) -10000) @@ -2520,8 +2510,13 @@ mmix_output_octa (FILE *stream, HOST_WIDEST_INT value, int do_begin_end) else if (value > (HOST_WIDEST_INT) 0 && value < ((HOST_WIDEST_INT) 1 << 31) * 2) fprintf (stream, "#%x", (unsigned int) value); - else - fprintf (stream, hex_format, value); + else if (sizeof (HOST_WIDE_INT) == sizeof (HOST_WIDEST_INT)) + /* We need to avoid the not-so-universal "0x" prefix; we need the + pure hex-digits together with the mmixal "#" hex prefix. */ + fprintf (stream, "#" HOST_WIDE_INT_PRINT_HEX_PURE, + (HOST_WIDE_INT) value); + else /* Need to avoid the hex output; there's no ...WIDEST...HEX_PURE. */ + fprintf (stream, HOST_WIDEST_INT_PRINT_UNSIGNED, value); if (do_begin_end) fprintf (stream, "\n"); diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index 8a7e6858c11..80c40f5047a 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -2881,15 +2881,17 @@ [(set_attr "type" "store") (set_attr "length" "4")]) -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (plus:HI (match_operand:HI 1 "register_operand" "r") - (match_operand 2 "const_int_operand" "J")))] +(define_insn "addhi3" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (plus:HI (match_operand:HI 1 "register_operand" "%r,r") + (match_operand:HI 2 "arith14_operand" "r,J")))] "" - "ldo %2(%1),%0" - [(set_attr "type" "binary") + "@ + {addl|add,l} %1,%2,%0 + ldo %2(%1),%0" + [(set_attr "type" "binary,binary") (set_attr "pa_combine_type" "addmove") - (set_attr "length" "4")]) + (set_attr "length" "4,4")]) (define_expand "movqi" [(set (match_operand:QI 0 "general_operand" "") @@ -5621,22 +5623,8 @@ [(set (match_operand:DI 0 "register_operand" "") (and:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "and_operand" "")))] - "" - " -{ - /* Both operands must be register operands. */ - if (!TARGET_64BIT && !register_operand (operands[2], DImode)) - FAIL; -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (and:DI (match_operand:DI 1 "register_operand" "%r") - (match_operand:DI 2 "register_operand" "r")))] - "!TARGET_64BIT" - "and %1,%2,%0\;and %R1,%R2,%R0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) + "TARGET_64BIT" + "") (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -5662,15 +5650,6 @@ [(set (match_operand:DI 0 "register_operand" "=r") (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) (match_operand:DI 2 "register_operand" "r")))] - "!TARGET_64BIT" - "andcm %2,%1,%0\;andcm %R2,%R1,%R0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (and:DI (not:DI (match_operand:DI 1 "register_operand" "r")) - (match_operand:DI 2 "register_operand" "r")))] "TARGET_64BIT" "andcm %2,%1,%0" [(set_attr "type" "binary") @@ -5689,22 +5668,8 @@ [(set (match_operand:DI 0 "register_operand" "") (ior:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "reg_or_cint_ior_operand" "")))] - "" - " -{ - /* Both operands must be register operands. */ - if (!TARGET_64BIT && !register_operand (operands[2], DImode)) - FAIL; -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (ior:DI (match_operand:DI 1 "register_operand" "%r") - (match_operand:DI 2 "register_operand" "r")))] - "!TARGET_64BIT" - "or %1,%2,%0\;or %R1,%R2,%R0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) + "TARGET_64BIT" + "") (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -5754,19 +5719,8 @@ [(set (match_operand:DI 0 "register_operand" "") (xor:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" "")))] - "" - " -{ -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (xor:DI (match_operand:DI 1 "register_operand" "%r") - (match_operand:DI 2 "register_operand" "r")))] - "!TARGET_64BIT" - "xor %1,%2,%0\;xor %R1,%R2,%R0" - [(set_attr "type" "binary") - (set_attr "length" "8")]) + "TARGET_64BIT" + "") (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 3e3d55324e9..1384a819b1c 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -14687,17 +14687,6 @@ print_operand (FILE *file, rtx x, int code) { /* %a is output_address. */ - case 'A': - /* If X is a constant integer whose low-order 5 bits are zero, - write 'l'. Otherwise, write 'r'. This is a kludge to fix a bug - in the AIX assembler where "sri" with a zero shift count - writes a trash instruction. */ - if (GET_CODE (x) == CONST_INT && (INTVAL (x) & 31) == 0) - putc ('l', file); - else - putc ('r', file); - return; - case 'b': /* If constant, low-order 16 bits of constant, unsigned. Otherwise, write normally. */ @@ -28295,6 +28284,7 @@ rs6000_code_end (void) TREE_PUBLIC (decl) = 1; TREE_STATIC (decl) = 1; +#if RS6000_WEAK if (USE_HIDDEN_LINKONCE) { DECL_COMDAT_GROUP (decl) = DECL_ASSEMBLER_NAME (decl); @@ -28307,6 +28297,7 @@ rs6000_code_end (void) ASM_DECLARE_FUNCTION_NAME (asm_out_file, name, decl); } else +#endif { switch_to_section (text_section); ASM_OUTPUT_LABEL (asm_out_file, name); diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index 05ad85808bb..89b4d0fc5a3 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -409,6 +409,14 @@ if (MEM_P (op)) { rtx inside = XEXP (op, 0); + + /* Disallow mems with GBR address here. They have to go through + separate special patterns. */ + if ((REG_P (inside) && REGNO (inside) == GBR_REG) + || (GET_CODE (inside) == PLUS && REG_P (XEXP (inside, 0)) + && REGNO (XEXP (inside, 0)) == GBR_REG)) + return 0; + if (GET_CODE (inside) == CONST) inside = XEXP (inside, 0); @@ -466,6 +474,17 @@ if (t_reg_operand (op, mode)) return 0; + if (MEM_P (op)) + { + rtx inside = XEXP (op, 0); + /* Disallow mems with GBR address here. They have to go through + separate special patterns. */ + if ((REG_P (inside) && REGNO (inside) == GBR_REG) + || (GET_CODE (inside) == PLUS && REG_P (XEXP (inside, 0)) + && REGNO (XEXP (inside, 0)) == GBR_REG)) + return 0; + } + /* Only pre dec allowed. */ if (MEM_P (op) && GET_CODE (XEXP (op, 0)) == POST_INC) return 0; diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index d908110dc1b..61d4eabfde9 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -161,7 +161,7 @@ extern bool sh_vector_mode_supported_p (enum machine_mode); extern bool sh_cfun_trap_exit_p (void); extern void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&, enum machine_mode mode = VOIDmode); - +extern rtx sh_find_equiv_gbr_addr (rtx cur_insn, rtx mem); #endif /* RTX_CODE */ extern void sh_cpu_cpp_builtins (cpp_reader* pfile); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 33ae28e7a69..d1ab28afd81 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -243,8 +243,6 @@ static bool sh_ms_bitfield_layout_p (const_tree); static void sh_init_builtins (void); static tree sh_builtin_decl (unsigned, bool); -static void sh_media_init_builtins (void); -static tree sh_media_builtin_decl (unsigned, bool); static rtx sh_expand_builtin (tree, rtx, rtx, enum machine_mode, int); static void sh_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree); static void sh_file_start (void); @@ -1889,7 +1887,7 @@ prepare_move_operands (rtx operands[], enum machine_mode mode) case TLS_MODEL_LOCAL_EXEC: tmp2 = gen_reg_rtx (Pmode); - emit_insn (gen_load_gbr (tmp2)); + emit_insn (gen_store_gbr (tmp2)); tmp = gen_reg_rtx (Pmode); emit_insn (gen_symTPOFF2reg (tmp, op1)); @@ -3612,6 +3610,10 @@ static int sh_address_cost (rtx x, enum machine_mode mode, addr_space_t as ATTRIBUTE_UNUSED, bool speed ATTRIBUTE_UNUSED) { + /* 'GBR + 0'. Account one more because of R0 restriction. */ + if (REG_P (x) && REGNO (x) == GBR_REG) + return 2; + /* Simple reg, post-inc, pre-dec addressing. */ if (REG_P (x) || GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_DEC) return 1; @@ -3620,6 +3622,11 @@ sh_address_cost (rtx x, enum machine_mode mode, if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))) { + /* 'GBR + disp'. Account one more because of R0 restriction. */ + if (REGNO (XEXP (x, 0)) == GBR_REG + && gbr_displacement (XEXP (x, 1), mode)) + return 2; + const HOST_WIDE_INT offset = INTVAL (XEXP (x, 1)); if (offset == 0) @@ -10187,11 +10194,16 @@ sh_legitimate_index_p (enum machine_mode mode, rtx op, bool consider_sh2a, REG+disp REG+r0 REG++ - --REG */ + --REG + GBR + GBR+disp */ static bool sh_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) { + if (REG_P (x) && REGNO (x) == GBR_REG) + return true; + if (MAYBE_BASE_REGISTER_RTX_P (x, strict)) return true; else if ((GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_DEC) @@ -10204,6 +10216,9 @@ sh_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) rtx xop0 = XEXP (x, 0); rtx xop1 = XEXP (x, 1); + if (REG_P (xop0) && REGNO (xop0) == GBR_REG) + return gbr_displacement (xop1, mode); + if (GET_MODE_SIZE (mode) <= 8 && MAYBE_BASE_REGISTER_RTX_P (xop0, strict) && sh_legitimate_index_p (mode, xop1, TARGET_SH2A, false)) @@ -11510,12 +11525,25 @@ sh_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) struct builtin_description { + bool (* const is_enabled) (void); const enum insn_code icode; const char *const name; int signature; tree fndecl; }; +static bool +shmedia_builtin_p (void) +{ + return TARGET_SHMEDIA; +} + +static bool +sh1_builtin_p (void) +{ + return TARGET_SH1; +} + /* describe number and signedness of arguments; arg[0] == result (1: unsigned, 2: signed, 4: don't care, 8: pointer 0: no argument */ /* 9: 64-bit pointer, 10: 32-bit pointer */ @@ -11573,6 +11601,8 @@ static const char signature_args[][4] = { 1, 1, 1, 1 }, #define SH_BLTIN_PV 23 { 0, 8 }, +#define SH_BLTIN_VP 24 + { 8, 0 }, }; /* mcmv: operands considered unsigned. */ /* mmulsum_wq, msad_ubq: result considered unsigned long long. */ @@ -11582,103 +11612,195 @@ static const char signature_args[][4] = /* nsb: takes long long arg, returns unsigned char. */ static struct builtin_description bdesc[] = { - { CODE_FOR_absv2si2, "__builtin_absv2si2", SH_BLTIN_V2SI2, 0 }, - { CODE_FOR_absv4hi2, "__builtin_absv4hi2", SH_BLTIN_V4HI2, 0 }, - { CODE_FOR_addv2si3, "__builtin_addv2si3", SH_BLTIN_V2SI3, 0 }, - { CODE_FOR_addv4hi3, "__builtin_addv4hi3", SH_BLTIN_V4HI3, 0 }, - { CODE_FOR_ssaddv2si3,"__builtin_ssaddv2si3", SH_BLTIN_V2SI3, 0 }, - { CODE_FOR_usaddv8qi3,"__builtin_usaddv8qi3", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_ssaddv4hi3,"__builtin_ssaddv4hi3", SH_BLTIN_V4HI3, 0 }, - { CODE_FOR_alloco_i, "__builtin_sh_media_ALLOCO", SH_BLTIN_PV, 0 }, - { CODE_FOR_negcmpeqv8qi,"__builtin_sh_media_MCMPEQ_B", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_negcmpeqv2si,"__builtin_sh_media_MCMPEQ_L", SH_BLTIN_V2SI3, 0 }, - { CODE_FOR_negcmpeqv4hi,"__builtin_sh_media_MCMPEQ_W", SH_BLTIN_V4HI3, 0 }, - { CODE_FOR_negcmpgtuv8qi,"__builtin_sh_media_MCMPGT_UB", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_negcmpgtv2si,"__builtin_sh_media_MCMPGT_L", SH_BLTIN_V2SI3, 0 }, - { CODE_FOR_negcmpgtv4hi,"__builtin_sh_media_MCMPGT_W", SH_BLTIN_V4HI3, 0 }, - { CODE_FOR_mcmv, "__builtin_sh_media_MCMV", SH_BLTIN_UUUU, 0 }, - { CODE_FOR_mcnvs_lw, "__builtin_sh_media_MCNVS_LW", SH_BLTIN_3, 0 }, - { CODE_FOR_mcnvs_wb, "__builtin_sh_media_MCNVS_WB", SH_BLTIN_V4HI2V8QI, 0 }, - { CODE_FOR_mcnvs_wub, "__builtin_sh_media_MCNVS_WUB", SH_BLTIN_V4HI2V8QI, 0 }, - { CODE_FOR_mextr1, "__builtin_sh_media_MEXTR1", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_mextr2, "__builtin_sh_media_MEXTR2", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_mextr3, "__builtin_sh_media_MEXTR3", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_mextr4, "__builtin_sh_media_MEXTR4", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_mextr5, "__builtin_sh_media_MEXTR5", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_mextr6, "__builtin_sh_media_MEXTR6", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_mextr7, "__builtin_sh_media_MEXTR7", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_mmacfx_wl, "__builtin_sh_media_MMACFX_WL", SH_BLTIN_MAC_HISI, 0 }, - { CODE_FOR_mmacnfx_wl,"__builtin_sh_media_MMACNFX_WL", SH_BLTIN_MAC_HISI, 0 }, - { CODE_FOR_mulv2si3, "__builtin_mulv2si3", SH_BLTIN_V2SI3, 0 }, - { CODE_FOR_mulv4hi3, "__builtin_mulv4hi3", SH_BLTIN_V4HI3, 0 }, - { CODE_FOR_mmulfx_l, "__builtin_sh_media_MMULFX_L", SH_BLTIN_V2SI3, 0 }, - { CODE_FOR_mmulfx_w, "__builtin_sh_media_MMULFX_W", SH_BLTIN_V4HI3, 0 }, - { CODE_FOR_mmulfxrp_w,"__builtin_sh_media_MMULFXRP_W", SH_BLTIN_V4HI3, 0 }, - { CODE_FOR_mmulhi_wl, "__builtin_sh_media_MMULHI_WL", SH_BLTIN_V4HI2V2SI, 0 }, - { CODE_FOR_mmullo_wl, "__builtin_sh_media_MMULLO_WL", SH_BLTIN_V4HI2V2SI, 0 }, - { CODE_FOR_mmulsum_wq,"__builtin_sh_media_MMULSUM_WQ", SH_BLTIN_XXUU, 0 }, - { CODE_FOR_mperm_w, "__builtin_sh_media_MPERM_W", SH_BLTIN_SH_HI, 0 }, - { CODE_FOR_msad_ubq, "__builtin_sh_media_MSAD_UBQ", SH_BLTIN_XXUU, 0 }, - { CODE_FOR_mshalds_l, "__builtin_sh_media_MSHALDS_L", SH_BLTIN_SH_SI, 0 }, - { CODE_FOR_mshalds_w, "__builtin_sh_media_MSHALDS_W", SH_BLTIN_SH_HI, 0 }, - { CODE_FOR_ashrv2si3, "__builtin_ashrv2si3", SH_BLTIN_SH_SI, 0 }, - { CODE_FOR_ashrv4hi3, "__builtin_ashrv4hi3", SH_BLTIN_SH_HI, 0 }, - { CODE_FOR_mshards_q, "__builtin_sh_media_MSHARDS_Q", SH_BLTIN_SUS, 0 }, - { CODE_FOR_mshfhi_b, "__builtin_sh_media_MSHFHI_B", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_mshfhi_l, "__builtin_sh_media_MSHFHI_L", SH_BLTIN_V2SI3, 0 }, - { CODE_FOR_mshfhi_w, "__builtin_sh_media_MSHFHI_W", SH_BLTIN_V4HI3, 0 }, - { CODE_FOR_mshflo_b, "__builtin_sh_media_MSHFLO_B", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_mshflo_l, "__builtin_sh_media_MSHFLO_L", SH_BLTIN_V2SI3, 0 }, - { CODE_FOR_mshflo_w, "__builtin_sh_media_MSHFLO_W", SH_BLTIN_V4HI3, 0 }, - { CODE_FOR_ashlv2si3, "__builtin_ashlv2si3", SH_BLTIN_SH_SI, 0 }, - { CODE_FOR_ashlv4hi3, "__builtin_ashlv4hi3", SH_BLTIN_SH_HI, 0 }, - { CODE_FOR_lshrv2si3, "__builtin_lshrv2si3", SH_BLTIN_SH_SI, 0 }, - { CODE_FOR_lshrv4hi3, "__builtin_lshrv4hi3", SH_BLTIN_SH_HI, 0 }, - { CODE_FOR_subv2si3, "__builtin_subv2si3", SH_BLTIN_V2SI3, 0 }, - { CODE_FOR_subv4hi3, "__builtin_subv4hi3", SH_BLTIN_V4HI3, 0 }, - { CODE_FOR_sssubv2si3,"__builtin_sssubv2si3", SH_BLTIN_V2SI3, 0 }, - { CODE_FOR_ussubv8qi3,"__builtin_ussubv8qi3", SH_BLTIN_V8QI3, 0 }, - { CODE_FOR_sssubv4hi3,"__builtin_sssubv4hi3", SH_BLTIN_V4HI3, 0 }, - { CODE_FOR_fcosa_s, "__builtin_sh_media_FCOSA_S", SH_BLTIN_SISF, 0 }, - { CODE_FOR_fsina_s, "__builtin_sh_media_FSINA_S", SH_BLTIN_SISF, 0 }, - { CODE_FOR_fipr, "__builtin_sh_media_FIPR_S", SH_BLTIN_3, 0 }, - { CODE_FOR_ftrv, "__builtin_sh_media_FTRV_S", SH_BLTIN_3, 0 }, - { CODE_FOR_sqrtdf2, "__builtin_sh_media_FSQRT_D", SH_BLTIN_2, 0 }, - { CODE_FOR_sqrtsf2, "__builtin_sh_media_FSQRT_S", SH_BLTIN_2, 0 }, - { CODE_FOR_fsrra_s, "__builtin_sh_media_FSRRA_S", SH_BLTIN_2, 0 }, - { CODE_FOR_ldhi_l, "__builtin_sh_media_LDHI_L", SH_BLTIN_LDUA_L, 0 }, - { CODE_FOR_ldhi_q, "__builtin_sh_media_LDHI_Q", SH_BLTIN_LDUA_Q, 0 }, - { CODE_FOR_ldlo_l, "__builtin_sh_media_LDLO_L", SH_BLTIN_LDUA_L, 0 }, - { CODE_FOR_ldlo_q, "__builtin_sh_media_LDLO_Q", SH_BLTIN_LDUA_Q, 0 }, - { CODE_FOR_sthi_l, "__builtin_sh_media_STHI_L", SH_BLTIN_STUA_L, 0 }, - { CODE_FOR_sthi_q, "__builtin_sh_media_STHI_Q", SH_BLTIN_STUA_Q, 0 }, - { CODE_FOR_stlo_l, "__builtin_sh_media_STLO_L", SH_BLTIN_STUA_L, 0 }, - { CODE_FOR_stlo_q, "__builtin_sh_media_STLO_Q", SH_BLTIN_STUA_Q, 0 }, - { CODE_FOR_ldhi_l64, "__builtin_sh_media_LDHI_L", SH_BLTIN_LDUA_L64, 0 }, - { CODE_FOR_ldhi_q64, "__builtin_sh_media_LDHI_Q", SH_BLTIN_LDUA_Q64, 0 }, - { CODE_FOR_ldlo_l64, "__builtin_sh_media_LDLO_L", SH_BLTIN_LDUA_L64, 0 }, - { CODE_FOR_ldlo_q64, "__builtin_sh_media_LDLO_Q", SH_BLTIN_LDUA_Q64, 0 }, - { CODE_FOR_sthi_l64, "__builtin_sh_media_STHI_L", SH_BLTIN_STUA_L64, 0 }, - { CODE_FOR_sthi_q64, "__builtin_sh_media_STHI_Q", SH_BLTIN_STUA_Q64, 0 }, - { CODE_FOR_stlo_l64, "__builtin_sh_media_STLO_L", SH_BLTIN_STUA_L64, 0 }, - { CODE_FOR_stlo_q64, "__builtin_sh_media_STLO_Q", SH_BLTIN_STUA_Q64, 0 }, - { CODE_FOR_nsb, "__builtin_sh_media_NSB", SH_BLTIN_SU, 0 }, - { CODE_FOR_byterev, "__builtin_sh_media_BYTEREV", SH_BLTIN_2, 0 }, - { CODE_FOR_prefetch, "__builtin_sh_media_PREFO", SH_BLTIN_PSSV, 0 }, + { shmedia_builtin_p, + CODE_FOR_absv2si2, "__builtin_absv2si2", SH_BLTIN_V2SI2, 0 }, + { shmedia_builtin_p, + CODE_FOR_absv4hi2, "__builtin_absv4hi2", SH_BLTIN_V4HI2, 0 }, + { shmedia_builtin_p, + CODE_FOR_addv2si3, "__builtin_addv2si3", SH_BLTIN_V2SI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_addv4hi3, "__builtin_addv4hi3", SH_BLTIN_V4HI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_ssaddv2si3,"__builtin_ssaddv2si3", SH_BLTIN_V2SI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_usaddv8qi3,"__builtin_usaddv8qi3", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_ssaddv4hi3,"__builtin_ssaddv4hi3", SH_BLTIN_V4HI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_alloco_i, "__builtin_sh_media_ALLOCO", SH_BLTIN_PV, 0 }, + { shmedia_builtin_p, + CODE_FOR_negcmpeqv8qi,"__builtin_sh_media_MCMPEQ_B", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_negcmpeqv2si,"__builtin_sh_media_MCMPEQ_L", SH_BLTIN_V2SI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_negcmpeqv4hi,"__builtin_sh_media_MCMPEQ_W", SH_BLTIN_V4HI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_negcmpgtuv8qi,"__builtin_sh_media_MCMPGT_UB", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_negcmpgtv2si,"__builtin_sh_media_MCMPGT_L", SH_BLTIN_V2SI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_negcmpgtv4hi,"__builtin_sh_media_MCMPGT_W", SH_BLTIN_V4HI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mcmv, "__builtin_sh_media_MCMV", SH_BLTIN_UUUU, 0 }, + { shmedia_builtin_p, + CODE_FOR_mcnvs_lw, "__builtin_sh_media_MCNVS_LW", SH_BLTIN_3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mcnvs_wb, "__builtin_sh_media_MCNVS_WB", SH_BLTIN_V4HI2V8QI, 0 }, + { shmedia_builtin_p, + CODE_FOR_mcnvs_wub, "__builtin_sh_media_MCNVS_WUB", SH_BLTIN_V4HI2V8QI, 0 }, + { shmedia_builtin_p, + CODE_FOR_mextr1, "__builtin_sh_media_MEXTR1", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mextr2, "__builtin_sh_media_MEXTR2", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mextr3, "__builtin_sh_media_MEXTR3", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mextr4, "__builtin_sh_media_MEXTR4", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mextr5, "__builtin_sh_media_MEXTR5", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mextr6, "__builtin_sh_media_MEXTR6", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mextr7, "__builtin_sh_media_MEXTR7", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mmacfx_wl, "__builtin_sh_media_MMACFX_WL", SH_BLTIN_MAC_HISI, 0 }, + { shmedia_builtin_p, + CODE_FOR_mmacnfx_wl,"__builtin_sh_media_MMACNFX_WL", SH_BLTIN_MAC_HISI, 0 }, + { shmedia_builtin_p, + CODE_FOR_mulv2si3, "__builtin_mulv2si3", SH_BLTIN_V2SI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mulv4hi3, "__builtin_mulv4hi3", SH_BLTIN_V4HI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mmulfx_l, "__builtin_sh_media_MMULFX_L", SH_BLTIN_V2SI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mmulfx_w, "__builtin_sh_media_MMULFX_W", SH_BLTIN_V4HI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mmulfxrp_w,"__builtin_sh_media_MMULFXRP_W", SH_BLTIN_V4HI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mmulhi_wl, "__builtin_sh_media_MMULHI_WL", SH_BLTIN_V4HI2V2SI, 0 }, + { shmedia_builtin_p, + CODE_FOR_mmullo_wl, "__builtin_sh_media_MMULLO_WL", SH_BLTIN_V4HI2V2SI, 0 }, + { shmedia_builtin_p, + CODE_FOR_mmulsum_wq,"__builtin_sh_media_MMULSUM_WQ", SH_BLTIN_XXUU, 0 }, + { shmedia_builtin_p, + CODE_FOR_mperm_w, "__builtin_sh_media_MPERM_W", SH_BLTIN_SH_HI, 0 }, + { shmedia_builtin_p, + CODE_FOR_msad_ubq, "__builtin_sh_media_MSAD_UBQ", SH_BLTIN_XXUU, 0 }, + { shmedia_builtin_p, + CODE_FOR_mshalds_l, "__builtin_sh_media_MSHALDS_L", SH_BLTIN_SH_SI, 0 }, + { shmedia_builtin_p, + CODE_FOR_mshalds_w, "__builtin_sh_media_MSHALDS_W", SH_BLTIN_SH_HI, 0 }, + { shmedia_builtin_p, + CODE_FOR_ashrv2si3, "__builtin_ashrv2si3", SH_BLTIN_SH_SI, 0 }, + { shmedia_builtin_p, + CODE_FOR_ashrv4hi3, "__builtin_ashrv4hi3", SH_BLTIN_SH_HI, 0 }, + { shmedia_builtin_p, + CODE_FOR_mshards_q, "__builtin_sh_media_MSHARDS_Q", SH_BLTIN_SUS, 0 }, + { shmedia_builtin_p, + CODE_FOR_mshfhi_b, "__builtin_sh_media_MSHFHI_B", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mshfhi_l, "__builtin_sh_media_MSHFHI_L", SH_BLTIN_V2SI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mshfhi_w, "__builtin_sh_media_MSHFHI_W", SH_BLTIN_V4HI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mshflo_b, "__builtin_sh_media_MSHFLO_B", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mshflo_l, "__builtin_sh_media_MSHFLO_L", SH_BLTIN_V2SI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_mshflo_w, "__builtin_sh_media_MSHFLO_W", SH_BLTIN_V4HI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_ashlv2si3, "__builtin_ashlv2si3", SH_BLTIN_SH_SI, 0 }, + { shmedia_builtin_p, + CODE_FOR_ashlv4hi3, "__builtin_ashlv4hi3", SH_BLTIN_SH_HI, 0 }, + { shmedia_builtin_p, + CODE_FOR_lshrv2si3, "__builtin_lshrv2si3", SH_BLTIN_SH_SI, 0 }, + { shmedia_builtin_p, + CODE_FOR_lshrv4hi3, "__builtin_lshrv4hi3", SH_BLTIN_SH_HI, 0 }, + { shmedia_builtin_p, + CODE_FOR_subv2si3, "__builtin_subv2si3", SH_BLTIN_V2SI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_subv4hi3, "__builtin_subv4hi3", SH_BLTIN_V4HI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_sssubv2si3,"__builtin_sssubv2si3", SH_BLTIN_V2SI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_ussubv8qi3,"__builtin_ussubv8qi3", SH_BLTIN_V8QI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_sssubv4hi3,"__builtin_sssubv4hi3", SH_BLTIN_V4HI3, 0 }, + { shmedia_builtin_p, + CODE_FOR_fcosa_s, "__builtin_sh_media_FCOSA_S", SH_BLTIN_SISF, 0 }, + { shmedia_builtin_p, + CODE_FOR_fsina_s, "__builtin_sh_media_FSINA_S", SH_BLTIN_SISF, 0 }, + { shmedia_builtin_p, + CODE_FOR_fipr, "__builtin_sh_media_FIPR_S", SH_BLTIN_3, 0 }, + { shmedia_builtin_p, + CODE_FOR_ftrv, "__builtin_sh_media_FTRV_S", SH_BLTIN_3, 0 }, + { shmedia_builtin_p, + CODE_FOR_sqrtdf2, "__builtin_sh_media_FSQRT_D", SH_BLTIN_2, 0 }, + { shmedia_builtin_p, + CODE_FOR_sqrtsf2, "__builtin_sh_media_FSQRT_S", SH_BLTIN_2, 0 }, + { shmedia_builtin_p, + CODE_FOR_fsrra_s, "__builtin_sh_media_FSRRA_S", SH_BLTIN_2, 0 }, + { shmedia_builtin_p, + CODE_FOR_ldhi_l, "__builtin_sh_media_LDHI_L", SH_BLTIN_LDUA_L, 0 }, + { shmedia_builtin_p, + CODE_FOR_ldhi_q, "__builtin_sh_media_LDHI_Q", SH_BLTIN_LDUA_Q, 0 }, + { shmedia_builtin_p, + CODE_FOR_ldlo_l, "__builtin_sh_media_LDLO_L", SH_BLTIN_LDUA_L, 0 }, + { shmedia_builtin_p, + CODE_FOR_ldlo_q, "__builtin_sh_media_LDLO_Q", SH_BLTIN_LDUA_Q, 0 }, + { shmedia_builtin_p, + CODE_FOR_sthi_l, "__builtin_sh_media_STHI_L", SH_BLTIN_STUA_L, 0 }, + { shmedia_builtin_p, + CODE_FOR_sthi_q, "__builtin_sh_media_STHI_Q", SH_BLTIN_STUA_Q, 0 }, + { shmedia_builtin_p, + CODE_FOR_stlo_l, "__builtin_sh_media_STLO_L", SH_BLTIN_STUA_L, 0 }, + { shmedia_builtin_p, + CODE_FOR_stlo_q, "__builtin_sh_media_STLO_Q", SH_BLTIN_STUA_Q, 0 }, + { shmedia_builtin_p, + CODE_FOR_ldhi_l64, "__builtin_sh_media_LDHI_L", SH_BLTIN_LDUA_L64, 0 }, + { shmedia_builtin_p, + CODE_FOR_ldhi_q64, "__builtin_sh_media_LDHI_Q", SH_BLTIN_LDUA_Q64, 0 }, + { shmedia_builtin_p, + CODE_FOR_ldlo_l64, "__builtin_sh_media_LDLO_L", SH_BLTIN_LDUA_L64, 0 }, + { shmedia_builtin_p, + CODE_FOR_ldlo_q64, "__builtin_sh_media_LDLO_Q", SH_BLTIN_LDUA_Q64, 0 }, + { shmedia_builtin_p, + CODE_FOR_sthi_l64, "__builtin_sh_media_STHI_L", SH_BLTIN_STUA_L64, 0 }, + { shmedia_builtin_p, + CODE_FOR_sthi_q64, "__builtin_sh_media_STHI_Q", SH_BLTIN_STUA_Q64, 0 }, + { shmedia_builtin_p, + CODE_FOR_stlo_l64, "__builtin_sh_media_STLO_L", SH_BLTIN_STUA_L64, 0 }, + { shmedia_builtin_p, + CODE_FOR_stlo_q64, "__builtin_sh_media_STLO_Q", SH_BLTIN_STUA_Q64, 0 }, + { shmedia_builtin_p, + CODE_FOR_nsb, "__builtin_sh_media_NSB", SH_BLTIN_SU, 0 }, + { shmedia_builtin_p, + CODE_FOR_byterev, "__builtin_sh_media_BYTEREV", SH_BLTIN_2, 0 }, + { shmedia_builtin_p, + CODE_FOR_prefetch, "__builtin_sh_media_PREFO", SH_BLTIN_PSSV, 0 }, + + { sh1_builtin_p, + CODE_FOR_get_thread_pointer, "__builtin_thread_pointer", SH_BLTIN_VP, 0 }, + { sh1_builtin_p, + CODE_FOR_set_thread_pointer, "__builtin_set_thread_pointer", + SH_BLTIN_PV, 0 }, }; static void -sh_media_init_builtins (void) +sh_init_builtins (void) { tree shared[SH_BLTIN_NUM_SHARED_SIGNATURES]; - struct builtin_description *d; - memset (shared, 0, sizeof shared); - for (d = bdesc; d - bdesc < (int) ARRAY_SIZE (bdesc); d++) + + for (unsigned int di = 0; di < ARRAY_SIZE (bdesc); ++di) { - tree type, arg_type = 0; + builtin_description* d = &bdesc[di]; + + if (!d->is_enabled ()) + continue; + + tree type, arg_type = NULL_TREE; int signature = d->signature; - int i; if (signature < SH_BLTIN_NUM_SHARED_SIGNATURES && shared[signature]) type = shared[signature]; @@ -11694,9 +11816,9 @@ sh_media_init_builtins (void) if (! TARGET_FPU_ANY && FLOAT_MODE_P (insn_data[d->icode].operand[0].mode)) continue; - for (i = 0; i < (int) ARRAY_SIZE (args); i++) + for (unsigned int i = 0; i < ARRAY_SIZE (args); i++) args[i] = NULL_TREE; - for (i = 3; ; i--) + for (int i = 3; ; i--) { int arg = signature_args[signature][i]; int opno = i - 1 + has_result; @@ -11705,8 +11827,7 @@ sh_media_init_builtins (void) arg_type = ptr_type_node; else if (arg) arg_type = (*lang_hooks.types.type_for_mode) - (insn_data[d->icode].operand[opno].mode, - (arg & 1)); + (insn_data[d->icode].operand[opno].mode, (arg & 1)); else if (i) continue; else @@ -11726,17 +11847,6 @@ sh_media_init_builtins (void) } } -/* Returns the shmedia builtin decl for CODE. */ - -static tree -sh_media_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) -{ - if (code >= ARRAY_SIZE (bdesc)) - return error_mark_node; - - return bdesc[code].fndecl; -} - /* Implements target hook vector_mode_supported_p. */ bool sh_vector_mode_supported_p (enum machine_mode mode) @@ -11782,22 +11892,18 @@ sh_dwarf_calling_convention (const_tree func) return DW_CC_normal; } -static void -sh_init_builtins (void) -{ - if (TARGET_SHMEDIA) - sh_media_init_builtins (); -} - /* Returns the sh builtin decl for CODE. */ static tree sh_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) -{ - if (TARGET_SHMEDIA) - return sh_media_builtin_decl (code, initialize_p); - - return error_mark_node; +{ + if (code >= ARRAY_SIZE (bdesc)) + return error_mark_node; + + if (!bdesc[code].is_enabled ()) + return error_mark_node; + + return bdesc[code].fndecl; } /* Expand an expression EXP that calls a built-in function, @@ -11815,27 +11921,24 @@ sh_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, const struct builtin_description *d = &bdesc[fcode]; enum insn_code icode = d->icode; int signature = d->signature; - enum machine_mode tmode = VOIDmode; - int nop = 0, i; + int nop = 0; rtx op[4]; - rtx pat = NULL_RTX; if (signature_args[signature][0]) { if (ignore) return NULL_RTX; - tmode = insn_data[icode].operand[0].mode; - if (! target - || GET_MODE (target) != tmode + enum machine_mode tmode = insn_data[icode].operand[0].mode; + if (! target || GET_MODE (target) != tmode || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) target = gen_reg_rtx (tmode); op[nop++] = target; } else - target = 0; + target = NULL_RTX; - for (i = 1; i <= 3; i++, nop++) + for (int i = 1; i <= 3; i++, nop++) { tree arg; enum machine_mode opmode, argmode; @@ -11864,6 +11967,8 @@ sh_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, op[nop] = copy_to_mode_reg (opmode, op[nop]); } + rtx pat = NULL_RTX; + switch (nop) { case 1: @@ -12926,6 +13031,17 @@ sh_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, { enum reg_class rclass = (enum reg_class) rclass_i; + if (MEM_P (x) && GET_CODE (XEXP (x, 0)) == PLUS + && REG_P (XEXP (XEXP (x, 0), 0)) + && REGNO (XEXP (XEXP (x, 0), 0)) == GBR_REG) + return rclass == R0_REGS ? NO_REGS : R0_REGS; + + if (MEM_P (x) && REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) == GBR_REG) + return rclass == R0_REGS ? NO_REGS : R0_REGS; + + if (REG_P (x) && REGNO (x) == GBR_REG) + return NO_REGS; + if (in_p) { if (REGCLASS_HAS_FP_REG (rclass) @@ -13158,7 +13274,152 @@ sh_can_use_simple_return_p (void) return false; return true; +} + +/*------------------------------------------------------------------------------ + Address mode optimization support code +*/ + +typedef HOST_WIDE_INT disp_t; +static const disp_t MIN_DISP = HOST_WIDE_INT_MIN; +static const disp_t MAX_DISP = HOST_WIDE_INT_MAX; +static const disp_t INVALID_DISP = MAX_DISP; +/* A memory reference which is described by a base register and a + displacement. */ +class base_reg_disp +{ +public: + base_reg_disp (rtx br, disp_t d); + + bool is_reg (void) const; + bool is_disp (void) const; + rtx reg (void) const; + disp_t disp (void) const; + +private: + rtx reg_; + disp_t disp_; +}; + +inline +base_reg_disp::base_reg_disp (rtx br, disp_t d) +: reg_ (br), disp_ (d) +{ +} + +inline bool +base_reg_disp::is_reg (void) const +{ + return reg_ != NULL_RTX && disp_ != INVALID_DISP; +} + +inline bool +base_reg_disp::is_disp (void) const +{ + return reg_ == NULL_RTX && disp_ != INVALID_DISP; +} + +inline rtx +base_reg_disp::reg (void) const +{ + return reg_; +} + +inline disp_t +base_reg_disp::disp (void) const +{ + return disp_; +} + +/* Find the base register and calculate the displacement for a given + address rtx 'x'. + This is done by walking the insn list backwards and following SET insns + that set the value of the specified reg 'x'. */ +static base_reg_disp +sh_find_base_reg_disp (rtx insn, rtx x, disp_t disp = 0, rtx base_reg = NULL) +{ + if (REG_P (x)) + { + if (REGNO (x) == GBR_REG) + return base_reg_disp (x, disp); + + /* We've reached a hard-reg. This is probably the point where + function args are copied to pseudos. Do not go any further and + stick to the pseudo. If the original mem addr was in a hard reg + from the beginning, it will become the base reg. */ + if (REGNO (x) < FIRST_PSEUDO_REGISTER) + return base_reg_disp (base_reg != NULL ? base_reg : x, disp); + + /* Try to find the previous insn that sets the reg. */ + for (rtx i = prev_nonnote_insn (insn); i != NULL; + i = prev_nonnote_insn (i)) + { + if (!NONJUMP_INSN_P (i)) + continue; + + rtx p = PATTERN (i); + if (p != NULL && GET_CODE (p) == SET && REG_P (XEXP (p, 0)) + && REGNO (XEXP (p, 0)) == REGNO (x)) + { + /* If the recursion can't find out any more details about the + source of the set, then this reg becomes our new base reg. */ + return sh_find_base_reg_disp (i, XEXP (p, 1), disp, XEXP (p, 0)); + } + } + + /* When here, no previous insn was found that sets the reg. + The input reg is already the base reg. */ + return base_reg_disp (x, disp); + } + + else if (GET_CODE (x) == PLUS) + { + base_reg_disp left_val = sh_find_base_reg_disp (insn, XEXP (x, 0)); + base_reg_disp right_val = sh_find_base_reg_disp (insn, XEXP (x, 1)); + + /* Either left or right val must be a reg. + We don't handle the case of 'reg + reg' here. */ + if (left_val.is_reg () && right_val.is_disp ()) + return base_reg_disp (left_val.reg (), left_val.disp () + + right_val.disp () + disp); + else if (right_val.is_reg () && left_val.is_disp ()) + return base_reg_disp (right_val.reg (), right_val.disp () + + left_val.disp () + disp); + else + return base_reg_disp (base_reg, disp); + } + + else if (CONST_INT_P (x)) + return base_reg_disp (NULL, disp + INTVAL (x)); + + /* Didn't find anything useful. */ + return base_reg_disp (base_reg, disp); +} + +/* Given an insn and a memory operand, try to find an equivalent GBR + based memory address and return the corresponding new memory address. + Return NULL_RTX if not found. */ +rtx +sh_find_equiv_gbr_addr (rtx insn, rtx mem) +{ + if (!MEM_P (mem)) + return NULL_RTX; + + /* Leave post/pre inc/dec or any other side effect addresses alone. */ + if (side_effects_p (XEXP (mem, 0))) + return NULL_RTX; + + base_reg_disp gbr_disp = sh_find_base_reg_disp (insn, XEXP (mem, 0)); + + if (gbr_disp.is_reg () && REGNO (gbr_disp.reg ()) == GBR_REG) + { + rtx disp = GEN_INT (gbr_disp.disp ()); + if (gbr_displacement (disp, GET_MODE (mem))) + return gen_rtx_PLUS (SImode, gen_rtx_REG (SImode, GBR_REG), disp); + } + + return NULL_RTX; } #include "gt-sh.h" diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 7a1c4d33a58..0a1cd09c1f8 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -175,6 +175,7 @@ (UNSPECV_WINDOW_END 10) (UNSPECV_CONST_END 11) (UNSPECV_EH_RETURN 12) + (UNSPECV_GBR 13) ]) ;; ------------------------------------------------------------------------- @@ -5188,11 +5189,61 @@ label: "neg %1,%0" [(set_attr "type" "arith")]) -(define_insn "one_cmplsi2" +(define_insn_and_split "one_cmplsi2" [(set (match_operand:SI 0 "arith_reg_dest" "=r") (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))] "TARGET_SH1" "not %1,%0" + "&& can_create_pseudo_p ()" + [(set (reg:SI T_REG) (ge:SI (match_dup 1) (const_int 0))) + (set (match_dup 0) (reg:SI T_REG))] +{ +/* PR 54685 + If the result of 'unsigned int <= 0x7FFFFFFF' ends up as the following + sequence: + + (set (reg0) (not:SI (reg0) (reg1))) + (parallel [(set (reg2) (lshiftrt:SI (reg0) (const_int 31))) + (clobber (reg:SI T_REG))]) + + ... match and combine the sequence manually in the split pass after the + combine pass. Notice that combine does try the target pattern of this + split, but if the pattern is added it interferes with other patterns, in + particular with the div0s comparisons. + This could also be done with a peephole but doing it here before register + allocation can save one temporary. + When we're here, the not:SI pattern obviously has been matched already + and we only have to see whether the following insn is the left shift. */ + + rtx i = next_nonnote_insn_bb (curr_insn); + if (i == NULL_RTX || !NONJUMP_INSN_P (i)) + FAIL; + + rtx p = PATTERN (i); + if (GET_CODE (p) != PARALLEL || XVECLEN (p, 0) != 2) + FAIL; + + rtx p0 = XVECEXP (p, 0, 0); + rtx p1 = XVECEXP (p, 0, 1); + + if (/* (set (reg2) (lshiftrt:SI (reg0) (const_int 31))) */ + GET_CODE (p0) == SET + && GET_CODE (XEXP (p0, 1)) == LSHIFTRT + && REG_P (XEXP (XEXP (p0, 1), 0)) + && REGNO (XEXP (XEXP (p0, 1), 0)) == REGNO (operands[0]) + && CONST_INT_P (XEXP (XEXP (p0, 1), 1)) + && INTVAL (XEXP (XEXP (p0, 1), 1)) == 31 + + /* (clobber (reg:SI T_REG)) */ + && GET_CODE (p1) == CLOBBER && REG_P (XEXP (p1, 0)) + && REGNO (XEXP (p1, 0)) == T_REG) + { + operands[0] = XEXP (p0, 0); + set_insn_deleted (i); + } + else + FAIL; +} [(set_attr "type" "arith")]) (define_expand "one_cmpldi2" @@ -10029,13 +10080,166 @@ label: DONE; }) -(define_insn "load_gbr" - [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG)) - (use (reg:SI GBR_REG))] +;;------------------------------------------------------------------------------ +;; Thread pointer getter and setter. +;; +;; On SH the thread pointer is kept in the GBR. +;; These patterns are usually expanded from the respective built-in functions. +(define_expand "get_thread_pointer" + [(set (match_operand:SI 0 "register_operand") (reg:SI GBR_REG))] + "TARGET_SH1") + +;; The store_gbr insn can also be used on !TARGET_SH1 for doing TLS accesses. +(define_insn "store_gbr" + [(set (match_operand:SI 0 "register_operand" "=r") (reg:SI GBR_REG))] "" "stc gbr,%0" [(set_attr "type" "tls_load")]) +(define_expand "set_thread_pointer" + [(set (reg:SI GBR_REG) + (unspec_volatile:SI [(match_operand:SI 0 "register_operand")] + UNSPECV_GBR))] + "TARGET_SH1") + +(define_insn "load_gbr" + [(set (reg:SI GBR_REG) + (unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] + UNSPECV_GBR))] + "TARGET_SH1" + "ldc %0,gbr" + [(set_attr "type" "move")]) + +;;------------------------------------------------------------------------------ +;; Thread pointer relative memory loads and stores. +;; +;; On SH there are GBR displacement address modes which can be utilized to +;; access memory behind the thread pointer. +;; Since we do not allow using GBR for general purpose memory accesses, these +;; GBR addressing modes are formed by the combine pass. +;; This could be done with fewer patterns than below by using a mem predicate +;; for the GBR mem, but then reload would try to reload addresses with a +;; zero displacement for some strange reason. + +(define_insn "*mov<mode>_gbr_load" + [(set (match_operand:QIHISI 0 "register_operand" "=z") + (mem:QIHISI (plus:SI (reg:SI GBR_REG) + (match_operand:QIHISI 1 "gbr_displacement"))))] + "TARGET_SH1" + "mov.<bwl> @(%O1,gbr),%0" + [(set_attr "type" "load")]) + +(define_insn "*mov<mode>_gbr_load" + [(set (match_operand:QIHISI 0 "register_operand" "=z") + (mem:QIHISI (reg:SI GBR_REG)))] + "TARGET_SH1" + "mov.<bwl> @(0,gbr),%0" + [(set_attr "type" "load")]) + +(define_insn "*mov<mode>_gbr_load" + [(set (match_operand:SI 0 "register_operand" "=z") + (sign_extend:SI + (mem:QIHI (plus:SI (reg:SI GBR_REG) + (match_operand:QIHI 1 "gbr_displacement")))))] + "TARGET_SH1" + "mov.<bw> @(%O1,gbr),%0" + [(set_attr "type" "load")]) + +(define_insn "*mov<mode>_gbr_load" + [(set (match_operand:SI 0 "register_operand" "=z") + (sign_extend:SI (mem:QIHI (reg:SI GBR_REG))))] + "TARGET_SH1" + "mov.<bw> @(0,gbr),%0" + [(set_attr "type" "load")]) + +(define_insn "*mov<mode>_gbr_store" + [(set (mem:QIHISI (plus:SI (reg:SI GBR_REG) + (match_operand:QIHISI 0 "gbr_displacement"))) + (match_operand:QIHISI 1 "register_operand" "z"))] + "TARGET_SH1" + "mov.<bwl> %1,@(%O0,gbr)" + [(set_attr "type" "store")]) + +(define_insn "*mov<mode>_gbr_store" + [(set (mem:QIHISI (reg:SI GBR_REG)) + (match_operand:QIHISI 0 "register_operand" "z"))] + "TARGET_SH1" + "mov.<bwl> %0,@(0,gbr)" + [(set_attr "type" "store")]) + +;; Sometimes memory accesses do not get combined with the store_gbr insn, +;; in particular when the displacements are in the range of the regular move +;; insns. Thus, in the first split pass after the combine pass we search +;; for missed opportunities and try to fix them up ourselves. +;; If an equivalent GBR address can be determined the load / store is split +;; into one of the GBR load / store patterns. +;; All of that must happen before reload (GBR address modes use R0 as the +;; other operand) and there's no point of doing it if the GBR is not +;; referenced in a function at all. +(define_split + [(set (match_operand:QIHISI 0 "register_operand") + (match_operand:QIHISI 1 "memory_operand"))] + "TARGET_SH1 && !reload_in_progress && !reload_completed + && df_regs_ever_live_p (GBR_REG)" + [(set (match_dup 0) (match_dup 1))] +{ + rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); + if (gbr_mem != NULL_RTX) + operands[1] = change_address (operands[1], GET_MODE (operands[1]), gbr_mem); + else + FAIL; +}) + +(define_split + [(set (match_operand:SI 0 "register_operand") + (sign_extend:SI (match_operand:QIHI 1 "memory_operand")))] + "TARGET_SH1 && !reload_in_progress && !reload_completed + && df_regs_ever_live_p (GBR_REG)" + [(set (match_dup 0) (sign_extend:SI (match_dup 1)))] +{ + rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); + if (gbr_mem != NULL_RTX) + operands[1] = change_address (operands[1], GET_MODE (operands[1]), gbr_mem); + else + FAIL; +}) + +;; On SH2A we've got movu.b and movu.w for doing zero-extending mem loads. +;; Split those so that a GBR load can be used. +(define_split + [(set (match_operand:SI 0 "register_operand") + (zero_extend:SI (match_operand:QIHI 1 "memory_operand")))] + "TARGET_SH2A && !reload_in_progress && !reload_completed + && df_regs_ever_live_p (GBR_REG)" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (zero_extend:SI (match_dup 2)))] +{ + rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[1]); + if (gbr_mem != NULL_RTX) + { + operands[2] = gen_reg_rtx (GET_MODE (operands[1])); + operands[1] = change_address (operands[1], GET_MODE (operands[1]), + gbr_mem); + } + else + FAIL; +}) + +(define_split + [(set (match_operand:QIHISI 0 "memory_operand") + (match_operand:QIHISI 1 "register_operand"))] + "TARGET_SH1 && !reload_in_progress && !reload_completed + && df_regs_ever_live_p (GBR_REG)" + [(set (match_dup 0) (match_dup 1))] +{ + rtx gbr_mem = sh_find_equiv_gbr_addr (curr_insn, operands[0]); + if (gbr_mem != NULL_RTX) + operands[0] = change_address (operands[0], GET_MODE (operands[0]), gbr_mem); + else + FAIL; +}) + +;;------------------------------------------------------------------------------ ;; case instruction for switch statements. ;; Operand 0 is index diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index fe72a9ca7e4..660a2199c8f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,138 @@ +2012-10-08 Dodji Seketeli <dodji@redhat.com> + + PR c++/53528 C++11 attribute support + * cp-tree.h (enum cpp0x_warn_str::CPP0X_ATTRIBUTES): New member. + (enum cp_decl_spec::ds_std_attribute): New enumerator. + (struct cp_decl_specifier_seq::std_attributes): New field. + (cxx_alignas_expr, warn_misplaced_attr_for_class_type): Declare + new functions. + (check_tag_decl): Take an extra parameter for explicit + instantiations. + * decl.c (warn_misplaced_attr_for_class_type): Extract from ... + (check_tag_decl): ... here. Add check for c++11 attributes being + applied to an explicit instantiation. Take an extra parameter for + explicit instantiations. + (grokdeclarator): Make sure a c++11 attribute after an array + declarator appertains to the array, an attribute after a function + declarator appertains to the function type, an attribute after a + declarator-id appertains to the entity being declared, and an + attribute after a pointer declarator appertain to the pointer. + * decl2.c (is_late_template_attribute): Use get_attribute_name. + * error.c (maybe_warn_cpp0x): Support + CPP0X_GENERALIZED_ATTRIBUTES. + * parser.c (cp_next_tokens_can_be_attribute_p) + (cp_next_tokens_can_be_gnu_attribute_p) + (cp_next_tokens_can_be_std_attribute_p) + (cp_nth_tokens_can_be_attribute_p) + (cp_nth_tokens_can_be_gnu_attribute_p) + (cp_nth_tokens_can_be_std_attribute_p) + (cp_parser_gnu_attribute_list, cp_parser_std_attribute) + (cp_parser_std_attribute_spec, cp_parser_std_attribute_spec_seq) + (cp_parser_attributes_opt, cp_parser_std_attribute_list): New + static functions. + (cp_parser_gnu_attributes_opt): Replace cp_parser_attributes_opt. + (cp_parser_gnu_attribute_list): Replace cp_parser_attribute_list. + (cp_parser_postfix_expression): Disallow "[[" tokens here. + (cp_parser_label_for_labeled_statement): Use take an extra + parameter for attributes. + (cp_parser_block_declaration): Use + cp_nth_tokens_can_be_std_attribute_p here. + (cp_parser_decl_specifier_seq): Likewise. Store C++11 attributes + that appears in in decl specifiers in cp_decl_specifier_seq::std_attributes. + declaration. Emit proper warning about misplaced c++11 attributes + for class type. + (cp_parser_explicit_instantiation): Adjust call to check_tag_decl. + (cp_parser_init_declarator): Parsing attributes here is no more a + GNU extension in c++-11. + (cp_parser_type_specifier_seq): Use + cp_next_tokens_can_be_attribute_p. + (cp_parser_direct_declarator): Likewise. Hang c++11 attributes + following the declarator to its syntactic construct. It'll later + be applied to the proper appertaining entity by grokdeclarator. + (cp_parser_ptr_operator): Likewise. + (make_declarator): Initialize cp_declarator::std_attribute. + (make_pointer_declarator, make_reference_declarator) + (make_ptrmem_declarator, cp_parser_make_indirect_declarator): Take + attributes that appertain to the pointer/reference in argument. + (cp_parser_ptr_operator): Take an out parameter for c++11 + attributes. Update comments. + (cp_parser_new_declarator_opt) + (cp_parser_conversion_declarator_opt): Adjust. + (cp_parser_declarator): Likewise. Handle C++11 attributes. + Rename attributes to gnu_attribute for better legibility. + (cp_parser_simple_declaration): Update comment. + (cp_parser_class_specifier_1): Parse GNU attributes specifically + (cp_parser_enum_specifier): Accept only gnu attributes after the + specifier. + (cp_parser_member_declaration): Don't clear attributes -- intended + for the entity being declared -- too early because check_tag_decl + needs them. + (cp_parser_statement): Update comment. Parse optional c++11 + attributes at the beginning of the relevant kind of statements and + ignore them, for now, unless when calling + cp_parser_label_for_labeled_statement. + (cp_parser_label_for_labeled_statement): Take c++11 attributes + in parameter. + * semantics.c (potential_constant_expression_1): Likewise. + * typeck.c (fundamental_alignment_p, cxx_alignas_expr): New public + functions. + +2012-10-07 Paolo Carlini <paolo.carlini@oracle.com> + + * pt.c (fold_non_dependent_expr_sfinae): Remove static specifier. + (tsubst_copy_and_build): Use get_target_expr_sfinae. + * call.c (build_conditional_expr_1, convert_like_real): Likewise. + * cvt.c (build_up_reference): Likewise. + (ocp_convert): Use abstract_virtuals_error_sfinae. + (build_up_reference): Propagate complain to cp_build_addr_expr. + * decl.c (compute_array_index_type): Use fold_non_dependent_expr_sfinae. + * cp-tree.h: Update declarations. + + * cvt.c (build_expr_type_conversion): Tidy. + + * tree.c (stabilize_aggr_init): Change to static. + +2012-10-07 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/51422 + * semantics.c (is_normal_capture_proxy): Return true for + error_mark_node as DECL_VALUE_EXPR. + +2012-10-05 Jakub Jelinek <jakub@redhat.com> + + * cp-tree.h (SIZEOF_EXPR_TYPE_P): Define. + * tree.c (cp_tree_equal): Handle SIZEOF_EXPR with + SIZEOF_EXPR_TYPE_P. + * mangle.c (write_expression): Likewise. + * cxx-pretty-print.c (pp_cxx_unary_expression): Likewise. + * error.c (dump_expr): Likewise. + * parser.c (cp_parser_unary_expression): For sizeof call + cxx_sizeof_or_alignof_{type,expr} just for diagnostics and + return SIZEOF_EXPR with the operand. + * pt.c (tsubst_copy, tsubst_copy_and_build): For SIZEOF_EXPR, + call cxx_sizeof_or_alignof_{type,expr} for diagnostics, but + return SIZEOF_EXPR with tsubsted operand. + (value_dependent_expression_p): Handle SIZEOF_EXPR with + SIZEOF_EXPR_TYPE_P. + (instantiation_dependent_r): Likewise. + * call.c (null_ptr_cst_p): Call maybe_constant_value for C++98. + * semantics.c (finish_call_expr): Call + sizeof_pointer_memaccess_warning if needed. + (cxx_eval_constant_expression): Handle SIZEOF_EXPR. + (potential_constant_expression_1): Remove early exit for + C++98. Handle PROPERTY_REF. + * decl.c (duplicate_decls): When redeclaring a builtin function, + keep the merged decl builtin also if newdecl is a gnu_inline + inline definition. + (fold_sizeof_expr_r): New function. + (compute_array_index_type): Fold SIZEOF_EXPRs in itype. + * cp-gimplify.c (cp_genericize_r): Fold SIZEOF_EXPR. + * typeck.c (cp_build_binary_op): For warn_for_sign_compare + try harder using maybe_constant_value to get INTEGER_CSTs. + + * decl.c (stabilize_vla_size): Call pointer_set_destroy + at the end. + 2012-10-04 Arnaud Charlet <charlet@adacore.com> * decl2.c (cp_write_global_declarations): Fix handling of diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d0492d8deef..f58dc8a52e0 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -557,7 +557,7 @@ null_ptr_cst_p (tree t) { /* Core issue 903 says only literal 0 is a null pointer constant. */ if (cxx_dialect < cxx0x) - t = integral_constant_value (t); + t = maybe_constant_value (t); STRIP_NOPS (t); if (integer_zerop (t) && !TREE_OVERFLOW (t)) return true; @@ -4777,7 +4777,7 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, but now we sometimes wrap them in NOP_EXPRs so the test would fail. */ if (CLASS_TYPE_P (TREE_TYPE (result))) - result = get_target_expr (result); + result = get_target_expr_sfinae (result, complain); /* If this expression is an rvalue, but might be mistaken for an lvalue, we must add a NON_LVALUE_EXPR. */ result = rvalue (result); @@ -5883,7 +5883,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, field = next_initializable_field (DECL_CHAIN (field)); CONSTRUCTOR_APPEND_ELT (vec, field, size_int (len)); new_ctor = build_constructor (totype, vec); - return get_target_expr (new_ctor); + return get_target_expr_sfinae (new_ctor, complain); } case ck_aggr: @@ -5899,7 +5899,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, return fold_if_not_in_template (expr); } expr = reshape_init (totype, expr, complain); - return get_target_expr (digest_init (totype, expr, complain)); + return get_target_expr_sfinae (digest_init (totype, expr, complain), + complain); default: break; diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index dd2ef067c8f..6178993fe89 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -1,6 +1,7 @@ /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, + 2012 Free Software Foundation, Inc. Contributed by Jason Merrill <jason@redhat.com> @@ -1119,6 +1120,22 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) genericize_break_stmt (stmt_p); else if (TREE_CODE (stmt) == OMP_FOR) genericize_omp_for_stmt (stmt_p, walk_subtrees, data); + else if (TREE_CODE (stmt) == SIZEOF_EXPR) + { + if (SIZEOF_EXPR_TYPE_P (stmt)) + *stmt_p + = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (stmt, 0)), + SIZEOF_EXPR, false); + else if (TYPE_P (TREE_OPERAND (stmt, 0))) + *stmt_p = cxx_sizeof_or_alignof_type (TREE_OPERAND (stmt, 0), + SIZEOF_EXPR, false); + else + *stmt_p = cxx_sizeof_or_alignof_expr (TREE_OPERAND (stmt, 0), + SIZEOF_EXPR, false); + if (*stmt_p == error_mark_node) + *stmt_p = size_one_node; + return NULL; + } pointer_set_insert (p_set, *stmt_p); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index bfe7ad70e0c..a1d44240189 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -78,6 +78,7 @@ c-common.h, not after. OVL_ARG_DEPENDENT (in OVERLOAD) PACK_EXPANSION_LOCAL_P (in *_PACK_EXPANSION) TINFO_RECHECK_ACCESS_P (in TEMPLATE_INFO) + SIZEOF_EXPR_TYPE_P (in SIZEOF_EXPR) 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -417,7 +418,9 @@ typedef enum cpp0x_warn_str /* user defined literals */ CPP0X_USER_DEFINED_LITERALS, /* delegating constructors */ - CPP0X_DELEGATING_CTORS + CPP0X_DELEGATING_CTORS, + /* C++11 attributes */ + CPP0X_ATTRIBUTES } cpp0x_warn_str; /* The various kinds of operation used by composite_pointer_type. */ @@ -4055,6 +4058,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define CONVERT_EXPR_VBASE_PATH(NODE) \ TREE_LANG_FLAG_0 (CONVERT_EXPR_CHECK (NODE)) +/* True if SIZEOF_EXPR argument is type. */ +#define SIZEOF_EXPR_TYPE_P(NODE) \ + TREE_LANG_FLAG_0 (SIZEOF_EXPR_CHECK (NODE)) + /* An enumeration of the kind of tags that C++ accepts. */ enum tag_types { none_type = 0, /* Not a tag type. */ @@ -4679,6 +4686,7 @@ typedef enum cp_decl_spec { ds_type_spec, ds_redefined_builtin_type_spec, ds_attribute, + ds_std_attribute, ds_storage_class, ds_long_long, ds_last /* This enumerator must always be the last one. */ @@ -4697,6 +4705,8 @@ typedef struct cp_decl_specifier_seq { tree type; /* The attributes, if any, provided with the specifier sequence. */ tree attributes; + /* The c++11 attributes that follows the type specifier. */ + tree std_attributes; /* If non-NULL, a built-in type that the user attempted to redefine to some other type. */ tree redefined_builtin_type; @@ -4765,8 +4775,14 @@ struct cp_declarator { to indicate this is a parameter pack. */ BOOL_BITFIELD parameter_pack_p : 1; location_t id_loc; /* Currently only set for cdk_id and cdk_function. */ - /* Attributes that apply to this declarator. */ + /* GNU Attributes that apply to this declarator. If the declarator + is a pointer or a reference, these attribute apply to the type + pointed to. */ tree attributes; + /* Standard C++11 attributes that apply to this declarator. If the + declarator is a pointer or a reference, these attributes apply + to the pointer, rather than to the type pointed to. */ + tree std_attributes; /* For all but cdk_id and cdk_error, the contained declarator. For cdk_id and cdk_error, guaranteed to be NULL. */ cp_declarator *declarator; @@ -5063,7 +5079,9 @@ extern tree build_cp_library_fn_ptr (const char *, tree); extern tree push_library_fn (tree, tree, tree); extern tree push_void_library_fn (tree, tree); extern tree push_throw_library_fn (tree, tree); -extern tree check_tag_decl (cp_decl_specifier_seq *); +extern void warn_misplaced_attr_for_class_type (source_location location, + tree class_type); +extern tree check_tag_decl (cp_decl_specifier_seq *, bool); extern tree shadow_tag (cp_decl_specifier_seq *); extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *, bool); extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *); @@ -5406,6 +5424,7 @@ extern tree build_non_dependent_expr (tree); extern void make_args_non_dependent (VEC(tree,gc) *); extern bool reregister_specialization (tree, tree, tree); extern tree fold_non_dependent_expr (tree); +extern tree fold_non_dependent_expr_sfinae (tree, tsubst_flags_t); extern bool alias_type_or_template_p (tree); extern bool alias_template_specialization_p (tree); extern bool explicit_class_specialization_p (tree); @@ -5695,7 +5714,6 @@ extern void lang_check_failed (const char *, int, const char *) ATTRIBUTE_NORETURN; extern tree stabilize_expr (tree, tree *); extern void stabilize_call (tree, tree *); -extern void stabilize_aggr_init (tree, tree *); extern bool stabilize_init (tree, tree *); extern tree add_stmt_to_compound (tree, tree); extern void init_tree (void); @@ -5824,6 +5842,7 @@ extern int comp_cv_qualification (const_tree, const_tree); extern int comp_cv_qual_signature (tree, tree); extern tree cxx_sizeof_or_alignof_expr (tree, enum tree_code, bool); extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool); +extern tree cxx_alignas_expr (tree); extern tree cxx_sizeof_nowarn (tree); extern tree is_bitfield_expr_with_lowered_type (const_tree); extern tree unlowered_expr_type (const_tree); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 86f01abf2f3..d30c7e5309e 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -339,12 +339,12 @@ build_up_reference (tree type, tree arg, int flags, tree decl, LOOKUP_ONLYCONVERTING|DIRECT_BIND); } else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg)) - return get_target_expr (arg); + return get_target_expr_sfinae (arg, complain); /* If we had a way to wrap this up, and say, if we ever needed its address, transform all occurrences of the register, into a memory reference we could win better. */ - rval = cp_build_addr_expr (arg, tf_warning_or_error); + rval = cp_build_addr_expr (arg, complain); if (rval == error_mark_node) return error_mark_node; @@ -842,7 +842,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags, ctor = e; - if (abstract_virtuals_error (NULL_TREE, type)) + if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain)) return error_mark_node; if (BRACE_ENCLOSED_INITIALIZER_P (ctor)) @@ -1514,8 +1514,6 @@ build_expr_type_conversion (int desires, tree expr, bool complain) "converting NULL to non-pointer type"); } - basetype = TREE_TYPE (expr); - if (basetype == error_mark_node) return error_mark_node; diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index 03d9149f4cf..ce64a7b2377 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -1,6 +1,6 @@ /* Implementation of subroutines for the GNU C++ pretty-printer. Copyright (C) 2003, 2004, 2005, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net> This file is part of GCC. @@ -798,7 +798,13 @@ pp_cxx_unary_expression (cxx_pretty_printer *pp, tree t) case ALIGNOF_EXPR: pp_cxx_ws_string (pp, code == SIZEOF_EXPR ? "sizeof" : "__alignof__"); pp_cxx_whitespace (pp); - if (TYPE_P (TREE_OPERAND (t, 0))) + if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t)) + { + pp_cxx_left_paren (pp); + pp_cxx_type_id (pp, TREE_TYPE (TREE_OPERAND (t, 0))); + pp_cxx_right_paren (pp); + } + else if (TYPE_P (TREE_OPERAND (t, 0))) { pp_cxx_left_paren (pp); pp_cxx_type_id (pp, TREE_OPERAND (t, 0)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d0933efc8dd..2848ad5b7be 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2160,39 +2160,40 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl); DECL_RESULT (olddecl) = DECL_RESULT (newdecl); } + /* If redeclaring a builtin function, it stays built in + if newdecl is a gnu_inline definition, or if newdecl is just + a declaration. */ + if (DECL_BUILT_IN (olddecl) + && (new_defines_function ? GNU_INLINE_P (newdecl) : types_match)) + { + DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); + DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); + /* If we're keeping the built-in definition, keep the rtl, + regardless of declaration matches. */ + COPY_DECL_RTL (olddecl, newdecl); + if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL) + { + enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl); + switch (fncode) + { + /* If a compatible prototype of these builtin functions + is seen, assume the runtime implements it with the + expected semantics. */ + case BUILT_IN_STPCPY: + if (builtin_decl_explicit_p (fncode)) + set_builtin_decl_implicit_p (fncode, true); + break; + default: + break; + } + } + } if (new_defines_function) /* If defining a function declared with other language linkage, use the previously declared language linkage. */ SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl)); else if (types_match) { - /* If redeclaring a builtin function, and not a definition, - it stays built in. */ - if (DECL_BUILT_IN (olddecl)) - { - DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); - DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); - /* If we're keeping the built-in definition, keep the rtl, - regardless of declaration matches. */ - COPY_DECL_RTL (olddecl, newdecl); - if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL) - { - enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl); - switch (fncode) - { - /* If a compatible prototype of these builtin functions - is seen, assume the runtime implements it with the - expected semantics. */ - case BUILT_IN_STPCPY: - if (builtin_decl_explicit_p (fncode)) - set_builtin_decl_implicit_p (fncode, true); - break; - default: - break; - } - } - } - DECL_RESULT (newdecl) = DECL_RESULT (olddecl); /* Don't clear out the arguments if we're just redeclaring a function. */ @@ -4131,13 +4132,32 @@ fixup_anonymous_aggr (tree t) } } +/* Warn for an attribute located at LOCATION that appertains to the + class type CLASS_TYPE that has not been properly placed after its + class-key, in it class-specifier. */ + +void +warn_misplaced_attr_for_class_type (source_location location, + tree class_type) +{ + gcc_assert (TAGGED_TYPE_P (class_type)); + + warning_at (location, OPT_Wattributes, + "attribute ignored in declaration " + "of %q#T", class_type); + inform (location, + "attribute for %q#T must follow the %qs keyword", + class_type, class_key_or_enum_as_string (class_type)); +} + /* Make sure that a declaration with no declarator is well-formed, i.e. just declares a tagged type or anonymous union. Returns the type declared; or NULL_TREE if none. */ tree -check_tag_decl (cp_decl_specifier_seq *declspecs) +check_tag_decl (cp_decl_specifier_seq *declspecs, + bool explicit_type_instantiation_p) { int saw_friend = decl_spec_seq_has_spec_p (declspecs, ds_friend); int saw_typedef = decl_spec_seq_has_spec_p (declspecs, ds_typedef); @@ -4246,10 +4266,22 @@ check_tag_decl (cp_decl_specifier_seq *declspecs) /* For a template class (an explicit instantiation), use the current location. */ loc = input_location; - warning_at (loc, OPT_Wattributes, "attribute ignored in declaration " - "of %q#T", declared_type); - inform (loc, "attribute for %q#T must follow the %qs keyword", - declared_type, class_key_or_enum_as_string (declared_type)); + + if (explicit_type_instantiation_p) + /* [dcl.attr.grammar]/4: + + No attribute-specifier-seq shall appertain to an explicit + instantiation. */ + { + warning_at (loc, OPT_Wattributes, + "attribute ignored in explicit instantiation %q#T", + declared_type); + inform (loc, + "no attribute can be applied to " + "an explicit instantiation"); + } + else + warn_misplaced_attr_for_class_type (loc, declared_type); } return declared_type; @@ -4271,7 +4303,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs) tree shadow_tag (cp_decl_specifier_seq *declspecs) { - tree t = check_tag_decl (declspecs); + tree t = check_tag_decl (declspecs, + /*explicit_type_instantiation_p=*/false); if (!t) return NULL_TREE; @@ -7931,6 +7964,36 @@ stabilize_vla_size (tree size) struct pointer_set_t *pset = pointer_set_create (); /* Break out any function calls into temporary variables. */ cp_walk_tree (&size, stabilize_save_expr_r, pset, pset); + pointer_set_destroy (pset); +} + +/* Helper function for compute_array_index_type. Look for SIZEOF_EXPR + not inside of SAVE_EXPR and fold them. */ + +static tree +fold_sizeof_expr_r (tree *expr_p, int *walk_subtrees, void *data) +{ + tree expr = *expr_p; + if (TREE_CODE (expr) == SAVE_EXPR || TYPE_P (expr)) + *walk_subtrees = 0; + else if (TREE_CODE (expr) == SIZEOF_EXPR) + { + *(bool *)data = true; + if (SIZEOF_EXPR_TYPE_P (expr)) + expr = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (expr, 0)), + SIZEOF_EXPR, false); + else if (TYPE_P (TREE_OPERAND (expr, 0))) + expr = cxx_sizeof_or_alignof_type (TREE_OPERAND (expr, 0), SIZEOF_EXPR, + false); + else + expr = cxx_sizeof_or_alignof_expr (TREE_OPERAND (expr, 0), SIZEOF_EXPR, + false); + if (expr == error_mark_node) + expr = size_one_node; + *expr_p = expr; + *walk_subtrees = 0; + } + return NULL; } /* Given the SIZE (i.e., number of elements) in an array, compute an @@ -7959,7 +8022,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) NOP_EXPR with TREE_SIDE_EFFECTS; don't fold in that case. */; else { - size = fold_non_dependent_expr (size); + size = fold_non_dependent_expr_sfinae (size, complain); if (CLASS_TYPE_P (type) && CLASSTYPE_LITERAL_P (type)) @@ -8126,8 +8189,21 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) processing_template_decl = saved_processing_template_decl; if (!TREE_CONSTANT (itype)) - /* A variable sized array. */ - itype = variable_size (itype); + { + /* A variable sized array. */ + itype = variable_size (itype); + if (TREE_CODE (itype) != SAVE_EXPR) + { + /* Look for SIZEOF_EXPRs in itype and fold them, otherwise + they might survive till gimplification. */ + tree newitype = itype; + bool found = false; + cp_walk_tree_without_duplicates (&newitype, + fold_sizeof_expr_r, &found); + if (found) + itype = variable_size (fold (newitype)); + } + } /* Make sure that there was no overflow when creating to a signed index type. (For example, on a 32-bit machine, an array with size 2^32 - 1 is too big.) */ @@ -9134,6 +9210,15 @@ grokdeclarator (const cp_declarator *declarator, } } + if (declspecs->std_attributes) + { + /* Apply the c++11 attributes to the type preceding them. */ + source_location saved_loc = input_location; + input_location = declspecs->locations[ds_std_attribute]; + decl_attributes (&type, declspecs->std_attributes, 0); + input_location = saved_loc; + } + /* Determine the type of the entity declared by recurring on the declarator. */ for (; declarator; declarator = declarator->declarator) @@ -9171,6 +9256,13 @@ grokdeclarator (const cp_declarator *declarator, case cdk_array: type = create_array_type_for_decl (dname, type, declarator->u.array.bounds); + if (declarator->std_attributes) + /* [dcl.array]/1: + + The optional attribute-specifier-seq appertains to the + array. */ + returned_attrs = chainon (returned_attrs, + declarator->std_attributes); break; case cdk_function: @@ -9367,6 +9459,13 @@ grokdeclarator (const cp_declarator *declarator, } type = build_function_type (type, arg_types); + if (declarator->std_attributes) + /* [dcl.fct]/2: + + The optional attribute-specifier-seq appertains to + the function type. */ + decl_attributes (&type, declarator->std_attributes, + 0); } break; @@ -9529,6 +9628,17 @@ grokdeclarator (const cp_declarator *declarator, declarator->u.pointer.qualifiers); type_quals = cp_type_quals (type); } + + /* Apply C++11 attributes to the pointer, and not to the + type pointed to. This is unlike what is done for GNU + attributes above. It is to comply with [dcl.ptr]/1: + + [the optional attribute-specifier-seq (7.6.1) appertains + to the pointer and not to the object pointed to]. */ + if (declarator->std_attributes) + decl_attributes (&type, declarator->std_attributes, + 0); + ctype = NULL_TREE; break; @@ -9654,6 +9764,13 @@ grokdeclarator (const cp_declarator *declarator, attrlist = &returned_attrs; } + if (declarator + && declarator->kind == cdk_id + && declarator->std_attributes) + /* [dcl.meaning]/1: The optional attribute-specifier-seq following + a declarator-id appertains to the entity that is declared. */ + *attrlist = chainon (*attrlist, declarator->std_attributes); + /* Handle parameter packs. */ if (parameter_pack_p) { diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 87e38d3bf6f..aad3d0b26f7 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1091,7 +1091,7 @@ grokbitfield (const cp_declarator *declarator, static bool is_late_template_attribute (tree attr, tree decl) { - tree name = TREE_PURPOSE (attr); + tree name = get_attribute_name (attr); tree args = TREE_VALUE (attr); const struct attribute_spec *spec = lookup_attribute_spec (name); tree arg; diff --git a/gcc/cp/error.c b/gcc/cp/error.c index c8b614b165c..2934c9b1078 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -2312,7 +2312,9 @@ dump_expr (tree t, int flags) } pp_cxx_whitespace (cxx_pp); pp_cxx_left_paren (cxx_pp); - if (TYPE_P (TREE_OPERAND (t, 0))) + if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t)) + dump_type (TREE_TYPE (TREE_OPERAND (t, 0)), flags); + else if (TYPE_P (TREE_OPERAND (t, 0))) dump_type (TREE_OPERAND (t, 0), flags); else dump_expr (TREE_OPERAND (t, 0), flags); @@ -3372,6 +3374,11 @@ maybe_warn_cpp0x (cpp0x_warn_str str) "delegating constructors " "only available with -std=c++11 or -std=gnu++11"); break; + case CPP0X_ATTRIBUTES: + pedwarn (input_location, 0, + "c++11 attributes " + "only available with -std=c++11 or -std=gnu++11"); + break; default: gcc_unreachable (); } diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 13c658b29e2..eee44a1bae2 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1,6 +1,6 @@ /* Name mangling for the 3.0 C++ ABI. Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + 2011, 2012 Free Software Foundation, Inc. Written by Alex Samuel <samuel@codesourcery.com> This file is part of GCC. @@ -2581,6 +2581,12 @@ write_expression (tree expr) write_char ('E'); } else if (TREE_CODE (expr) == SIZEOF_EXPR + && SIZEOF_EXPR_TYPE_P (expr)) + { + write_string ("st"); + write_type (TREE_TYPE (TREE_OPERAND (expr, 0))); + } + else if (TREE_CODE (expr) == SIZEOF_EXPR && TYPE_P (TREE_OPERAND (expr, 0))) { write_string ("st"); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 155b51a180d..07f76e39ec6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1197,13 +1197,13 @@ static cp_declarator *make_call_declarator static cp_declarator *make_array_declarator (cp_declarator *, tree); static cp_declarator *make_pointer_declarator - (cp_cv_quals, cp_declarator *); + (cp_cv_quals, cp_declarator *, tree); static cp_declarator *make_reference_declarator - (cp_cv_quals, cp_declarator *, bool); + (cp_cv_quals, cp_declarator *, bool, tree); static cp_parameter_declarator *make_parameter_declarator (cp_decl_specifier_seq *, cp_declarator *, tree); static cp_declarator *make_ptrmem_declarator - (cp_cv_quals, tree, cp_declarator *); + (cp_cv_quals, tree, cp_declarator *, tree); /* An erroneous declarator. */ static cp_declarator *cp_error_declarator; @@ -1231,6 +1231,7 @@ make_declarator (cp_declarator_kind kind) declarator = (cp_declarator *) alloc_declarator (sizeof (cp_declarator)); declarator->kind = kind; declarator->attributes = NULL_TREE; + declarator->std_attributes = NULL_TREE; declarator->declarator = NULL; declarator->parameter_pack_p = false; declarator->id_loc = UNKNOWN_LOCATION; @@ -1277,10 +1278,12 @@ make_id_declarator (tree qualifying_scope, tree unqualified_name, /* Make a declarator for a pointer to TARGET. CV_QUALIFIERS is a list of modifiers such as const or volatile to apply to the pointer - type, represented as identifiers. */ + type, represented as identifiers. ATTRIBUTES represent the attributes that + appertain to the pointer or reference. */ cp_declarator * -make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target) +make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target, + tree attributes) { cp_declarator *declarator; @@ -1297,14 +1300,18 @@ make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target) else declarator->parameter_pack_p = false; + declarator->std_attributes = attributes; + return declarator; } -/* Like make_pointer_declarator -- but for references. */ +/* Like make_pointer_declarator -- but for references. ATTRIBUTES + represent the attributes that appertain to the pointer or + reference. */ cp_declarator * make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target, - bool rvalue_ref) + bool rvalue_ref, tree attributes) { cp_declarator *declarator; @@ -1321,15 +1328,19 @@ make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target, else declarator->parameter_pack_p = false; + declarator->std_attributes = attributes; + return declarator; } /* Like make_pointer_declarator -- but for a pointer to a non-static - member of CLASS_TYPE. */ + member of CLASS_TYPE. ATTRIBUTES represent the attributes that + appertain to the pointer or reference. */ cp_declarator * make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type, - cp_declarator *pointee) + cp_declarator *pointee, + tree attributes) { cp_declarator *declarator; @@ -1346,6 +1357,8 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type, else declarator->parameter_pack_p = false; + declarator->std_attributes = attributes; + return declarator; } @@ -1853,7 +1866,7 @@ static void cp_parser_lambda_body static void cp_parser_statement (cp_parser *, tree, bool, bool *); static void cp_parser_label_for_labeled_statement - (cp_parser *); +(cp_parser *, tree); static tree cp_parser_expression_statement (cp_parser *, tree); static tree cp_parser_compound_statement @@ -1957,7 +1970,7 @@ static cp_declarator *cp_parser_declarator static cp_declarator *cp_parser_direct_declarator (cp_parser *, cp_parser_declarator_kind, int *, bool); static enum tree_code cp_parser_ptr_operator - (cp_parser *, tree *, cp_cv_quals *); + (cp_parser *, tree *, cp_cv_quals *, tree *); static cp_cv_quals cp_parser_cv_qualifier_seq_opt (cp_parser *); static cp_virt_specifiers cp_parser_virt_specifier_seq_opt @@ -2099,9 +2112,29 @@ static tree cp_parser_asm_clobber_list (cp_parser *); static tree cp_parser_asm_label_list (cp_parser *); +static bool cp_next_tokens_can_be_attribute_p + (cp_parser *); +static bool cp_next_tokens_can_be_gnu_attribute_p + (cp_parser *); +static bool cp_next_tokens_can_be_std_attribute_p + (cp_parser *); +static bool cp_nth_tokens_can_be_std_attribute_p + (cp_parser *, size_t); +static bool cp_nth_tokens_can_be_gnu_attribute_p + (cp_parser *, size_t); +static bool cp_nth_tokens_can_be_attribute_p + (cp_parser *, size_t); static tree cp_parser_attributes_opt (cp_parser *); -static tree cp_parser_attribute_list +static tree cp_parser_gnu_attributes_opt + (cp_parser *); +static tree cp_parser_gnu_attribute_list + (cp_parser *); +static tree cp_parser_std_attribute + (cp_parser *); +static tree cp_parser_std_attribute_spec + (cp_parser *); +static tree cp_parser_std_attribute_spec_seq (cp_parser *); static bool cp_parser_extension_opt (cp_parser *, int *); @@ -2308,7 +2341,7 @@ static bool cp_parser_is_keyword static tree cp_parser_make_typename_type (cp_parser *, tree, tree, location_t location); static cp_declarator * cp_parser_make_indirect_declarator - (enum tree_code, tree, cp_cv_quals, cp_declarator *); + (enum tree_code, tree, cp_cv_quals, cp_declarator *, tree); /* Returns nonzero if we are parsing tentatively. */ @@ -3178,24 +3211,30 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope, make_{pointer,ptrmem,reference}_declarator functions that decides which one to call based on the CODE and CLASS_TYPE arguments. The CODE argument should be one of the values returned by - cp_parser_ptr_operator. */ + cp_parser_ptr_operator. ATTRIBUTES represent the attributes that + appertain to the pointer or reference. */ + static cp_declarator * cp_parser_make_indirect_declarator (enum tree_code code, tree class_type, cp_cv_quals cv_qualifiers, - cp_declarator *target) + cp_declarator *target, + tree attributes) { if (code == ERROR_MARK) return cp_error_declarator; if (code == INDIRECT_REF) if (class_type == NULL_TREE) - return make_pointer_declarator (cv_qualifiers, target); + return make_pointer_declarator (cv_qualifiers, target, attributes); else - return make_ptrmem_declarator (cv_qualifiers, class_type, target); + return make_ptrmem_declarator (cv_qualifiers, class_type, + target, attributes); else if (code == ADDR_EXPR && class_type == NULL_TREE) - return make_reference_declarator (cv_qualifiers, target, false); + return make_reference_declarator (cv_qualifiers, target, + false, attributes); else if (code == NON_LVALUE_EXPR && class_type == NULL_TREE) - return make_reference_declarator (cv_qualifiers, target, true); + return make_reference_declarator (cv_qualifiers, target, + true, attributes); gcc_unreachable (); } @@ -5605,6 +5644,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, switch (token->type) { case CPP_OPEN_SQUARE: + if (cp_next_tokens_can_be_std_attribute_p (parser)) + { + cp_parser_error (parser, + "two consecutive %<[%> shall " + "only introduce an attribute"); + return error_mark_node; + } postfix_expression = cp_parser_postfix_open_square_expression (parser, postfix_expression, @@ -6383,17 +6429,19 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, case RID_ALIGNOF: case RID_SIZEOF: { - tree operand; + tree operand, ret; enum tree_code op; + location_t first_loc; op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR; /* Consume the token. */ cp_lexer_consume_token (parser->lexer); + first_loc = cp_lexer_peek_token (parser->lexer)->location; /* Parse the operand. */ operand = cp_parser_sizeof_operand (parser, keyword); if (TYPE_P (operand)) - return cxx_sizeof_or_alignof_type (operand, op, true); + ret = cxx_sizeof_or_alignof_type (operand, op, true); else { /* ISO C++ defines alignof only with types, not with @@ -6404,8 +6452,29 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, "ISO C++ does not allow %<alignof%> " "with a non-type"); - return cxx_sizeof_or_alignof_expr (operand, op, true); + ret = cxx_sizeof_or_alignof_expr (operand, op, true); + } + /* For SIZEOF_EXPR, just issue diagnostics, but keep + SIZEOF_EXPR with the original operand. */ + if (op == SIZEOF_EXPR && ret != error_mark_node) + { + if (TREE_CODE (ret) != SIZEOF_EXPR || TYPE_P (operand)) + { + if (!processing_template_decl && TYPE_P (operand)) + { + ret = build_min (SIZEOF_EXPR, size_type_node, + build1 (NOP_EXPR, operand, + error_mark_node)); + SIZEOF_EXPR_TYPE_P (ret) = 1; + } + else + ret = build_min (SIZEOF_EXPR, size_type_node, operand); + TREE_SIDE_EFFECTS (ret) = 0; + TREE_READONLY (ret) = 1; + } + SET_EXPR_LOCATION (ret, first_loc); } + return ret; } case RID_NEW: @@ -6850,13 +6919,13 @@ static cp_declarator * cp_parser_new_declarator_opt (cp_parser* parser) { enum tree_code code; - tree type; - cp_cv_quals cv_quals; + tree type, std_attributes = NULL_TREE; + cp_cv_quals cv_quals; /* We don't know if there's a ptr-operator next, or not. */ cp_parser_parse_tentatively (parser); /* Look for a ptr-operator. */ - code = cp_parser_ptr_operator (parser, &type, &cv_quals); + code = cp_parser_ptr_operator (parser, &type, &cv_quals, &std_attributes); /* If that worked, look for more new-declarators. */ if (cp_parser_parse_definitely (parser)) { @@ -6865,8 +6934,10 @@ cp_parser_new_declarator_opt (cp_parser* parser) /* Parse another optional declarator. */ declarator = cp_parser_new_declarator_opt (parser); - return cp_parser_make_indirect_declarator - (code, type, cv_quals, declarator); + declarator = cp_parser_make_indirect_declarator + (code, type, cv_quals, declarator, std_attributes); + + return declarator; } /* If the next token is a `[', there is a direct-new-declarator. */ @@ -8605,6 +8676,18 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) declaration-statement try-block + C++11: + + statement: + labeled-statement + attribute-specifier-seq (opt) expression-statement + attribute-specifier-seq (opt) compound-statement + attribute-specifier-seq (opt) selection-statement + attribute-specifier-seq (opt) iteration-statement + attribute-specifier-seq (opt) jump-statement + declaration-statement + attribute-specifier-seq (opt) try-block + TM Extension: statement: @@ -8621,15 +8704,20 @@ static void cp_parser_statement (cp_parser* parser, tree in_statement_expr, bool in_compound, bool *if_p) { - tree statement; + tree statement, std_attrs = NULL_TREE; cp_token *token; - location_t statement_location; + location_t statement_location, attrs_location; restart: if (if_p != NULL) *if_p = false; /* There is no statement yet. */ statement = NULL_TREE; + + cp_lexer_save_tokens (parser->lexer); + attrs_location = cp_lexer_peek_token (parser->lexer)->location; + std_attrs = cp_parser_std_attribute_spec_seq (parser); + /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* Remember the location of the first token in the statement. */ @@ -8647,7 +8735,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, /* Looks like a labeled-statement with a case label. Parse the label, and then use tail recursion to parse the statement. */ - cp_parser_label_for_labeled_statement (parser); + cp_parser_label_for_labeled_statement (parser, std_attrs); goto restart; case RID_IF: @@ -8710,7 +8798,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, /* Looks like a labeled-statement with an ordinary label. Parse the label, and then use tail recursion to parse the statement. */ - cp_parser_label_for_labeled_statement (parser); + + cp_parser_label_for_labeled_statement (parser, std_attrs); goto restart; } } @@ -8746,6 +8835,14 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, { if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) { + if (std_attrs != NULL_TREE) + { + /* Attributes should be parsed as part of the the + declaration, so let's un-parse them. */ + cp_lexer_rollback_tokens (parser->lexer); + std_attrs = NULL_TREE; + } + cp_parser_parse_tentatively (parser); /* Try to parse the declaration-statement. */ cp_parser_declaration_statement (parser); @@ -8760,6 +8857,13 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, /* Set the line number for the statement. */ if (statement && STATEMENT_CODE_P (TREE_CODE (statement))) SET_EXPR_LOCATION (statement, statement_location); + + /* Note that for now, we don't do anything with c++11 statements + parsed at this level. */ + if (std_attrs != NULL_TREE) + warning_at (attrs_location, + OPT_Wattributes, + "attributes at the beginning of statement are ignored"); } /* Parse the label for a labeled-statement, i.e. @@ -8776,7 +8880,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, have to return the label. */ static void -cp_parser_label_for_labeled_statement (cp_parser* parser) +cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes) { cp_token *token; tree label = NULL_TREE; @@ -8856,21 +8960,23 @@ cp_parser_label_for_labeled_statement (cp_parser* parser) lab: __attribute__ ((unused)) int i; we want the attribute to attach to "i", not "lab". */ if (label != NULL_TREE - && cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE)) + && cp_next_tokens_can_be_gnu_attribute_p (parser)) { tree attrs; - cp_parser_parse_tentatively (parser); - attrs = cp_parser_attributes_opt (parser); + attrs = cp_parser_gnu_attributes_opt (parser); if (attrs == NULL_TREE || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) cp_parser_abort_tentative_parse (parser); else if (!cp_parser_parse_definitely (parser)) ; else - cplus_decl_attributes (&label, attrs, 0); + attributes = chainon (attributes, attrs); } + if (attributes != NULL_TREE) + cplus_decl_attributes (&label, attributes, 0); + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; } @@ -10296,8 +10402,7 @@ cp_parser_block_declaration (cp_parser *parser, else if (cxx_dialect >= cxx0x && token2->type == CPP_NAME && ((cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_EQ) - || (cp_lexer_peek_nth_token (parser->lexer, 3)->keyword - == RID_ATTRIBUTE))) + || (cp_nth_tokens_can_be_attribute_p (parser, 3)))) cp_parser_alias_declaration (parser); /* Otherwise, it's a using-declaration. */ else @@ -10527,6 +10632,7 @@ cp_parser_simple_declaration (cp_parser* parser, decl-specifier-seq: decl-specifier-seq [opt] decl-specifier + decl-specifier attribute-specifier-seq [opt] (C++11) decl-specifier: storage-class-specifier @@ -10561,6 +10667,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser, int* declares_class_or_enum) { bool constructor_possible_p = !parser->in_declarator_p; + bool found_decl_spec = false; cp_token *start_token = NULL; cp_decl_spec ds; @@ -10574,7 +10681,6 @@ cp_parser_decl_specifier_seq (cp_parser* parser, while (true) { bool constructor_p; - bool found_decl_spec; cp_token *token; ds = ds_last; @@ -10586,12 +10692,55 @@ cp_parser_decl_specifier_seq (cp_parser* parser, if (!start_token) start_token = token; /* Handle attributes. */ - if (token->keyword == RID_ATTRIBUTE) + if (cp_next_tokens_can_be_attribute_p (parser)) { /* Parse the attributes. */ - decl_specs->attributes - = chainon (decl_specs->attributes, - cp_parser_attributes_opt (parser)); + tree attrs = cp_parser_attributes_opt (parser); + + /* In a sequence of declaration specifiers, c++11 attributes + appertain to the type that precede them. In that case + [dcl.spec]/1 says: + + The attribute-specifier-seq affects the type only for + the declaration it appears in, not other declarations + involving the same type. + + But for now let's force the user to position the + attribute either at the beginning of the declaration or + after the declarator-id, which would clearly mean that it + applies to the declarator. */ + if (cxx11_attribute_p (attrs)) + { + if (!found_decl_spec) + /* The c++11 attribute is at the beginning of the + declaration. It appertains to the entity being + declared. */; + else + { + if (decl_specs->type && CLASS_TYPE_P (decl_specs->type)) + { + /* This is an attribute following a + class-specifier. */ + if (decl_specs->type_definition_p) + warn_misplaced_attr_for_class_type (token->location, + decl_specs->type); + attrs = NULL_TREE; + } + else + { + decl_specs->std_attributes + = chainon (decl_specs->std_attributes, + attrs); + if (decl_specs->locations[ds_std_attribute] == 0) + decl_specs->locations[ds_std_attribute] = token->location; + } + continue; + } + } + + decl_specs->attributes + = chainon (decl_specs->attributes, + attrs); if (decl_specs->locations[ds_attribute] == 0) decl_specs->locations[ds_attribute] = token->location; continue; @@ -11318,13 +11467,14 @@ static cp_declarator * cp_parser_conversion_declarator_opt (cp_parser* parser) { enum tree_code code; - tree class_type; + tree class_type, std_attributes = NULL_TREE; cp_cv_quals cv_quals; /* We don't know if there's a ptr-operator next, or not. */ cp_parser_parse_tentatively (parser); /* Try the ptr-operator. */ - code = cp_parser_ptr_operator (parser, &class_type, &cv_quals); + code = cp_parser_ptr_operator (parser, &class_type, &cv_quals, + &std_attributes); /* If it worked, look for more conversion-declarators. */ if (cp_parser_parse_definitely (parser)) { @@ -11333,8 +11483,10 @@ cp_parser_conversion_declarator_opt (cp_parser* parser) /* Parse another optional declarator. */ declarator = cp_parser_conversion_declarator_opt (parser); - return cp_parser_make_indirect_declarator - (code, class_type, cv_quals, declarator); + declarator = cp_parser_make_indirect_declarator + (code, class_type, cv_quals, declarator, std_attributes); + + return declarator; } return NULL; @@ -13165,7 +13317,8 @@ cp_parser_explicit_instantiation (cp_parser* parser) { tree type; - type = check_tag_decl (&decl_specifiers); + type = check_tag_decl (&decl_specifiers, + /*explicit_type_instantiation_p=*/true); /* Turn access control back on for names used during template instantiation. */ pop_deferring_access_checks (); @@ -14596,7 +14749,7 @@ cp_parser_enum_specifier (cp_parser* parser) apply them if appropriate. */ if (cp_parser_allow_gnu_extensions_p (parser)) { - tree trailing_attr = cp_parser_attributes_opt (parser); + tree trailing_attr = cp_parser_gnu_attributes_opt (parser); trailing_attr = chainon (trailing_attr, attributes); cplus_decl_attributes (&type, trailing_attr, @@ -15498,7 +15651,7 @@ cp_parser_init_declarator (cp_parser* parser, *attributes_start_token = NULL; cp_declarator *declarator; tree prefix_attributes; - tree attributes; + tree attributes = NULL; tree asm_specification; tree initializer; tree decl = NULL_TREE; @@ -15564,22 +15717,20 @@ cp_parser_init_declarator (cp_parser* parser, decl_specifiers->type = maybe_update_decl_type (decl_specifiers->type, scope); - /* If we're allowing GNU extensions, look for an asm-specification - and attributes. */ + /* If we're allowing GNU extensions, look for an + asm-specification. */ if (cp_parser_allow_gnu_extensions_p (parser)) { /* Look for an asm-specification. */ asm_spec_start_token = cp_lexer_peek_token (parser->lexer); asm_specification = cp_parser_asm_specification_opt (parser); - /* And attributes. */ - attributes_start_token = cp_lexer_peek_token (parser->lexer); - attributes = cp_parser_attributes_opt (parser); } else - { - asm_specification = NULL_TREE; - attributes = NULL_TREE; - } + asm_specification = NULL_TREE; + + /* Look for attributes. */ + attributes_start_token = cp_lexer_peek_token (parser->lexer); + attributes = cp_parser_attributes_opt (parser); /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -15908,7 +16059,7 @@ cp_parser_declarator (cp_parser* parser, enum tree_code code; cp_cv_quals cv_quals; tree class_type; - tree attributes = NULL_TREE; + tree gnu_attributes = NULL_TREE, std_attributes = NULL_TREE; /* Assume this is not a constructor, destructor, or type-conversion operator. */ @@ -15916,14 +16067,16 @@ cp_parser_declarator (cp_parser* parser, *ctor_dtor_or_conv_p = 0; if (cp_parser_allow_gnu_extensions_p (parser)) - attributes = cp_parser_attributes_opt (parser); + gnu_attributes = cp_parser_gnu_attributes_opt (parser); /* Check for the ptr-operator production. */ cp_parser_parse_tentatively (parser); /* Parse the ptr-operator. */ code = cp_parser_ptr_operator (parser, &class_type, - &cv_quals); + &cv_quals, + &std_attributes); + /* If that worked, then we have a ptr-operator. */ if (cp_parser_parse_definitely (parser)) { @@ -15949,7 +16102,7 @@ cp_parser_declarator (cp_parser* parser, declarator = NULL; declarator = cp_parser_make_indirect_declarator - (code, class_type, cv_quals, declarator); + (code, class_type, cv_quals, declarator, std_attributes); } /* Everything else is a direct-declarator. */ else @@ -15962,9 +16115,8 @@ cp_parser_declarator (cp_parser* parser, member_p); } - if (attributes && declarator && declarator != cp_error_declarator) - declarator->attributes = attributes; - + if (gnu_attributes && declarator && declarator != cp_error_declarator) + declarator->attributes = gnu_attributes; return declarator; } @@ -16104,6 +16256,7 @@ cp_parser_direct_declarator (cp_parser* parser, cp_virt_specifiers virt_specifiers; tree exception_specification; tree late_return; + tree attrs; is_declarator = true; @@ -16117,6 +16270,8 @@ cp_parser_direct_declarator (cp_parser* parser, exception_specification = cp_parser_exception_specification_opt (parser); + attrs = cp_parser_std_attribute_spec_seq (parser); + late_return = (cp_parser_late_return_type_opt (parser, member_p ? cv_quals : -1)); @@ -16130,6 +16285,7 @@ cp_parser_direct_declarator (cp_parser* parser, virt_specifiers, exception_specification, late_return); + declarator->std_attributes = attrs; /* Any subsequent parameter lists are to do with return type, so are not those of the declared function. */ @@ -16179,10 +16335,11 @@ cp_parser_direct_declarator (cp_parser* parser, break; } else if ((!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED) - && token->type == CPP_OPEN_SQUARE) + && token->type == CPP_OPEN_SQUARE + && !cp_next_tokens_can_be_attribute_p (parser)) { /* Parse an array-declarator. */ - tree bounds; + tree bounds, attrs; if (ctor_dtor_or_conv_p) *ctor_dtor_or_conv_p = 0; @@ -16235,13 +16392,16 @@ cp_parser_direct_declarator (cp_parser* parser, break; } + attrs = cp_parser_std_attribute_spec_seq (parser); declarator = make_array_declarator (declarator, bounds); + declarator->std_attributes = attrs; } else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT) { { tree qualifying_scope; tree unqualified_name; + tree attrs; special_function_kind sfk; bool abstract_ok; bool pack_expansion_p = false; @@ -16308,6 +16468,8 @@ cp_parser_direct_declarator (cp_parser* parser, break; } + attrs = cp_parser_std_attribute_spec_seq (parser); + if (qualifying_scope && at_namespace_scope_p () && TREE_CODE (qualifying_scope) == TYPENAME_TYPE) { @@ -16422,6 +16584,7 @@ cp_parser_direct_declarator (cp_parser* parser, declarator = make_id_declarator (qualifying_scope, unqualified_name, sfk); + declarator->std_attributes = attrs; declarator->id_loc = token->location; declarator->parameter_pack_p = pack_expansion_p; @@ -16469,9 +16632,11 @@ cp_parser_direct_declarator (cp_parser* parser, /* Parse a ptr-operator. ptr-operator: + * attribute-specifier-seq [opt] cv-qualifier-seq [opt] (C++11) * cv-qualifier-seq [opt] & :: [opt] nested-name-specifier * cv-qualifier-seq [opt] + nested-name-specifier * attribute-specifier-seq [opt] cv-qualifier-seq [opt] (C++11) GNU Extension: @@ -16491,10 +16656,12 @@ cp_parser_direct_declarator (cp_parser* parser, static enum tree_code cp_parser_ptr_operator (cp_parser* parser, tree* type, - cp_cv_quals *cv_quals) + cp_cv_quals *cv_quals, + tree *attributes) { enum tree_code code = ERROR_MARK; cp_token *token; + tree attrs = NULL_TREE; /* Assume that it's not a pointer-to-member. */ *type = NULL_TREE; @@ -16525,6 +16692,10 @@ cp_parser_ptr_operator (cp_parser* parser, if (code == INDIRECT_REF || cp_parser_allow_gnu_extensions_p (parser)) *cv_quals = cp_parser_cv_qualifier_seq_opt (parser); + + attrs = cp_parser_std_attribute_spec_seq (parser); + if (attributes != NULL) + *attributes = attrs; } else { @@ -16562,6 +16733,10 @@ cp_parser_ptr_operator (cp_parser* parser, parser->scope = NULL_TREE; parser->qualifying_scope = NULL_TREE; parser->object_scope = NULL_TREE; + /* Look for optional c++11 attributes. */ + attrs = cp_parser_std_attribute_spec_seq (parser); + if (attributes != NULL) + *attributes = attrs; /* Look for the optional cv-qualifier-seq. */ *cv_quals = cp_parser_cv_qualifier_seq_opt (parser); } @@ -16921,7 +17096,7 @@ cp_parser_type_specifier_seq (cp_parser* parser, bool is_cv_qualifier; /* Check for attributes first. */ - if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE)) + if (cp_next_tokens_can_be_attribute_p (parser)) { type_specifier_seq->attributes = chainon (type_specifier_seq->attributes, @@ -18027,7 +18202,7 @@ cp_parser_class_specifier_1 (cp_parser* parser) closing_brace = cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); /* Look for trailing attributes to apply to this class. */ if (cp_parser_allow_gnu_extensions_p (parser)) - attributes = cp_parser_attributes_opt (parser); + attributes = cp_parser_gnu_attributes_opt (parser); if (type != error_mark_node) type = finish_struct (type, attributes); if (nested_name_specifier_p) @@ -18048,6 +18223,12 @@ cp_parser_class_specifier_1 (cp_parser* parser) cp_token *token = cp_lexer_peek_token (parser->lexer); bool want_semicolon = true; + if (cp_next_tokens_can_be_std_attribute_p (parser)) + /* Don't try to parse c++11 attributes here. As per the + grammar, that should be a task for + cp_parser_decl_specifier_seq. */ + want_semicolon = false; + switch (token->type) { case CPP_NAME: @@ -18898,8 +19079,6 @@ cp_parser_member_declaration (cp_parser* parser) CP_PARSER_FLAGS_OPTIONAL, &decl_specifiers, &declares_class_or_enum); - prefix_attributes = decl_specifiers.attributes; - decl_specifiers.attributes = NULL_TREE; /* Check for an invalid type-name. */ if (!decl_specifiers.any_type_specifiers_p && cp_parser_parse_and_diagnose_invalid_type_name (parser)) @@ -18931,7 +19110,8 @@ cp_parser_member_declaration (cp_parser* parser) friend_p = cp_parser_friend_p (&decl_specifiers); /* If there were decl-specifiers, check to see if there was a class-declaration. */ - type = check_tag_decl (&decl_specifiers); + type = check_tag_decl (&decl_specifiers, + /*explicit_type_instantiation_p=*/false); /* Nested classes have already been added to the class, but a `friend' needs to be explicitly registered. */ if (friend_p) @@ -18998,6 +19178,12 @@ cp_parser_member_declaration (cp_parser* parser) { bool assume_semicolon = false; + /* Clear attributes from the decl_specifiers but keep them + around as prefix attributes that apply them to the entity + being declared. */ + prefix_attributes = decl_specifiers.attributes; + decl_specifiers.attributes = NULL_TREE; + /* See if these declarations will be friends. */ friend_p = cp_parser_friend_p (&decl_specifiers); @@ -20104,6 +20290,80 @@ cp_parser_asm_label_list (cp_parser* parser) return nreverse (labels); } +/* Return TRUE iff the next tokens in the stream are possibly the + beginning of a GNU extension attribute. */ + +static bool +cp_next_tokens_can_be_gnu_attribute_p (cp_parser *parser) +{ + return cp_nth_tokens_can_be_gnu_attribute_p (parser, 1); +} + +/* Return TRUE iff the next tokens in the stream are possibly the + beginning of a standard C++-11 attribute. */ + +static bool +cp_next_tokens_can_be_std_attribute_p (cp_parser *parser) +{ + return cp_nth_tokens_can_be_std_attribute_p (parser, 1); +} + +/* Return TRUE iff the next Nth tokens in the stream are possibly the + beginning of a standard C++-11 attribute. */ + +static bool +cp_nth_tokens_can_be_std_attribute_p (cp_parser *parser, size_t n) +{ + cp_token *token = cp_lexer_peek_nth_token (parser->lexer, n); + + return (cxx_dialect >= cxx0x + && token->type == CPP_OPEN_SQUARE + && (token = cp_lexer_peek_nth_token (parser->lexer, n + 1)) + && token->type == CPP_OPEN_SQUARE); +} + +/* Return TRUE iff the next Nth tokens in the stream are possibly the + beginning of a GNU extension attribute. */ + +static bool +cp_nth_tokens_can_be_gnu_attribute_p (cp_parser *parser, size_t n) +{ + cp_token *token = cp_lexer_peek_nth_token (parser->lexer, n); + + return token->type == CPP_KEYWORD && token->keyword == RID_ATTRIBUTE; +} + +/* Return true iff the next tokens can be the beginning of either a + GNU attribute list, or a standard C++11 attribute sequence. */ + +static bool +cp_next_tokens_can_be_attribute_p (cp_parser *parser) +{ + return (cp_next_tokens_can_be_gnu_attribute_p (parser) + || cp_next_tokens_can_be_std_attribute_p (parser)); +} + +/* Return true iff the next Nth tokens can be the beginning of either + a GNU attribute list, or a standard C++11 attribute sequence. */ + +static bool +cp_nth_tokens_can_be_attribute_p (cp_parser *parser, size_t n) +{ + return (cp_nth_tokens_can_be_gnu_attribute_p (parser, n) + || cp_nth_tokens_can_be_std_attribute_p (parser, n)); +} + +/* Parse either a standard C++-11 attribute-specifier-seq, or a series + of GNU attributes, or return NULL. */ + +static tree +cp_parser_attributes_opt (cp_parser *parser) +{ + if (cp_next_tokens_can_be_gnu_attribute_p (parser)) + return cp_parser_gnu_attributes_opt (parser); + return cp_parser_std_attribute_spec_seq (parser); +} + /* Parse an (optional) series of attributes. attributes: @@ -20112,10 +20372,10 @@ cp_parser_asm_label_list (cp_parser* parser) attribute: __attribute__ (( attribute-list [opt] )) - The return value is as for cp_parser_attribute_list. */ + The return value is as for cp_parser_gnu_attribute_list. */ static tree -cp_parser_attributes_opt (cp_parser* parser) +cp_parser_gnu_attributes_opt (cp_parser* parser) { tree attributes = NULL_TREE; @@ -20141,7 +20401,7 @@ cp_parser_attributes_opt (cp_parser* parser) token = cp_lexer_peek_token (parser->lexer); if (token->type != CPP_CLOSE_PAREN) /* Parse the attribute-list. */ - attribute_list = cp_parser_attribute_list (parser); + attribute_list = cp_parser_gnu_attribute_list (parser); else /* If the next token is a `)', then there is no attribute list. */ @@ -20162,7 +20422,7 @@ cp_parser_attributes_opt (cp_parser* parser) return attributes; } -/* Parse an attribute-list. +/* Parse a GNU attribute-list. attribute-list: attribute @@ -20180,7 +20440,7 @@ cp_parser_attributes_opt (cp_parser* parser) the arguments, if any. */ static tree -cp_parser_attribute_list (cp_parser* parser) +cp_parser_gnu_attribute_list (cp_parser* parser) { tree attribute_list = NULL_TREE; bool save_translate_strings_p = parser->translate_strings_p; @@ -20259,6 +20519,277 @@ cp_parser_attribute_list (cp_parser* parser) return nreverse (attribute_list); } +/* Parse a standard C++11 attribute. + + The returned representation is a TREE_LIST which TREE_PURPOSE is + the scoped name of the attribute, and the TREE_VALUE is its + arguments list. + + Note that the scoped name of the attribute is itself a TREE_LIST + which TREE_PURPOSE is the namespace of the attribute, and + TREE_VALUE its name. This is unlike a GNU attribute -- as parsed + by cp_parser_gnu_attribute_list -- that doesn't have any namespace + and which TREE_PURPOSE is directly the attribute name. + + Clients of the attribute code should use get_attribute_namespace + and get_attribute_name to get the actual namespace and name of + attributes, regardless of their being GNU or C++11 attributes. + + attribute: + attribute-token attribute-argument-clause [opt] + + attribute-token: + identifier + attribute-scoped-token + + attribute-scoped-token: + attribute-namespace :: identifier + + attribute-namespace: + identifier + + attribute-argument-clause: + ( balanced-token-seq ) + + balanced-token-seq: + balanced-token [opt] + balanced-token-seq balanced-token + + balanced-token: + ( balanced-token-seq ) + [ balanced-token-seq ] + { balanced-token-seq }. */ + +static tree +cp_parser_std_attribute (cp_parser *parser) +{ + tree attribute, attr_ns = NULL_TREE, attr_id = NULL_TREE, arguments; + cp_token *token; + + /* First, parse name of the the attribute, a.k.a + attribute-token. */ + + token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_NAME) + attr_id = token->u.value; + else if (token->type == CPP_KEYWORD) + attr_id = ridpointers[(int) token->keyword]; + else if (token->flags & NAMED_OP) + attr_id = get_identifier (cpp_type2name (token->type, token->flags)); + + if (attr_id == NULL_TREE) + return NULL_TREE; + + cp_lexer_consume_token (parser->lexer); + + token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_SCOPE) + { + /* We are seeing a scoped attribute token. */ + + cp_lexer_consume_token (parser->lexer); + attr_ns = attr_id; + + token = cp_lexer_consume_token (parser->lexer); + if (token->type == CPP_NAME) + attr_id = token->u.value; + else if (token->type == CPP_KEYWORD) + attr_id = ridpointers[(int) token->keyword]; + else + { + error_at (token->location, + "expected an identifier for the attribute name"); + return error_mark_node; + } + attribute = build_tree_list (build_tree_list (attr_ns, attr_id), + NULL_TREE); + token = cp_lexer_peek_token (parser->lexer); + } + else + attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id), + NULL_TREE); + + /* Now parse the optional argument clause of the attribute. */ + + if (token->type != CPP_OPEN_PAREN) + return attribute; + + { + VEC(tree, gc) *vec; + int attr_flag = normal_attr; + + if (attr_ns == get_identifier ("gnu") + && attribute_takes_identifier_p (attr_id)) + /* A GNU attribute that takes an identifier in parameter. */ + attr_flag = id_attr; + + vec = cp_parser_parenthesized_expression_list + (parser, attr_flag, /*cast_p=*/false, + /*allow_expansion_p=*/true, + /*non_constant_p=*/NULL); + if (vec == NULL) + arguments = error_mark_node; + else + { + arguments = build_tree_list_vec (vec); + release_tree_vector (vec); + } + + if (arguments == error_mark_node) + attribute = error_mark_node; + else + TREE_VALUE (attribute) = arguments; + } + + return attribute; +} + +/* Parse a list of standard C++-11 attributes. + + attribute-list: + attribute [opt] + attribute-list , attribute[opt] + attribute ... + attribute-list , attribute ... +*/ + +static tree +cp_parser_std_attribute_list (cp_parser *parser) +{ + tree attributes = NULL_TREE, attribute = NULL_TREE; + cp_token *token = NULL; + + while (true) + { + attribute = cp_parser_std_attribute (parser); + if (attribute == error_mark_node) + break; + if (attribute != NULL_TREE) + { + TREE_CHAIN (attribute) = attributes; + attributes = attribute; + } + token = cp_lexer_peek_token (parser->lexer); + if (token->type != CPP_COMMA) + break; + cp_lexer_consume_token (parser->lexer); + } + attributes = nreverse (attributes); + return attributes; +} + +/* Parse a standard C++-11 attribute specifier. + + attribute-specifier: + [ [ attribute-list ] ] + alignment-specifier + + alignment-specifier: + alignas ( type-id ... [opt] ) + alignas ( alignment-expression ... [opt] ). */ + +static tree +cp_parser_std_attribute_spec (cp_parser *parser) +{ + tree attributes = NULL_TREE; + cp_token *token = cp_lexer_peek_token (parser->lexer); + + if (token->type == CPP_OPEN_SQUARE + && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_SQUARE) + { + cp_lexer_consume_token (parser->lexer); + maybe_warn_cpp0x (CPP0X_ATTRIBUTES); + cp_lexer_consume_token (parser->lexer); + + attributes = cp_parser_std_attribute_list (parser); + + if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE) + || !cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)) + cp_parser_skip_to_end_of_statement (parser); + } + else + { + tree alignas_expr; + + /* Look for an alignment-specifier. */ + + token = cp_lexer_peek_token (parser->lexer); + + if (token->type != CPP_KEYWORD + || token->keyword != RID_ALIGNAS) + return NULL_TREE; + + cp_lexer_consume_token (parser->lexer); + maybe_warn_cpp0x (CPP0X_ATTRIBUTES); + + if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN) == NULL) + { + cp_parser_error (parser, "expected %<(%>"); + return error_mark_node; + } + + cp_parser_parse_tentatively (parser); + alignas_expr = cp_parser_type_id (parser); + + if (!cp_parser_parse_definitely (parser)) + { + gcc_assert (alignas_expr == error_mark_node + || alignas_expr == NULL_TREE); + + alignas_expr = + cp_parser_assignment_expression (parser, /*cast_p=*/false, + /**cp_id_kind=*/NULL); + if (alignas_expr == NULL_TREE + || alignas_expr == error_mark_node) + return alignas_expr; + } + + if (cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN) == NULL) + { + cp_parser_error (parser, "expected %<)%>"); + return error_mark_node; + } + + alignas_expr = cxx_alignas_expr (alignas_expr); + + /* Build the C++-11 representation of an 'aligned' + attribute. */ + attributes = + build_tree_list (build_tree_list (get_identifier ("gnu"), + get_identifier ("aligned")), + build_tree_list (NULL_TREE, alignas_expr)); + } + + return attributes; +} + +/* Parse a standard C++-11 attribute-specifier-seq. + + attribute-specifier-seq: + attribute-specifier-seq [opt] attribute-specifier + */ + +static tree +cp_parser_std_attribute_spec_seq (cp_parser *parser) +{ + tree attr_specs = NULL; + + while (true) + { + tree attr_spec = cp_parser_std_attribute_spec (parser); + if (attr_spec == NULL_TREE) + break; + if (attr_spec == error_mark_node) + return error_mark_node; + + TREE_CHAIN (attr_spec) = attr_specs; + attr_specs = attr_spec; + } + + attr_specs = nreverse (attr_specs); + return attr_specs; +} + /* Parse an optional `__extension__' keyword. Returns TRUE if it is present, and FALSE otherwise. *SAVED_PEDANTIC is set to the current value of the PEDANTIC flag, regardless of whether or not diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 104d4dd6898..1377b3eed52 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5020,7 +5020,7 @@ redeclare_class_template (tree type, tree parms) /* Simplify EXPR if it is a non-dependent expression. Returns the (possibly simplified) expression. */ -static tree +tree fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain) { if (expr == NULL_TREE) @@ -12031,14 +12031,16 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))) { - tree expanded; + tree expanded, op = TREE_OPERAND (t, 0); int len = 0; + if (SIZEOF_EXPR_TYPE_P (t)) + op = TREE_TYPE (op); + ++cp_unevaluated_operand; ++c_inhibit_evaluation_warnings; /* We only want to compute the number of arguments. */ - expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args, - complain, in_decl); + expanded = tsubst_pack_expansion (op, args, complain, in_decl); --cp_unevaluated_operand; --c_inhibit_evaluation_warnings; @@ -12065,6 +12067,16 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) else return build_int_cst (size_type_node, len); } + if (SIZEOF_EXPR_TYPE_P (t)) + { + r = tsubst_copy (TREE_TYPE (TREE_OPERAND (t, 0)), + args, complain, in_decl); + r = build1 (NOP_EXPR, r, error_mark_node); + r = build1 (SIZEOF_EXPR, + tsubst (TREE_TYPE (t), args, complain, in_decl), r); + SIZEOF_EXPR_TYPE_P (r) = 1; + return r; + } /* Fall through */ case INDIRECT_REF: @@ -13468,31 +13480,56 @@ tsubst_copy_and_build (tree t, /* Fall through */ case ALIGNOF_EXPR: - op1 = TREE_OPERAND (t, 0); - if (!args) - { - /* When there are no ARGS, we are trying to evaluate a - non-dependent expression from the parser. Trying to do - the substitutions may not work. */ - if (!TYPE_P (op1)) - op1 = TREE_TYPE (op1); - } - else - { - ++cp_unevaluated_operand; - ++c_inhibit_evaluation_warnings; - op1 = tsubst_copy_and_build (op1, args, complain, in_decl, - /*function_p=*/false, - /*integral_constant_expression_p=*/false); - --cp_unevaluated_operand; - --c_inhibit_evaluation_warnings; - } - if (TYPE_P (op1)) - RETURN (cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), - complain & tf_error)); - else - RETURN (cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t), - complain & tf_error)); + { + tree r; + + op1 = TREE_OPERAND (t, 0); + if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t)) + op1 = TREE_TYPE (op1); + if (!args) + { + /* When there are no ARGS, we are trying to evaluate a + non-dependent expression from the parser. Trying to do + the substitutions may not work. */ + if (!TYPE_P (op1)) + op1 = TREE_TYPE (op1); + } + else + { + ++cp_unevaluated_operand; + ++c_inhibit_evaluation_warnings; + op1 = tsubst_copy_and_build (op1, args, complain, in_decl, + /*function_p=*/false, + /*integral_constant_expression_p=*/ + false); + --cp_unevaluated_operand; + --c_inhibit_evaluation_warnings; + } + if (TYPE_P (op1)) + r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), + complain & tf_error); + else + r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t), + complain & tf_error); + if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node) + { + if (TREE_CODE (r) != SIZEOF_EXPR || TYPE_P (op1)) + { + if (TYPE_P (op1)) + { + r = build_min (SIZEOF_EXPR, size_type_node, + build1 (NOP_EXPR, op1, error_mark_node)); + SIZEOF_EXPR_TYPE_P (r) = 1; + } + else + r = build_min (SIZEOF_EXPR, size_type_node, op1); + TREE_SIDE_EFFECTS (r) = 0; + TREE_READONLY (r) = 1; + } + SET_EXPR_LOCATION (r, EXPR_LOCATION (t)); + } + RETURN (r); + } case AT_ENCODE_EXPR: { @@ -14250,7 +14287,8 @@ tsubst_copy_and_build (tree t, FIXME stop folding in cp_parser_initializer_clause. */ gcc_assert (TREE_CONSTANT (t)); { - tree r = get_target_expr (RECUR (TARGET_EXPR_INITIAL (t))); + tree r = get_target_expr_sfinae (RECUR (TARGET_EXPR_INITIAL (t)), + complain); TREE_CONSTANT (r) = true; RETURN (r); } @@ -19288,6 +19326,9 @@ value_dependent_expression_p (tree expression) } case SIZEOF_EXPR: + if (SIZEOF_EXPR_TYPE_P (expression)) + return dependent_type_p (TREE_TYPE (TREE_OPERAND (expression, 0))); + /* FALLTHRU */ case ALIGNOF_EXPR: case TYPEID_EXPR: /* A `sizeof' expression is value-dependent if the operand is @@ -19627,6 +19668,8 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees, case TRAIT_EXPR: { tree op = TREE_OPERAND (*tp, 0); + if (code == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (*tp)) + op = TREE_TYPE (op); if (TYPE_P (op)) { if (dependent_type_p (op) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 68cbb4ba8c4..7174927094c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3,8 +3,7 @@ building RTL. These routines are used both during actual parsing and during the instantiation of template functions. - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 1998-2012 Free Software Foundation, Inc. Written by Mark Mitchell (mmitchell@usa.net) based on code found formerly in parse.y and pt.c. @@ -2170,8 +2169,25 @@ finish_call_expr (tree fn, VEC(tree,gc) **args, bool disallow_virtual, result = resolve_overloaded_builtin (input_location, fn, *args); if (!result) - /* A call to a namespace-scope function. */ - result = build_new_function_call (fn, args, koenig_p, complain); + { + if (warn_sizeof_pointer_memaccess + && !VEC_empty(tree, *args) + && TREE_CODE (VEC_last(tree, *args)) == SIZEOF_EXPR + && !processing_template_decl) + { + tree sizeof_arg = VEC_last(tree, *args); + if (SIZEOF_EXPR_TYPE_P (sizeof_arg)) + sizeof_arg = TREE_TYPE (TREE_OPERAND (sizeof_arg, 0)); + else + sizeof_arg = TREE_OPERAND (sizeof_arg, 0); + sizeof_pointer_memaccess_warning + (EXPR_LOCATION (VEC_last(tree, *args)), fn, *args, + sizeof_arg, same_type_ignoring_top_level_qualifiers_p); + } + + /* A call to a namespace-scope function. */ + result = build_new_function_call (fn, args, koenig_p, complain); + } } else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR) { @@ -7723,6 +7739,21 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, non_constant_p); break; + case SIZEOF_EXPR: + if (SIZEOF_EXPR_TYPE_P (t)) + r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)), + SIZEOF_EXPR, false); + else if (TYPE_P (TREE_OPERAND (t, 0))) + r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR, + false); + else + r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR, + false); + if (r == error_mark_node) + r = size_one_node; + VERIFY_CONSTANT (r); + break; + case COMPOUND_EXPR: { /* check_return_expr sometimes wraps a TARGET_EXPR in a @@ -8107,12 +8138,6 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) int i; tree tmp; - /* C++98 has different rules for the form of a constant expression that - are enforced in the parser, so we can assume that anything that gets - this far is suitable. */ - if (cxx_dialect < cxx0x) - return true; - if (t == error_mark_node) return false; if (t == NULL_TREE) @@ -8633,6 +8658,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) return false; default: + if (objc_is_property_ref (t)) + return false; + sorry ("unexpected AST of kind %s", tree_code_name[TREE_CODE (t)]); gcc_unreachable(); return false; @@ -8976,14 +9004,15 @@ is_capture_proxy (tree decl) bool is_normal_capture_proxy (tree decl) { - tree val; - if (!is_capture_proxy (decl)) /* It's not a capture proxy. */ return false; /* It is a capture proxy, is it a normal capture? */ - val = DECL_VALUE_EXPR (decl); + tree val = DECL_VALUE_EXPR (decl); + if (val == error_mark_node) + return true; + gcc_assert (TREE_CODE (val) == COMPONENT_REF); val = TREE_OPERAND (val, 1); return DECL_NORMAL_CAPTURE_P (val); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 7dddf2299c3..e1af378645a 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -2602,6 +2602,10 @@ cp_tree_equal (tree t1, tree t2) tree o1 = TREE_OPERAND (t1, 0); tree o2 = TREE_OPERAND (t2, 0); + if (SIZEOF_EXPR_TYPE_P (t1)) + o1 = TREE_TYPE (o1); + if (SIZEOF_EXPR_TYPE_P (t2)) + o2 = TREE_TYPE (o2); if (TREE_CODE (o1) != TREE_CODE (o2)) return false; if (TYPE_P (o1)) @@ -3553,7 +3557,7 @@ stabilize_call (tree call, tree *initp) arguments, while, upon return, *INITP contains an expression to compute the arguments. */ -void +static void stabilize_aggr_init (tree call, tree *initp) { tree inits = NULL_TREE; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 884f7d0573b..ae4d0a44589 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1701,6 +1701,56 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op, bool complain) else return cxx_alignof_expr (e, complain? tf_warning_or_error : tf_none); } + +/* Build a representation of an expression 'alignas(E).' Return the + folded integer value of E if it is an integral constant expression + that resolves to a valid alignment. If E depends on a template + parameter, return a syntactic representation tree of kind + ALIGNOF_EXPR. Otherwise, return an error_mark_node if the + expression is ill formed, or NULL_TREE if E is NULL_TREE. */ + +tree +cxx_alignas_expr (tree e) +{ + if (e == NULL_TREE || e == error_mark_node + || (!TYPE_P (e) && !require_potential_rvalue_constant_expression (e))) + return e; + + if (TYPE_P (e)) + /* [dcl.align]/3: + + When the alignment-specifier is of the form + alignas(type-id ), it shall have the same effect as + alignas( alignof(type-id )). */ + + return cxx_sizeof_or_alignof_type (e, ALIGNOF_EXPR, false); + + + /* If we reach this point, it means the alignas expression if of + the form "alignas(assignment-expression)", so we should follow + what is stated by [dcl.align]/2. */ + + e = mark_rvalue_use (e); + + /* [dcl.align]/2 says: + + the assignment-expression shall be an integral constant + expression. */ + + e = fold_non_dependent_expr (e); + if (value_dependent_expression_p (e)) + /* Leave value-dependent expression alone for now. */; + else + e = cxx_constant_value (e); + + if (e == NULL_TREE + || e == error_mark_node + || TREE_CODE (e) != INTEGER_CST) + return error_mark_node; + + return e; +} + /* EXPR is being used in a context that is not a function call. Enforce: @@ -4624,7 +4674,14 @@ cp_build_binary_op (location_t location, && !enum_cast_to_int (orig_op0) && !enum_cast_to_int (orig_op1)) { - warn_for_sign_compare (location, orig_op0, orig_op1, op0, op1, + tree oop0 = maybe_constant_value (orig_op0); + tree oop1 = maybe_constant_value (orig_op1); + + if (TREE_CODE (oop0) != INTEGER_CST) + oop0 = orig_op0; + if (TREE_CODE (oop1) != INTEGER_CST) + oop1 = orig_op1; + warn_for_sign_compare (location, oop0, oop1, op0, op1, result_type, resultcode); } } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 63dd3eb67d9..c415bbe45b7 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -388,7 +388,7 @@ Objective-C and Objective-C++ Dialects}. -fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol -fomit-frame-pointer -foptimize-register-move -foptimize-sibling-calls @gol -fpartial-inlining -fpeel-loops -fpredictive-commoning @gol --fprefetch-loop-arrays @gol +-fprefetch-loop-arrays -fprofile-report @gol -fprofile-correction -fprofile-dir=@var{path} -fprofile-generate @gol -fprofile-generate=@var{path} @gol -fprofile-use -fprofile-use=@var{path} -fprofile-values @gol @@ -505,7 +505,7 @@ Objective-C and Objective-C++ Dialects}. @emph{AVR Options} @gccoptlist{-mmcu=@var{mcu} -maccumulate-args -mbranch-cost=@var{cost} @gol --mcall-prologues -mint8 -mno-interrupts -mrelax -mshort-calls @gol +-mcall-prologues -mint8 -mno-interrupts -mrelax @gol -mstrict-X -mtiny-stack} @emph{Blackfin Options} @@ -5157,6 +5157,11 @@ allocation for the WPA phase only. Makes the compiler print some statistics about permanent memory allocation before or after interprocedural optimization. +@item -fprofile-report +@opindex fprofile-report +Makes the compiler print some statistics about consistency of the +(estimated) profile and effect of individual passes. + @item -fstack-usage @opindex fstack-usage Makes the compiler output stack usage information for the program, on a @@ -9242,6 +9247,11 @@ The minimal probability of speculation success (in percents), so that speculative insns are scheduled. The default value is 40. +@item sched-spec-state-edge-prob-cutoff +The minimum probability an edge must have for the scheduler to save its +state across it. +The default value is 10. + @item sched-mem-true-dep-cost Minimal distance (in CPU cycles) between store and load targeting same memory locations. The default value is 1. @@ -11296,13 +11306,6 @@ differ from instructions in the assembler code. Relaxing must be turned on if linker stubs are needed, see the section on @code{EIND} and linker stubs below. -@item -mshort-calls -@opindex mshort-calls -Use @code{RCALL}/@code{RJMP} instructions even on devices with -16@tie{}KiB or more of program memory, i.e.@: on devices that -have the @code{CALL} and @code{JMP} instructions. -See also the @code{-mrelax} command line option. - @item -msp8 @opindex msp8 Treat the stack pointer register as an 8-bit register, @@ -11565,7 +11568,7 @@ The device has a hardware multiplier. @item __AVR_HAVE_JMP_CALL__ The device has the @code{JMP} and @code{CALL} instructions. This is the case for devices with at least 16@tie{}KiB of program -memory and if @code{-mshort-calls} is not set. +memory. @item __AVR_HAVE_EIJMP_EICALL__ @item __AVR_3_BYTE_PC__ diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index a861601e0c2..7a3092a420c 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,17 @@ +2012-10-06 Janus Weil <janus@gcc.gnu.org> + + PR fortran/54832 + * resolve.c (resolve_fl_derived0): Correctly copy the 'class_ok' + attribute for proc-ptr components with RESULT variable. + +2012-10-06 Janus Weil <janus@gcc.gnu.org> + + PR fortran/45521 + * interface.c (generic_correspondence): Implement additional + distinguishability criteria of F08. + (compare_actual_formal): Reject data object as actual argument for + procedure formal argument. + 2012-10-04 Tobias Burnus <burnus@net-b.de> * expr.c (scalarize_intrinsic_call): Plug memory leak. diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c index fb3da1fb7ba..4822149cc0b 100644 --- a/gcc/fortran/interface.c +++ b/gcc/fortran/interface.c @@ -932,9 +932,9 @@ count_types_test (gfc_formal_arglist *f1, gfc_formal_arglist *f2, } -/* Perform the correspondence test in rule 3 of section F03:16.2.3. - Returns zero if no argument is found that satisfies rule 3, nonzero - otherwise. 'p1' and 'p2' are the PASS arguments of both procedures +/* Perform the correspondence test in rule (3) of F08:C1215. + Returns zero if no argument is found that satisfies this rule, + nonzero otherwise. 'p1' and 'p2' are the PASS arguments of both procedures (if applicable). This test is also not symmetric in f1 and f2 and must be called @@ -942,13 +942,13 @@ count_types_test (gfc_formal_arglist *f1, gfc_formal_arglist *f2, argument list with keywords. For example: INTERFACE FOO - SUBROUTINE F1(A, B) - INTEGER :: A ; REAL :: B - END SUBROUTINE F1 + SUBROUTINE F1(A, B) + INTEGER :: A ; REAL :: B + END SUBROUTINE F1 - SUBROUTINE F2(B, A) - INTEGER :: A ; REAL :: B - END SUBROUTINE F1 + SUBROUTINE F2(B, A) + INTEGER :: A ; REAL :: B + END SUBROUTINE F1 END INTERFACE FOO At this point, 'CALL FOO(A=1, B=1.0)' is ambiguous. */ @@ -973,7 +973,10 @@ generic_correspondence (gfc_formal_arglist *f1, gfc_formal_arglist *f2, f2 = f2->next; if (f2 != NULL && (compare_type_rank (f1->sym, f2->sym) - || compare_type_rank (f2->sym, f1->sym))) + || compare_type_rank (f2->sym, f1->sym)) + && !((gfc_option.allow_std & GFC_STD_F2008) + && ((f1->sym->attr.allocatable && f2->sym->attr.pointer) + || (f2->sym->attr.allocatable && f1->sym->attr.pointer)))) goto next; /* Now search for a disambiguating keyword argument starting at @@ -984,7 +987,10 @@ generic_correspondence (gfc_formal_arglist *f1, gfc_formal_arglist *f2, continue; sym = find_keyword_arg (g->sym->name, f2_save); - if (sym == NULL || !compare_type_rank (g->sym, sym)) + if (sym == NULL || !compare_type_rank (g->sym, sym) + || ((gfc_option.allow_std & GFC_STD_F2008) + && ((sym->attr.allocatable && g->sym->attr.pointer) + || (sym->attr.pointer && g->sym->attr.allocatable)))) return 1; } @@ -2551,8 +2557,8 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal, skip_size_check: - /* Satisfy 12.4.1.3 by ensuring that a procedure pointer actual argument - is provided for a procedure pointer formal argument. */ + /* Satisfy F03:12.4.1.3 by ensuring that a procedure pointer actual + argument is provided for a procedure pointer formal argument. */ if (f->sym->attr.proc_pointer && !((a->expr->expr_type == EXPR_VARIABLE && a->expr->symtree->n.sym->attr.proc_pointer) @@ -2566,11 +2572,10 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal, return 0; } - /* Satisfy 12.4.1.2 by ensuring that a procedure actual argument is + /* Satisfy F03:12.4.1.3 by ensuring that a procedure actual argument is provided for a procedure formal argument. */ - if (a->expr->ts.type != BT_PROCEDURE && !gfc_is_proc_ptr_comp (a->expr) - && a->expr->expr_type == EXPR_VARIABLE - && f->sym->attr.flavor == FL_PROCEDURE) + if (f->sym->attr.flavor == FL_PROCEDURE + && gfc_expr_attr (a->expr).flavor != FL_PROCEDURE) { if (where) gfc_error ("Expected a procedure for argument '%s' at %L", diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 7c30cba9756..722e036510e 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -12022,6 +12022,7 @@ resolve_fl_derived0 (gfc_symbol *sym) c->attr.pointer = ifc->result->attr.pointer; c->attr.dimension = ifc->result->attr.dimension; c->as = gfc_copy_array_spec (ifc->result->as); + c->attr.class_ok = ifc->result->attr.class_ok; } else { @@ -12030,6 +12031,7 @@ resolve_fl_derived0 (gfc_symbol *sym) c->attr.pointer = ifc->attr.pointer; c->attr.dimension = ifc->attr.dimension; c->as = gfc_copy_array_spec (ifc->as); + c->attr.class_ok = ifc->attr.class_ok; } c->ts.interface = ifc; c->attr.function = ifc->attr.function; @@ -12041,7 +12043,6 @@ resolve_fl_derived0 (gfc_symbol *sym) c->attr.recursive = ifc->attr.recursive; c->attr.always_explicit = ifc->attr.always_explicit; c->attr.ext_attr |= ifc->attr.ext_attr; - c->attr.class_ok = ifc->attr.class_ok; /* Replace symbols in array spec. */ if (c->as) { diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index 424ad550d78..677e41f2673 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -425,6 +425,14 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data) case GIMPLE_CALL: { tree decl = gimple_call_fndecl (stmt); + unsigned i; + + for (i = 0; i < gimple_call_num_args (stmt); i++) + { + tree arg = gimple_call_arg (stmt, i); + if (EXPR_P (arg)) + TREE_SET_BLOCK (arg, data->block); + } if (decl && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h index fc8cfa674f0..9f6e7419ca1 100644 --- a/gcc/ginclude/stddef.h +++ b/gcc/ginclude/stddef.h @@ -427,6 +427,13 @@ typedef struct { #endif #endif /* C11 or C++11. */ +#if defined(__cplusplus) && __cplusplus >= 201103L +#ifndef _GXX_NULLPTR_T +#define _GXX_NULLPTR_T + typedef decltype(nullptr) nullptr_t; +#endif +#endif /* C++11. */ + #endif /* _STDDEF_H was defined this time */ #endif /* !_STDDEF_H && !_STDDEF_H_ && !_ANSI_STDDEF_H && !__STDDEF_H__ diff --git a/gcc/ginclude/stdint-gcc.h b/gcc/ginclude/stdint-gcc.h index 22780a15efa..64b389930c9 100644 --- a/gcc/ginclude/stdint-gcc.h +++ b/gcc/ginclude/stdint-gcc.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008, 2009 Free Software Foundation, Inc. +/* Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GCC. @@ -91,7 +91,8 @@ typedef __UINTPTR_TYPE__ uintptr_t; typedef __INTMAX_TYPE__ intmax_t; typedef __UINTMAX_TYPE__ uintmax_t; -#if !defined __cplusplus || defined __STDC_LIMIT_MACROS +#if (!defined __cplusplus || __cplusplus >= 201103L \ + || defined __STDC_LIMIT_MACROS) /* 7.18.2 Limits of specified-width integer types */ @@ -229,9 +230,11 @@ typedef __UINTMAX_TYPE__ uintmax_t; #undef WINT_MIN #define WINT_MIN __WINT_MIN__ -#endif /* !defined __cplusplus || defined __STDC_LIMIT_MACROS */ +#endif /* (!defined __cplusplus || __cplusplus >= 201103L + || defined __STDC_LIMIT_MACROS) */ -#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS +#if (!defined __cplusplus || __cplusplus >= 201103L \ + || defined __STDC_CONSTANT_MACROS) #undef INT8_C #define INT8_C(c) __INT8_C(c) @@ -254,6 +257,7 @@ typedef __UINTMAX_TYPE__ uintmax_t; #undef UINTMAX_C #define UINTMAX_C(c) __UINTMAX_C(c) -#endif /* !defined __cplusplus || defined __STDC_CONSTANT_MACROS */ +#endif /* (!defined __cplusplus || __cplusplus >= 201103L + || defined __STDC_CONSTANT_MACROS) */ #endif /* _GCC_STDINT_H */ diff --git a/gcc/ginclude/stdint-wrap.h b/gcc/ginclude/stdint-wrap.h index e45f8198b97..83b6f70c837 100644 --- a/gcc/ginclude/stdint-wrap.h +++ b/gcc/ginclude/stdint-wrap.h @@ -1,5 +1,11 @@ #ifndef _GCC_WRAP_STDINT_H #if __STDC_HOSTED__ +# if defined __cplusplus && __cplusplus >= 201103L +# undef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +# undef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +# endif # include_next <stdint.h> #else # include "stdint-gcc.h" diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index 8072beb85ff..f45caf48771 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -5840,7 +5840,7 @@ verify_shadows (void) region. */ bool -schedule_block (basic_block *target_bb) +schedule_block (basic_block *target_bb, state_t init_state) { int i; bool success = modulo_ii == 0; @@ -5875,7 +5875,10 @@ schedule_block (basic_block *target_bb) if (sched_verbose) dump_new_block_header (0, *target_bb, head, tail); - state_reset (curr_state); + if (init_state == NULL) + state_reset (curr_state); + else + memcpy (curr_state, init_state, dfa_state_size); /* Clear the ready list. */ ready.first = ready.veclen - 1; @@ -6335,6 +6338,7 @@ schedule_block (basic_block *target_bb) if (ls.modulo_epilogue) success = true; end_schedule: + advance_one_cycle (); perform_replacements_new_cycle (); if (modulo_ii > 0) { diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index 31ecec9af99..6cea94225b0 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -3312,14 +3312,12 @@ do_estimate_edge_time (struct cgraph_edge *edge) VEC_free (tree, heap, known_binfos); VEC_free (ipa_agg_jump_function_p, heap, known_aggs); - ret = (((gcov_type)time - - es->call_stmt_time) * edge->frequency - + CGRAPH_FREQ_BASE / 2) / CGRAPH_FREQ_BASE; + ret = RDIV ((gcov_type)time * edge->frequency, + CGRAPH_FREQ_BASE); /* When caching, update the cache entry. */ if (edge_growth_cache) { - int ret_size; if ((int)VEC_length (edge_growth_cache_entry, edge_growth_cache) <= edge->uid) VEC_safe_grow_cleared (edge_growth_cache_entry, heap, edge_growth_cache, @@ -3327,10 +3325,8 @@ do_estimate_edge_time (struct cgraph_edge *edge) VEC_index (edge_growth_cache_entry, edge_growth_cache, edge->uid).time = ret + (ret >= 0); - ret_size = size - es->call_stmt_size; - gcc_checking_assert (es->call_stmt_size); VEC_index (edge_growth_cache_entry, edge_growth_cache, edge->uid).size - = ret_size + (ret_size >= 0); + = size + (size >= 0); VEC_index (edge_growth_cache_entry, edge_growth_cache, edge->uid).hints = hints + 1; } @@ -3338,11 +3334,11 @@ do_estimate_edge_time (struct cgraph_edge *edge) } -/* Estimate the growth of the caller when inlining EDGE. +/* Return estimated callee growth after inlining EDGE. Only to be called via estimate_edge_size. */ int -do_estimate_edge_growth (struct cgraph_edge *edge) +do_estimate_edge_size (struct cgraph_edge *edge) { int size; struct cgraph_node *callee; @@ -3375,8 +3371,7 @@ do_estimate_edge_growth (struct cgraph_edge *edge) VEC_free (tree, heap, known_vals); VEC_free (tree, heap, known_binfos); VEC_free (ipa_agg_jump_function_p, heap, known_aggs); - gcc_checking_assert (inline_edge_summary (edge)->call_stmt_size); - return size - inline_edge_summary (edge)->call_stmt_size; + return size; } diff --git a/gcc/ipa-inline.h b/gcc/ipa-inline.h index ec9cf4d13ac..df8b3a7e202 100644 --- a/gcc/ipa-inline.h +++ b/gcc/ipa-inline.h @@ -201,7 +201,7 @@ void estimate_ipcp_clone_size_and_time (struct cgraph_node *, int do_estimate_growth (struct cgraph_node *); void inline_merge_summary (struct cgraph_edge *edge); void inline_update_overall_summary (struct cgraph_node *node); -int do_estimate_edge_growth (struct cgraph_edge *edge); +int do_estimate_edge_size (struct cgraph_edge *edge); int do_estimate_edge_time (struct cgraph_edge *edge); inline_hints do_estimate_edge_hints (struct cgraph_edge *edge); void initialize_growth_caches (void); @@ -245,20 +245,31 @@ estimate_growth (struct cgraph_node *node) } -/* Return estimated callee growth after inlining EDGE. */ +/* Return estimated size of the inline sequence of EDGE. */ static inline int -estimate_edge_growth (struct cgraph_edge *edge) +estimate_edge_size (struct cgraph_edge *edge) { int ret; if ((int)VEC_length (edge_growth_cache_entry, edge_growth_cache) <= edge->uid || !(ret = VEC_index (edge_growth_cache_entry, edge_growth_cache, edge->uid).size)) - return do_estimate_edge_growth (edge); + return do_estimate_edge_size (edge); return ret - (ret > 0); } +/* Return estimated callee growth after inlining EDGE. */ + +static inline int +estimate_edge_growth (struct cgraph_edge *edge) +{ +#ifdef ENABLE_CHECKING + gcc_checking_assert (inline_edge_summary (edge)->call_stmt_size); +#endif + return (estimate_edge_size (edge) + - inline_edge_summary (edge)->call_stmt_size); +} /* Return estimated callee runtime increase after inlning EDGE. */ diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index e1d1c4928e6..6750c11381a 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -1059,6 +1059,7 @@ split_function (struct split_point *split_point) gimple last_stmt = NULL; unsigned int i; tree arg, ddef; + VEC(tree, gc) **debug_args = NULL; if (dump_file) { @@ -1232,6 +1233,83 @@ split_function (struct split_point *split_point) gimple_set_block (call, DECL_INITIAL (current_function_decl)); VEC_free (tree, heap, args_to_pass); + /* For optimized away parameters, add on the caller side + before the call + DEBUG D#X => parm_Y(D) + stmts and associate D#X with parm in decl_debug_args_lookup + vector to say for debug info that if parameter parm had been passed, + it would have value parm_Y(D). */ + if (args_to_skip) + for (parm = DECL_ARGUMENTS (current_function_decl), num = 0; + parm; parm = DECL_CHAIN (parm), num++) + if (bitmap_bit_p (args_to_skip, num) + && is_gimple_reg (parm)) + { + tree ddecl; + gimple def_temp; + + /* This needs to be done even without MAY_HAVE_DEBUG_STMTS, + otherwise if it didn't exist before, we'd end up with + different SSA_NAME_VERSIONs between -g and -g0. */ + arg = get_or_create_ssa_default_def (cfun, parm); + if (!MAY_HAVE_DEBUG_STMTS) + continue; + + if (debug_args == NULL) + debug_args = decl_debug_args_insert (node->symbol.decl); + ddecl = make_node (DEBUG_EXPR_DECL); + DECL_ARTIFICIAL (ddecl) = 1; + TREE_TYPE (ddecl) = TREE_TYPE (parm); + DECL_MODE (ddecl) = DECL_MODE (parm); + VEC_safe_push (tree, gc, *debug_args, DECL_ORIGIN (parm)); + VEC_safe_push (tree, gc, *debug_args, ddecl); + def_temp = gimple_build_debug_bind (ddecl, unshare_expr (arg), + call); + gsi_insert_after (&gsi, def_temp, GSI_NEW_STMT); + } + /* And on the callee side, add + DEBUG D#Y s=> parm + DEBUG var => D#Y + stmts to the first bb where var is a VAR_DECL created for the + optimized away parameter in DECL_INITIAL block. This hints + in the debug info that var (whole DECL_ORIGIN is the parm PARM_DECL) + is optimized away, but could be looked up at the call site + as value of D#X there. */ + if (debug_args != NULL) + { + unsigned int i; + tree var, vexpr; + gimple_stmt_iterator cgsi; + gimple def_temp; + + push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + var = BLOCK_VARS (DECL_INITIAL (node->symbol.decl)); + i = VEC_length (tree, *debug_args); + cgsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR)); + do + { + i -= 2; + while (var != NULL_TREE + && DECL_ABSTRACT_ORIGIN (var) + != VEC_index (tree, *debug_args, i)) + var = TREE_CHAIN (var); + if (var == NULL_TREE) + break; + vexpr = make_node (DEBUG_EXPR_DECL); + parm = VEC_index (tree, *debug_args, i); + DECL_ARTIFICIAL (vexpr) = 1; + TREE_TYPE (vexpr) = TREE_TYPE (parm); + DECL_MODE (vexpr) = DECL_MODE (parm); + def_temp = gimple_build_debug_source_bind (vexpr, parm, + NULL); + gsi_insert_before (&cgsi, def_temp, GSI_SAME_STMT); + def_temp = gimple_build_debug_bind (var, vexpr, NULL); + gsi_insert_before (&cgsi, def_temp, GSI_SAME_STMT); + } + while (i); + pop_cfun (); + } + /* We avoid address being taken on any variable used by split part, so return slot optimization is always possible. Moreover this is required to make DECL_BY_REFERENCE work. */ diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index f96ed3d36d3..4f952f59bf9 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -72,13 +72,17 @@ enum LTO_symtab_tags LTO_symtab_last_tag }; -/* Create a new symtab encoder. */ +/* Create a new symtab encoder. + if FOR_INPUT, the encoder allocate only datastructures needed + to read the symtab. */ lto_symtab_encoder_t -lto_symtab_encoder_new (void) +lto_symtab_encoder_new (bool for_input) { lto_symtab_encoder_t encoder = XCNEW (struct lto_symtab_encoder_d); - encoder->map = pointer_map_create (); + + if (!for_input) + encoder->map = pointer_map_create (); encoder->nodes = NULL; return encoder; } @@ -90,7 +94,8 @@ void lto_symtab_encoder_delete (lto_symtab_encoder_t encoder) { VEC_free (lto_encoder_entry, heap, encoder->nodes); - pointer_map_destroy (encoder->map); + if (encoder->map) + pointer_map_destroy (encoder->map); free (encoder); } @@ -106,6 +111,15 @@ lto_symtab_encoder_encode (lto_symtab_encoder_t encoder, int ref; void **slot; + if (!encoder->map) + { + lto_encoder_entry entry = {node, false, false, false}; + + ref = VEC_length (lto_encoder_entry, encoder->nodes); + VEC_safe_push (lto_encoder_entry, heap, encoder->nodes, entry); + return ref; + } + slot = pointer_map_contains (encoder->map, node); if (!slot || !*slot) { @@ -688,7 +702,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) lto_symtab_encoder_t encoder; lto_symtab_encoder_iterator lsei; - encoder = lto_symtab_encoder_new (); + encoder = lto_symtab_encoder_new (false); /* Go over all entries in the IN_ENCODER and duplicate them to ENCODER. At the same time insert masters of clones so @@ -1316,7 +1330,7 @@ input_symtab (void) if (!ib) fatal_error ("cannot find LTO cgraph in %s", file_data->file_name); input_profile_summary (ib, file_data); - file_data->symtab_node_encoder = lto_symtab_encoder_new (); + file_data->symtab_node_encoder = lto_symtab_encoder_new (true); nodes = input_cgraph_1 (file_data, ib); lto_destroy_simple_input_block (file_data, LTO_section_symtab_nodes, ib, data, len); diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index afe49517eb1..083db74f911 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -1285,11 +1285,9 @@ produce_symtab (struct output_block *ob) struct streamer_tree_cache_d *cache = ob->writer_cache; char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL); struct pointer_set_t *seen; - struct cgraph_node *node; - struct varpool_node *vnode; struct lto_output_stream stream; lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder; - int i; + lto_symtab_encoder_iterator lsei; lto_begin_section (section_name, false); free (section_name); @@ -1297,78 +1295,26 @@ produce_symtab (struct output_block *ob) seen = pointer_set_create (); memset (&stream, 0, sizeof (stream)); - /* Write all functions. - First write all defined functions and then write all used functions. - This is done so only to handle duplicated symbols in cgraph. */ - for (i = 0; i < lto_symtab_encoder_size (encoder); i++) + /* Write the symbol table. + First write everything defined and then all declarations. + This is neccesary to handle cases where we have duplicated symbols. */ + for (lsei = lsei_start (encoder); + !lsei_end_p (lsei); lsei_next (&lsei)) { - if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i))) - continue; - node = cgraph (lto_symtab_encoder_deref (encoder, i)); - if (DECL_EXTERNAL (node->symbol.decl)) - continue; - if (DECL_COMDAT (node->symbol.decl) - && cgraph_comdat_can_be_unshared_p (node)) - continue; - if ((node->alias && !node->thunk.alias) || node->global.inlined_to) + symtab_node node = lsei_node (lsei); + + if (!symtab_real_symbol_p (node) || DECL_EXTERNAL (node->symbol.decl)) continue; write_symbol (cache, &stream, node->symbol.decl, seen, false); } - for (i = 0; i < lto_symtab_encoder_size (encoder); i++) + for (lsei = lsei_start (encoder); + !lsei_end_p (lsei); lsei_next (&lsei)) { - if (!symtab_function_p (lto_symtab_encoder_deref (encoder, i))) - continue; - node = cgraph (lto_symtab_encoder_deref (encoder, i)); - if (!DECL_EXTERNAL (node->symbol.decl)) - continue; - /* We keep around unused extern inlines in order to be able to inline - them indirectly or via vtables. Do not output them to symbol - table: they end up being undefined and just consume space. */ - if (!node->symbol.address_taken && !node->callers) - continue; - if (DECL_COMDAT (node->symbol.decl) - && cgraph_comdat_can_be_unshared_p (node)) - continue; - if ((node->alias && !node->thunk.alias) || node->global.inlined_to) - continue; - write_symbol (cache, &stream, node->symbol.decl, seen, false); - } + symtab_node node = lsei_node (lsei); - /* Write all variables. */ - for (i = 0; i < lto_symtab_encoder_size (encoder); i++) - { - if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i))) - continue; - vnode = varpool (lto_symtab_encoder_deref (encoder, i)); - if (DECL_EXTERNAL (vnode->symbol.decl)) - continue; - /* COMDAT virtual tables can be unshared. Do not declare them - in the LTO symbol table to prevent linker from forcing them - into the output. */ - if (DECL_COMDAT (vnode->symbol.decl) - && !vnode->symbol.force_output - && vnode->finalized - && DECL_VIRTUAL_P (vnode->symbol.decl)) - continue; - if (vnode->alias && !vnode->alias_of) - continue; - write_symbol (cache, &stream, vnode->symbol.decl, seen, false); - } - for (i = 0; i < lto_symtab_encoder_size (encoder); i++) - { - if (!symtab_variable_p (lto_symtab_encoder_deref (encoder, i))) - continue; - vnode = varpool (lto_symtab_encoder_deref (encoder, i)); - if (!DECL_EXTERNAL (vnode->symbol.decl)) + if (!symtab_real_symbol_p (node) || !DECL_EXTERNAL (node->symbol.decl)) continue; - if (DECL_COMDAT (vnode->symbol.decl) - && !vnode->symbol.force_output - && vnode->finalized - && DECL_VIRTUAL_P (vnode->symbol.decl)) - continue; - if (vnode->alias && !vnode->alias_of) - continue; - write_symbol (cache, &stream, vnode->symbol.decl, seen, false); + write_symbol (cache, &stream, node->symbol.decl, seen, false); } lto_write_stream (&stream); diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 059959e737f..b2f8d30ff63 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -833,7 +833,7 @@ void lto_output_location (struct output_block *, location_t); /* In lto-cgraph.c */ -lto_symtab_encoder_t lto_symtab_encoder_new (void); +lto_symtab_encoder_t lto_symtab_encoder_new (bool); int lto_symtab_encoder_encode (lto_symtab_encoder_t, symtab_node); void lto_symtab_encoder_delete (lto_symtab_encoder_t); bool lto_symtab_encoder_delete_node (lto_symtab_encoder_t, symtab_node); @@ -860,12 +860,9 @@ lto_symtab_encoder_t compute_ltrans_boundary (lto_symtab_encoder_t encoder); /* In lto-symtab.c. */ -extern void lto_symtab_register_decl (tree, ld_plugin_symbol_resolution_t, - struct lto_file_decl_data *); extern void lto_symtab_merge_decls (void); extern void lto_symtab_merge_cgraph_nodes (void); extern tree lto_symtab_prevailing_decl (tree decl); -extern enum ld_plugin_symbol_resolution lto_symtab_get_resolution (tree decl); extern GTY(()) VEC(tree,gc) *lto_global_var_decls; @@ -873,11 +870,6 @@ extern GTY(()) VEC(tree,gc) *lto_global_var_decls; extern void lto_write_options (void); -/* In lto-wpa-fixup.c */ -void lto_mark_nothrow_fndecl (tree); -void lto_fixup_nothrow_decls (void); - - /* Statistics gathered during LTO, WPA and LTRANS. */ extern struct lto_stats_d lto_stats; diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c index cd8ca67b0c0..25c0b22dc48 100644 --- a/gcc/lto-symtab.c +++ b/gcc/lto-symtab.c @@ -32,40 +32,6 @@ along with GCC; see the file COPYING3. If not see /* Vector to keep track of external variables we've seen so far. */ VEC(tree,gc) *lto_global_var_decls; -/* Registers DECL with the LTO symbol table as having resolution RESOLUTION - and read from FILE_DATA. */ - -void -lto_symtab_register_decl (tree decl, - ld_plugin_symbol_resolution_t resolution, - struct lto_file_decl_data *file_data) -{ - symtab_node node; - - /* Check that declarations reaching this function do not have - properties inconsistent with having external linkage. If any of - these asertions fail, then the object file reader has failed to - detect these cases and issue appropriate error messages. */ - gcc_assert (decl - && TREE_PUBLIC (decl) - && (TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == FUNCTION_DECL) - && DECL_ASSEMBLER_NAME_SET_P (decl)); - if (TREE_CODE (decl) == VAR_DECL - && DECL_INITIAL (decl)) - gcc_assert (!DECL_EXTERNAL (decl) - || (TREE_STATIC (decl) && TREE_READONLY (decl))); - if (TREE_CODE (decl) == FUNCTION_DECL) - gcc_assert (!DECL_ABSTRACT (decl)); - - node = symtab_get_node (decl); - if (node) - { - node->symbol.resolution = resolution; - gcc_assert (node->symbol.lto_file_data == file_data); - } -} - /* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging all edges and removing the old node. */ diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 7c437d6c9e5..7218f4873cd 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,17 @@ +2012-10-07 Jan Hubicka <jh@suse.cz> + + * lto.c (read_cgraph_and_symbols): Release type merging hash early; + release input encoders. + * lto-partition.c (new_partition): Update for new lto_symtab_encoder_new. + +2012-10-06 Jan Hubicka <jh@suse.cz> + + PR lto/54790 + * lto.c (resolution_map): New static var. + (register_resolution): New function. + (lto_register_var_decl_in_symtab): Use it. + (read_cgraph_and_symbols): Copy resolutions into the symtab. + 2012-09-20 Martin Jambor <mjambor@suse.cz> * lto.c (lto_materialize_function): Call push_struct_function and diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c index b1310335a4a..32243fb83d3 100644 --- a/gcc/lto/lto-partition.c +++ b/gcc/lto/lto-partition.c @@ -99,7 +99,7 @@ static ltrans_partition new_partition (const char *name) { ltrans_partition part = XCNEW (struct ltrans_partition_def); - part->encoder = lto_symtab_encoder_new (); + part->encoder = lto_symtab_encoder_new (false); part->name = name; part->insns = 0; VEC_safe_push (ltrans_partition, heap, ltrans_partitions, part); diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 44718537b3c..d880c8a2062 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -1692,6 +1692,19 @@ get_resolution (struct data_in *data_in, unsigned index) return LDPR_UNKNOWN; } +/* Map assigning declarations their resolutions. */ +static pointer_map_t *resolution_map; + +/* We need to record resolutions until symbol table is read. */ +static void +register_resolution (tree decl, enum ld_plugin_symbol_resolution resolution) +{ + if (resolution == LDPR_UNKNOWN) + return; + if (!resolution_map) + resolution_map = pointer_map_create (); + *pointer_map_insert (resolution_map, decl) = (void *)(size_t)resolution; +} /* Register DECL with the global symbol table and change its name if necessary to avoid name clashes for static globals across @@ -1730,8 +1743,7 @@ lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl) unsigned ix; if (!streamer_tree_cache_lookup (data_in->reader_cache, decl, &ix)) gcc_unreachable (); - lto_symtab_register_decl (decl, get_resolution (data_in, ix), - data_in->file_data); + register_resolution (decl, get_resolution (data_in, ix)); } } @@ -1789,8 +1801,7 @@ lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl) unsigned ix; if (!streamer_tree_cache_lookup (data_in->reader_cache, decl, &ix)) gcc_unreachable (); - lto_symtab_register_decl (decl, get_resolution (data_in, ix), - data_in->file_data); + register_resolution (decl, get_resolution (data_in, ix)); } } @@ -2935,6 +2946,17 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) if (resolution_file_name) fclose (resolution); + /* Free gimple type merging datastructures. */ + htab_delete (gimple_types); + gimple_types = NULL; + htab_delete (type_hash_cache); + type_hash_cache = NULL; + free (type_pair_cache); + type_pair_cache = NULL; + gimple_type_leader = NULL; + free_gimple_type_tables (); + ggc_collect (); + /* Set the hooks so that all of the ipa passes can read in their data. */ lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data); @@ -2946,6 +2968,24 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) timevar_push (TV_IPA_LTO_CGRAPH_IO); /* Read the symtab. */ input_symtab (); + + /* Store resolutions into the symbol table. */ + if (resolution_map) + { + void **res; + symtab_node snode; + + FOR_EACH_SYMBOL (snode) + if (symtab_real_symbol_p (snode) + && (res = pointer_map_contains (resolution_map, + snode->symbol.decl))) + snode->symbol.resolution + = (enum ld_plugin_symbol_resolution)(size_t)*res; + + pointer_map_destroy (resolution_map); + resolution_map = NULL; + } + timevar_pop (TV_IPA_LTO_CGRAPH_IO); if (!quiet_flag) @@ -2960,18 +3000,10 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) if (seen_error ()) fatal_error ("errors during merging of translation units"); - /* Fixup all decls and types and free the type hash tables. */ + /* Fixup all decls. */ lto_fixup_decls (all_file_decl_data); htab_delete (tree_with_vars); tree_with_vars = NULL; - htab_delete (gimple_types); - gimple_types = NULL; - htab_delete (type_hash_cache); - type_hash_cache = NULL; - free (type_pair_cache); - type_pair_cache = NULL; - gimple_type_leader = NULL; - free_gimple_type_tables (); ggc_collect (); timevar_pop (TV_IPA_LTO_DECL_MERGE); @@ -2986,6 +3018,13 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) else ipa_read_summaries (); + for (i = 0; all_file_decl_data[i]; i++) + { + gcc_assert (all_file_decl_data[i]->symtab_node_encoder); + lto_symtab_encoder_delete (all_file_decl_data[i]->symtab_node_encoder); + all_file_decl_data[i]->symtab_node_encoder = NULL; + } + /* Finally merge the cgraph according to the decl merging decisions. */ timevar_push (TV_IPA_LTO_CGRAPH_MERGE); if (cgraph_dump_file) diff --git a/gcc/machmode.h b/gcc/machmode.h index bdaf1bee274..b95d05b096e 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -217,6 +217,11 @@ extern const unsigned char mode_inner[NUM_MACHINE_MODES]; #define GET_MODE_UNIT_BITSIZE(MODE) \ ((unsigned short) (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT)) +#define GET_MODE_UNIT_PRECISION(MODE) \ + (GET_MODE_INNER (MODE) == VOIDmode \ + ? GET_MODE_PRECISION (MODE) \ + : GET_MODE_PRECISION (GET_MODE_INNER (MODE))) + /* Get the number of units in the object. */ extern const unsigned char mode_nunits[NUM_MACHINE_MODES]; diff --git a/gcc/params.def b/gcc/params.def index 59b64c5c452..9aba422bddd 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -611,6 +611,11 @@ DEFPARAM(PARAM_SCHED_SPEC_PROB_CUTOFF, "The minimal probability of speculation success (in percents), so that speculative insn will be scheduled.", 40, 0, 100) +DEFPARAM(PARAM_SCHED_STATE_EDGE_PROB_CUTOFF, + "sched-state-edge-prob-cutoff", + "The minimum probability an edge must have for the scheduler to save its state across it.", + 10, 0, 100) + DEFPARAM(PARAM_SELSCHED_MAX_LOOKAHEAD, "selsched-max-lookahead", "The maximum size of the lookahead window of selective scheduling", diff --git a/gcc/passes.c b/gcc/passes.c index a5e1ca6c400..a7a4e8d1227 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1778,6 +1778,209 @@ execute_function_dump (void *data ATTRIBUTE_UNUSED) } } +/* Make statistic about profile consistency. */ + +struct profile_record +{ + int num_mismatched_freq_in[2]; + int num_mismatched_freq_out[2]; + int num_mismatched_count_in[2]; + int num_mismatched_count_out[2]; + bool run; + gcov_type time[2]; + int size[2]; +}; + +static struct profile_record *profile_record; + +static void +check_profile_consistency (int index, int subpass, bool run) +{ + basic_block bb; + edge_iterator ei; + edge e; + int sum; + gcov_type lsum; + + if (index == -1) + return; + if (!profile_record) + profile_record = XCNEWVEC (struct profile_record, + passes_by_id_size); + gcc_assert (index < passes_by_id_size && index >= 0); + gcc_assert (subpass < 2); + profile_record[index].run |= run; + + FOR_ALL_BB (bb) + { + if (bb != EXIT_BLOCK_PTR_FOR_FUNCTION (cfun) + && profile_status != PROFILE_ABSENT) + { + sum = 0; + FOR_EACH_EDGE (e, ei, bb->succs) + sum += e->probability; + if (EDGE_COUNT (bb->succs) && abs (sum - REG_BR_PROB_BASE) > 100) + profile_record[index].num_mismatched_freq_out[subpass]++; + lsum = 0; + FOR_EACH_EDGE (e, ei, bb->succs) + lsum += e->count; + if (EDGE_COUNT (bb->succs) + && (lsum - bb->count > 100 || lsum - bb->count < -100)) + profile_record[index].num_mismatched_count_out[subpass]++; + } + if (bb != ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun) + && profile_status != PROFILE_ABSENT) + { + sum = 0; + FOR_EACH_EDGE (e, ei, bb->preds) + sum += EDGE_FREQUENCY (e); + if (abs (sum - bb->frequency) > 100 + || (MAX (sum, bb->frequency) > 10 + && abs ((sum - bb->frequency) * 100 / (MAX (sum, bb->frequency) + 1)) > 10)) + profile_record[index].num_mismatched_freq_in[subpass]++; + lsum = 0; + FOR_EACH_EDGE (e, ei, bb->preds) + lsum += e->count; + if (lsum - bb->count > 100 || lsum - bb->count < -100) + profile_record[index].num_mismatched_count_in[subpass]++; + } + if (bb == ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun) + || bb == EXIT_BLOCK_PTR_FOR_FUNCTION (cfun)) + continue; + if ((cfun && (cfun->curr_properties & PROP_trees))) + { + gimple_stmt_iterator i; + + for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) + { + profile_record[index].size[subpass] + += estimate_num_insns (gsi_stmt (i), &eni_size_weights); + if (profile_status == PROFILE_READ) + profile_record[index].time[subpass] + += estimate_num_insns (gsi_stmt (i), + &eni_time_weights) * bb->count; + else if (profile_status == PROFILE_GUESSED) + profile_record[index].time[subpass] + += estimate_num_insns (gsi_stmt (i), + &eni_time_weights) * bb->frequency; + } + } + else if (cfun && (cfun->curr_properties & PROP_rtl)) + { + rtx insn; + for (insn = NEXT_INSN (BB_HEAD (bb)); insn && insn != NEXT_INSN (BB_END (bb)); + insn = NEXT_INSN (insn)) + if (INSN_P (insn)) + { + profile_record[index].size[subpass] + += insn_rtx_cost (PATTERN (insn), false); + if (profile_status == PROFILE_READ) + profile_record[index].time[subpass] + += insn_rtx_cost (PATTERN (insn), true) * bb->count; + else if (profile_status == PROFILE_GUESSED) + profile_record[index].time[subpass] + += insn_rtx_cost (PATTERN (insn), true) * bb->frequency; + } + } + } +} + +/* Output profile consistency. */ + +void +dump_profile_report (void) +{ + int i, j; + int last_freq_in = 0, last_count_in = 0, last_freq_out = 0, last_count_out = 0; + gcov_type last_time = 0, last_size = 0; + double rel_time_change, rel_size_change; + int last_reported = 0; + + if (!profile_record) + return; + fprintf (stderr, "\nProfile consistency report:\n\n"); + fprintf (stderr, "Pass name |mismatch in |mismated out|Overall\n"); + fprintf (stderr, " |freq count |freq count |size time\n"); + + for (i = 0; i < passes_by_id_size; i++) + for (j = 0 ; j < 2; j++) + if (profile_record[i].run) + { + if (last_time) + rel_time_change = (profile_record[i].time[j] + - (double)last_time) * 100 / (double)last_time; + else + rel_time_change = 0; + if (last_size) + rel_size_change = (profile_record[i].size[j] + - (double)last_size) * 100 / (double)last_size; + else + rel_size_change = 0; + + if (profile_record[i].num_mismatched_freq_in[j] != last_freq_in + || profile_record[i].num_mismatched_freq_out[j] != last_freq_out + || profile_record[i].num_mismatched_count_in[j] != last_count_in + || profile_record[i].num_mismatched_count_out[j] != last_count_out + || rel_time_change || rel_size_change) + { + last_reported = i; + fprintf (stderr, "%-20s %s", + passes_by_id [i]->name, + j ? "(after TODO)" : " "); + if (profile_record[i].num_mismatched_freq_in[j] != last_freq_in) + fprintf (stderr, "| %+5i", + profile_record[i].num_mismatched_freq_in[j] + - last_freq_in); + else + fprintf (stderr, "| "); + if (profile_record[i].num_mismatched_count_in[j] != last_count_in) + fprintf (stderr, " %+5i", + profile_record[i].num_mismatched_count_in[j] + - last_count_in); + else + fprintf (stderr, " "); + if (profile_record[i].num_mismatched_freq_out[j] != last_freq_out) + fprintf (stderr, "| %+5i", + profile_record[i].num_mismatched_freq_out[j] + - last_freq_out); + else + fprintf (stderr, "| "); + if (profile_record[i].num_mismatched_count_out[j] != last_count_out) + fprintf (stderr, " %+5i", + profile_record[i].num_mismatched_count_out[j] + - last_count_out); + else + fprintf (stderr, " "); + + /* Size/time units change across gimple and RTL. */ + if (i == pass_expand.pass.static_pass_number) + fprintf (stderr, "|----------"); + else + { + if (rel_size_change) + fprintf (stderr, "| %+8.4f%%", rel_size_change); + else + fprintf (stderr, "| "); + if (rel_time_change) + fprintf (stderr, " %+8.4f%%", rel_time_change); + } + fprintf (stderr, "\n"); + last_freq_in = profile_record[i].num_mismatched_freq_in[j]; + last_freq_out = profile_record[i].num_mismatched_freq_out[j]; + last_count_in = profile_record[i].num_mismatched_count_in[j]; + last_count_out = profile_record[i].num_mismatched_count_out[j]; + } + else if (j && last_reported != i) + { + last_reported = i; + fprintf (stderr, "%-20s ------------| | |\n", + passes_by_id [i]->name); + } + last_time = profile_record[i].time[j]; + last_size = profile_record[i].size[j]; + } +} + /* Perform all TODO actions that ought to be done on each function. */ static void @@ -2042,9 +2245,14 @@ execute_one_ipa_transform_pass (struct cgraph_node *node, if (pass->tv_id != TV_NONE) timevar_pop (pass->tv_id); + if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) + check_profile_consistency (pass->static_pass_number, 0, true); + /* Run post-pass cleanup and verification. */ execute_todo (todo_after); verify_interpass_invariants (); + if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) + check_profile_consistency (pass->static_pass_number, 1, true); do_per_function (execute_function_dump, NULL); pass_fini_dump_file (pass); @@ -2144,6 +2352,13 @@ execute_one_pass (struct opt_pass *pass) if (!gate_status) { + /* Run so passes selectively disabling themselves on a given function + are not miscounted. */ + if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) + { + check_profile_consistency (pass->static_pass_number, 0, false); + check_profile_consistency (pass->static_pass_number, 1, false); + } current_pass = NULL; return false; } @@ -2214,8 +2429,14 @@ execute_one_pass (struct opt_pass *pass) clean_graph_dump_file (dump_file_name); } + if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) + check_profile_consistency (pass->static_pass_number, 0, true); + /* Run post-pass cleanup and verification. */ execute_todo (todo_after | pass->todo_flags_finish); + if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) + check_profile_consistency (pass->static_pass_number, 1, true); + verify_interpass_invariants (); do_per_function (execute_function_dump, NULL); if (pass->type == IPA_PASS) @@ -2327,7 +2548,7 @@ ipa_write_summaries (void) if (!flag_generate_lto || seen_error ()) return; - encoder = lto_symtab_encoder_new (); + encoder = lto_symtab_encoder_new (false); /* Create the callgraph set in the same order used in cgraph_expand_all_functions. This mostly facilitates debugging, diff --git a/gcc/plugin.h b/gcc/plugin.h index 4d2d12a9da6..c514e67d031 100644 --- a/gcc/plugin.h +++ b/gcc/plugin.h @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "gcc-plugin.h" struct attribute_spec; +struct scoped_attributes; extern void add_new_plugin (const char *); extern void parse_plugin_arg_opt (const char *); @@ -64,5 +65,7 @@ invoke_plugin_callbacks (int event ATTRIBUTE_UNUSED, /* In attribs.c. */ extern void register_attribute (const struct attribute_spec *attr); +extern struct scoped_attributes* register_scoped_attributes (const struct attribute_spec *, + const char *); #endif /* PLUGIN_H */ diff --git a/gcc/sched-ebb.c b/gcc/sched-ebb.c index 372d1081b4f..9e524f9f13e 100644 --- a/gcc/sched-ebb.c +++ b/gcc/sched-ebb.c @@ -544,7 +544,7 @@ schedule_ebb (rtx head, rtx tail, bool modulo_scheduling) /* Make ready list big enough to hold all the instructions from the ebb. */ sched_extend_ready_list (rgn_n_insns); - success = schedule_block (&target_bb); + success = schedule_block (&target_bb, NULL); gcc_assert (success || modulo_scheduling); /* Free ready list. */ diff --git a/gcc/sched-int.h b/gcc/sched-int.h index 32bdeb42ab9..d3a15aa90a7 100644 --- a/gcc/sched-int.h +++ b/gcc/sched-int.h @@ -1321,7 +1321,7 @@ extern int dep_cost (dep_t); extern int set_priorities (rtx, rtx); extern void sched_setup_bb_reg_pressure_info (basic_block, rtx); -extern bool schedule_block (basic_block *); +extern bool schedule_block (basic_block *, state_t); extern int cycle_issued_insns; extern int issue_rate; diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c index 5d39a36d7fa..ba85238e6fd 100644 --- a/gcc/sched-rgn.c +++ b/gcc/sched-rgn.c @@ -124,6 +124,9 @@ int current_blocks; static basic_block *bblst_table; static int bblst_size, bblst_last; +static char *bb_state_array; +static state_t *bb_state; + /* Target info declarations. The block currently being scheduled is referred to as the "target" block, @@ -2982,9 +2985,21 @@ schedule_region (int rgn) curr_bb = first_bb; if (dbg_cnt (sched_block)) { - schedule_block (&curr_bb); + edge f; + + schedule_block (&curr_bb, bb_state[first_bb->index]); gcc_assert (EBB_FIRST_BB (bb) == first_bb); sched_rgn_n_insns += sched_n_insns; + f = find_fallthru_edge (last_bb->succs); + if (f && f->probability * 100 / REG_BR_PROB_BASE >= + PARAM_VALUE (PARAM_SCHED_STATE_EDGE_PROB_CUTOFF)) + { + memcpy (bb_state[f->dest->index], curr_state, + dfa_state_size); + if (sched_verbose >= 5) + fprintf (sched_dump, "saving state for edge %d->%d\n", + f->src->index, f->dest->index); + } } else { @@ -3017,6 +3032,8 @@ schedule_region (int rgn) void sched_rgn_init (bool single_blocks_p) { + int i; + min_spec_prob = ((PARAM_VALUE (PARAM_MIN_SPEC_PROB) * REG_BR_PROB_BASE) / 100); @@ -3028,6 +3045,23 @@ sched_rgn_init (bool single_blocks_p) CONTAINING_RGN (ENTRY_BLOCK) = -1; CONTAINING_RGN (EXIT_BLOCK) = -1; + if (!sel_sched_p ()) + { + bb_state_array = (char *) xmalloc (last_basic_block * dfa_state_size); + bb_state = XNEWVEC (state_t, last_basic_block); + for (i = 0; i < last_basic_block; i++) + { + bb_state[i] = (state_t) (bb_state_array + i * dfa_state_size); + + state_reset (bb_state[i]); + } + } + else + { + bb_state_array = NULL; + bb_state = NULL; + } + /* Compute regions for scheduling. */ if (single_blocks_p || n_basic_blocks == NUM_FIXED_BLOCKS + 1 @@ -3064,6 +3098,9 @@ sched_rgn_init (bool single_blocks_p) void sched_rgn_finish (void) { + free (bb_state_array); + free (bb_state); + /* Reposition the prologue and epilogue notes in case we moved the prologue/epilogue insns. */ if (reload_completed) diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index acd47987603..95cf1860af0 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -564,6 +564,212 @@ simplify_replace_rtx (rtx x, const_rtx old_rtx, rtx new_rtx) return simplify_replace_fn_rtx (x, old_rtx, 0, new_rtx); } +/* Try to simplify a MODE truncation of OP, which has OP_MODE. + Only handle cases where the truncated value is inherently an rvalue. + + RTL provides two ways of truncating a value: + + 1. a lowpart subreg. This form is only a truncation when both + the outer and inner modes (here MODE and OP_MODE respectively) + are scalar integers, and only then when the subreg is used as + an rvalue. + + It is only valid to form such truncating subregs if the + truncation requires no action by the target. The onus for + proving this is on the creator of the subreg -- e.g. the + caller to simplify_subreg or simplify_gen_subreg -- and typically + involves either TRULY_NOOP_TRUNCATION_MODES_P or truncated_to_mode. + + 2. a TRUNCATE. This form handles both scalar and compound integers. + + The first form is preferred where valid. However, the TRUNCATE + handling in simplify_unary_operation turns the second form into the + first form when TRULY_NOOP_TRUNCATION_MODES_P or truncated_to_mode allow, + so it is generally safe to form rvalue truncations using: + + simplify_gen_unary (TRUNCATE, ...) + + and leave simplify_unary_operation to work out which representation + should be used. + + Because of the proof requirements on (1), simplify_truncation must + also use simplify_gen_unary (TRUNCATE, ...) to truncate parts of OP, + regardless of whether the outer truncation came from a SUBREG or a + TRUNCATE. For example, if the caller has proven that an SImode + truncation of: + + (and:DI X Y) + + is a no-op and can be represented as a subreg, it does not follow + that SImode truncations of X and Y are also no-ops. On a target + like 64-bit MIPS that requires SImode values to be stored in + sign-extended form, an SImode truncation of: + + (and:DI (reg:DI X) (const_int 63)) + + is trivially a no-op because only the lower 6 bits can be set. + However, X is still an arbitrary 64-bit number and so we cannot + assume that truncating it too is a no-op. */ + +static rtx +simplify_truncation (enum machine_mode mode, rtx op, + enum machine_mode op_mode) +{ + unsigned int precision = GET_MODE_UNIT_PRECISION (mode); + unsigned int op_precision = GET_MODE_UNIT_PRECISION (op_mode); + gcc_assert (precision <= op_precision); + + /* Optimize truncations of zero and sign extended values. */ + if (GET_CODE (op) == ZERO_EXTEND + || GET_CODE (op) == SIGN_EXTEND) + { + /* There are three possibilities. If MODE is the same as the + origmode, we can omit both the extension and the subreg. + If MODE is not larger than the origmode, we can apply the + truncation without the extension. Finally, if the outermode + is larger than the origmode, we can just extend to the appropriate + mode. */ + enum machine_mode origmode = GET_MODE (XEXP (op, 0)); + if (mode == origmode) + return XEXP (op, 0); + else if (precision <= GET_MODE_UNIT_PRECISION (origmode)) + return simplify_gen_unary (TRUNCATE, mode, + XEXP (op, 0), origmode); + else + return simplify_gen_unary (GET_CODE (op), mode, + XEXP (op, 0), origmode); + } + + /* Simplify (truncate:SI (op:DI (x:DI) (y:DI))) + to (op:SI (truncate:SI (x:DI)) (truncate:SI (x:DI))). */ + if (GET_CODE (op) == PLUS + || GET_CODE (op) == MINUS + || GET_CODE (op) == MULT) + { + rtx op0 = simplify_gen_unary (TRUNCATE, mode, XEXP (op, 0), op_mode); + if (op0) + { + rtx op1 = simplify_gen_unary (TRUNCATE, mode, XEXP (op, 1), op_mode); + if (op1) + return simplify_gen_binary (GET_CODE (op), mode, op0, op1); + } + } + + /* Simplify (truncate:QI (lshiftrt:SI (sign_extend:SI (x:QI)) C)) into + to (ashiftrt:QI (x:QI) C), where C is a suitable small constant and + the outer subreg is effectively a truncation to the original mode. */ + if ((GET_CODE (op) == LSHIFTRT + || GET_CODE (op) == ASHIFTRT) + /* Ensure that OP_MODE is at least twice as wide as MODE + to avoid the possibility that an outer LSHIFTRT shifts by more + than the sign extension's sign_bit_copies and introduces zeros + into the high bits of the result. */ + && 2 * precision <= op_precision + && CONST_INT_P (XEXP (op, 1)) + && GET_CODE (XEXP (op, 0)) == SIGN_EXTEND + && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode + && INTVAL (XEXP (op, 1)) < precision) + return simplify_gen_binary (ASHIFTRT, mode, + XEXP (XEXP (op, 0), 0), XEXP (op, 1)); + + /* Likewise (truncate:QI (lshiftrt:SI (zero_extend:SI (x:QI)) C)) into + to (lshiftrt:QI (x:QI) C), where C is a suitable small constant and + the outer subreg is effectively a truncation to the original mode. */ + if ((GET_CODE (op) == LSHIFTRT + || GET_CODE (op) == ASHIFTRT) + && CONST_INT_P (XEXP (op, 1)) + && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND + && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode + && INTVAL (XEXP (op, 1)) < precision) + return simplify_gen_binary (LSHIFTRT, mode, + XEXP (XEXP (op, 0), 0), XEXP (op, 1)); + + /* Likewise (truncate:QI (ashift:SI (zero_extend:SI (x:QI)) C)) into + to (ashift:QI (x:QI) C), where C is a suitable small constant and + the outer subreg is effectively a truncation to the original mode. */ + if (GET_CODE (op) == ASHIFT + && CONST_INT_P (XEXP (op, 1)) + && (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND + || GET_CODE (XEXP (op, 0)) == SIGN_EXTEND) + && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode + && INTVAL (XEXP (op, 1)) < precision) + return simplify_gen_binary (ASHIFT, mode, + XEXP (XEXP (op, 0), 0), XEXP (op, 1)); + + /* Recognize a word extraction from a multi-word subreg. */ + if ((GET_CODE (op) == LSHIFTRT + || GET_CODE (op) == ASHIFTRT) + && SCALAR_INT_MODE_P (mode) + && SCALAR_INT_MODE_P (op_mode) + && precision >= BITS_PER_WORD + && 2 * precision <= op_precision + && CONST_INT_P (XEXP (op, 1)) + && (INTVAL (XEXP (op, 1)) & (precision - 1)) == 0 + && INTVAL (XEXP (op, 1)) >= 0 + && INTVAL (XEXP (op, 1)) < op_precision) + { + int byte = subreg_lowpart_offset (mode, op_mode); + int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT; + return simplify_gen_subreg (mode, XEXP (op, 0), op_mode, + (WORDS_BIG_ENDIAN + ? byte - shifted_bytes + : byte + shifted_bytes)); + } + + /* If we have a TRUNCATE of a right shift of MEM, make a new MEM + and try replacing the TRUNCATE and shift with it. Don't do this + if the MEM has a mode-dependent address. */ + if ((GET_CODE (op) == LSHIFTRT + || GET_CODE (op) == ASHIFTRT) + && SCALAR_INT_MODE_P (op_mode) + && MEM_P (XEXP (op, 0)) + && CONST_INT_P (XEXP (op, 1)) + && (INTVAL (XEXP (op, 1)) % GET_MODE_BITSIZE (mode)) == 0 + && INTVAL (XEXP (op, 1)) > 0 + && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (op_mode) + && ! mode_dependent_address_p (XEXP (XEXP (op, 0), 0), + MEM_ADDR_SPACE (XEXP (op, 0))) + && ! MEM_VOLATILE_P (XEXP (op, 0)) + && (GET_MODE_SIZE (mode) >= UNITS_PER_WORD + || WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN)) + { + int byte = subreg_lowpart_offset (mode, op_mode); + int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT; + return adjust_address_nv (XEXP (op, 0), mode, + (WORDS_BIG_ENDIAN + ? byte - shifted_bytes + : byte + shifted_bytes)); + } + + /* (truncate:SI (OP:DI ({sign,zero}_extend:DI foo:SI))) is + (OP:SI foo:SI) if OP is NEG or ABS. */ + if ((GET_CODE (op) == ABS + || GET_CODE (op) == NEG) + && (GET_CODE (XEXP (op, 0)) == SIGN_EXTEND + || GET_CODE (XEXP (op, 0)) == ZERO_EXTEND) + && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode) + return simplify_gen_unary (GET_CODE (op), mode, + XEXP (XEXP (op, 0), 0), mode); + + /* (truncate:A (subreg:B (truncate:C X) 0)) is + (truncate:A X). */ + if (GET_CODE (op) == SUBREG + && SCALAR_INT_MODE_P (mode) + && SCALAR_INT_MODE_P (op_mode) + && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (op))) + && GET_CODE (SUBREG_REG (op)) == TRUNCATE + && subreg_lowpart_p (op)) + return simplify_gen_unary (TRUNCATE, mode, XEXP (SUBREG_REG (op), 0), + GET_MODE (XEXP (SUBREG_REG (op), 0))); + + /* (truncate:A (truncate:B X)) is (truncate:A X). */ + if (GET_CODE (op) == TRUNCATE) + return simplify_gen_unary (TRUNCATE, mode, XEXP (op, 0), + GET_MODE (XEXP (op, 0))); + + return NULL_RTX; +} + /* Try to simplify a unary operation CODE whose output mode is to be MODE with input operand OP whose mode was originally OP_MODE. Return zero if no simplification can be made. */ @@ -815,50 +1021,34 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) break; case TRUNCATE: - /* We can't handle truncation to a partial integer mode here - because we don't know the real bitsize of the partial - integer mode. */ - if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) - break; - - /* (truncate:SI ({sign,zero}_extend:DI foo:SI)) == foo:SI. */ - if ((GET_CODE (op) == SIGN_EXTEND - || GET_CODE (op) == ZERO_EXTEND) - && GET_MODE (XEXP (op, 0)) == mode) - return XEXP (op, 0); + /* Don't optimize (lshiftrt (mult ...)) as it would interfere + with the umulXi3_highpart patterns. */ + if (GET_CODE (op) == LSHIFTRT + && GET_CODE (XEXP (op, 0)) == MULT) + break; - /* (truncate:SI (OP:DI ({sign,zero}_extend:DI foo:SI))) is - (OP:SI foo:SI) if OP is NEG or ABS. */ - if ((GET_CODE (op) == ABS - || GET_CODE (op) == NEG) - && (GET_CODE (XEXP (op, 0)) == SIGN_EXTEND - || GET_CODE (XEXP (op, 0)) == ZERO_EXTEND) - && GET_MODE (XEXP (XEXP (op, 0), 0)) == mode) - return simplify_gen_unary (GET_CODE (op), mode, - XEXP (XEXP (op, 0), 0), mode); + if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) + { + if (TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op))) + return rtl_hooks.gen_lowpart_no_emit (mode, op); + /* We can't handle truncation to a partial integer mode here + because we don't know the real bitsize of the partial + integer mode. */ + break; + } - /* (truncate:A (subreg:B (truncate:C X) 0)) is - (truncate:A X). */ - if (GET_CODE (op) == SUBREG - && GET_CODE (SUBREG_REG (op)) == TRUNCATE - && subreg_lowpart_p (op)) - return simplify_gen_unary (TRUNCATE, mode, XEXP (SUBREG_REG (op), 0), - GET_MODE (XEXP (SUBREG_REG (op), 0))); + if (GET_MODE (op) != VOIDmode) + { + temp = simplify_truncation (mode, op, GET_MODE (op)); + if (temp) + return temp; + } /* If we know that the value is already truncated, we can - replace the TRUNCATE with a SUBREG. Note that this is also - valid if TRULY_NOOP_TRUNCATION is false for the corresponding - modes we just have to apply a different definition for - truncation. But don't do this for an (LSHIFTRT (MULT ...)) - since this will cause problems with the umulXi3_highpart - patterns. */ - if ((TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op)) - ? (num_sign_bit_copies (op, GET_MODE (op)) - > (unsigned int) (GET_MODE_PRECISION (GET_MODE (op)) - - GET_MODE_PRECISION (mode))) - : truncated_to_mode (mode, op)) - && ! (GET_CODE (op) == LSHIFTRT - && GET_CODE (XEXP (op, 0)) == MULT)) + replace the TRUNCATE with a SUBREG. */ + if (GET_MODE_NUNITS (mode) == 1 + && (TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (op)) + || truncated_to_mode (mode, op))) return rtl_hooks.gen_lowpart_no_emit (mode, op); /* A truncate of a comparison can be replaced with a subreg if @@ -5596,14 +5786,6 @@ simplify_subreg (enum machine_mode outermode, rtx op, return NULL_RTX; } - /* Merge implicit and explicit truncations. */ - - if (GET_CODE (op) == TRUNCATE - && GET_MODE_SIZE (outermode) < GET_MODE_SIZE (innermode) - && subreg_lowpart_offset (outermode, innermode) == byte) - return simplify_gen_unary (TRUNCATE, outermode, XEXP (op, 0), - GET_MODE (XEXP (op, 0))); - /* SUBREG of a hard register => just change the register number and/or mode. If the hard register is not valid in that mode, suppress this simplification. If the hard register is the stack, @@ -5689,160 +5871,23 @@ simplify_subreg (enum machine_mode outermode, rtx op, return NULL_RTX; } - /* Optimize SUBREG truncations of zero and sign extended values. */ - if ((GET_CODE (op) == ZERO_EXTEND - || GET_CODE (op) == SIGN_EXTEND) - && SCALAR_INT_MODE_P (innermode) - && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode)) + /* A SUBREG resulting from a zero extension may fold to zero if + it extracts higher bits that the ZERO_EXTEND's source bits. */ + if (GET_CODE (op) == ZERO_EXTEND) { unsigned int bitpos = subreg_lsb_1 (outermode, innermode, byte); - - /* If we're requesting the lowpart of a zero or sign extension, - there are three possibilities. If the outermode is the same - as the origmode, we can omit both the extension and the subreg. - If the outermode is not larger than the origmode, we can apply - the truncation without the extension. Finally, if the outermode - is larger than the origmode, but both are integer modes, we - can just extend to the appropriate mode. */ - if (bitpos == 0) - { - enum machine_mode origmode = GET_MODE (XEXP (op, 0)); - if (outermode == origmode) - return XEXP (op, 0); - if (GET_MODE_PRECISION (outermode) <= GET_MODE_PRECISION (origmode)) - return simplify_gen_subreg (outermode, XEXP (op, 0), origmode, - subreg_lowpart_offset (outermode, - origmode)); - if (SCALAR_INT_MODE_P (outermode)) - return simplify_gen_unary (GET_CODE (op), outermode, - XEXP (op, 0), origmode); - } - - /* A SUBREG resulting from a zero extension may fold to zero if - it extracts higher bits that the ZERO_EXTEND's source bits. */ - if (GET_CODE (op) == ZERO_EXTEND - && bitpos >= GET_MODE_PRECISION (GET_MODE (XEXP (op, 0)))) + if (bitpos >= GET_MODE_PRECISION (GET_MODE (XEXP (op, 0)))) return CONST0_RTX (outermode); } - /* Simplify (subreg:SI (op:DI ((x:DI) (y:DI)), 0) - to (op:SI (subreg:SI (x:DI) 0) (subreg:SI (x:DI) 0)), where - the outer subreg is effectively a truncation to the original mode. */ - if ((GET_CODE (op) == PLUS - || GET_CODE (op) == MINUS - || GET_CODE (op) == MULT) - && SCALAR_INT_MODE_P (outermode) + if (SCALAR_INT_MODE_P (outermode) && SCALAR_INT_MODE_P (innermode) && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode) && byte == subreg_lowpart_offset (outermode, innermode)) { - rtx op0 = simplify_gen_subreg (outermode, XEXP (op, 0), - innermode, byte); - if (op0) - { - rtx op1 = simplify_gen_subreg (outermode, XEXP (op, 1), - innermode, byte); - if (op1) - return simplify_gen_binary (GET_CODE (op), outermode, op0, op1); - } - } - - /* Simplify (subreg:QI (lshiftrt:SI (sign_extend:SI (x:QI)) C), 0) into - to (ashiftrt:QI (x:QI) C), where C is a suitable small constant and - the outer subreg is effectively a truncation to the original mode. */ - if ((GET_CODE (op) == LSHIFTRT - || GET_CODE (op) == ASHIFTRT) - && SCALAR_INT_MODE_P (outermode) - && SCALAR_INT_MODE_P (innermode) - /* Ensure that OUTERMODE is at least twice as wide as the INNERMODE - to avoid the possibility that an outer LSHIFTRT shifts by more - than the sign extension's sign_bit_copies and introduces zeros - into the high bits of the result. */ - && (2 * GET_MODE_PRECISION (outermode)) <= GET_MODE_PRECISION (innermode) - && CONST_INT_P (XEXP (op, 1)) - && GET_CODE (XEXP (op, 0)) == SIGN_EXTEND - && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode - && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (outermode) - && subreg_lsb_1 (outermode, innermode, byte) == 0) - return simplify_gen_binary (ASHIFTRT, outermode, - XEXP (XEXP (op, 0), 0), XEXP (op, 1)); - - /* Likewise (subreg:QI (lshiftrt:SI (zero_extend:SI (x:QI)) C), 0) into - to (lshiftrt:QI (x:QI) C), where C is a suitable small constant and - the outer subreg is effectively a truncation to the original mode. */ - if ((GET_CODE (op) == LSHIFTRT - || GET_CODE (op) == ASHIFTRT) - && SCALAR_INT_MODE_P (outermode) - && SCALAR_INT_MODE_P (innermode) - && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode) - && CONST_INT_P (XEXP (op, 1)) - && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND - && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode - && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (outermode) - && subreg_lsb_1 (outermode, innermode, byte) == 0) - return simplify_gen_binary (LSHIFTRT, outermode, - XEXP (XEXP (op, 0), 0), XEXP (op, 1)); - - /* Likewise (subreg:QI (ashift:SI (zero_extend:SI (x:QI)) C), 0) into - to (ashift:QI (x:QI) C), where C is a suitable small constant and - the outer subreg is effectively a truncation to the original mode. */ - if (GET_CODE (op) == ASHIFT - && SCALAR_INT_MODE_P (outermode) - && SCALAR_INT_MODE_P (innermode) - && GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode) - && CONST_INT_P (XEXP (op, 1)) - && (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND - || GET_CODE (XEXP (op, 0)) == SIGN_EXTEND) - && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode - && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (outermode) - && subreg_lsb_1 (outermode, innermode, byte) == 0) - return simplify_gen_binary (ASHIFT, outermode, - XEXP (XEXP (op, 0), 0), XEXP (op, 1)); - - /* Recognize a word extraction from a multi-word subreg. */ - if ((GET_CODE (op) == LSHIFTRT - || GET_CODE (op) == ASHIFTRT) - && SCALAR_INT_MODE_P (innermode) - && GET_MODE_PRECISION (outermode) >= BITS_PER_WORD - && GET_MODE_PRECISION (innermode) >= (2 * GET_MODE_PRECISION (outermode)) - && CONST_INT_P (XEXP (op, 1)) - && (INTVAL (XEXP (op, 1)) & (GET_MODE_PRECISION (outermode) - 1)) == 0 - && INTVAL (XEXP (op, 1)) >= 0 - && INTVAL (XEXP (op, 1)) < GET_MODE_PRECISION (innermode) - && byte == subreg_lowpart_offset (outermode, innermode)) - { - int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT; - return simplify_gen_subreg (outermode, XEXP (op, 0), innermode, - (WORDS_BIG_ENDIAN - ? byte - shifted_bytes - : byte + shifted_bytes)); - } - - /* If we have a lowpart SUBREG of a right shift of MEM, make a new MEM - and try replacing the SUBREG and shift with it. Don't do this if - the MEM has a mode-dependent address or if we would be widening it. */ - - if ((GET_CODE (op) == LSHIFTRT - || GET_CODE (op) == ASHIFTRT) - && SCALAR_INT_MODE_P (innermode) - && MEM_P (XEXP (op, 0)) - && CONST_INT_P (XEXP (op, 1)) - && GET_MODE_SIZE (outermode) < GET_MODE_SIZE (GET_MODE (op)) - && (INTVAL (XEXP (op, 1)) % GET_MODE_BITSIZE (outermode)) == 0 - && INTVAL (XEXP (op, 1)) > 0 - && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (innermode) - && ! mode_dependent_address_p (XEXP (XEXP (op, 0), 0), - MEM_ADDR_SPACE (XEXP (op, 0))) - && ! MEM_VOLATILE_P (XEXP (op, 0)) - && byte == subreg_lowpart_offset (outermode, innermode) - && (GET_MODE_SIZE (outermode) >= UNITS_PER_WORD - || WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN)) - { - int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT; - return adjust_address_nv (XEXP (op, 0), outermode, - (WORDS_BIG_ENDIAN - ? byte - shifted_bytes - : byte + shifted_bytes)); + rtx tem = simplify_truncation (outermode, op, innermode); + if (tem) + return tem; } return NULL_RTX; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6d99e71c68d..1eb751ed9b7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,193 @@ +2012-10-08 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/54685 + * gcc.target/sh/pr54685.c: New. + +2012-10-08 Dodji Seketeli <dodji@redhat.com> + + PR c++/53528 C++11 attribute support + * g++.dg/cpp0x/gen-attrs-1.C: New test. + * g++.dg/cpp0x/gen-attrs-2.C: Likewise. + * g++.dg/cpp0x/gen-attrs-2-1.C: Likewise. + * g++.dg/cpp0x/gen-attrs-3.C: Likewise. + * g++.dg/cpp0x/gen-attrs-4.C: Likewise. + * g++.dg/cpp0x/gen-attrs-5.C: Likewise. + * g++.dg/cpp0x/gen-attrs-6.C: Likewise. + * g++.dg/cpp0x/gen-attrs-7.C: Likewise. + * g++.dg/cpp0x/gen-attrs-8.C: Likewise. + * g++.dg/cpp0x/gen-attrs-9.C: Likewise. + * g++.dg/cpp0x/gen-attrs-10.C: Likewise. + * g++.dg/cpp0x/gen-attrs-11.C: Likewise. + * g++.dg/cpp0x/gen-attrs-12.C: Likewise. + * g++.dg/cpp0x/gen-attrs-13.C: Likewise. + * g++.dg/cpp0x/gen-attrs-14.C: Likewise. + * g++.dg/cpp0x/gen-attrs-15.C: Likewise. + * g++.dg/cpp0x/gen-attrs-16.C: Likewise. + * g++.dg/cpp0x/gen-attrs-17.C: Likewise. + * g++.dg/cpp0x/gen-attrs-18.C: Likewise. + * g++.dg/cpp0x/gen-attrs-19.C: Likewise. + * g++.dg/cpp0x/gen-attrs-20.C: Likewise. + * g++.dg/cpp0x/gen-attrs-21.C: Likewise. + * g++.dg/cpp0x/gen-attrs-22.C: Likewise. + * g++.dg/cpp0x/gen-attrs-23.C: Likewise. + * g++.dg/cpp0x/gen-attrs-24.C: Likewise. + * g++.dg/cpp0x/gen-attrs-25.C: Likewise. + * g++.dg/cpp0x/gen-attrs-26.C: Likewise. + * g++.dg/cpp0x/gen-attrs-27.C: Likewise. + * g++.dg/cpp0x/gen-attrs-28.C: Likewise. + * g++.dg/cpp0x/gen-attrs-29.C: Likewise. + * g++.dg/cpp0x/gen-attrs-30.C: Likewise. + * g++.dg/cpp0x/gen-attrs-31.C: Likewise. + * g++.dg/cpp0x/gen-attrs-32.C: Likewise. + * g++.dg/cpp0x/gen-attrs-33.C: Likewise. + * g++.dg/cpp0x/gen-attrs-34.C: Likewise. + * g++.dg/cpp0x/gen-attrs-35.C: Likewise. + * g++.dg/cpp0x/gen-attrs-36.C: Likewise. + * g++.dg/cpp0x/gen-attrs-36-1.C: Likewise. + * g++.dg/cpp0x/gen-attrs-37.C: Likewise. + * g++.dg/cpp0x/gen-attrs-38.C: Likewise. + * g++.dg/cpp0x/gen-attrs-39.C: Likewise. + * g++.dg/cpp0x/gen-attrs-39-1.C: Likewise. + * g++.dg/cpp0x/gen-attrs-40.C: Likewise. + * g++.dg/cpp0x/gen-attrs-41.C: Likewise. + * g++.dg/cpp0x/gen-attrs-42.C: Likewise. + * g++.dg/cpp0x/gen-attrs-43.C: Likewise. + * g++.dg/cpp0x/gen-attrs-44.C: Likewise. + * g++.dg/cpp0x/gen-attrs-45.C: Likewise. + * g++.dg/cpp0x/gen-attrs-46.C: Likewise. + * g++.dg/cpp0x/gen-attrs-47.C: Likewise. + * g++.dg/cpp0x/gen-attrs-47-1.C: Likewise. + * g++.dg/cpp0x/gen-attrs-48.C: Likewise. + * g++.dg/cpp0x/gen-attrs-49.C: Likewise. + * g++.dg/cpp0x/gen-attrs-50.C: Likewise. + * g++.dg/cpp0x/gen-attrs-51.C: Likewise. + * g++.dg/cpp0x/gen-attrs-52.C: Likewise. + * g++.dg/cpp0x/gen-attrs-53.C: Likewise. + +2012-10-08 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.dg/tree-ssa/slsr-30.c: Use correct cleanup directive. + * gcc.dg/tree-ssa/attr-hotcold-2.c: Likewise. + * gcc.dg/tree-ssa/ldist-21.c: Add missing cleanup directive. + +2012-10-08 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/54760 + * gcc.target/sh/pr54760-2.c: New. + * gcc.target/sh/pr54760-3.c: New. + +2012-10-07 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/51422 + * g++.dg/cpp0x/lambda/lambda-ice8.C: New. + +2012-10-07 Richard Sandiford <rdsandiford@googlemail.com> + Sandra Loosemore <sandra@codesourcery.com> + + * gcc.target/mips/madd-9.c: Force code to be tuned for the 4kc + and test that the accumulator is initialized using MULT. + * gcc.target/mips/mips32-dsp-accinit-1.c: New test. + * gcc.target/mips/mips32-dsp-accinit-2.c: Likewise. + +2012-10-06 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/52764 + * g++.dg/cpp0x/stdint.C: New. + +2012-10-06 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/54249 + * g++.dg/cpp0x/stddef.C: New. + +2012-10-06 Janus Weil <janus@gcc.gnu.org> + + PR fortran/54832 + * gfortran.dg/typebound_operator_17.f90: New. + +2012-10-06 Jan Hubicka <jh@suse.cz> + + PR lto/53831 + PR lto/54776 + * g++.dg/lto/v1-plugin-api-not-supported.C: New testcase. + +2012-10-06 Jan Hubicka <jh@suse.cz> + + * gcc.dg/lto/resolutions_0.c: New testcase. + +2012-10-06 Janus Weil <janus@gcc.gnu.org> + + PR fortran/45521 + * gfortran.dg/generic_25.f90: New. + * gfortran.dg/generic_26.f90: New. + * gfortran.dg/generic_27.f90: New. + +2012-10-06 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/54760 + * gcc.target/sh/pr54760-1.c: New. + +2012-10-05 Jakub Jelinek <jakub@redhat.com> + + * g++.dg/torture/Wsizeof-pointer-memaccess1.C: New test. + * g++.dg/torture/Wsizeof-pointer-memaccess2.C: New test. + * g++.dg/warn/Wsign-compare-5.C: New test. + * g++.dg/warn/Wsizeof-pointer-memaccess-1.C: New test. + * g++.dg/warn/Wnull-conversion-1.C: For c++11 add dg-error. + * g++.dg/ext/builtin30.C: New test. + * g++.dg/ext/vla12.C: New test. + * gcc.dg/builtins-85.c: New test. + + PR debug/54519 + * gcc.dg/guality/pr54519-1.c: New test. + * gcc.dg/guality/pr54519-2.c: New test. + * gcc.dg/guality/pr54519-3.c: New test. + * gcc.dg/guality/pr54519-4.c: New test. + * gcc.dg/guality/pr54519-5.c: New test. + * gcc.dg/guality/pr54519-6.c: New test. + +2012-10-05 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/50893 + * g++.dg/cpp0x/defaulted38.C: New. + +2012-10-05 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/33763 + * c-c++-common/pr33763.c: New test. + + PR tree-optimization/54810 + * gcc.dg/tree-ssa/vrp85.c: New test. + +2012-10-04 David Edelsohn <dje.gcc@gmail.com> + + * gcc.dg/ucnid-7.c: Skip on AIX. + * gcc.dg/ucnid-8.c: Same. + * gcc.dg/ucnid-10.c: Same. + * gcc.dg/ucnid-13.c: Same. + * gcc.dg/attr-alias-3.c: Same. + * gcc.dg/attr-alias-5.c: Same. + * gcc.dg/torture/pr51106-2.c: Same. + * gcc.dg/vmx/3b-13.c: Use valid splat index. + +2012-10-04 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/52233 + * g++.dg/cpp0x/alias-decl-23.C: New. + +2012-10-04 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/53403 + * g++.dg/template/friend53.C: New. + +2012-10-04 Eric Botcazou <ebotcazou@adacore.com> + + * lib/gcc-dg.exp (cleanup-ada-spec): New procedure. + * lib/scanasm.exp (get_ada_spec_filename): Likewise. + (scan-ada-spec): Likewise. + (scan-ada-spec-not): Likewise. + * gcc.dg/dump-ada-spec-1.c: New test. + * g++.dg/other/dump-ada-spec-1.C: Likewise. + 2012-10-04 Eric Botcazou <ebotcazou@adacore.com> * gcc.dg/lto/20120723_0.c: Skip on SPARC 32-bit. diff --git a/gcc/testsuite/c-c++-common/pr33763.c b/gcc/testsuite/c-c++-common/pr33763.c new file mode 100644 index 00000000000..dbdfa77fc3d --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr33763.c @@ -0,0 +1,60 @@ +/* PR tree-optimization/33763 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef struct +{ + void *a; + void *b; +} T; +extern void *foo (const char *, const char *); +extern void *bar (void *, const char *, T); +extern int baz (const char *, int); + +extern inline __attribute__ ((always_inline, gnu_inline)) int +baz (const char *x, int y) +{ + return 2; +} + +int +baz (const char *x, int y) +{ + return 1; +} + +int xa, xb; + +static void * +inl (const char *x, const char *y) +{ + T t = { &xa, &xb }; + int *f = (int *) __builtin_malloc (sizeof (int)); + const char *z; + int o = 0; + void *r = 0; + + for (z = y; *z; z++) + { + if (*z == 'r') + o |= 1; + if (*z == 'w') + o |= 2; + } + if (o == 1) + *f = baz (x, 0); + if (o == 2) + *f = baz (x, 1); + if (o == 3) + *f = baz (x, 2); + + if (o && *f > 0) + r = bar (f, "w", t); + return r; +} + +void * +foo (const char *x, const char *y) +{ + return inl (x, y); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-23.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-23.C new file mode 100644 index 00000000000..0e4ba45aa20 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-23.C @@ -0,0 +1,17 @@ +// PR c++/52233 +// { dg-do compile { target c++11 } } + +template <typename t> +struct foo +{ + template <template <typename...> class... xs> + using type = int; +}; + +template <typename t, template <typename...> class... xs> +struct bar +{ + using type = typename foo<t>::template type<xs...>; +}; + +bar<int, foo> x; diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted38.C b/gcc/testsuite/g++.dg/cpp0x/defaulted38.C new file mode 100644 index 00000000000..39424f641c7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted38.C @@ -0,0 +1,14 @@ +// PR c++/50893 +// { dg-do compile { target c++11 } } + +class Base +{ + public: + virtual ~Base() = default; +}; + +class Derived : public Base +{ + public: + virtual ~Derived() = default; +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C new file mode 100644 index 00000000000..a55698c9383 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C @@ -0,0 +1,3 @@ +// { dg-do compile { target c++11 } } + +int **** [[gnu::format(printf, 1, 2)]] foo(const char *, ...); // { dg-warning "ignored" } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-10.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-10.C new file mode 100644 index 00000000000..cac568e0b7a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-10.C @@ -0,0 +1,9 @@ +// PR c++/12795 +// { dg-do compile { target c++11 } } +// { dg-require-alias "" } + +void foo() +{ + extern void bar [[gnu::__alias__ ("BAR")]] (); // { dg-warning "ignored" } + bar (); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-11.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-11.C new file mode 100644 index 00000000000..504b4565679 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-11.C @@ -0,0 +1,17 @@ +// { dg-do compile { target c++11 } } +// PR c++/13791 + +template <typename T> struct O { + struct [[gnu::packed]] I { + int i; + char c; + }; + + I* foo(); +}; + +template <typename T> +typename O<T>::I* +O<T>::foo() { return 0; } + +template class O<int>; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-12.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-12.C new file mode 100644 index 00000000000..504b4565679 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-12.C @@ -0,0 +1,17 @@ +// { dg-do compile { target c++11 } } +// PR c++/13791 + +template <typename T> struct O { + struct [[gnu::packed]] I { + int i; + char c; + }; + + I* foo(); +}; + +template <typename T> +typename O<T>::I* +O<T>::foo() { return 0; } + +template class O<int>; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-13.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-13.C new file mode 100644 index 00000000000..a1b4a84b7e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-13.C @@ -0,0 +1,5 @@ +// { dg-do compile { target c++11 } } +// PR c++/13854 + +extern char *rindex [[gnu::__pure__]] (__const char *__s, int __c) throw (); +extern char *rindex [[gnu::__pure__]] (__const char *__s, int __c) throw (); diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-14.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-14.C new file mode 100644 index 00000000000..d646d274df0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-14.C @@ -0,0 +1,14 @@ +// { dg-do compile { target c++11 } } +// PR c++/13170 +// The bogus attribute is ignored, but was in TYPE_ATTRIBUTES during +// parsing of the class, causing some variants to have it and some not. + +struct [[gnu::bogus]] A // { dg-warning "ignored" "" } +{ + virtual ~A(); + void foo(const A&); + void bar(const A&); +}; + +void A::foo(const A&) {} +void A::bar(const A& a) { foo(a); } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-15.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-15.C new file mode 100644 index 00000000000..bf05dbeb31b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-15.C @@ -0,0 +1,9 @@ +// { dg-do compile { target c++11 } } +// PR c++/15317 + +struct A +{ + A(char); +}; +A::A([[gnu::unused]] char i2) +{} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-16.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-16.C new file mode 100644 index 00000000000..4adefdb32d5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-16.C @@ -0,0 +1,8 @@ +// { dg-do compile { target c++11 } } +// Origin: <rguenth at tat dot physik dot uni-tuebingen dot de> +// PR c++/10479: use of non dependent expressions in attributes in templates + +template <int i> +struct foo2 { + float bar [[gnu::aligned(alignof(double))]]; +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.2.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.2.C new file mode 100644 index 00000000000..636f9a9ac8b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.2.C @@ -0,0 +1,19 @@ +// { dg-do compile { target c++11 } } +// Origin: Benjamin Kosnik <bkoz at gcc dot gnu dot org> +// PR c++/17743: Attributes applied to typedefs. + +struct A { + typedef char layout_type[sizeof(double)] + [[gnu::aligned(alignof(double)]]); // { dg-error "expected" } + layout_type data; +}; + +struct B { + typedef char layout_type[sizeof(double)]; + layout_type data [[gnu::aligned(alignof(double))]]; +}; + +template<bool> struct StaticAssert; +template<> struct StaticAssert<true> {}; + +StaticAssert<alignof(A) == alignof(B)> a1;// { dg-error "incomplete type and cannot be defined" } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.C new file mode 100644 index 00000000000..566461b0e7f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-17.C @@ -0,0 +1,19 @@ +// { dg-do compile { target c++11 } } +// Origin: Benjamin Kosnik <bkoz at gcc dot gnu dot org> +// PR c++/17743: Attributes applied to typedefs. + +struct A { + typedef char layout_type[sizeof(double)] + [[gnu::aligned(alignof(double))]]; + layout_type data; +}; + +struct B { + typedef char layout_type[sizeof(double)]; + layout_type data [[gnu::aligned(alignof(double))]]; +}; + +template<bool> struct StaticAssert; +template<> struct StaticAssert<true> {}; + +StaticAssert<alignof(A) == alignof(B)> a1; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-18.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-18.C new file mode 100644 index 00000000000..3df13e6440b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-18.C @@ -0,0 +1,10 @@ +// PR c++/17542 +// Test that we warn when an attribute preceding the class-key is ignored. +// { dg-do compile { target c++11 } } + +[[gnu::packed]] struct A // { dg-warning "attribute" } +{ + char c; + int x; + void f(); +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-19.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-19.C new file mode 100644 index 00000000000..5ac93d84590 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-19.C @@ -0,0 +1,11 @@ +// PR c++/19739 +// { dg-do compile { target c++11 } } + +void Dummy() [[ , ]]; +void Dummy() {} + +int main (int argc, char **argv) +{ + Dummy(); + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2-1.C new file mode 100644 index 00000000000..2f47b325579 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2-1.C @@ -0,0 +1,3 @@ +// { dg-do compile { target c++11 } } + +struct [[gnu::unused]] A {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2.C new file mode 100644 index 00000000000..8c777c1df8b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-2.C @@ -0,0 +1,11 @@ +// { dg-do compile { target c++11 } } + +struct [[gnu::packed]] A +{ + void f () const; +}; + +void +A::f () const +{ +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-20.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-20.C new file mode 100644 index 00000000000..f989ab20789 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-20.C @@ -0,0 +1,22 @@ +// { dg-do compile { target c++11 } } +// { dg-options "-g" } +// Origin: <jan at etpmod dot phys dot tue dot nl> +// PR c++/19508: avoid attributes for template parameters + +template <typename T> +struct BVector +{ + typedef T T2; + typedef T value_type [[gnu::aligned(8)]]; // { dg-bogus "attribute" "attribute" } + typedef T2 value_type2 [[gnu::aligned(8)]]; // { dg-bogus "attribute" "attribute" } + value_type v; +}; +BVector<int> m; + +template <template <class> class T> +struct BV2 +{ + typedef T<float> value_type [[gnu::aligned(8)]]; // { dg-bogus "attribute" "attribute" } + value_type v; +}; +BV2<BVector> m2; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-21.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-21.C new file mode 100644 index 00000000000..2d5ad04b02c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-21.C @@ -0,0 +1,21 @@ +// PR c++/20763 +// { dg-do compile { target c++11 } } + +typedef void *voidp; + +struct S +{ + char a; + voidp b [[gnu::aligned (16)]]; +}; + +struct T +{ + char a; + void * b [[gnu::aligned (16)]]; +}; + +static_assert (sizeof (S) == sizeof (T), + "struct S and T should have the same size"); + +static_assert (sizeof (S) == 32, "sizeof (S) == 8 + 16 + 8"); diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C new file mode 100644 index 00000000000..4c07df995c7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C @@ -0,0 +1,7 @@ +// PR c++/27648 +// { dg-do compile { target c++11 } } + +void f() +{ + static_cast<float *[[gnu::unused]]>(0); // { dg-warning "ignored" } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-23.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-23.C new file mode 100644 index 00000000000..57ea6b8097f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-23.C @@ -0,0 +1,11 @@ +// PR c++/28112 +// { dg-do compile { target c++11 } } + +int i [[gnu::init_priority(;)]]; // { dg-error "before" } +int j [[gnu::vector_size(;)]]; // { dg-error "before" } +int k [[gnu::visibility(;)]]; // { dg-error "before" } +struct A {} [[gnu::aligned(;)]]; // { dg-error "before" } +struct B {} [[gnu::mode(;)]]; // { dg-error "before" } +void foo() [[gnu::alias(;)]]; // { dg-error "before" } +void bar() [[gnu::nonnull(;)]]; // { dg-error "before" } +void baz() [[gnu::section(;)]]; // { dg-error "before" } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-24.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-24.C new file mode 100644 index 00000000000..e1f26c3d337 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-24.C @@ -0,0 +1,4 @@ +// PR c++/28387 +// { dg-do compile { target c++11 } } + +enum [[gnu::unused]] E; // { dg-error "without previous declaration" } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-25.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-25.C new file mode 100644 index 00000000000..09486d66b76 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-25.C @@ -0,0 +1,12 @@ +// PR c++/28559 +// { dg-do compile { target c++11 } } + +template<typename T> struct A +{ + struct B; +}; + +struct C +{ + template<typename T> friend struct [[gnu::packed]] A<T>::B; // { dg-warning "uninstantiated" } +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-26.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-26.C new file mode 100644 index 00000000000..00069b8f518 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-26.C @@ -0,0 +1,15 @@ +// PR c++/28659 +// The attribute was causing us to get confused in merge_types when +// combining the template type with an uninstantiated version. +// { dg-do compile { target c++11 } } + +template<class T> +struct [[gnu::aligned(1)]] A +{ + A& operator=(const A &t); +}; + +template<class T> +A<T>& A<T>::operator=(const A<T> &t) +{ +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-27.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-27.C new file mode 100644 index 00000000000..e38d8d3f6d9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-27.C @@ -0,0 +1,6 @@ +//PR c++/29980 +// { dg-do compile { target c++11 } } + +struct A { typedef int X; }; // { dg-message "previous declaration" } + +struct [[gnu::unused]] A::X; // { dg-error "typedef-name" } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-28.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-28.C new file mode 100644 index 00000000000..94f1756ae2b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-28.C @@ -0,0 +1,13 @@ +// PR c++/28558 +// { dg-options "" } +// { dg-do compile { target c++11 } } + +struct A +{ + A(int) { } +}; + +int main() +{ + A a = (A [[gnu::unused]])0; // { dg-warning "attribute" } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-29.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-29.C new file mode 100644 index 00000000000..f3da4522994 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-29.C @@ -0,0 +1,10 @@ +// PR c++/33506 +// { dg-do compile { target c++11 } } + +extern int f1 [[gnu::warn_unused_result]] (char *) ; +extern int f2 [[gnu::warn_unused_result]] (char *) throw () ; +extern int f2 (char *) throw (); + +extern int f3 [[gnu::nonnull (1)]] (char *) ; +extern int f4 [[gnu::nonnull (1)]] (char *) throw (); +extern int f4 (char *) throw (); diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-3.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-3.C new file mode 100644 index 00000000000..edd10672636 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-3.C @@ -0,0 +1,22 @@ +// Test that attributes work in a variety of situations. +// { dg-options "-O -ftrack-macro-expansion=0" } +// { dg-do run { target c++11 } } + +#define attrib [[gnu::mode (QI)]] +#define gnu_attrib __attribute((mode (QI))) + +attrib signed int a; +static unsigned int b attrib; + +int foo(attrib int o) +{ + return (sizeof (a) != 1 + || sizeof (b) != 1 + || sizeof (o) != 1 + || sizeof ((gnu_attrib signed int) b) != 1); +} + +int main () +{ + return foo (42); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-30.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-30.C new file mode 100644 index 00000000000..537dec50e97 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-30.C @@ -0,0 +1,9 @@ +// { dg-do compile { target c++11 } } +// PR c++/35074 + +template<typename T> struct A +{ + void foo() const; +} [[gnu::aligned(4)]]; // { dg-warning "ignored" } + +template<typename T> void A<T>::foo() const {} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-31.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-31.C new file mode 100644 index 00000000000..ab58e6e2b27 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-31.C @@ -0,0 +1,16 @@ +// PR c++/35097 +// { dg-do compile { target c++11 } } + +template<int> struct A; + +template<> struct A<0> +{ + typedef int X [[gnu::aligned(4)]]; +}; + +template<typename T> void foo(const A<0>::X&, T); + +void bar() +{ + foo(A<0>::X(), 0); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-32.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-32.C new file mode 100644 index 00000000000..f3446611748 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-32.C @@ -0,0 +1,37 @@ +// PR c++/35315 +// { dg-do compile { target c++11 } } + +typedef union { int i; } U [[gnu::transparent_union]]; // { dg-warning "ignored" } + +static void foo(U) {} +static void foo(int) {} + +void bar() +{ + foo(0); +} + +typedef union U1 { int i; } U2 [[gnu::transparent_union]]; // { dg-warning "ignored" } + +static void foo2(U1) {} // { dg-error "previously defined" } +static void foo2(U2) {} // { dg-error "redefinition" } + +void bar2(U1 u1, U2 u2) +{ + foo2(u1); + foo2(u2); +} + +// PR c++/36410 +struct A +{ + typedef union [[gnu::transparent_union]] + { + int i; + } B; +}; + +void foo(A::B b) +{ + b.i; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-33.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-33.C new file mode 100644 index 00000000000..efb2a1ad6d0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-33.C @@ -0,0 +1,19 @@ +// PR c++/35546 +// { dg-do compile { target c++11 } } +// { dg-options "-g" } + +template <int N> +struct T +{ + void foo [[gnu::format (printf,2,3)]] (char const * ...); +}; + +template struct T<3>; + +template <typename T> +struct U +{ + typedef T V [[gnu::mode (SI)]]; +}; + +U<int>::V v; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-34.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-34.C new file mode 100644 index 00000000000..ae8e99090e9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-34.C @@ -0,0 +1,19 @@ +// PR c/37171 +// { dg-do compile { target c++11 } } +// { dg-options "-O2 -fdump-tree-optimized" } + +unsigned int f1 [[gnu::const]] (); +unsigned int f2 [[gnu::__const]] () ; +unsigned int f3 [[gnu::__const__]] () ; + +unsigned int f4 () +{ + return f1 () + f1 () + f1 () + f1 () + + f2 () + f2 () + f2 () + f2 () + + f3 () + f3 () + f3 () + f3 (); +} + +// { dg-final { scan-tree-dump-times "= f1 \\(\\)" 1 "optimized" } } +// { dg-final { scan-tree-dump-times "= f2 \\(\\)" 1 "optimized" } } +// { dg-final { scan-tree-dump-times "= f3 \\(\\)" 1 "optimized" } } +// { dg-final { cleanup-tree-dump "optimized" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-35.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-35.C new file mode 100644 index 00000000000..34f20cf3076 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-35.C @@ -0,0 +1,20 @@ +// { dg-do compile { target i?86-*-* x86_64-*-* } } +// { dg-options "-O3 -msse2 -std=c++11" } +// { dg-require-effective-target sse2 } + +// You can make NON-template typedefs with a large alignment. +typedef double AlignedDoubleType [[gnu::aligned(16)]]; + +template <typename RealType> +RealType f(const RealType* p) +{ + // But if you use a template parameter it complains. + typedef RealType AlignedRealType [[gnu::aligned(16)]]; + + return p[0]; +} + +double f2(const double* p) +{ + return f<double>(p); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C new file mode 100644 index 00000000000..2aae9cae00b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C @@ -0,0 +1,11 @@ +// { dg-do compile { target c++11 } } + +struct S; + +typedef int (*F [[gnu::warn_unused_result]]) (int); + +typedef int (*F2 [[gnu::warn_unused_result]]) (int); + +typedef int (S::*F3 [[gnu::warn_unused_result]]) (int); // { dg-warning "only applies to function types" } + +typedef int [[gnu::warn_unused_result]] (*F5) (int); // { dg-warning "ignored" } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36.C new file mode 100644 index 00000000000..2665188a630 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-36.C @@ -0,0 +1,23 @@ +// PR c++/43031 +// { dg-options "-std=c++11 -pedantic" } +// { dg-do compile { target { { i?86-*-* x86_64-*-* } && ia32 } } } + +class T; +class L { }; +class P : public L +{ + typedef void (T::* [[gnu::__stdcall__]] F2) (L*); // { dg-warning "only applies to function types" } + typedef void (T::*F) (L*) [[gnu::__stdcall__]]; + void f(bool aAdd); +}; + +class T +{ +public: + virtual void A(L *listener) [[gnu::__stdcall__]] = 0; + virtual void R(L *listener) [[gnu::__stdcall__]] = 0; +}; +void P::f(bool aAdd) +{ + F addRemoveEventListener = (aAdd ? &T::A : &T::R); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-37.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-37.C new file mode 100644 index 00000000000..15d69e8175e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-37.C @@ -0,0 +1,15 @@ +// PR c++/43093 +// { dg-options "-std=c++11 -pedantic" } +// { dg-do compile { target { { i?86-*-* x86_64-*-* } && ia32 } } } + +struct S { + int x; + S(const S &s) {} +}; + +S getS() [[gnu::__stdcall__]]; + +void test() +{ + S s = getS(); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-38.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-38.C new file mode 100644 index 00000000000..3db981aeb22 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-38.C @@ -0,0 +1,12 @@ +// { dg-do compile { target c++11 } } +// PR c++/36625 + +template <int N> +struct A { + struct S { short f[3]; } [[gnu::aligned (N)]]; // { dg-warning "ignored" } +}; + +int main () +{ + A<4>::S s; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C new file mode 100644 index 00000000000..453fc01a2e9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39-1.C @@ -0,0 +1,10 @@ +// { dg-do compile { target c++11 } } + +int fragile_block(void) { + typedef + [[gnu::aligned (16)]] // { dg-warning "ignored" } + struct { + int i; + } XmmUint16; + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39.C new file mode 100644 index 00000000000..83fa8b5e66d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-39.C @@ -0,0 +1,10 @@ +// PR debug/43370 +// { dg-do compile { target c++11 } } +// { dg-options "-g" } + +int fragile_block(void) { + typedef struct [[gnu::aligned (16)]] { + int i; + } XmmUint16; + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C new file mode 100644 index 00000000000..bad33d6e822 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C @@ -0,0 +1,30 @@ +// { dg-options "-std=c++11 -Wunused -pedantic-errors" } +// { dg-do compile } +// Test for syntax support of various attribute permutations. + +int +[[gnu::noreturn]] // { dg-warning "ignored" } +one +[[gnu::unused]] +(void); + +int one_third [[gnu::noreturn]] [[gnu::unused]] (void); + +int [[gnu::unused]] one_half(); // { dg-warning "ignored" } + +static +[[gnu::noreturn]] // { dg-warning "ignored" } +void two [[gnu::unused]] (void) {} + + + +[[gnu::unused]] +int +five(void) +[[gnu::noreturn]] // { dg-warning "ignored" } +{} + +[[gnu::noreturn]] +void +six (void) +; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-40.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-40.C new file mode 100644 index 00000000000..f3ccb727dfa --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-40.C @@ -0,0 +1,5 @@ +// PR c++/46803 +// { dg-do compile { target c++11 } } + +int strftime(char *, int, const char *, const struct tm *) + [[gnu::__bounded__(__string__,1,2)]]; // { dg-warning "ignored" } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-41.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-41.C new file mode 100644 index 00000000000..6e47a1e3d75 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-41.C @@ -0,0 +1,20 @@ +// PR c++/45267 +// { dg-do compile { target c++11 } } +// { dg-options "-O" } + +template<typename T> struct Vector { + Vector(long long x); + inline Vector<T> operator<< [[gnu::always_inline]] (int x) const; +}; +long long bar (long long); +template<> inline Vector<int> Vector<int>::operator<<(int x) const { + return bar(x); +} +bool b; +int main() { + Vector<int> a(1); + if ((a << 2), b) { + a << 2; + throw 1; + } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-42.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-42.C new file mode 100644 index 00000000000..7df63cf675e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-42.C @@ -0,0 +1,13 @@ +// { dg-options "-std=c++11 -pedantic" } +// { dg-do compile { target { i?86-*-* && ilp32 } } } + +struct A { + [[gnu::fastcall]] + void f(); +}; + +int main() +{ + typedef void (A::*FP)(); + FP fp[] = {&A::f}; // { dg-error "cannot convert" } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C new file mode 100644 index 00000000000..c850622723e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-43.C @@ -0,0 +1,4 @@ +// { dg-do compile { target c++11 } } +template <class T> struct A { }; + +template [[gnu::packed]] struct A<int>; // { dg-warning "ignored in explicit instantiation" } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-44.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-44.C new file mode 100644 index 00000000000..81d70e52b0e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-44.C @@ -0,0 +1,3 @@ +// PR c++/52671 +// { dg-do compile { target c++11 } } +[[gnu::deprecated]] enum E { E0 }; // { dg-warning "ignored in declaration" } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C new file mode 100644 index 00000000000..573a1ab6cb0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-45.C @@ -0,0 +1,4 @@ +// PR c++/52906 +// { dg-do compile { target c++11 } } + +[[gnu::deprecated]]; // { dg-error "does not declare anything" } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-46.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-46.C new file mode 100644 index 00000000000..53fcb77ff7b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-46.C @@ -0,0 +1,5 @@ +// PR c++/40821 +// { dg-do compile { target c++11 } } + +struct [[gnu::aligned(8)] S1 { int i; }; // { dg-error "" } +struct [aligned(8) S2 { int i; }; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47-1.C new file mode 100644 index 00000000000..4a5d73a1927 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47-1.C @@ -0,0 +1,8 @@ +// { dg-do compile { target c++11 } } +int +foo () +{ + int i [[and, bitor, xor_eq, compl, bitand]]; // { dg-warning "ignored" } + i = 0; + return i; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47.C new file mode 100644 index 00000000000..af74abd1862 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-47.C @@ -0,0 +1,13 @@ +// { dg-do compile { target c++11 } } +// Example taken from dcl.attr.grammar: + +int p[10]; +void f() +{ + int x = 42, y[5]; + /* Here, the '[[' should have introduced an attribute, on a + lambda invocation an array subscripting expression. */ + int(p[[x] { return x; }()]); // { dg-error "expected|consecutive" } + /* Likewise, the '[[gnu::' is invalid here. */ + y[[] { return 2; }()] = 2; // { dg-error "expected|consecutive" } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-48.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-48.C new file mode 100644 index 00000000000..360c093bf5a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-48.C @@ -0,0 +1,17 @@ +// { dg-do compile { target c++11 } } + +typedef char layout_type; + +struct A { + layout_type member alignas (double); +}; + +static_assert (alignof (A) == alignof (double), + "alignment of struct A must be alignof (double)"); + +struct alignas (alignof (long double)) B { + layout_type member; +}; + +static_assert (alignof (B) == alignof (long double), + "alignment of struct A must be alignof (double double)"); diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-49.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-49.C new file mode 100644 index 00000000000..8b68f927368 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-49.C @@ -0,0 +1,17 @@ +// { dg-do compile { target c++11 } } + +typedef char layout_type; + +template<class> struct A { + layout_type member alignas (double); +}; + +static_assert (alignof (A<int>) == alignof (double), + "alignment of struct A must be alignof (double)"); + +template<class> struct alignas (alignof (long double)) B { + layout_type member; +}; + +static_assert (alignof (B<int>) == alignof (long double), + "alignment of struct A must be alignof (double double)"); diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-5.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-5.C new file mode 100644 index 00000000000..83de121dfbf --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-5.C @@ -0,0 +1,23 @@ +// { dg-do compile { target c++11 } } +// +// There were two related problems here, depending on the vintage. At +// one time: +// +// typedef struct A { ... } A [[gnu::aligned (16)]]; +// +// would cause original_types to go into an infinite loop. At other +// times, the attributes applied to an explicit typedef would be lost +// (check_b3 would have a negative size). + +// First check that the declaration is accepted and has an effect. +typedef struct A { int i; } A [[gnu::aligned (16)]]; +int check_A[alignof (A) >= 16 ? 1 : -1]; + +// Check that the alignment is only applied to the typedef. +struct B { int i; }; +struct B b1; +typedef struct B B [[gnu::aligned (16)]]; +struct B b2; +B b3; +int check_b1[__alignof__ (b1) == __alignof__ (b2) ? 1 : -1]; +int check_b3[__alignof__ (b3) >= 16 ? 1 : -1]; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-50.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-50.C new file mode 100644 index 00000000000..2479dfdf19c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-50.C @@ -0,0 +1,22 @@ +// { dg-do compile { target c++11 } } + +typedef char layout_type; + +template<class> struct A { + layout_type member alignas (double) alignas (int); +}; + +// Here, the spec says that A<int> should have the stricter alignment, +// so that would be the alignment of 'double', not 'int'. +static_assert (alignof (A<int>) == alignof (double), + "alignment of struct A must be alignof (double)"); + +template<class> struct alignas (1) alignas (alignof (long double)) B { + layout_type member; +}; + +// Similarly, the B<int> should have the stricter alignment, so that would +// so that would be the alignment of 'long double', not '1'. +static_assert (alignof (B<int>) == alignof (long double), + "alignment of struct A must be alignof (double double)"); + diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-51.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-51.C new file mode 100644 index 00000000000..f2b66029e5a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-51.C @@ -0,0 +1,9 @@ +// { dg-do compile { target c++11 } } + +typedef char layout_type; +struct A +{ + layout_type member [[gnu::aligned (16)]]; +}; + +static_assert (sizeof (A) == 16, "Alignment should be 16"); diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C new file mode 100644 index 00000000000..0f87fd490e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-52.C @@ -0,0 +1,21 @@ +// { dg-do compile { target c++11 } } + +struct A {int i;} a [[gnu::aligned(16)]]; +struct B {int i;} __attribute__((aligned(16))) b; + +int +main () +{ + A aa; + B bb; + + static_assert (sizeof (a) == 4, "sizeof (a) should be 4"); + static_assert (sizeof (b) == 16, "sizeof (b) should be 16"); + static_assert (sizeof (aa) == 4, "sizeof (aa) should be 4"); + static_assert (sizeof (bb) == 16, "sizeof (bb) should be 16"); + + static_assert (__alignof__ (a) == 16, "alignof (a) should be 16"); + static_assert (__alignof__ (b) == 16, "alignof (b) should be 16"); + static_assert (__alignof__ (aa) == 4, "alignof (aa) should be 4"); + static_assert (__alignof__ (bb) == 16, "alignof (bb) should be 16"); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C new file mode 100644 index 00000000000..723c8ef8ec0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-53.C @@ -0,0 +1,39 @@ +// { dg-do compile { target c++11 } } + +int +toto () +{ + [[gnu::unused]] good: + return 0; +} + +int +foo () +{ + [[gnu::unused]] good: + int i = 0; + + // A C++11 attribute at the beginning of the return statement is + // syntactically correct, appertains to the return statement (not to + // the label) but is currently ignored by this implementation. + good_ignored : [[gnu::unused]] // { dg-warning "attributes at the beginning of statement are ignored" } + return i; +} + +int +bar () +{ + // A GNU attribute after the label appertains to the label. + good: __attribute__((unused)); + return 0; +} + +int +baz () +{ + // The c++ attribute after the label appertains to the (empty) + // statement. + bad: [[gnu::unused]]; // { dg-warning "attributes at the beginning of statement are ignored" } + return 0; +} + diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-6.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-6.C new file mode 100644 index 00000000000..54071d5ed14 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-6.C @@ -0,0 +1,20 @@ +// Copyright (C) 2002 Free Software Foundation. +// +// Test that the nothrow attribute is working correctly. +// +// Written by Richard Henderson, 26 May 2002. + +// { dg-do link { target c++11} } +extern void foo [[gnu::nothrow]] (); +extern void link_error(); + +int main() +{ + try { + foo(); + } catch (...) { + link_error(); + } +} + +void foo() { } diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-7.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-7.C new file mode 100644 index 00000000000..33412506852 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-7.C @@ -0,0 +1,4 @@ +// { dg-do compile { target c++11 } } +// { dg-options "-Wunused-parameter" } + +void f (int i [[gnu::__unused__]]) {} diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-8.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-8.C new file mode 100644 index 00000000000..a842b5352cc --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-8.C @@ -0,0 +1,6 @@ +// { dg-options "-std=c++11 -pedantic" } +// { dg-do compile { target { { i?86-*-* x86_64-*-* } && ia32 } } } + +extern int * ([[gnu::stdcall]] *fooPtr)( void); // { dg-error "expected" } +int * [[gnu::stdcall]] myFn01( void) { return 0; }// { dg-warning "attribute only applies to function types" } + diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C new file mode 100644 index 00000000000..3dc51eef9e8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-9.C @@ -0,0 +1,12 @@ +// { dg-do compile { target c++11 } } + +class C; +struct S; +union U; +enum e {}; +enum [[gnu::unused]] e; // { dg-warning "already defined" } + +struct [[gnu::unused]] B *p; // { dg-warning "attributes" } + +template <class T> struct A { }; +struct [[gnu::unused]] A<int>; // { dg-warning "attributes" } diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice8.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice8.C new file mode 100644 index 00000000000..00078d53b7b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice8.C @@ -0,0 +1,10 @@ +// PR c++/51422 +// { dg-do compile { target c++11 } } + +template<typename> struct A {}; + +void foo() +{ + [i] { A<decltype(i)>(); }; // { dg-error "not declared|invalid" } + [i] { A<decltype(i)>(); }; // { dg-error "invalid" } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/stddef.C b/gcc/testsuite/g++.dg/cpp0x/stddef.C new file mode 100644 index 00000000000..dad9200cc01 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/stddef.C @@ -0,0 +1,6 @@ +// PR c++/54249 +// { dg-do compile { target c++11 } } + +#include <stddef.h> + +::nullptr_t n; diff --git a/gcc/testsuite/g++.dg/cpp0x/stdint.C b/gcc/testsuite/g++.dg/cpp0x/stdint.C new file mode 100644 index 00000000000..434d4582415 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/stdint.C @@ -0,0 +1,135 @@ +// PR c++/52764 +// { dg-require-effective-target stdint_types } +// { dg-do compile { target c++11 } } + +#include <stdint.h> + +#ifdef __INT8_TYPE__ +# if (!defined INT8_MAX \ + || !defined INT8_MIN) +# error +# endif +#endif +#ifdef __UINT8_TYPE__ +# if !defined UINT8_MAX +# error +# endif +#endif +#ifdef __INT16_TYPE__ +# if (!defined INT16_MAX \ + || !defined INT16_MIN) +# error +# endif +#endif +#ifdef __UINT16_TYPE__ +# if !defined UINT16_MAX +# error +# endif +#endif +#ifdef __INT32_TYPE__ +# if (!defined INT32_MAX \ + || !defined INT32_MIN) +# error +# endif +#endif +#ifdef __UINT32_TYPE__ +# if !defined UINT32_MAX +# error +# endif +#endif +#ifdef __INT64_TYPE__ +# if (!defined INT64_MAX \ + || !defined INT64_MIN) +# error +# endif +#endif +#ifdef __UINT64_TYPE__ +# if !defined UINT64_MAX +# error +# endif +#endif + +#if (!defined INT_LEAST8_MAX \ + || !defined INT_LEAST8_MIN \ + || !defined UINT_LEAST8_MAX \ + || !defined INT_LEAST16_MAX \ + || !defined INT_LEAST16_MIN \ + || !defined UINT_LEAST16_MAX \ + || !defined INT_LEAST32_MAX \ + || !defined INT_LEAST32_MIN \ + || !defined UINT_LEAST32_MAX \ + || !defined INT_LEAST64_MAX \ + || !defined INT_LEAST64_MIN \ + || !defined UINT_LEAST64_MAX) +#error +#endif + +#if (!defined INT_FAST8_MAX \ + || !defined INT_FAST8_MIN \ + || !defined UINT_FAST8_MAX \ + || !defined INT_FAST16_MAX \ + || !defined INT_FAST16_MIN \ + || !defined UINT_FAST16_MAX \ + || !defined INT_FAST32_MAX \ + || !defined INT_FAST32_MIN \ + || !defined UINT_FAST32_MAX \ + || !defined INT_FAST64_MAX \ + || !defined INT_FAST64_MIN \ + || !defined UINT_FAST64_MAX) +#error +#endif + +#ifdef __INTPTR_TYPE__ +# if (!defined INTPTR_MAX \ + || !defined INTPTR_MIN) +# error +# endif +#endif +#ifdef __UINTPTR_TYPE__ +# if !defined UINTPTR_MAX +# error +# endif +#endif + +#if (!defined INTMAX_MAX \ + || !defined INTMAX_MIN \ + || !defined UINTMAX_MAX) +#error +#endif + +#if (!defined PTRDIFF_MAX \ + || !defined PTRDIFF_MIN) +#error +#endif + +#if (!defined SIG_ATOMIC_MAX \ + || !defined SIG_ATOMIC_MIN) +#error +#endif + +#if !defined SIZE_MAX +#error +#endif + +#if (!defined WCHAR_MAX \ + || !defined WCHAR_MIN) +#error +#endif + +#if (!defined WINT_MAX \ + || !defined WINT_MIN) +#error +#endif + +#if (!defined INT8_C \ + || !defined INT16_C \ + || !defined INT32_C \ + || !defined INT64_C \ + || !defined UINT8_C \ + || !defined UINT16_C \ + || !defined UINT32_C \ + || !defined UINT64_C \ + || !defined INTMAX_C \ + || !defined UINTMAX_C) +#error +#endif diff --git a/gcc/testsuite/g++.dg/ext/builtin30.C b/gcc/testsuite/g++.dg/ext/builtin30.C new file mode 100644 index 00000000000..d0a75fb173d --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/builtin30.C @@ -0,0 +1,27 @@ +// { dg-do compile } +// { dg-options "-O2" } + +typedef __SIZE_TYPE__ size_t; +extern "C" { +extern void __chk_fail (void); +extern int snprintf (char *, size_t, const char *, ...); +extern inline __attribute__((gnu_inline, always_inline)) int snprintf (char *a, size_t b, const char *fmt, ...) +{ + if (__builtin_object_size (a, 0) != -1UL && __builtin_object_size (a, 0) < b) + __chk_fail (); + return __builtin_snprintf (a, b, fmt, __builtin_va_arg_pack ()); +} +extern int snprintf (char *, size_t, const char *, ...) __asm ("mysnprintf"); +} + +char buf[10]; + +int +main (void) +{ + snprintf (buf, 10, "%d%d\n", 10, 10); + return 0; +} + +// { dg-final { scan-assembler "mysnprintf" } } +// { dg-final { scan-assembler-not "__chk_fail" } } diff --git a/gcc/testsuite/g++.dg/ext/vla12.C b/gcc/testsuite/g++.dg/ext/vla12.C new file mode 100644 index 00000000000..bca836507a9 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/vla12.C @@ -0,0 +1,28 @@ +// VLA sizeof test +// { dg-do compile } +// { dg-options "" } + +int +f1 (int i) +{ + char a[sizeof (i) + 6 + i]; + char b[sizeof (a) + 1]; + return sizeof (b); +} + +int +f2 (int i) +{ + char a[sizeof (i) + 6 + i]; + char b[sizeof (a)]; + return sizeof (b); +} + +int +f3 (int i) +{ + char a[sizeof (i) + 6 + i]; + char b[sizeof (i) + i]; + char c[sizeof (a) + sizeof (b) + 7]; + return sizeof (c); +} diff --git a/gcc/testsuite/g++.dg/lto/v1-plugin-api-not-supported_0.C b/gcc/testsuite/g++.dg/lto/v1-plugin-api-not-supported_0.C new file mode 100644 index 00000000000..f79dfae5c6f --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/v1-plugin-api-not-supported_0.C @@ -0,0 +1,54 @@ +// { dg-lto-do run } +// { dg-require-linker-plugin "" } +// { dg-lto-options {{-O2 -fuse-linker-plugin -fno-early-inlining}} + +extern "C" void abort (void); +extern "C" void linker_error (); + +class A +{ +public: + int data; + virtual int foo (int i) + { + return i + 1; + } +}; + +class B : public A +{ +public: + virtual int foo (int i) + { + return i + 2; + } +}; + +class C : public A +{ +public: + virtual int foo (int i) + { + linker_error (); + return i + 3; + } +}; + + +static int middleman (class A *obj, int i) +{ + return obj->foo (i); +} + +int __attribute__ ((noinline,noclone)) get_input(void) +{ + return 1; +} + +int main (int argc, char *argv[]) +{ + class B b; + if (middleman (&b, get_input ()) != 3) + abort (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/other/dump-ada-spec-1.C b/gcc/testsuite/g++.dg/other/dump-ada-spec-1.C new file mode 100644 index 00000000000..eb249e79854 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/dump-ada-spec-1.C @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-ada-spec" } */ + +struct S +{ + int i; +}; + +/* { dg-final { scan-ada-spec "type S is record" } } */ +/* { dg-final { cleanup-ada-spec } } */ diff --git a/gcc/testsuite/g++.dg/template/friend53.C b/gcc/testsuite/g++.dg/template/friend53.C new file mode 100644 index 00000000000..6cbbb2b0993 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend53.C @@ -0,0 +1,23 @@ +// PR c++/53403 + +template <typename T> +class Foo +{ + typedef void type; + template <typename U> friend void f(); +public: + Foo() {} +}; + +template class Foo<void>; + +template <typename T> +void f() +{ + typedef Foo<void>::type type; +} + +int main() +{ + f<void>(); +} diff --git a/gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C b/gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C new file mode 100644 index 00000000000..c57096cc063 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess1.C @@ -0,0 +1,702 @@ +// Test -Wsizeof-pointer-memaccess warnings. +// { dg-do compile } +// { dg-options "-Wall" } +// Test just twice, once with -O0 non-fortified, once with -O2 fortified. +// { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O2" } } +// { dg-skip-if "" { *-*-* } { "-flto" } { "" } } + +extern "C" { + +typedef __SIZE_TYPE__ size_t; +extern void *memset (void *, int, size_t); +extern void *memcpy (void *__restrict, const void *__restrict, size_t); +extern void *memmove (void *__restrict, const void *__restrict, size_t); +extern int memcmp (const void *, const void *, size_t); +extern char *strncpy (char *__restrict, const char *__restrict, size_t); +extern char *strncat (char *__restrict, const char *__restrict, size_t); +extern char *strndup (const char *, size_t); +extern int strncmp (const char *, const char *, size_t); +extern int strncasecmp (const char *, const char *, size_t); + +#ifdef __OPTIMIZE__ +# define bos(ptr) __builtin_object_size (ptr, 1) +# define bos0(ptr) __builtin_object_size (ptr, 0) + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline void * +memset (void *dest, int c, size_t len) +{ + return __builtin___memset_chk (dest, c, len, bos0 (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline void * +memcpy (void *__restrict dest, const void *__restrict src, size_t len) +{ + return __builtin___memcpy_chk (dest, src, len, bos0 (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline void * +memmove (void *dest, const void *src, size_t len) +{ + return __builtin___memmove_chk (dest, src, len, bos0 (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline char * +strncpy (char *__restrict dest, const char *__restrict src, size_t len) +{ + return __builtin___strncpy_chk (dest, src, len, bos (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline char * +strncat (char *dest, const char *src, size_t len) +{ + return __builtin___strncat_chk (dest, src, len, bos (dest)); +} +#endif + +} + +struct A { short a, b; int c, d; long e, f; }; +typedef struct A TA; +typedef struct A *PA; +typedef TA *PTA; +struct B {}; +typedef struct B TB; +typedef struct B *PB; +typedef TB *PTB; +typedef int X[3][3][3]; + +int +f1 (void *x, int z) +{ + struct A a, *pa1 = &a; + TA *pa2 = &a; + PA pa3 = &a; + PTA pa4 = &a; + memset (&a, 0, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memset (pa1, 0, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pa2, 0, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pa3, 0, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pa4, 0, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pa1, 0, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pa2, 0, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pa3, 0, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pa4, 0, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memcpy (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memcpy (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pa1, x, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pa4, x, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memcpy (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memcpy (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pa1, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pa4, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + memmove (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memmove (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pa1, x, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pa4, x, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memmove (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memmove (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pa1, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pa4, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + z += memcmp (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + z += memcmp (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pa1, x, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + z += memcmp (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + z += memcmp (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + z += memcmp (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + z += memcmp (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pa1, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + z += memcmp (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + z += memcmp (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + // These are correct, no warning. + memset (&a, 0, sizeof a); + memset (&a, 0, sizeof (a)); + memset (&a, 0, sizeof (struct A)); + memset (&a, 0, sizeof (const struct A)); + memset (&a, 0, sizeof (volatile struct A)); + memset (&a, 0, sizeof (volatile const struct A)); + memset (&a, 0, sizeof (TA)); + memset (&a, 0, sizeof (__typeof (*&a))); + memset (pa1, 0, sizeof (*pa1)); + memset (pa2, 0, sizeof (*pa3)); + memset (pa3, 0, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memset ((void *) &a, 0, sizeof (&a)); + memset ((char *) &a, 0, sizeof (&a)); + memset (&a, 0, sizeof (&a) + 0); + memset (&a, 0, 0 + sizeof (&a)); + + // These are correct, no warning. + memcpy (&a, x, sizeof a); + memcpy (&a, x, sizeof (a)); + memcpy (&a, x, sizeof (struct A)); + memcpy (&a, x, sizeof (const struct A)); + memcpy (&a, x, sizeof (volatile struct A)); + memcpy (&a, x, sizeof (volatile const struct A)); + memcpy (&a, x, sizeof (TA)); + memcpy (&a, x, sizeof (__typeof (*&a))); + memcpy (pa1, x, sizeof (*pa1)); + memcpy (pa2, x, sizeof (*pa3)); + memcpy (pa3, x, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memcpy ((void *) &a, x, sizeof (&a)); + memcpy ((char *) &a, x, sizeof (&a)); + memcpy (&a, x, sizeof (&a) + 0); + memcpy (&a, x, 0 + sizeof (&a)); + + // These are correct, no warning. + memcpy (x, &a, sizeof a); + memcpy (x, &a, sizeof (a)); + memcpy (x, &a, sizeof (struct A)); + memcpy (x, &a, sizeof (const struct A)); + memcpy (x, &a, sizeof (volatile struct A)); + memcpy (x, &a, sizeof (volatile const struct A)); + memcpy (x, &a, sizeof (TA)); + memcpy (x, &a, sizeof (__typeof (*&a))); + memcpy (x, pa1, sizeof (*pa1)); + memcpy (x, pa2, sizeof (*pa3)); + memcpy (x, pa3, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memcpy (x, (void *) &a, sizeof (&a)); + memcpy (x, (char *) &a, sizeof (&a)); + memcpy (x, &a, sizeof (&a) + 0); + memcpy (x, &a, 0 + sizeof (&a)); + + // These are correct, no warning. + memmove (&a, x, sizeof a); + memmove (&a, x, sizeof (a)); + memmove (&a, x, sizeof (struct A)); + memmove (&a, x, sizeof (const struct A)); + memmove (&a, x, sizeof (volatile struct A)); + memmove (&a, x, sizeof (volatile const struct A)); + memmove (&a, x, sizeof (TA)); + memmove (&a, x, sizeof (__typeof (*&a))); + memmove (pa1, x, sizeof (*pa1)); + memmove (pa2, x, sizeof (*pa3)); + memmove (pa3, x, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memmove ((void *) &a, x, sizeof (&a)); + memmove ((char *) &a, x, sizeof (&a)); + memmove (&a, x, sizeof (&a) + 0); + memmove (&a, x, 0 + sizeof (&a)); + + // These are correct, no warning. + memmove (x, &a, sizeof a); + memmove (x, &a, sizeof (a)); + memmove (x, &a, sizeof (struct A)); + memmove (x, &a, sizeof (const struct A)); + memmove (x, &a, sizeof (volatile struct A)); + memmove (x, &a, sizeof (volatile const struct A)); + memmove (x, &a, sizeof (TA)); + memmove (x, &a, sizeof (__typeof (*&a))); + memmove (x, pa1, sizeof (*pa1)); + memmove (x, pa2, sizeof (*pa3)); + memmove (x, pa3, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memmove (x, (void *) &a, sizeof (&a)); + memmove (x, (char *) &a, sizeof (&a)); + memmove (x, &a, sizeof (&a) + 0); + memmove (x, &a, 0 + sizeof (&a)); + + // These are correct, no warning. + z += memcmp (&a, x, sizeof a); + z += memcmp (&a, x, sizeof (a)); + z += memcmp (&a, x, sizeof (struct A)); + z += memcmp (&a, x, sizeof (const struct A)); + z += memcmp (&a, x, sizeof (volatile struct A)); + z += memcmp (&a, x, sizeof (volatile const struct A)); + z += memcmp (&a, x, sizeof (TA)); + z += memcmp (&a, x, sizeof (__typeof (*&a))); + z += memcmp (pa1, x, sizeof (*pa1)); + z += memcmp (pa2, x, sizeof (*pa3)); + z += memcmp (pa3, x, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + z += memcmp ((void *) &a, x, sizeof (&a)); + z += memcmp ((char *) &a, x, sizeof (&a)); + z += memcmp (&a, x, sizeof (&a) + 0); + z += memcmp (&a, x, 0 + sizeof (&a)); + + // These are correct, no warning. + z += memcmp (x, &a, sizeof a); + z += memcmp (x, &a, sizeof (a)); + z += memcmp (x, &a, sizeof (struct A)); + z += memcmp (x, &a, sizeof (const struct A)); + z += memcmp (x, &a, sizeof (volatile struct A)); + z += memcmp (x, &a, sizeof (volatile const struct A)); + z += memcmp (x, &a, sizeof (TA)); + z += memcmp (x, &a, sizeof (__typeof (*&a))); + z += memcmp (x, pa1, sizeof (*pa1)); + z += memcmp (x, pa2, sizeof (*pa3)); + z += memcmp (x, pa3, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + z += memcmp (x, (void *) &a, sizeof (&a)); + z += memcmp (x, (char *) &a, sizeof (&a)); + z += memcmp (x, &a, sizeof (&a) + 0); + z += memcmp (x, &a, 0 + sizeof (&a)); + + return z; +} + +int +f2 (void *x, int z) +{ + struct B b, *pb1 = &b; + TB *pb2 = &b; + PB pb3 = &b; + PTB pb4 = &b; + memset (&b, 0, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memset (pb1, 0, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pb2, 0, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pb3, 0, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pb4, 0, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pb1, 0, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pb2, 0, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pb3, 0, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pb4, 0, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memcpy (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memcpy (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pb1, x, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pb4, x, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memcpy (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memcpy (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pb1, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pb4, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + memmove (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memmove (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pb1, x, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pb4, x, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memmove (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memmove (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pb1, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pb4, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + z += memcmp (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + z += memcmp (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pb1, x, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + z += memcmp (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + z += memcmp (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + z += memcmp (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + z += memcmp (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pb1, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + z += memcmp (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + z += memcmp (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + // These are correct, no warning. + memset (&b, 0, sizeof b); + memset (&b, 0, sizeof (b)); + memset (&b, 0, sizeof (struct B)); + memset (&b, 0, sizeof (const struct B)); + memset (&b, 0, sizeof (volatile struct B)); + memset (&b, 0, sizeof (volatile const struct B)); + memset (&b, 0, sizeof (TB)); + memset (&b, 0, sizeof (__typeof (*&b))); + memset (pb1, 0, sizeof (*pb1)); + memset (pb2, 0, sizeof (*pb3)); + memset (pb3, 0, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memset ((void *) &b, 0, sizeof (&b)); + memset ((char *) &b, 0, sizeof (&b)); + memset (&b, 0, sizeof (&b) + 0); + memset (&b, 0, 0 + sizeof (&b)); + + // These are correct, no warning. + memcpy (&b, x, sizeof b); + memcpy (&b, x, sizeof (b)); + memcpy (&b, x, sizeof (struct B)); + memcpy (&b, x, sizeof (const struct B)); + memcpy (&b, x, sizeof (volatile struct B)); + memcpy (&b, x, sizeof (volatile const struct B)); + memcpy (&b, x, sizeof (TB)); + memcpy (&b, x, sizeof (__typeof (*&b))); + memcpy (pb1, x, sizeof (*pb1)); + memcpy (pb2, x, sizeof (*pb3)); + memcpy (pb3, x, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memcpy ((void *) &b, x, sizeof (&b)); + memcpy ((char *) &b, x, sizeof (&b)); + memcpy (&b, x, sizeof (&b) + 0); + memcpy (&b, x, 0 + sizeof (&b)); + + // These are correct, no warning. + memcpy (x, &b, sizeof b); + memcpy (x, &b, sizeof (b)); + memcpy (x, &b, sizeof (struct B)); + memcpy (x, &b, sizeof (const struct B)); + memcpy (x, &b, sizeof (volatile struct B)); + memcpy (x, &b, sizeof (volatile const struct B)); + memcpy (x, &b, sizeof (TB)); + memcpy (x, &b, sizeof (__typeof (*&b))); + memcpy (x, pb1, sizeof (*pb1)); + memcpy (x, pb2, sizeof (*pb3)); + memcpy (x, pb3, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memcpy (x, (void *) &b, sizeof (&b)); + memcpy (x, (char *) &b, sizeof (&b)); + memcpy (x, &b, sizeof (&b) + 0); + memcpy (x, &b, 0 + sizeof (&b)); + + // These are correct, no warning. + memmove (&b, x, sizeof b); + memmove (&b, x, sizeof (b)); + memmove (&b, x, sizeof (struct B)); + memmove (&b, x, sizeof (const struct B)); + memmove (&b, x, sizeof (volatile struct B)); + memmove (&b, x, sizeof (volatile const struct B)); + memmove (&b, x, sizeof (TB)); + memmove (&b, x, sizeof (__typeof (*&b))); + memmove (pb1, x, sizeof (*pb1)); + memmove (pb2, x, sizeof (*pb3)); + memmove (pb3, x, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memmove ((void *) &b, x, sizeof (&b)); + memmove ((char *) &b, x, sizeof (&b)); + memmove (&b, x, sizeof (&b) + 0); + memmove (&b, x, 0 + sizeof (&b)); + + // These are correct, no warning. + memmove (x, &b, sizeof b); + memmove (x, &b, sizeof (b)); + memmove (x, &b, sizeof (struct B)); + memmove (x, &b, sizeof (const struct B)); + memmove (x, &b, sizeof (volatile struct B)); + memmove (x, &b, sizeof (volatile const struct B)); + memmove (x, &b, sizeof (TB)); + memmove (x, &b, sizeof (__typeof (*&b))); + memmove (x, pb1, sizeof (*pb1)); + memmove (x, pb2, sizeof (*pb3)); + memmove (x, pb3, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memmove (x, (void *) &b, sizeof (&b)); + memmove (x, (char *) &b, sizeof (&b)); + memmove (x, &b, sizeof (&b) + 0); + memmove (x, &b, 0 + sizeof (&b)); + + // These are correct, no warning. + z += memcmp (&b, x, sizeof b); + z += memcmp (&b, x, sizeof (b)); + z += memcmp (&b, x, sizeof (struct B)); + z += memcmp (&b, x, sizeof (const struct B)); + z += memcmp (&b, x, sizeof (volatile struct B)); + z += memcmp (&b, x, sizeof (volatile const struct B)); + z += memcmp (&b, x, sizeof (TB)); + z += memcmp (&b, x, sizeof (__typeof (*&b))); + z += memcmp (pb1, x, sizeof (*pb1)); + z += memcmp (pb2, x, sizeof (*pb3)); + z += memcmp (pb3, x, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + z += memcmp ((void *) &b, x, sizeof (&b)); + z += memcmp ((char *) &b, x, sizeof (&b)); + z += memcmp (&b, x, sizeof (&b) + 0); + z += memcmp (&b, x, 0 + sizeof (&b)); + + // These are correct, no warning. + z += memcmp (x, &b, sizeof b); + z += memcmp (x, &b, sizeof (b)); + z += memcmp (x, &b, sizeof (struct B)); + z += memcmp (x, &b, sizeof (const struct B)); + z += memcmp (x, &b, sizeof (volatile struct B)); + z += memcmp (x, &b, sizeof (volatile const struct B)); + z += memcmp (x, &b, sizeof (TB)); + z += memcmp (x, &b, sizeof (__typeof (*&b))); + z += memcmp (x, pb1, sizeof (*pb1)); + z += memcmp (x, pb2, sizeof (*pb3)); + z += memcmp (x, pb3, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + z += memcmp (x, (void *) &b, sizeof (&b)); + z += memcmp (x, (char *) &b, sizeof (&b)); + z += memcmp (x, &b, sizeof (&b) + 0); + z += memcmp (x, &b, 0 + sizeof (&b)); + + return z; +} + +int +f3 (void *x, char *y, int z, X w) +{ + unsigned char *y1 = (unsigned char *) __builtin_alloca (z + 16); + char buf1[7]; + signed char buf2[z + 32]; + long buf3[17]; + int *buf4[9]; + signed char *y2 = buf2; + char c; + char *y3; + memset (y, 0, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memset (y1, 0, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memset (y2, 0, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memset (&c, 0, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memset (w, 0, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + + memcpy (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memcpy (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memcpy (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memcpy (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memcpy (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + + memcpy (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memcpy (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memcpy (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memcpy (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memcpy (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + + memmove (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memmove (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memmove (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memmove (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memmove (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + + memmove (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memmove (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memmove (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memmove (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memmove (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + + z += memcmp (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += memcmp (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += memcmp (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += memcmp (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + z += memcmp (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + + z += memcmp (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += memcmp (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += memcmp (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += memcmp (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + z += memcmp (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + + // These are correct, no warning. + memset (y, 0, sizeof (*y)); + memset (y1, 0, sizeof (*y2)); + memset (buf1, 0, sizeof buf1); + memset (buf3, 0, sizeof (buf3)); + memset (&buf3[0], 0, sizeof (buf3)); + memset (&buf4[0], 0, sizeof (buf4)); + memset (w, 0, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memset ((void *) y, 0, sizeof (y)); + memset ((char *) y1, 0, sizeof (y2)); + memset (y, 0, sizeof (y) + 0); + memset (y1, 0, 0 + sizeof (y2)); + memset ((void *) &c, 0, sizeof (&c)); + memset ((signed char *) &c, 0, sizeof (&c)); + memset (&c, 0, sizeof (&c) + 0); + memset (&c, 0, 0 + sizeof (&c)); + + // These are correct, no warning. + memcpy (y, x, sizeof (*y)); + memcpy (y1, x, sizeof (*y2)); + memcpy (buf1, x, sizeof buf1); + memcpy (buf3, x, sizeof (buf3)); + memcpy (&buf3[0], x, sizeof (buf3)); + memcpy (&buf4[0], x, sizeof (buf4)); + memcpy (&y3, y, sizeof (y3)); + memcpy ((char *) &y3, y, sizeof (y3)); + memcpy (w, x, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memcpy ((void *) y, x, sizeof (y)); + memcpy ((char *) y1, x, sizeof (y2)); + memcpy (y, x, sizeof (y) + 0); + memcpy (y1, x, 0 + sizeof (y2)); + memcpy ((void *) &c, x, sizeof (&c)); + memcpy ((signed char *) &c, x, sizeof (&c)); + memcpy (&c, x, sizeof (&c) + 0); + memcpy (&c, x, 0 + sizeof (&c)); + + // These are correct, no warning. + memcpy (x, y, sizeof (*y)); + memcpy (x, y1, sizeof (*y2)); + memcpy (x, buf1, sizeof buf1); + memcpy (x, buf3, sizeof (buf3)); + memcpy (x, &buf3[0], sizeof (buf3)); + memcpy (x, &buf4[0], sizeof (buf4)); + memcpy (y, &y3, sizeof (y3)); + memcpy (y, (char *) &y3, sizeof (y3)); + memcpy (x, w, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memcpy (x, (void *) y, sizeof (y)); + memcpy (x, (char *) y1, sizeof (y2)); + memcpy (x, y, sizeof (y) + 0); + memcpy (x, y1, 0 + sizeof (y2)); + memcpy (x, (void *) &c, sizeof (&c)); + memcpy (x, (signed char *) &c, sizeof (&c)); + memcpy (x, &c, sizeof (&c) + 0); + memcpy (x, &c, 0 + sizeof (&c)); + + // These are correct, no warning. + memmove (y, x, sizeof (*y)); + memmove (y1, x, sizeof (*y2)); + memmove (buf1, x, sizeof buf1); + memmove (buf3, x, sizeof (buf3)); + memmove (&buf3[0], x, sizeof (buf3)); + memmove (&buf4[0], x, sizeof (buf4)); + memmove (&y3, y, sizeof (y3)); + memmove ((char *) &y3, y, sizeof (y3)); + memmove (w, x, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memmove ((void *) y, x, sizeof (y)); + memmove ((char *) y1, x, sizeof (y2)); + memmove (y, x, sizeof (y) + 0); + memmove (y1, x, 0 + sizeof (y2)); + memmove ((void *) &c, x, sizeof (&c)); + memmove ((signed char *) &c, x, sizeof (&c)); + memmove (&c, x, sizeof (&c) + 0); + memmove (&c, x, 0 + sizeof (&c)); + + // These are correct, no warning. + memmove (x, y, sizeof (*y)); + memmove (x, y1, sizeof (*y2)); + memmove (x, buf1, sizeof buf1); + memmove (x, buf3, sizeof (buf3)); + memmove (x, &buf3[0], sizeof (buf3)); + memmove (x, &buf4[0], sizeof (buf4)); + memmove (y, &y3, sizeof (y3)); + memmove (y, (char *) &y3, sizeof (y3)); + memmove (x, w, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memmove (x, (void *) y, sizeof (y)); + memmove (x, (char *) y1, sizeof (y2)); + memmove (x, y, sizeof (y) + 0); + memmove (x, y1, 0 + sizeof (y2)); + memmove (x, (void *) &c, sizeof (&c)); + memmove (x, (signed char *) &c, sizeof (&c)); + memmove (x, &c, sizeof (&c) + 0); + memmove (x, &c, 0 + sizeof (&c)); + + // These are correct, no warning. + z += memcmp (y, x, sizeof (*y)); + z += memcmp (y1, x, sizeof (*y2)); + z += memcmp (buf1, x, sizeof buf1); + z += memcmp (buf3, x, sizeof (buf3)); + z += memcmp (&buf3[0], x, sizeof (buf3)); + z += memcmp (&buf4[0], x, sizeof (buf4)); + z += memcmp (&y3, y, sizeof (y3)); + z += memcmp ((char *) &y3, y, sizeof (y3)); + z += memcmp (w, x, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + z += memcmp ((void *) y, x, sizeof (y)); + z += memcmp ((char *) y1, x, sizeof (y2)); + z += memcmp (y, x, sizeof (y) + 0); + z += memcmp (y1, x, 0 + sizeof (y2)); + z += memcmp ((void *) &c, x, sizeof (&c)); + z += memcmp ((signed char *) &c, x, sizeof (&c)); + z += memcmp (&c, x, sizeof (&c) + 0); + z += memcmp (&c, x, 0 + sizeof (&c)); + + // These are correct, no warning. + z += memcmp (x, y, sizeof (*y)); + z += memcmp (x, y1, sizeof (*y2)); + z += memcmp (x, buf1, sizeof buf1); + z += memcmp (x, buf3, sizeof (buf3)); + z += memcmp (x, &buf3[0], sizeof (buf3)); + z += memcmp (x, &buf4[0], sizeof (buf4)); + z += memcmp (y, &y3, sizeof (y3)); + z += memcmp (y, (char *) &y3, sizeof (y3)); + z += memcmp (x, w, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + z += memcmp (x, (void *) y, sizeof (y)); + z += memcmp (x, (char *) y1, sizeof (y2)); + z += memcmp (x, y, sizeof (y) + 0); + z += memcmp (x, y1, 0 + sizeof (y2)); + z += memcmp (x, (void *) &c, sizeof (&c)); + z += memcmp (x, (signed char *) &c, sizeof (&c)); + z += memcmp (x, &c, sizeof (&c) + 0); + z += memcmp (x, &c, 0 + sizeof (&c)); + + return z; +} + +int +f4 (char *x, char **y, int z) +{ + const char *s1 = "foobarbaz"; + const char *s2 = "abcde12345678"; + strncpy (x, s1, sizeof (s1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + strncat (x, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + y[0] = strndup (s1, sizeof (s1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += strncmp (s1, s2, sizeof (s1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += strncmp (s1, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += strncasecmp (s1, s2, sizeof (s1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += strncasecmp (s1, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + + // These are correct, no warning. + const char s3[] = "foobarbaz"; + const char s4[] = "abcde12345678"; + strncpy (x, s3, sizeof (s3)); + strncat (x, s4, sizeof (s4)); + y[1] = strndup (s3, sizeof (s3)); + z += strncmp (s3, s4, sizeof (s3)); + z += strncmp (s3, s4, sizeof (s4)); + z += strncasecmp (s3, s4, sizeof (s3)); + z += strncasecmp (s3, s4, sizeof (s4)); + + return z; +} + +// { dg-prune-output "\[\n\r\]*will always overflow\[\n\r\]*" } diff --git a/gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C b/gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C new file mode 100644 index 00000000000..d5a29d8f582 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/Wsizeof-pointer-memaccess2.C @@ -0,0 +1,716 @@ +// Test -Wsizeof-pointer-memaccess warnings. +// { dg-do compile } +// { dg-options "-Wall" } +// Test just twice, once with -O0 non-fortified, once with -O2 fortified. +// { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O2" } } +// { dg-skip-if "" { *-*-* } { "-flto" } { "" } } + +extern "C" { + +typedef __SIZE_TYPE__ size_t; +extern void *memset (void *, int, size_t); +extern void *memcpy (void *__restrict, const void *__restrict, size_t); +extern void *memmove (void *__restrict, const void *__restrict, size_t); +extern int memcmp (const void *, const void *, size_t); +extern char *strncpy (char *__restrict, const char *__restrict, size_t); +extern char *strncat (char *__restrict, const char *__restrict, size_t); +extern char *strndup (const char *, size_t); +extern int strncmp (const char *, const char *, size_t); +extern int strncasecmp (const char *, const char *, size_t); + +#ifdef __OPTIMIZE__ +# define bos(ptr) __builtin_object_size (ptr, 1) +# define bos0(ptr) __builtin_object_size (ptr, 0) + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline void * +memset (void *dest, int c, size_t len) +{ + return __builtin___memset_chk (dest, c, len, bos0 (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline void * +memcpy (void *__restrict dest, const void *__restrict src, size_t len) +{ + return __builtin___memcpy_chk (dest, src, len, bos0 (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline void * +memmove (void *dest, const void *src, size_t len) +{ + return __builtin___memmove_chk (dest, src, len, bos0 (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline char * +strncpy (char *__restrict dest, const char *__restrict src, size_t len) +{ + return __builtin___strncpy_chk (dest, src, len, bos (dest)); +} + +__attribute__((__always_inline__, __gnu_inline__, __artificial__)) +extern inline char * +strncat (char *dest, const char *src, size_t len) +{ + return __builtin___strncat_chk (dest, src, len, bos (dest)); +} +#endif + +} + +struct A { short a, b; int c, d; long e, f; }; +typedef struct A TA; +typedef struct A *PA; +typedef TA *PTA; +struct B {}; +typedef struct B TB; +typedef struct B *PB; +typedef TB *PTB; +typedef int X[3][3][3]; + +template <int N> +int +f1 (void *x, int z) +{ + struct A a, *pa1 = &a; + TA *pa2 = &a; + PA pa3 = &a; + PTA pa4 = &a; + memset (&a, 0, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memset (pa1, 0, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pa2, 0, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pa3, 0, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pa4, 0, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pa1, 0, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pa2, 0, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pa3, 0, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pa4, 0, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memcpy (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memcpy (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pa1, x, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pa4, x, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memcpy (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memcpy (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pa1, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pa4, sizeof (__typeof (pa4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + memmove (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memmove (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pa1, x, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pa4, x, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memmove (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memmove (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pa1, sizeof (struct A *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pa4, sizeof (__typeof (pa4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + z += memcmp (&a, x, sizeof (&a)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + z += memcmp (pa1, x, sizeof (pa1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pa2, x, sizeof pa2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pa3, x, sizeof (pa3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pa4, x, sizeof pa4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pa1, x, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + z += memcmp (pa2, x, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + z += memcmp (pa3, x, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + z += memcmp (x, &a, sizeof (&a)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + z += memcmp (x, pa1, sizeof (pa1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pa2, sizeof pa2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pa3, sizeof (pa3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pa4, sizeof pa4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pa1, sizeof (struct A *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + z += memcmp (x, pa2, sizeof (PTA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + z += memcmp (x, pa3, sizeof (PA)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + // These are correct, no warning. + memset (&a, 0, sizeof a); + memset (&a, 0, sizeof (a)); + memset (&a, 0, sizeof (struct A)); + memset (&a, 0, sizeof (const struct A)); + memset (&a, 0, sizeof (volatile struct A)); + memset (&a, 0, sizeof (volatile const struct A)); + memset (&a, 0, sizeof (TA)); + memset (&a, 0, sizeof (__typeof (*&a))); + memset (pa1, 0, sizeof (*pa1)); + memset (pa2, 0, sizeof (*pa3)); + memset (pa3, 0, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memset ((void *) &a, 0, sizeof (&a)); + memset ((char *) &a, 0, sizeof (&a)); + memset (&a, 0, sizeof (&a) + 0); + memset (&a, 0, 0 + sizeof (&a)); + + // These are correct, no warning. + memcpy (&a, x, sizeof a); + memcpy (&a, x, sizeof (a)); + memcpy (&a, x, sizeof (struct A)); + memcpy (&a, x, sizeof (const struct A)); + memcpy (&a, x, sizeof (volatile struct A)); + memcpy (&a, x, sizeof (volatile const struct A)); + memcpy (&a, x, sizeof (TA)); + memcpy (&a, x, sizeof (__typeof (*&a))); + memcpy (pa1, x, sizeof (*pa1)); + memcpy (pa2, x, sizeof (*pa3)); + memcpy (pa3, x, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memcpy ((void *) &a, x, sizeof (&a)); + memcpy ((char *) &a, x, sizeof (&a)); + memcpy (&a, x, sizeof (&a) + 0); + memcpy (&a, x, 0 + sizeof (&a)); + + // These are correct, no warning. + memcpy (x, &a, sizeof a); + memcpy (x, &a, sizeof (a)); + memcpy (x, &a, sizeof (struct A)); + memcpy (x, &a, sizeof (const struct A)); + memcpy (x, &a, sizeof (volatile struct A)); + memcpy (x, &a, sizeof (volatile const struct A)); + memcpy (x, &a, sizeof (TA)); + memcpy (x, &a, sizeof (__typeof (*&a))); + memcpy (x, pa1, sizeof (*pa1)); + memcpy (x, pa2, sizeof (*pa3)); + memcpy (x, pa3, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memcpy (x, (void *) &a, sizeof (&a)); + memcpy (x, (char *) &a, sizeof (&a)); + memcpy (x, &a, sizeof (&a) + 0); + memcpy (x, &a, 0 + sizeof (&a)); + + // These are correct, no warning. + memmove (&a, x, sizeof a); + memmove (&a, x, sizeof (a)); + memmove (&a, x, sizeof (struct A)); + memmove (&a, x, sizeof (const struct A)); + memmove (&a, x, sizeof (volatile struct A)); + memmove (&a, x, sizeof (volatile const struct A)); + memmove (&a, x, sizeof (TA)); + memmove (&a, x, sizeof (__typeof (*&a))); + memmove (pa1, x, sizeof (*pa1)); + memmove (pa2, x, sizeof (*pa3)); + memmove (pa3, x, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memmove ((void *) &a, x, sizeof (&a)); + memmove ((char *) &a, x, sizeof (&a)); + memmove (&a, x, sizeof (&a) + 0); + memmove (&a, x, 0 + sizeof (&a)); + + // These are correct, no warning. + memmove (x, &a, sizeof a); + memmove (x, &a, sizeof (a)); + memmove (x, &a, sizeof (struct A)); + memmove (x, &a, sizeof (const struct A)); + memmove (x, &a, sizeof (volatile struct A)); + memmove (x, &a, sizeof (volatile const struct A)); + memmove (x, &a, sizeof (TA)); + memmove (x, &a, sizeof (__typeof (*&a))); + memmove (x, pa1, sizeof (*pa1)); + memmove (x, pa2, sizeof (*pa3)); + memmove (x, pa3, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + memmove (x, (void *) &a, sizeof (&a)); + memmove (x, (char *) &a, sizeof (&a)); + memmove (x, &a, sizeof (&a) + 0); + memmove (x, &a, 0 + sizeof (&a)); + + // These are correct, no warning. + z += memcmp (&a, x, sizeof a); + z += memcmp (&a, x, sizeof (a)); + z += memcmp (&a, x, sizeof (struct A)); + z += memcmp (&a, x, sizeof (const struct A)); + z += memcmp (&a, x, sizeof (volatile struct A)); + z += memcmp (&a, x, sizeof (volatile const struct A)); + z += memcmp (&a, x, sizeof (TA)); + z += memcmp (&a, x, sizeof (__typeof (*&a))); + z += memcmp (pa1, x, sizeof (*pa1)); + z += memcmp (pa2, x, sizeof (*pa3)); + z += memcmp (pa3, x, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + z += memcmp ((void *) &a, x, sizeof (&a)); + z += memcmp ((char *) &a, x, sizeof (&a)); + z += memcmp (&a, x, sizeof (&a) + 0); + z += memcmp (&a, x, 0 + sizeof (&a)); + + // These are correct, no warning. + z += memcmp (x, &a, sizeof a); + z += memcmp (x, &a, sizeof (a)); + z += memcmp (x, &a, sizeof (struct A)); + z += memcmp (x, &a, sizeof (const struct A)); + z += memcmp (x, &a, sizeof (volatile struct A)); + z += memcmp (x, &a, sizeof (volatile const struct A)); + z += memcmp (x, &a, sizeof (TA)); + z += memcmp (x, &a, sizeof (__typeof (*&a))); + z += memcmp (x, pa1, sizeof (*pa1)); + z += memcmp (x, pa2, sizeof (*pa3)); + z += memcmp (x, pa3, sizeof (__typeof (*pa3))); + // These are probably broken, but obfuscated, no warning. + z += memcmp (x, (void *) &a, sizeof (&a)); + z += memcmp (x, (char *) &a, sizeof (&a)); + z += memcmp (x, &a, sizeof (&a) + 0); + z += memcmp (x, &a, 0 + sizeof (&a)); + + return z; +} + +template <int N> +int +f2 (void *x, int z) +{ + struct B b, *pb1 = &b; + TB *pb2 = &b; + PB pb3 = &b; + PTB pb4 = &b; + memset (&b, 0, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memset (pb1, 0, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pb2, 0, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pb3, 0, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pb4, 0, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memset (pb1, 0, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pb2, 0, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pb3, 0, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memset (pb4, 0, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memcpy (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memcpy (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memcpy (pb1, x, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memcpy (pb4, x, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memcpy (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memcpy (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memcpy (x, pb1, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memcpy (x, pb4, sizeof (__typeof (pb4))); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + memmove (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memmove (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + memmove (pb1, x, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + memmove (pb4, x, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + memmove (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memmove (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + memmove (x, pb1, sizeof (struct B *)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + memmove (x, pb4, sizeof (__typeof (pb4)));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + z += memcmp (&b, x, sizeof (&b)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + z += memcmp (pb1, x, sizeof (pb1)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pb2, x, sizeof pb2); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pb3, x, sizeof (pb3)); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pb4, x, sizeof pb4); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + z += memcmp (pb1, x, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + z += memcmp (pb2, x, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + z += memcmp (pb3, x, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the destination; expected \[^\n\r\]* or an explicit length" } + + z += memcmp (x, &b, sizeof (&b)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + z += memcmp (x, pb1, sizeof (pb1)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pb2, sizeof pb2); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pb3, sizeof (pb3)); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pb4, sizeof pb4); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + z += memcmp (x, pb1, sizeof (struct B *));// { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + z += memcmp (x, pb2, sizeof (PTB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + z += memcmp (x, pb3, sizeof (PB)); // { dg-warning "call is the same pointer type \[^\n\r\]* as the source; expected \[^\n\r\]* or an explicit length" } + + // These are correct, no warning. + memset (&b, 0, sizeof b); + memset (&b, 0, sizeof (b)); + memset (&b, 0, sizeof (struct B)); + memset (&b, 0, sizeof (const struct B)); + memset (&b, 0, sizeof (volatile struct B)); + memset (&b, 0, sizeof (volatile const struct B)); + memset (&b, 0, sizeof (TB)); + memset (&b, 0, sizeof (__typeof (*&b))); + memset (pb1, 0, sizeof (*pb1)); + memset (pb2, 0, sizeof (*pb3)); + memset (pb3, 0, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memset ((void *) &b, 0, sizeof (&b)); + memset ((char *) &b, 0, sizeof (&b)); + memset (&b, 0, sizeof (&b) + 0); + memset (&b, 0, 0 + sizeof (&b)); + + // These are correct, no warning. + memcpy (&b, x, sizeof b); + memcpy (&b, x, sizeof (b)); + memcpy (&b, x, sizeof (struct B)); + memcpy (&b, x, sizeof (const struct B)); + memcpy (&b, x, sizeof (volatile struct B)); + memcpy (&b, x, sizeof (volatile const struct B)); + memcpy (&b, x, sizeof (TB)); + memcpy (&b, x, sizeof (__typeof (*&b))); + memcpy (pb1, x, sizeof (*pb1)); + memcpy (pb2, x, sizeof (*pb3)); + memcpy (pb3, x, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memcpy ((void *) &b, x, sizeof (&b)); + memcpy ((char *) &b, x, sizeof (&b)); + memcpy (&b, x, sizeof (&b) + 0); + memcpy (&b, x, 0 + sizeof (&b)); + + // These are correct, no warning. + memcpy (x, &b, sizeof b); + memcpy (x, &b, sizeof (b)); + memcpy (x, &b, sizeof (struct B)); + memcpy (x, &b, sizeof (const struct B)); + memcpy (x, &b, sizeof (volatile struct B)); + memcpy (x, &b, sizeof (volatile const struct B)); + memcpy (x, &b, sizeof (TB)); + memcpy (x, &b, sizeof (__typeof (*&b))); + memcpy (x, pb1, sizeof (*pb1)); + memcpy (x, pb2, sizeof (*pb3)); + memcpy (x, pb3, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memcpy (x, (void *) &b, sizeof (&b)); + memcpy (x, (char *) &b, sizeof (&b)); + memcpy (x, &b, sizeof (&b) + 0); + memcpy (x, &b, 0 + sizeof (&b)); + + // These are correct, no warning. + memmove (&b, x, sizeof b); + memmove (&b, x, sizeof (b)); + memmove (&b, x, sizeof (struct B)); + memmove (&b, x, sizeof (const struct B)); + memmove (&b, x, sizeof (volatile struct B)); + memmove (&b, x, sizeof (volatile const struct B)); + memmove (&b, x, sizeof (TB)); + memmove (&b, x, sizeof (__typeof (*&b))); + memmove (pb1, x, sizeof (*pb1)); + memmove (pb2, x, sizeof (*pb3)); + memmove (pb3, x, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memmove ((void *) &b, x, sizeof (&b)); + memmove ((char *) &b, x, sizeof (&b)); + memmove (&b, x, sizeof (&b) + 0); + memmove (&b, x, 0 + sizeof (&b)); + + // These are correct, no warning. + memmove (x, &b, sizeof b); + memmove (x, &b, sizeof (b)); + memmove (x, &b, sizeof (struct B)); + memmove (x, &b, sizeof (const struct B)); + memmove (x, &b, sizeof (volatile struct B)); + memmove (x, &b, sizeof (volatile const struct B)); + memmove (x, &b, sizeof (TB)); + memmove (x, &b, sizeof (__typeof (*&b))); + memmove (x, pb1, sizeof (*pb1)); + memmove (x, pb2, sizeof (*pb3)); + memmove (x, pb3, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + memmove (x, (void *) &b, sizeof (&b)); + memmove (x, (char *) &b, sizeof (&b)); + memmove (x, &b, sizeof (&b) + 0); + memmove (x, &b, 0 + sizeof (&b)); + + // These are correct, no warning. + z += memcmp (&b, x, sizeof b); + z += memcmp (&b, x, sizeof (b)); + z += memcmp (&b, x, sizeof (struct B)); + z += memcmp (&b, x, sizeof (const struct B)); + z += memcmp (&b, x, sizeof (volatile struct B)); + z += memcmp (&b, x, sizeof (volatile const struct B)); + z += memcmp (&b, x, sizeof (TB)); + z += memcmp (&b, x, sizeof (__typeof (*&b))); + z += memcmp (pb1, x, sizeof (*pb1)); + z += memcmp (pb2, x, sizeof (*pb3)); + z += memcmp (pb3, x, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + z += memcmp ((void *) &b, x, sizeof (&b)); + z += memcmp ((char *) &b, x, sizeof (&b)); + z += memcmp (&b, x, sizeof (&b) + 0); + z += memcmp (&b, x, 0 + sizeof (&b)); + + // These are correct, no warning. + z += memcmp (x, &b, sizeof b); + z += memcmp (x, &b, sizeof (b)); + z += memcmp (x, &b, sizeof (struct B)); + z += memcmp (x, &b, sizeof (const struct B)); + z += memcmp (x, &b, sizeof (volatile struct B)); + z += memcmp (x, &b, sizeof (volatile const struct B)); + z += memcmp (x, &b, sizeof (TB)); + z += memcmp (x, &b, sizeof (__typeof (*&b))); + z += memcmp (x, pb1, sizeof (*pb1)); + z += memcmp (x, pb2, sizeof (*pb3)); + z += memcmp (x, pb3, sizeof (__typeof (*pb3))); + // These are probably broken, but obfuscated, no warning. + z += memcmp (x, (void *) &b, sizeof (&b)); + z += memcmp (x, (char *) &b, sizeof (&b)); + z += memcmp (x, &b, sizeof (&b) + 0); + z += memcmp (x, &b, 0 + sizeof (&b)); + + return z; +} + +template <int N> +int +f3 (void *x, char *y, int z, X w) +{ + unsigned char *y1 = (unsigned char *) __builtin_alloca (z + 16); + char buf1[7]; + signed char buf2[z + 32]; + long buf3[17]; + int *buf4[9]; + signed char *y2 = buf2; + char c; + char *y3; + memset (y, 0, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memset (y1, 0, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memset (y2, 0, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memset (&c, 0, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memset (w, 0, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + + memcpy (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memcpy (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memcpy (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memcpy (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memcpy (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + + memcpy (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memcpy (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memcpy (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memcpy (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memcpy (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + + memmove (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memmove (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memmove (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + memmove (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + memmove (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + + memmove (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memmove (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memmove (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + memmove (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + memmove (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + + z += memcmp (y, x, sizeof (y)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += memcmp (y1, x, sizeof (y1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += memcmp (y2, x, sizeof (y2)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += memcmp (&c, x, sizeof (&c)); // { dg-warning "call is the same expression as the destination; did you mean to remove the addressof" } + z += memcmp (w, x, sizeof w); // { dg-warning "call is the same expression as the destination; did you mean to dereference it" } + + z += memcmp (x, y, sizeof (y)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += memcmp (x, y1, sizeof (y1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += memcmp (x, y2, sizeof (y2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += memcmp (x, &c, sizeof (&c)); // { dg-warning "call is the same expression as the source; did you mean to remove the addressof" } + z += memcmp (x, w, sizeof w); // { dg-warning "call is the same expression as the source; did you mean to dereference it" } + + // These are correct, no warning. + memset (y, 0, sizeof (*y)); + memset (y1, 0, sizeof (*y2)); + memset (buf1, 0, sizeof buf1); + memset (buf3, 0, sizeof (buf3)); + memset (&buf3[0], 0, sizeof (buf3)); + memset (&buf4[0], 0, sizeof (buf4)); + memset (w, 0, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memset ((void *) y, 0, sizeof (y)); + memset ((char *) y1, 0, sizeof (y2)); + memset (y, 0, sizeof (y) + 0); + memset (y1, 0, 0 + sizeof (y2)); + memset ((void *) &c, 0, sizeof (&c)); + memset ((signed char *) &c, 0, sizeof (&c)); + memset (&c, 0, sizeof (&c) + 0); + memset (&c, 0, 0 + sizeof (&c)); + + // These are correct, no warning. + memcpy (y, x, sizeof (*y)); + memcpy (y1, x, sizeof (*y2)); + memcpy (buf1, x, sizeof buf1); + memcpy (buf3, x, sizeof (buf3)); + memcpy (&buf3[0], x, sizeof (buf3)); + memcpy (&buf4[0], x, sizeof (buf4)); + memcpy (&y3, y, sizeof (y3)); + memcpy ((char *) &y3, y, sizeof (y3)); + memcpy (w, x, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memcpy ((void *) y, x, sizeof (y)); + memcpy ((char *) y1, x, sizeof (y2)); + memcpy (y, x, sizeof (y) + 0); + memcpy (y1, x, 0 + sizeof (y2)); + memcpy ((void *) &c, x, sizeof (&c)); + memcpy ((signed char *) &c, x, sizeof (&c)); + memcpy (&c, x, sizeof (&c) + 0); + memcpy (&c, x, 0 + sizeof (&c)); + + // These are correct, no warning. + memcpy (x, y, sizeof (*y)); + memcpy (x, y1, sizeof (*y2)); + memcpy (x, buf1, sizeof buf1); + memcpy (x, buf3, sizeof (buf3)); + memcpy (x, &buf3[0], sizeof (buf3)); + memcpy (x, &buf4[0], sizeof (buf4)); + memcpy (y, &y3, sizeof (y3)); + memcpy (y, (char *) &y3, sizeof (y3)); + memcpy (x, w, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memcpy (x, (void *) y, sizeof (y)); + memcpy (x, (char *) y1, sizeof (y2)); + memcpy (x, y, sizeof (y) + 0); + memcpy (x, y1, 0 + sizeof (y2)); + memcpy (x, (void *) &c, sizeof (&c)); + memcpy (x, (signed char *) &c, sizeof (&c)); + memcpy (x, &c, sizeof (&c) + 0); + memcpy (x, &c, 0 + sizeof (&c)); + + // These are correct, no warning. + memmove (y, x, sizeof (*y)); + memmove (y1, x, sizeof (*y2)); + memmove (buf1, x, sizeof buf1); + memmove (buf3, x, sizeof (buf3)); + memmove (&buf3[0], x, sizeof (buf3)); + memmove (&buf4[0], x, sizeof (buf4)); + memmove (&y3, y, sizeof (y3)); + memmove ((char *) &y3, y, sizeof (y3)); + memmove (w, x, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memmove ((void *) y, x, sizeof (y)); + memmove ((char *) y1, x, sizeof (y2)); + memmove (y, x, sizeof (y) + 0); + memmove (y1, x, 0 + sizeof (y2)); + memmove ((void *) &c, x, sizeof (&c)); + memmove ((signed char *) &c, x, sizeof (&c)); + memmove (&c, x, sizeof (&c) + 0); + memmove (&c, x, 0 + sizeof (&c)); + + // These are correct, no warning. + memmove (x, y, sizeof (*y)); + memmove (x, y1, sizeof (*y2)); + memmove (x, buf1, sizeof buf1); + memmove (x, buf3, sizeof (buf3)); + memmove (x, &buf3[0], sizeof (buf3)); + memmove (x, &buf4[0], sizeof (buf4)); + memmove (y, &y3, sizeof (y3)); + memmove (y, (char *) &y3, sizeof (y3)); + memmove (x, w, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + memmove (x, (void *) y, sizeof (y)); + memmove (x, (char *) y1, sizeof (y2)); + memmove (x, y, sizeof (y) + 0); + memmove (x, y1, 0 + sizeof (y2)); + memmove (x, (void *) &c, sizeof (&c)); + memmove (x, (signed char *) &c, sizeof (&c)); + memmove (x, &c, sizeof (&c) + 0); + memmove (x, &c, 0 + sizeof (&c)); + + // These are correct, no warning. + z += memcmp (y, x, sizeof (*y)); + z += memcmp (y1, x, sizeof (*y2)); + z += memcmp (buf1, x, sizeof buf1); + z += memcmp (buf3, x, sizeof (buf3)); + z += memcmp (&buf3[0], x, sizeof (buf3)); + z += memcmp (&buf4[0], x, sizeof (buf4)); + z += memcmp (&y3, y, sizeof (y3)); + z += memcmp ((char *) &y3, y, sizeof (y3)); + z += memcmp (w, x, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + z += memcmp ((void *) y, x, sizeof (y)); + z += memcmp ((char *) y1, x, sizeof (y2)); + z += memcmp (y, x, sizeof (y) + 0); + z += memcmp (y1, x, 0 + sizeof (y2)); + z += memcmp ((void *) &c, x, sizeof (&c)); + z += memcmp ((signed char *) &c, x, sizeof (&c)); + z += memcmp (&c, x, sizeof (&c) + 0); + z += memcmp (&c, x, 0 + sizeof (&c)); + + // These are correct, no warning. + z += memcmp (x, y, sizeof (*y)); + z += memcmp (x, y1, sizeof (*y2)); + z += memcmp (x, buf1, sizeof buf1); + z += memcmp (x, buf3, sizeof (buf3)); + z += memcmp (x, &buf3[0], sizeof (buf3)); + z += memcmp (x, &buf4[0], sizeof (buf4)); + z += memcmp (y, &y3, sizeof (y3)); + z += memcmp (y, (char *) &y3, sizeof (y3)); + z += memcmp (x, w, sizeof (X)); + // These are probably broken, but obfuscated, no warning. + z += memcmp (x, (void *) y, sizeof (y)); + z += memcmp (x, (char *) y1, sizeof (y2)); + z += memcmp (x, y, sizeof (y) + 0); + z += memcmp (x, y1, 0 + sizeof (y2)); + z += memcmp (x, (void *) &c, sizeof (&c)); + z += memcmp (x, (signed char *) &c, sizeof (&c)); + z += memcmp (x, &c, sizeof (&c) + 0); + z += memcmp (x, &c, 0 + sizeof (&c)); + + return z; +} + +template <int N> +int +f4 (char *x, char **y, int z) +{ + const char *s1 = "foobarbaz"; + const char *s2 = "abcde12345678"; + strncpy (x, s1, sizeof (s1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + strncat (x, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + y[0] = strndup (s1, sizeof (s1)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += strncmp (s1, s2, sizeof (s1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += strncmp (s1, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + z += strncasecmp (s1, s2, sizeof (s1)); // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length" } + z += strncasecmp (s1, s2, sizeof (s2)); // { dg-warning "call is the same expression as the source; did you mean to provide an explicit length" } + + // These are correct, no warning. + const char s3[] = "foobarbaz"; + const char s4[] = "abcde12345678"; + strncpy (x, s3, sizeof (s3)); + strncat (x, s4, sizeof (s4)); + y[1] = strndup (s3, sizeof (s3)); + z += strncmp (s3, s4, sizeof (s3)); + z += strncmp (s3, s4, sizeof (s4)); + z += strncasecmp (s3, s4, sizeof (s3)); + z += strncasecmp (s3, s4, sizeof (s4)); + + return z; +} + +int +f (void *x, char *y, int z, X w, char **u) +{ + z += f1<0> (x, z); + z += f2<0> (x, z); + z += f3<0> (x, y, z, w); + z += f4<0> (y, u, z); + return z; +} + +// { dg-prune-output "\[\n\r\]*will always overflow\[\n\r\]*" } diff --git a/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C b/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C index 511f091f2cf..84a1d380bb7 100644 --- a/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C +++ b/gcc/testsuite/g++.dg/warn/Wnull-conversion-1.C @@ -9,7 +9,7 @@ void func2() { int* t = false; // { dg-warning "converting 'false' to pointer" } int* p; p = false; // { dg-warning "converting 'false' to pointer" } - int* r = sizeof(char) / 2; + int* r = sizeof(char) / 2; // { dg-error "invalid conversion from" "" { target c++11 } } func1(false); // { dg-warning "converting 'false' to pointer" } int i = NULL; // { dg-warning "converting to non-pointer" } } diff --git a/gcc/testsuite/g++.dg/warn/Wsign-compare-5.C b/gcc/testsuite/g++.dg/warn/Wsign-compare-5.C new file mode 100644 index 00000000000..641c49972ee --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wsign-compare-5.C @@ -0,0 +1,20 @@ +// Test that -Wsign-compare doesn't warn about +// equality/non-equality comparisons with sizeof. +// { dg-do compile } +// { dg-options "-Wsign-compare" } + +int +foo (int x) +{ + if (x != sizeof (sizeof (x))) // { dg-bogus "comparison between signed and unsigned integer expressions" } + return 1; + return 0; +} + +int +bar (int x) +{ + if (x == sizeof (sizeof (x)) + 1) // { dg-bogus "comparison between signed and unsigned integer expressions" } + return 1; + return 0; +} diff --git a/gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C b/gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C new file mode 100644 index 00000000000..e2ba8769b9a --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wsizeof-pointer-memaccess-1.C @@ -0,0 +1,13 @@ +// Test -Wsizeof-pointer-memaccess warnings. +// { dg-do compile } +// { dg-options "-Wall" } + +typedef __SIZE_TYPE__ size_t; +extern "C" void *memset (void *, int, size_t); + +int +foo (int x, char b[10]) +{ + long a[memset (b, 0, sizeof (b)) ? x + 10 : x]; // { dg-warning "call is the same expression as the destination; did you mean to provide an explicit length?" } + return a[0]; +} diff --git a/gcc/testsuite/gcc.dg/attr-alias-3.c b/gcc/testsuite/gcc.dg/attr-alias-3.c index 02637b2313e..6ff1b475ad9 100644 --- a/gcc/testsuite/gcc.dg/attr-alias-3.c +++ b/gcc/testsuite/gcc.dg/attr-alias-3.c @@ -1,5 +1,5 @@ // { dg-do link } -// { dg-xfail-if "" { "powerpc-ibm-aix*" } { "*" } { "" } } +// { dg-skip-if "" { "powerpc-ibm-aix*" } { "*" } { "" } } // { dg-require-alias "" } // { dg-options "-O2 -fno-common" } diff --git a/gcc/testsuite/gcc.dg/attr-alias-5.c b/gcc/testsuite/gcc.dg/attr-alias-5.c index d22c286fc65..56d9b302c66 100644 --- a/gcc/testsuite/gcc.dg/attr-alias-5.c +++ b/gcc/testsuite/gcc.dg/attr-alias-5.c @@ -4,6 +4,7 @@ /* { dg-options "-std=gnu99" } */ /* { dg-require-alias "" } */ /* { dg-require-ascii-locale "" } */ +/* { dg-skip-if "" { powerpc*-*-aix* } { "*" } { "" } } */ void f0 (void) __attribute__((alias("\xa1"))); /* { dg-error "undefined symbol '\\\\241'" } */ void f1 (void) __attribute__((alias("\u00e9"))); /* { dg-error "undefined symbol '\\\\U000000e9'" } */ diff --git a/gcc/testsuite/gcc.dg/builtins-85.c b/gcc/testsuite/gcc.dg/builtins-85.c new file mode 100644 index 00000000000..0993fbc19f4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-85.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef __SIZE_TYPE__ size_t; +extern void __chk_fail (void); +extern int snprintf (char *, size_t, const char *, ...); +extern inline __attribute__((gnu_inline, always_inline)) int snprintf (char *a, size_t b, const char *fmt, ...) +{ + if (__builtin_object_size (a, 0) != -1UL && __builtin_object_size (a, 0) < b) + __chk_fail (); + return __builtin_snprintf (a, b, fmt, __builtin_va_arg_pack ()); +} +extern int snprintf (char *, size_t, const char *, ...) __asm ("mysnprintf"); + +char buf[10]; + +int +main (void) +{ + snprintf (buf, 10, "%d%d\n", 10, 10); + return 0; +} + +/* { dg-final { scan-assembler "mysnprintf" } } */ +/* { dg-final { scan-assembler-not "__chk_fail" } } */ diff --git a/gcc/testsuite/gcc.dg/dump-ada-spec-1.c b/gcc/testsuite/gcc.dg/dump-ada-spec-1.c new file mode 100644 index 00000000000..eb249e79854 --- /dev/null +++ b/gcc/testsuite/gcc.dg/dump-ada-spec-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-ada-spec" } */ + +struct S +{ + int i; +}; + +/* { dg-final { scan-ada-spec "type S is record" } } */ +/* { dg-final { cleanup-ada-spec } } */ diff --git a/gcc/testsuite/gcc.dg/guality/pr54519-1.c b/gcc/testsuite/gcc.dg/guality/pr54519-1.c new file mode 100644 index 00000000000..98afd45c18f --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr54519-1.c @@ -0,0 +1,48 @@ +/* PR debug/54519 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +__attribute__((noinline, noclone)) void +fn1 (int x) +{ + __asm volatile ("" : "+r" (x) : : "memory"); +} + +static int +fn2 (int x, int y, int z) +{ + int a = 8; + if (x != z) + { + fn1 (x); + fn1 (x); /* { dg-final { gdb-test 20 "x" "36" } } */ + if (x == 36) /* { dg-final { gdb-test 20 "y" "25" } } */ + fn1 (x); /* { dg-final { gdb-test 20 "z" "6" } } */ + fn1 (x); /* { dg-final { gdb-test 23 "x" "98" } } */ + if (x == 98) /* { dg-final { gdb-test 23 "y" "117" } } */ + fn1 (x); /* { dg-final { gdb-test 23 "z" "8" } } */ + fn1 (x); + fn1 (x + a); + } + return y; +} + +__attribute__((noinline, noclone)) int +fn3 (int x, int y) +{ + return fn2 (x, y, 6); +} + +__attribute__((noinline, noclone)) int +fn4 (int x, int y) +{ + return fn2 (x, y, 8); +} + +int +main () +{ + fn3 (36, 25); + fn4 (98, 117); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/guality/pr54519-2.c b/gcc/testsuite/gcc.dg/guality/pr54519-2.c new file mode 100644 index 00000000000..4ee3c9e2f84 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr54519-2.c @@ -0,0 +1,45 @@ +/* PR debug/54519 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +__attribute__((noinline, noclone)) void +fn1 (int x) +{ + __asm volatile ("" : "+r" (x) : : "memory"); +} + +static int +fn2 (int x, int y) +{ + if (y) + { + fn1 (x); /* { dg-final { gdb-test 17 "x" "6" } } */ + fn1 (x); /* { dg-final { gdb-test 17 "y" "25" } } */ + fn1 (x); + fn1 (x); + y = -2 + x; + y = y * y * y + y; + fn1 (x + y); /* { dg-final { gdb-test 22 "y" "68" } } */ + } + return x; +} + +__attribute__((noinline, noclone)) int +fn3 (int x, int y) +{ + return fn2 (x, y) + y; +} + +__attribute__((noinline, noclone)) int +fn4 (int x, int y) +{ + return fn2 (x, y) + y; +} + +int +main () +{ + fn3 (6, 25); + fn4 (4, 117); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/guality/pr54519-3.c b/gcc/testsuite/gcc.dg/guality/pr54519-3.c new file mode 100644 index 00000000000..aa8369e15b8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr54519-3.c @@ -0,0 +1,42 @@ +/* PR debug/54519 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +__attribute__((noinline, noclone)) void +fn1 (int x) +{ + __asm volatile ("" : "+r" (x) : : "memory"); +} + +static int +fn2 (int x, int y, int z) +{ + int a = 8; + if (x != z) + { + fn1 (x); + fn1 (x); /* { dg-final { gdb-test 20 "x" "36" } } */ + if (x == 36) /* { dg-final { gdb-test 20 "y" "25" } } */ + fn1 (x); /* { dg-final { gdb-test 20 "z" "6" } } */ + fn1 (x); /* { dg-final { gdb-test 23 "x" "98" } } */ + if (x == 98) /* { dg-final { gdb-test 23 "y" "117" } } */ + fn1 (x); /* { dg-final { gdb-test 23 "z" "8" } } */ + fn1 (x); + fn1 (x + a); + } + return y; +} + +int (*p) (int, int, int) = fn2; + +int +main () +{ + __asm volatile ("" : : : "memory"); + int (*q) (int, int, int) = p; + __asm volatile ("" : : : "memory"); + q (36, 25, 6); + q (98, 117, 8); + q (0, 0, 0); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/guality/pr54519-4.c b/gcc/testsuite/gcc.dg/guality/pr54519-4.c new file mode 100644 index 00000000000..d2765d148c2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr54519-4.c @@ -0,0 +1,39 @@ +/* PR debug/54519 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +__attribute__((noinline, noclone)) void +fn1 (int x) +{ + __asm volatile ("" : "+r" (x) : : "memory"); +} + +static int +fn2 (int x, int y) +{ + if (y) + { + fn1 (x); /* { dg-final { gdb-test 17 "x" "6" } } */ + fn1 (x); /* { dg-final { gdb-test 17 "y" "25" } } */ + fn1 (x); + fn1 (x); + y = -2 + x; + y = y * y * y + y; + fn1 (x + y); /* { dg-final { gdb-test 22 "y" "68" } } */ + } + return x; +} + +int (*p) (int, int) = fn2; + +int +main () +{ + __asm volatile ("" : : : "memory"); + int (*q) (int, int) = p; + __asm volatile ("" : : : "memory"); + q (6, 25); + q (4, 117); + q (0, 0); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/guality/pr54519-5.c b/gcc/testsuite/gcc.dg/guality/pr54519-5.c new file mode 100644 index 00000000000..c64527a45d9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr54519-5.c @@ -0,0 +1,45 @@ +/* PR debug/54519 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +__attribute__((noinline, noclone)) void +fn1 (int x) +{ + __asm volatile ("" : "+r" (x) : : "memory"); +} + +static int +fn2 (int x, int y) +{ + if (y) + { + fn1 (x); /* { dg-final { gdb-test 17 "x" "6" } } */ + fn1 (x); /* { dg-final { gdb-test 17 "y" "25" } } */ + fn1 (x); + fn1 (x); + y = -2 + x; + y = y * y * y + y; + fn1 (x + y); /* { dg-final { gdb-test 22 "y" "68" } } */ + } + return x; +} + +__attribute__((noinline, noclone)) int +fn3 (int x, int y) +{ + return fn2 (x, y); +} + +__attribute__((noinline, noclone)) int +fn4 (int x, int y) +{ + return fn2 (x, y); +} + +int +main () +{ + fn3 (6, 25); + fn4 (4, 117); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/guality/pr54519-6.c b/gcc/testsuite/gcc.dg/guality/pr54519-6.c new file mode 100644 index 00000000000..836ab1f6601 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr54519-6.c @@ -0,0 +1,27 @@ +/* PR debug/54519 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +#include "../nop.h" + +static inline void +f1 (int x, int y) +{ + asm volatile (NOP); /* { dg-final { gdb-test 11 "x" "2" } } */ + asm volatile (NOP); /* { dg-final { gdb-test 11 "y" "0" } } */ +} + +static inline void +f2 (int z) +{ + f1 (z, 0); + f1 (z, 1); +} + +int +main () +{ + f2 (2); + f2 (3); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/lto/resolutions_0.c b/gcc/testsuite/gcc.dg/lto/resolutions_0.c new file mode 100644 index 00000000000..9e59cb0690c --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/resolutions_0.c @@ -0,0 +1,10 @@ +/* { dg-require-linker-plugin "" } */ +/* { dg-extra-ld-options "-fuse-linker-plugin -O1" } */ + +link_error() +{ +} +main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr51106-2.c b/gcc/testsuite/gcc.dg/torture/pr51106-2.c index 80328a92e7e..bab0987fff7 100644 --- a/gcc/testsuite/gcc.dg/torture/pr51106-2.c +++ b/gcc/testsuite/gcc.dg/torture/pr51106-2.c @@ -1,7 +1,7 @@ /* PR target/51106 */ /* { dg-do "compile" } */ /* { dg-skip-if "RTL error" { "*-*-*" } { "-fno-fat-lto-objects" } { "" } } */ -/* { dg-xfail-if "" { powerpc-ibm-aix* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc-ibm-aix* } { "*" } { "" } } */ int bar (int x) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c b/gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c index 27c4bfa27ce..d0225ec164e 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/attr-hotcold-2.c @@ -25,4 +25,4 @@ void f(int x, int y) the testcase around too much. */ /* { dg-final { scan-ipa-dump-times "block 5, loop depth 0, count 0, freq \[6-9\]\[0-9\]\[0-9\]\[0-9\]" 1 "profile_estimate" } } */ -/* { dg-final { cleanup-tree-dump "profile_estimate" } } */ +/* { dg-final { cleanup-ipa-dump "profile_estimate" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-21.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-21.c index 35f01aba2a6..5401dcf0414 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ldist-21.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-21.c @@ -9,3 +9,4 @@ void bar(char *p, int n) } /* { dg-final { scan-tree-dump "generated memmove" "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-30.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-30.c index 9620f224115..5fea3d3db82 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-30.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-30.c @@ -21,4 +21,4 @@ f (int s, long c) } /* { dg-final { scan-tree-dump-times " \\* " 3 "dom2" } } */ -/* { dg-final { cleanup-tree-dump "optimized" } } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp85.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp85.c new file mode 100644 index 00000000000..ad2b38d02c1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp85.c @@ -0,0 +1,40 @@ +/* PR tree-optimization/54810 */ +/* { dg-do link } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +extern void link_error (void); + +#define T(n, ntype, wtype) \ +void \ +f##n (wtype s) \ +{ \ + if ((ntype) s == 0) \ + return; \ + if (s == 0) \ + link_error (); \ +} + +T(1, unsigned char, unsigned char) +T(2, unsigned char, unsigned short) +T(3, unsigned char, unsigned int) +T(4, unsigned char, unsigned long int) +T(5, unsigned char, unsigned long long int) +T(6, unsigned short int, unsigned short int) +T(7, unsigned short int, unsigned int) +T(8, unsigned short int, unsigned long int) +T(9, unsigned short int, unsigned long long int) +T(10, unsigned int, unsigned int) +T(11, unsigned int, unsigned long int) +T(12, unsigned int, unsigned long long int) +T(13, unsigned long int, unsigned long int) +T(14, unsigned long int, unsigned long long int) +T(15, unsigned long long int, unsigned long long int) + +int +main () +{ + return 0; +} + +/* { dg-final { scan-tree-dump-not "link_error" "vrp1"} } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/ucnid-10.c b/gcc/testsuite/gcc.dg/ucnid-10.c index 37b18d7e08d..83425d3cf15 100644 --- a/gcc/testsuite/gcc.dg/ucnid-10.c +++ b/gcc/testsuite/gcc.dg/ucnid-10.c @@ -3,7 +3,7 @@ /* { dg-do compile } */ /* { dg-options "-std=gnu99 -fextended-identifiers" } */ /* { dg-require-ascii-locale "" } */ -/* { dg-xfail-if "" { powerpc-ibm-aix* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc-ibm-aix* } { "*" } { "" } } */ #pragma pack(push) #pragma pack(pop, \u00f3) /* { dg-warning "pop, \\\\U000000f3.*push, \\\\U000000f3" } */ diff --git a/gcc/testsuite/gcc.dg/ucnid-13.c b/gcc/testsuite/gcc.dg/ucnid-13.c index 24309d125c8..0b94247ba9f 100644 --- a/gcc/testsuite/gcc.dg/ucnid-13.c +++ b/gcc/testsuite/gcc.dg/ucnid-13.c @@ -3,7 +3,7 @@ /* { dg-do compile } */ /* { dg-options "-std=gnu99 -fextended-identifiers -Wpacked" } */ /* { dg-require-ascii-locale "" } */ -/* { dg-xfail-if "" { powerpc-ibm-aix* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc-ibm-aix* } { "*" } { "" } } */ int a __attribute__((\u00c0)); /* { dg-warning "'\\\\U000000c0' attribute directive ignored" } */ diff --git a/gcc/testsuite/gcc.dg/ucnid-7.c b/gcc/testsuite/gcc.dg/ucnid-7.c index da5aa0ddb3c..3f73e35d4b1 100644 --- a/gcc/testsuite/gcc.dg/ucnid-7.c +++ b/gcc/testsuite/gcc.dg/ucnid-7.c @@ -3,7 +3,7 @@ /* { dg-do compile } */ /* { dg-options "-std=c99 -fextended-identifiers" } */ /* { dg-require-ascii-locale "" } */ -/* { dg-xfail-if "" { "powerpc-ibm-aix*" } { "*" } { "" } } */ +/* { dg-skip-if "" { "powerpc-ibm-aix*" } { "*" } { "" } } */ void *p = &\u00e9; /* { dg-error "'\\\\U000000e9' undeclared" } */ void *q = &\u1e00; /* { dg-error "'\\\\U00001e00' undeclared" } */ diff --git a/gcc/testsuite/gcc.dg/ucnid-8.c b/gcc/testsuite/gcc.dg/ucnid-8.c index 0e48a7f6dd7..df1f35053d0 100644 --- a/gcc/testsuite/gcc.dg/ucnid-8.c +++ b/gcc/testsuite/gcc.dg/ucnid-8.c @@ -3,7 +3,7 @@ /* { dg-do compile } */ /* { dg-options "-std=gnu99 -fextended-identifiers -Wvla" } */ /* { dg-require-ascii-locale "" } */ -/* { dg-xfail-if "" { powerpc-ibm-aix* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc-ibm-aix* } { "*" } { "" } } */ int a __attribute__((__mode__(\u00e9))); /* { dg-error "unknown machine mode '\\\\U000000e9'" } */ struct s1 { int \u00e9 : 0; }; /* { dg-error "zero width for bit-field '\\\\U000000e9'" } */ diff --git a/gcc/testsuite/gcc.dg/vmx/3b-13.c b/gcc/testsuite/gcc.dg/vmx/3b-13.c index 146f737aebd..42c3ca4fa8a 100644 --- a/gcc/testsuite/gcc.dg/vmx/3b-13.c +++ b/gcc/testsuite/gcc.dg/vmx/3b-13.c @@ -3,7 +3,7 @@ vector signed int f(vector float a, vector signed int b) { - return vec_splat(vec_cts(vec_ctf(vec_ctu(a, 31),0),9),30); + return vec_splat(vec_cts(vec_ctf(vec_ctu(a, 31),0),9),2); } static void test() diff --git a/gcc/testsuite/gcc.target/mips/madd-9.c b/gcc/testsuite/gcc.target/mips/madd-9.c index 6d545495c03..28681a91002 100644 --- a/gcc/testsuite/gcc.target/mips/madd-9.c +++ b/gcc/testsuite/gcc.target/mips/madd-9.c @@ -1,7 +1,13 @@ /* { dg-do compile } */ -/* { dg-options "isa_rev>=1 -mgp32" } */ -/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */ +/* { dg-options "isa_rev>=1 -mgp32 -mtune=4kc" } */ +/* References to X within the loop need to have a higher frequency than + references to X outside the loop, otherwise there is no reason + to prefer multiply/accumulator registers over GPRs. */ +/* { dg-skip-if "requires register frequencies" { *-*-* } { "-O0" "-Os" } { "" } } */ /* { dg-final { scan-assembler-not "\tmul\t" } } */ +/* { dg-final { scan-assembler-not "\tmthi" } } */ +/* { dg-final { scan-assembler-not "\tmtlo" } } */ +/* { dg-final { scan-assembler "\tmult\t" } } */ /* { dg-final { scan-assembler "\tmadd\t" } } */ NOMIPS16 long long diff --git a/gcc/testsuite/gcc.target/mips/mips32-dsp-accinit-1.c b/gcc/testsuite/gcc.target/mips/mips32-dsp-accinit-1.c new file mode 100644 index 00000000000..d26f998407d --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/mips32-dsp-accinit-1.c @@ -0,0 +1,22 @@ +/* { dg-options "-mdspr2 -mgp32 -mtune=74kc" } */ +/* References to RESULT within the loop need to have a higher frequency than + references to RESULT outside the loop, otherwise there is no reason + to prefer multiply/accumulator registers over GPRs. */ +/* { dg-skip-if "requires register frequencies" { *-*-* } { "-O0" "-Os" } { "" } } */ + +/* Check that the zero-initialization of the accumulator feeding into + the madd is done by means of a mult instruction instead of mthi/mtlo. */ + +NOMIPS16 long long f (int n, int *v, int m) +{ + long long result = 0; + int i; + + for (i = 0; i < n; i++) + result = __builtin_mips_madd (result, v[i], m); + return result; +} + +/* { dg-final { scan-assembler "\tmult\t\\\$ac.,\\\$0,\\\$0" } } */ +/* { dg-final { scan-assembler-not "mthi\t" } } */ +/* { dg-final { scan-assembler-not "mtlo\t" } } */ diff --git a/gcc/testsuite/gcc.target/mips/mips32-dsp-accinit-2.c b/gcc/testsuite/gcc.target/mips/mips32-dsp-accinit-2.c new file mode 100644 index 00000000000..8d06a8039a1 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/mips32-dsp-accinit-2.c @@ -0,0 +1,22 @@ +/* { dg-options "-mdspr2 -mgp32 -mtune=4kp" } */ +/* References to RESULT within the loop need to have a higher frequency than + references to RESULT outside the loop, otherwise there is no reason + to prefer multiply/accumulator registers over GPRs. */ +/* { dg-skip-if "requires register frequencies" { *-*-* } { "-O0" "-Os" } { "" } } */ + +/* Check that the zero-initialization of the accumulator feeding into + the madd is done by means of a mult instruction instead of mthi/mtlo. */ + +NOMIPS16 long long f (int n, int *v, int m) +{ + long long result = 0; + int i; + + for (i = 0; i < n; i++) + result = __builtin_mips_madd (result, v[i], m); + return result; +} + +/* { dg-final { scan-assembler-not "mult\t\[^\n\]*\\\$0" } } */ +/* { dg-final { scan-assembler "\tmthi\t" } } */ +/* { dg-final { scan-assembler "\tmtlo\t" } } */ diff --git a/gcc/testsuite/gcc.target/sh/pr54685.c b/gcc/testsuite/gcc.target/sh/pr54685.c new file mode 100644 index 00000000000..ba08a4ade9e --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr54685.c @@ -0,0 +1,58 @@ +/* Check that a comparison 'unsigned int <= 0x7FFFFFFF' results in code + utilizing the cmp/pz instruction. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ +/* { dg-final { scan-assembler-not "not" } } */ +/* { dg-final { scan-assembler-times "cmp/pz" 7 } } */ +/* { dg-final { scan-assembler-times "shll" 1 } } */ +/* { dg-final { scan-assembler-times "movt" 4 } } */ + +int +test_00 (unsigned int a) +{ + return !(a > 0x7FFFFFFF); +} + +int +test_01 (unsigned int a) +{ + return !(a > 0x7FFFFFFF) ? -5 : 10; +} + +int +test_02 (unsigned int a) +{ + /* 1x shll, 1x movt */ + return a >= 0x80000000; +} + +int +test_03 (unsigned int a) +{ + return a >= 0x80000000 ? -5 : 10; +} + +int +test_04 (unsigned int a) +{ + return a <= 0x7FFFFFFF; +} + +int +test_05 (unsigned int a) +{ + return a <= 0x7FFFFFFF ? -5 : 10; +} + +int +test_06 (unsigned int a) +{ + return a < 0x80000000; +} + +int +test_07 (unsigned int a) +{ + return a < 0x80000000 ? -5 : 10; +} diff --git a/gcc/testsuite/gcc.target/sh/pr54760-1.c b/gcc/testsuite/gcc.target/sh/pr54760-1.c new file mode 100644 index 00000000000..9108a3fde8a --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr54760-1.c @@ -0,0 +1,20 @@ +/* Check that the __builtin_thread_pointer and __builtin_set_thread_pointer + built-in functions result in gbr store / load instructions. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ +/* { dg-final { scan-assembler-times "ldc" 1 } } */ +/* { dg-final { scan-assembler-times "stc" 1 } } */ +/* { dg-final { scan-assembler-times "gbr" 2 } } */ + +void* +test00 (void) +{ + return __builtin_thread_pointer (); +} + +void +test01 (void* p) +{ + __builtin_set_thread_pointer (p); +} diff --git a/gcc/testsuite/gcc.target/sh/pr54760-2.c b/gcc/testsuite/gcc.target/sh/pr54760-2.c new file mode 100644 index 00000000000..b8a50184785 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr54760-2.c @@ -0,0 +1,223 @@ +/* Check that thread pointer relative memory accesses are converted to + gbr displacement address modes. If we see a gbr register store + instruction something is not working properly. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ +/* { dg-final { scan-assembler-times "stc\tgbr" 0 } } */ + +/* --------------------------------------------------------------------------- + Simple GBR load. +*/ +#define func(name, type, disp)\ + int \ + name ## _tp_load (void) \ + { \ + type* tp = (type*)__builtin_thread_pointer (); \ + return tp[disp]; \ + } + +func (test00, int, 0) +func (test01, int, 5) +func (test02, int, 255) + +func (test03, short, 0) +func (test04, short, 5) +func (test05, short, 255) + +func (test06, char, 0) +func (test07, char, 5) +func (test08, char, 255) + +func (test09, unsigned int, 0) +func (test10, unsigned int, 5) +func (test11, unsigned int, 255) + +func (test12, unsigned short, 0) +func (test13, unsigned short, 5) +func (test14, unsigned short, 255) + +func (test15, unsigned char, 0) +func (test16, unsigned char, 5) +func (test17, unsigned char, 255) + +#undef func + +/* --------------------------------------------------------------------------- + Simple GBR store. +*/ +#define func(name, type, disp)\ + void \ + name ## _tp_store (int a) \ + { \ + type* tp = (type*)__builtin_thread_pointer (); \ + tp[disp] = (type)a; \ + } + +func (test00, int, 0) +func (test01, int, 5) +func (test02, int, 255) + +func (test03, short, 0) +func (test04, short, 5) +func (test05, short, 255) + +func (test06, char, 0) +func (test07, char, 5) +func (test08, char, 255) + +func (test09, unsigned int, 0) +func (test10, unsigned int, 5) +func (test11, unsigned int, 255) + +func (test12, unsigned short, 0) +func (test13, unsigned short, 5) +func (test14, unsigned short, 255) + +func (test15, unsigned char, 0) +func (test16, unsigned char, 5) +func (test17, unsigned char, 255) + +#undef func + +/* --------------------------------------------------------------------------- + Arithmetic on the result of a GBR load. +*/ +#define func(name, type, disp, op, opname)\ + int \ + name ## _tp_load_arith_ ##opname (int a) \ + { \ + type* tp = (type*)__builtin_thread_pointer (); \ + return tp[disp] op a; \ + } + +#define funcs(op, opname) \ + func (test00, int, 0, op, opname) \ + func (test01, int, 5, op, opname) \ + func (test02, int, 255, op, opname) \ + func (test03, short, 0, op, opname) \ + func (test04, short, 5, op, opname) \ + func (test05, short, 255, op, opname) \ + func (test06, char, 0, op, opname) \ + func (test07, char, 5, op, opname) \ + func (test08, char, 255, op, opname) \ + func (test09, unsigned int, 0, op, opname) \ + func (test10, unsigned int, 5, op, opname) \ + func (test11, unsigned int, 255, op, opname) \ + func (test12, unsigned short, 0, op, opname) \ + func (test13, unsigned short, 5, op, opname) \ + func (test14, unsigned short, 255, op, opname) \ + func (test15, unsigned char, 0, op, opname) \ + func (test16, unsigned char, 5, op, opname) \ + func (test17, unsigned char, 255, op, opname) \ + +funcs (+, plus) +funcs (-, minus) +funcs (*, mul) +funcs (&, and) +funcs (|, or) +funcs (^, xor) + +#undef funcs +#undef func + +/* --------------------------------------------------------------------------- + Arithmetic of the result of two GBR loads. +*/ +#define func(name, type, disp0, disp1, op, opname)\ + int \ + name ## _tp_load_load_arith_ ##opname (void) \ + { \ + type* tp = (type*)__builtin_thread_pointer (); \ + return tp[disp0] op tp[disp1]; \ + } + +#define funcs(op, opname) \ + func (test00, int, 0, 5, op, opname) \ + func (test02, int, 1, 255, op, opname) \ + func (test03, short, 0, 5, op, opname) \ + func (test05, short, 1, 255, op, opname) \ + func (test06, char, 0, 5, op, opname) \ + func (test08, char, 1, 255, op, opname) \ + func (test09, unsigned int, 0, 5, op, opname) \ + func (test11, unsigned int, 1, 255, op, opname) \ + func (test12, unsigned short, 0, 5, op, opname) \ + func (test14, unsigned short, 1, 255, op, opname) \ + func (test15, unsigned char, 0, 5, op, opname) \ + func (test17, unsigned char, 1, 255, op, opname) \ + +funcs (+, plus) +funcs (-, minus) +funcs (*, mul) +funcs (&, and) +funcs (|, or) +funcs (^, xor) + +#undef funcs +#undef func + +/* --------------------------------------------------------------------------- + GBR load GBR store copy. +*/ + +#define func(name, type, disp0, disp1)\ + void \ + name ## _tp_copy (void) \ + { \ + type* tp = (type*)__builtin_thread_pointer (); \ + tp[disp0] = tp[disp1]; \ + } + +func (test00, int, 0, 5) +func (test02, int, 1, 255) +func (test03, short, 0, 5) +func (test05, short, 1, 255) +func (test06, char, 0, 5) +func (test08, char, 1, 255) +func (test09, unsigned int, 0, 5) +func (test11, unsigned int, 1, 255) +func (test12, unsigned short, 0, 5) +func (test14, unsigned short, 1, 255) +func (test15, unsigned char, 0, 5) +func (test17, unsigned char, 1, 255) + +#undef func + +/* --------------------------------------------------------------------------- + GBR load, arithmetic, GBR store +*/ + +#define func(name, type, disp, op, opname)\ + void \ + name ## _tp_load_arith_store_ ##opname (int a) \ + { \ + type* tp = (type*)__builtin_thread_pointer (); \ + tp[disp] op a; \ + } + +#define funcs(op, opname) \ + func (test00, int, 0, op, opname) \ + func (test01, int, 5, op, opname) \ + func (test02, int, 255, op, opname) \ + func (test03, short, 0, op, opname) \ + func (test04, short, 5, op, opname) \ + func (test05, short, 255, op, opname) \ + func (test06, char, 0, op, opname) \ + func (test07, char, 5, op, opname) \ + func (test08, char, 255, op, opname) \ + func (test09, unsigned int, 0, op, opname) \ + func (test10, unsigned int, 5, op, opname) \ + func (test11, unsigned int, 255, op, opname) \ + func (test12, unsigned short, 0, op, opname) \ + func (test13, unsigned short, 5, op, opname) \ + func (test14, unsigned short, 255, op, opname) \ + func (test15, unsigned char, 0, op, opname) \ + func (test16, unsigned char, 5, op, opname) \ + func (test17, unsigned char, 255, op, opname) \ + +funcs (+=, plus) +funcs (-=, minus) +funcs (*=, mul) +funcs (&=, and) +funcs (|=, or) +funcs (^=, xor) diff --git a/gcc/testsuite/gcc.target/sh/pr54760-3.c b/gcc/testsuite/gcc.target/sh/pr54760-3.c new file mode 100644 index 00000000000..2b6f1861783 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr54760-3.c @@ -0,0 +1,69 @@ +/* Check that these thread relative memory accesses play along with + surrounding code. + These should be moved to C torture tests once there are target + independent thread_pointer built-in functions available. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ + +int +test00 (void* p, int x) +{ + int* tcb = (int*)__builtin_thread_pointer (); + int r = tcb[4]; + + __builtin_set_thread_pointer (p); + + tcb = (int*)__builtin_thread_pointer (); + return tcb[255] + r; +} + +int +test01 (void) +{ + unsigned short* tcb = (unsigned short*)__builtin_thread_pointer (); + return tcb[500]; +} + +void +test02 (int* x, int a, int b) +{ + int* tcb = (int*)__builtin_thread_pointer (); + tcb[50] = a; + + __builtin_set_thread_pointer (x); + + tcb = (int*)__builtin_thread_pointer (); + tcb[40] = b; +} + +int +test03 (const int* x, int c) +{ + volatile int* tcb = (volatile int*)__builtin_thread_pointer (); + + int s = 0; + int i; + for (i = 0; i < c; ++i) + s ^= x[i] + tcb[40]; + + return s; +} + +int +test04 (const int* x, int c, int** xx, int d) +{ + int s = 0; + int i; + for (i = 0; i < c; ++i) + { + volatile int* tcb = (volatile int*)__builtin_thread_pointer (); + tcb[20] = s; + + __builtin_set_thread_pointer (xx[i]); + + tcb = (volatile int*)__builtin_thread_pointer (); + s ^= x[i] + tcb[40] + d; + } + return s; +} diff --git a/gcc/testsuite/gfortran.dg/generic_25.f90 b/gcc/testsuite/gfortran.dg/generic_25.f90 new file mode 100644 index 00000000000..39b7e23eb0f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/generic_25.f90 @@ -0,0 +1,30 @@ +! { dg-do run } +! +! PR 45521: [F08] GENERIC resolution with ALLOCATABLE/POINTER and PROCEDURE +! +! Contributed by <wangmianzhi1@linuxmail.org> + + interface test + procedure testAlloc + procedure testPtr + end interface + + integer, allocatable :: a1 + integer, pointer :: a2 + + if (.not.test(a1)) call abort() + if (test(a2)) call abort() + +contains + + logical function testAlloc(obj) + integer, allocatable :: obj + testAlloc = .true. + end function + + logical function testPtr(obj) + integer, pointer :: obj + testPtr = .false. + end function + +end diff --git a/gcc/testsuite/gfortran.dg/generic_26.f90 b/gcc/testsuite/gfortran.dg/generic_26.f90 new file mode 100644 index 00000000000..a1deef19f99 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/generic_26.f90 @@ -0,0 +1,29 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! +! PR 45521: [F08] GENERIC resolution with ALLOCATABLE/POINTER and PROCEDURE +! +! Contributed by <wangmianzhi1@linuxmail.org> + +module a + + interface test + procedure testAlloc + procedure testPtr ! { dg-error "Ambiguous interfaces" } + end interface + +contains + + logical function testAlloc(obj) + integer, allocatable :: obj + testAlloc = .true. + end function + + logical function testPtr(obj) + integer, pointer :: obj + testPtr = .false. + end function + +end + +! { dg-final { cleanup-modules "a" } } diff --git a/gcc/testsuite/gfortran.dg/generic_27.f90 b/gcc/testsuite/gfortran.dg/generic_27.f90 new file mode 100644 index 00000000000..f4f4f5ab9c3 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/generic_27.f90 @@ -0,0 +1,34 @@ +! { dg-do run } +! +! PR 45521: [F08] GENERIC resolution with ALLOCATABLE/POINTER and PROCEDURE +! +! Contributed by Janus Weil <janus@gcc.gnu.org> + +module m + implicit none + interface testIF + module procedure test1 + module procedure test2 + end interface +contains + real function test1 (obj) + real :: obj + test1 = obj + end function + real function test2 (pr) + procedure(real) :: pr + test2 = pr(0.) + end function +end module + +program test + use m + implicit none + intrinsic :: cos + + if (testIF(2.0)/=2.0) call abort() + if (testIF(cos)/=1.0) call abort() + +end program + +! { dg-final { cleanup-modules "m" } } diff --git a/gcc/testsuite/gfortran.dg/typebound_operator_17.f90 b/gcc/testsuite/gfortran.dg/typebound_operator_17.f90 new file mode 100644 index 00000000000..4e58a7fa27a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/typebound_operator_17.f90 @@ -0,0 +1,43 @@ +! { dg-do compile } +! +! PR 54832: [4.8 Regression] [OOP] Type-bound operator not picked up with RESULT variable +! +! Contributed by Damian Rouson <rouson@sandia.gov> + + type, abstract :: integrand + contains + procedure(t_interface), deferred :: t + procedure(assign_interface), deferred :: assign + procedure(times_interface), deferred :: times + generic :: operator(*) => times + generic :: assignment(=) => assign + end type + + abstract interface + function t_interface(this) result(dState_dt) + import :: integrand + class(integrand) ,intent(in) :: this + class(integrand) ,allocatable :: dState_dt + end function + function times_interface(lhs,rhs) + import :: integrand + class(integrand) ,intent(in) :: lhs + class(integrand) ,allocatable :: times_interface + real, intent(in) :: rhs + end function + subroutine assign_interface(lhs,rhs) + import :: integrand + class(integrand) ,intent(in) :: rhs + class(integrand) ,intent(inout) :: lhs + end subroutine + end interface + +contains + + subroutine integrate(model,dt) + class(integrand) :: model + real dt + model = model%t()*dt + end subroutine + +end diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index 2cc49f7e6b7..b3f8d3bb185 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -503,6 +503,19 @@ proc cleanup-stack-usage { } { } } +# Remove an Ada spec file for the current test. +proc cleanup-ada-spec { } { + set testcase [testname-for-summary] + remove-build-file "[get_ada_spec_filename $testcase]" + + # Clean up files for additional source files. + if [info exists additional_sources] { + foreach srcfile $additional_sources { + remove-build-file "[get_ada_spec_filename $srcfile]" + } + } +} + # Remove all dump files with the provided suffix. proc cleanup-dump { suffix } { set testcase [testname-for-summary] diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp index c513857cd8d..598948e8147 100644 --- a/gcc/testsuite/lib/scanasm.exp +++ b/gcc/testsuite/lib/scanasm.exp @@ -184,6 +184,38 @@ proc scan-stack-usage-not { args } { dg-scan "scan-file-not" 0 $testcase $output_file $args } +# Return the filename of the Ada spec corresponding to the argument. + +proc get_ada_spec_filename { testcase } { + # The name might include a list of options; extract the file name. + set filename [lindex $testcase 0] + set tailname [file tail $filename] + set extension [string trimleft [file extension $tailname] {.}] + set rootname [regsub -all {\-} [file rootname $tailname] {_}] + + return [string tolower "${rootname}_${extension}.ads"] +} + +# Look for a pattern in the .ads file produced by the compiler. See +# dg-scan for details. + +proc scan-ada-spec { args } { + set testcase [testname-for-summary] + set output_file "[get_ada_spec_filename $testcase]" + + dg-scan "scan-file" 1 $testcase $output_file $args +} + +# Check that a pattern is not present in the .ads file produced by the +# compiler. See dg-scan for details. + +proc scan-ada-spec-not { args } { + set testcase [testname-for-summary] + set output_file "[get_ada_spec_filename $testcase]" + + dg-scan "scan-file-not" 0 $testcase $output_file $args +} + # Call pass if pattern is present given number of times, otherwise fail. proc scan-assembler-times { args } { if { [llength $args] < 2 } { diff --git a/gcc/toplev.c b/gcc/toplev.c index 583fa15acd3..5aa9a4456e4 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1839,6 +1839,9 @@ finalize (bool no_backend) if (mem_report) dump_memory_report (true); + if (profile_report) + dump_profile_report (); + /* Language-specific end of compilation actions. */ lang_hooks.finish (); } diff --git a/gcc/toplev.h b/gcc/toplev.h index 16699d560d6..b47edff9028 100644 --- a/gcc/toplev.h +++ b/gcc/toplev.h @@ -49,6 +49,7 @@ extern void emit_debug_global_declarations (tree *, int); extern void write_global_declarations (void); extern void dump_memory_report (bool); +extern void dump_profile_report (void); extern void target_reinit (void); diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index a585c0b88dc..2c8071e8c99 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -2374,6 +2374,31 @@ copy_debug_stmt (gimple stmt, copy_body_data *id) gimple_debug_source_bind_set_var (stmt, t); walk_tree (gimple_debug_source_bind_get_value_ptr (stmt), remap_gimple_op_r, &wi, NULL); + /* When inlining and source bind refers to one of the optimized + away parameters, change the source bind into normal debug bind + referring to the corresponding DEBUG_EXPR_DECL that should have + been bound before the call stmt. */ + t = gimple_debug_source_bind_get_value (stmt); + if (t != NULL_TREE + && TREE_CODE (t) == PARM_DECL + && id->gimple_call) + { + VEC(tree, gc) **debug_args = decl_debug_args_lookup (id->src_fn); + unsigned int i; + if (debug_args != NULL) + { + for (i = 0; i < VEC_length (tree, *debug_args); i += 2) + if (VEC_index (tree, *debug_args, i) == DECL_ORIGIN (t) + && TREE_CODE (VEC_index (tree, *debug_args, i + 1)) + == DEBUG_EXPR_DECL) + { + t = VEC_index (tree, *debug_args, i + 1); + stmt->gsbase.subcode = GIMPLE_DEBUG_BIND; + gimple_debug_bind_set_value (stmt, t); + break; + } + } + } } processing_debug_stmt = 0; @@ -3814,6 +3839,12 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) goto egress; if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) + /* For extern inline functions that get redefined we always + silently ignored always_inline flag. Better behaviour would + be to be able to keep both bodies and use extern inline body + for inlining, but we can't do that because frontends overwrite + the body. */ + && !cg_edge->callee->local.redefined_extern_inline /* Avoid warnings during early inline pass. */ && cgraph_global_info_ready /* PR 20090218-1_0.c. Body can be provided by another module. */ @@ -3921,7 +3952,29 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) initialize_inlined_parameters (id, stmt, fn, bb); if (DECL_INITIAL (fn)) - prepend_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id)); + { + tree *var; + + prepend_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id)); + gcc_checking_assert (BLOCK_SUBBLOCKS (id->block) + && (BLOCK_CHAIN (BLOCK_SUBBLOCKS (id->block)) + == NULL_TREE)); + /* Move vars for PARM_DECLs from DECL_INITIAL block to id->block, + otherwise for DWARF DW_TAG_formal_parameter will not be children of + DW_TAG_inlined_subroutine, but of a DW_TAG_lexical_block + under it. The parameters can be then evaluated in the debugger, + but don't show in backtraces. */ + for (var = &BLOCK_VARS (BLOCK_SUBBLOCKS (id->block)); *var; ) + if (TREE_CODE (DECL_ORIGIN (*var)) == PARM_DECL) + { + tree v = *var; + *var = TREE_CHAIN (v); + TREE_CHAIN (v) = BLOCK_VARS (id->block); + BLOCK_VARS (id->block) = v; + } + else + var = &TREE_CHAIN (*var); + } /* Return statements in the function body will be replaced by jumps to the RET_LABEL. */ diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index 7bf89d19fdb..b63dc7e8170 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -621,6 +621,11 @@ clear_unused_block_pointer_1 (tree *tp, int *, void *) if (EXPR_P (*tp) && TREE_BLOCK (*tp) && !TREE_USED (TREE_BLOCK (*tp))) TREE_SET_BLOCK (*tp, NULL); + if (TREE_CODE (*tp) == VAR_DECL && DECL_DEBUG_EXPR_IS_FROM (*tp)) + { + tree debug_expr = DECL_DEBUG_EXPR (*tp); + walk_tree (&debug_expr, clear_unused_block_pointer_1, NULL, NULL); + } return NULL_TREE; } diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 8dbbed236c7..fe9186cefa9 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -430,6 +430,7 @@ typedef struct bb_bitmap_sets /* Basic block list in postorder. */ static int *postorder; +static int postorder_num; /* This structure is used to keep track of statistics on what optimization PRE was able to perform. */ @@ -2456,7 +2457,7 @@ compute_antic (void) has_abnormal_preds = sbitmap_alloc (last_basic_block); sbitmap_zero (has_abnormal_preds); - FOR_EACH_BB (block) + FOR_ALL_BB (block) { edge_iterator ei; edge e; @@ -2480,9 +2481,7 @@ compute_antic (void) } /* At the exit block we anticipate nothing. */ - ANTIC_IN (EXIT_BLOCK_PTR) = bitmap_set_new (); BB_VISITED (EXIT_BLOCK_PTR) = 1; - PA_IN (EXIT_BLOCK_PTR) = bitmap_set_new (); changed_blocks = sbitmap_alloc (last_basic_block + 1); sbitmap_ones (changed_blocks); @@ -2496,7 +2495,7 @@ compute_antic (void) for PA ANTIC computation. */ num_iterations++; changed = false; - for (i = n_basic_blocks - NUM_FIXED_BLOCKS - 1; i >= 0; i--) + for (i = postorder_num - 1; i >= 0; i--) { if (TEST_BIT (changed_blocks, postorder[i])) { @@ -2525,7 +2524,7 @@ compute_antic (void) fprintf (dump_file, "Starting iteration %d\n", num_iterations); num_iterations++; changed = false; - for (i = n_basic_blocks - NUM_FIXED_BLOCKS - 1 ; i >= 0; i--) + for (i = postorder_num - 1 ; i >= 0; i--) { if (TEST_BIT (changed_blocks, postorder[i])) { @@ -3850,11 +3849,7 @@ compute_avail (void) || code == VEC_COND_EXPR) continue; - vn_nary_op_lookup_pieces (gimple_num_ops (stmt) - 1, - code, - gimple_expr_type (stmt), - gimple_assign_rhs1_ptr (stmt), - &nary); + vn_nary_op_lookup_stmt (stmt, &nary); if (!nary) continue; @@ -4593,78 +4588,6 @@ remove_dead_inserted_code (void) BITMAP_FREE (worklist); } -/* Compute a reverse post-order in *POST_ORDER. If INCLUDE_ENTRY_EXIT is - true, then then ENTRY_BLOCK and EXIT_BLOCK are included. Returns - the number of visited blocks. */ - -static int -my_rev_post_order_compute (int *post_order, bool include_entry_exit) -{ - edge_iterator *stack; - int sp; - int post_order_num = 0; - sbitmap visited; - - if (include_entry_exit) - post_order[post_order_num++] = EXIT_BLOCK; - - /* Allocate stack for back-tracking up CFG. */ - stack = XNEWVEC (edge_iterator, n_basic_blocks + 1); - sp = 0; - - /* Allocate bitmap to track nodes that have been visited. */ - visited = sbitmap_alloc (last_basic_block); - - /* None of the nodes in the CFG have been visited yet. */ - sbitmap_zero (visited); - - /* Push the last edge on to the stack. */ - stack[sp++] = ei_start (EXIT_BLOCK_PTR->preds); - - while (sp) - { - edge_iterator ei; - basic_block src; - basic_block dest; - - /* Look at the edge on the top of the stack. */ - ei = stack[sp - 1]; - src = ei_edge (ei)->src; - dest = ei_edge (ei)->dest; - - /* Check if the edge source has been visited yet. */ - if (src != ENTRY_BLOCK_PTR && ! TEST_BIT (visited, src->index)) - { - /* Mark that we have visited the destination. */ - SET_BIT (visited, src->index); - - if (EDGE_COUNT (src->preds) > 0) - /* Since the SRC node has been visited for the first - time, check its predecessors. */ - stack[sp++] = ei_start (src->preds); - else - post_order[post_order_num++] = src->index; - } - else - { - if (ei_one_before_end_p (ei) && dest != EXIT_BLOCK_PTR) - post_order[post_order_num++] = dest->index; - - if (!ei_one_before_end_p (ei)) - ei_next (&stack[sp - 1]); - else - sp--; - } - } - - if (include_entry_exit) - post_order[post_order_num++] = ENTRY_BLOCK; - - free (stack); - sbitmap_free (visited); - return post_order_num; -} - /* Initialize data structures used by PRE. */ @@ -4686,9 +4609,8 @@ init_pre (void) connect_infinite_loops_to_exit (); memset (&pre_stats, 0, sizeof (pre_stats)); - - postorder = XNEWVEC (int, n_basic_blocks - NUM_FIXED_BLOCKS); - my_rev_post_order_compute (postorder, false); + postorder = XNEWVEC (int, n_basic_blocks); + postorder_num = inverted_post_order_compute (postorder); alloc_aux_for_blocks (sizeof (struct bb_bitmap_sets)); diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 832328d328a..2391632364d 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2194,6 +2194,9 @@ vn_nary_length_from_stmt (gimple stmt) case VIEW_CONVERT_EXPR: return 1; + case BIT_FIELD_REF: + return 3; + case CONSTRUCTOR: return CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt)); @@ -2220,6 +2223,13 @@ init_vn_nary_op_from_stmt (vn_nary_op_t vno, gimple stmt) vno->op[0] = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0); break; + case BIT_FIELD_REF: + vno->length = 3; + vno->op[0] = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0); + vno->op[1] = TREE_OPERAND (gimple_assign_rhs1 (stmt), 1); + vno->op[2] = TREE_OPERAND (gimple_assign_rhs1 (stmt), 2); + break; + case CONSTRUCTOR: vno->length = CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt)); for (i = 0; i < vno->length; ++i) @@ -2227,6 +2237,7 @@ init_vn_nary_op_from_stmt (vn_nary_op_t vno, gimple stmt) break; default: + gcc_checking_assert (!gimple_assign_single_p (stmt)); vno->length = gimple_num_ops (stmt) - 1; for (i = 0; i < vno->length; ++i) vno->op[i] = gimple_op (stmt, i + 1); diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h index 956bde22da1..cd418da8704 100644 --- a/gcc/tree-ssa-sccvn.h +++ b/gcc/tree-ssa-sccvn.h @@ -51,7 +51,7 @@ typedef const struct vn_nary_op_s *const_vn_nary_op_t; static inline size_t sizeof_vn_nary_op (unsigned int length) { - return sizeof (struct vn_nary_op_s) + sizeof (tree) * (length - 1); + return sizeof (struct vn_nary_op_s) + sizeof (tree) * length - sizeof (tree); } /* Phi nodes in the hashtable consist of their non-VN_TOP phi diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index d01203e8a82..58edfcbe480 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -140,6 +140,8 @@ along with GCC; see the file COPYING3. If not see http://gcc.gnu.org/projects/tree-ssa/vectorization.html */ +static void vect_estimate_min_profitable_iters (loop_vec_info, int *, int *); + /* Function vect_determine_vectorization_factor Determine the vectorization factor (VF). VF is the number of data elements @@ -1287,6 +1289,8 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo, bool slp) unsigned int th; bool only_slp_in_loop = true, ok; HOST_WIDE_INT max_niter; + HOST_WIDE_INT estimated_niter; + int min_profitable_estimate; if (dump_kind_p (MSG_NOTE)) dump_printf_loc (MSG_NOTE, vect_location, @@ -1490,7 +1494,8 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo, bool slp) vector stmts depends on VF. */ vect_update_slp_costs_according_to_vf (loop_vinfo); - min_profitable_iters = vect_estimate_min_profitable_iters (loop_vinfo); + vect_estimate_min_profitable_iters (loop_vinfo, &min_profitable_iters, + &min_profitable_estimate); LOOP_VINFO_COST_MODEL_MIN_ITERS (loop_vinfo) = min_profitable_iters; if (min_profitable_iters < 0) @@ -1508,6 +1513,7 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo, bool slp) min_scalar_loop_bound = ((PARAM_VALUE (PARAM_MIN_VECT_LOOP_BOUND) * vectorization_factor) - 1); + /* Use the cost model only if it is more conservative than user specified threshold. */ @@ -1531,6 +1537,23 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo, bool slp) return false; } + if ((estimated_niter = estimated_stmt_executions_int (loop)) != -1 + && ((unsigned HOST_WIDE_INT) estimated_niter + <= MAX (th, (unsigned)min_profitable_estimate))) + { + if (dump_kind_p (MSG_MISSED_OPTIMIZATION)) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "not vectorized: estimated iteration count too " + "small."); + if (dump_kind_p (MSG_NOTE)) + dump_printf_loc (MSG_NOTE, vect_location, + "not vectorized: estimated iteration count smaller " + "than specified loop bound parameter or minimum " + "profitable iterations (whichever is more " + "conservative)."); + return false; + } + if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo) || LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0 || LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo)) @@ -2603,15 +2626,15 @@ vect_get_known_peeling_cost (loop_vec_info loop_vinfo, int peel_iters_prologue, Return the number of iterations required for the vector version of the loop to be profitable relative to the cost of the scalar version of the - loop. + loop. */ - TODO: Take profile info into account before making vectorization - decisions, if available. */ - -int -vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo) +static void +vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo, + int *ret_min_profitable_niters, + int *ret_min_profitable_estimate) { int min_profitable_iters; + int min_profitable_estimate; int peel_iters_prologue; int peel_iters_epilogue; unsigned vec_inside_cost = 0; @@ -2628,7 +2651,9 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo) if (!flag_vect_cost_model) { dump_printf_loc (MSG_NOTE, vect_location, "cost model disabled."); - return 0; + *ret_min_profitable_niters = 0; + *ret_min_profitable_estimate = 0; + return; } /* Requires loop versioning tests to handle misalignment. */ @@ -2863,7 +2888,9 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo) "divided by the scalar iteration cost = %d " "is greater or equal to the vectorization factor = %d.", vec_inside_cost, scalar_single_iter_cost, vf); - return -1; + *ret_min_profitable_niters = -1; + *ret_min_profitable_estimate = -1; + return; } if (dump_kind_p (MSG_NOTE)) @@ -2879,6 +2906,8 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo) scalar_single_iter_cost); dump_printf (MSG_NOTE, " Scalar outside cost: %d\n", scalar_outside_cost); + dump_printf (MSG_NOTE, " Vector outside cost: %d\n", + vec_outside_cost); dump_printf (MSG_NOTE, " prologue iterations: %d\n", peel_iters_prologue); dump_printf (MSG_NOTE, " epilogue iterations: %d\n", @@ -2898,9 +2927,35 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo) if (dump_kind_p (MSG_NOTE)) dump_printf_loc (MSG_NOTE, vect_location, - " Profitability threshold = %d\n", min_profitable_iters); + " Runtime profitability threshold = %d\n", min_profitable_iters); + + *ret_min_profitable_niters = min_profitable_iters; + + /* Calculate number of iterations required to make the vector version + profitable, relative to the loop bodies only. + + Non-vectorized variant is SIC * niters and it must win over vector + variant on the expected loop trip count. The following condition must hold true: + SIC * niters > VIC * ((niters-PL_ITERS-EP_ITERS)/VF) + VOC + SOC */ + + if (vec_outside_cost <= 0) + min_profitable_estimate = 1; + else + { + min_profitable_estimate = ((vec_outside_cost + scalar_outside_cost) * vf + - vec_inside_cost * peel_iters_prologue + - vec_inside_cost * peel_iters_epilogue) + / ((scalar_single_iter_cost * vf) + - vec_inside_cost); + } + min_profitable_estimate --; + min_profitable_estimate = MAX (min_profitable_estimate, min_profitable_iters); + if (dump_kind_p (MSG_NOTE)) + dump_printf_loc (MSG_NOTE, vect_location, + " Static estimate profitability threshold = %d\n", + min_profitable_iters); - return min_profitable_iters; + *ret_min_profitable_estimate = min_profitable_estimate; } diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 6c997760cd7..5762e00b69e 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -976,7 +976,6 @@ extern bool vectorizable_live_operation (gimple, gimple_stmt_iterator *, extern bool vectorizable_reduction (gimple, gimple_stmt_iterator *, gimple *, slp_tree); extern bool vectorizable_induction (gimple, gimple_stmt_iterator *, gimple *); -extern int vect_estimate_min_profitable_iters (loop_vec_info); extern tree get_initial_def_for_reduction (gimple, tree, tree *); extern int vect_min_worthwhile_factor (enum tree_code); extern int vect_get_known_peeling_cost (loop_vec_info, int, int *, int, diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index b728dddb871..de3eb2c6a98 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -4712,6 +4712,11 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, tree val2 = NULL_TREE; double_int mask = double_int_zero; unsigned int prec = TYPE_PRECISION (TREE_TYPE (val)); + unsigned int nprec = prec; + enum tree_code rhs_code = ERROR_MARK; + + if (is_gimple_assign (def_stmt)) + rhs_code = gimple_assign_rhs_code (def_stmt); /* Add asserts for NAME cmp CST and NAME being defined as NAME = (int) NAME2. */ @@ -4721,7 +4726,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, && gimple_assign_cast_p (def_stmt)) { name2 = gimple_assign_rhs1 (def_stmt); - if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)) + if (CONVERT_EXPR_CODE_P (rhs_code) && INTEGRAL_TYPE_P (TREE_TYPE (name2)) && TYPE_UNSIGNED (TREE_TYPE (name2)) && prec == TYPE_PRECISION (TREE_TYPE (name2)) @@ -4767,8 +4772,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, NAME = NAME2 >> CST2. Extract CST2 from the right shift. */ - if (is_gimple_assign (def_stmt) - && gimple_assign_rhs_code (def_stmt) == RSHIFT_EXPR) + if (rhs_code == RSHIFT_EXPR) { name2 = gimple_assign_rhs1 (def_stmt); cst2 = gimple_assign_rhs2 (def_stmt); @@ -4840,21 +4844,37 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, /* Add asserts for NAME cmp CST and NAME being defined as NAME = NAME2 & CST2. - Extract CST2 from the and. */ + Extract CST2 from the and. + + Also handle + NAME = (unsigned) NAME2; + casts where NAME's type is unsigned and has smaller precision + than NAME2's type as if it was NAME = NAME2 & MASK. */ names[0] = NULL_TREE; names[1] = NULL_TREE; cst2 = NULL_TREE; - if (is_gimple_assign (def_stmt) - && gimple_assign_rhs_code (def_stmt) == BIT_AND_EXPR) + if (rhs_code == BIT_AND_EXPR + || (CONVERT_EXPR_CODE_P (rhs_code) + && TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE + && TYPE_UNSIGNED (TREE_TYPE (val)) + && TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (def_stmt))) + > prec + && !retval)) { name2 = gimple_assign_rhs1 (def_stmt); - cst2 = gimple_assign_rhs2 (def_stmt); + if (rhs_code == BIT_AND_EXPR) + cst2 = gimple_assign_rhs2 (def_stmt); + else + { + cst2 = TYPE_MAX_VALUE (TREE_TYPE (val)); + nprec = TYPE_PRECISION (TREE_TYPE (name2)); + } if (TREE_CODE (name2) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (name2)) && TREE_CODE (cst2) == INTEGER_CST && !integer_zerop (cst2) - && prec <= HOST_BITS_PER_DOUBLE_INT - && (prec > 1 + && nprec <= HOST_BITS_PER_DOUBLE_INT + && (nprec > 1 || TYPE_UNSIGNED (TREE_TYPE (val)))) { gimple def_stmt2 = SSA_NAME_DEF_STMT (name2); @@ -4881,12 +4901,12 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, bool valid_p = false, valn = false, cst2n = false; enum tree_code ccode = comp_code; - valv = tree_to_double_int (val).zext (prec); - cst2v = tree_to_double_int (cst2).zext (prec); + valv = tree_to_double_int (val).zext (nprec); + cst2v = tree_to_double_int (cst2).zext (nprec); if (!TYPE_UNSIGNED (TREE_TYPE (val))) { - valn = valv.sext (prec).is_negative (); - cst2n = cst2v.sext (prec).is_negative (); + valn = valv.sext (nprec).is_negative (); + cst2n = cst2v.sext (nprec).is_negative (); } /* If CST2 doesn't have most significant bit set, but VAL is negative, we have comparison like @@ -4894,7 +4914,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, if (!cst2n && valn) ccode = ERROR_MARK; if (cst2n) - sgnbit = double_int_one.llshift (prec - 1, prec).zext (prec); + sgnbit = double_int_one.llshift (nprec - 1, nprec).zext (nprec); else sgnbit = double_int_zero; minv = valv & cst2v; @@ -4906,12 +4926,12 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, have folded the comparison into false) and maximum unsigned value is VAL | ~CST2. */ maxv = valv | ~cst2v; - maxv = maxv.zext (prec); + maxv = maxv.zext (nprec); valid_p = true; break; case NE_EXPR: tem = valv | ~cst2v; - tem = tem.zext (prec); + tem = tem.zext (nprec); /* If VAL is 0, handle (X & CST2) != 0 as (X & CST2) > 0U. */ if (valv.is_zero ()) { @@ -4921,7 +4941,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, } /* If (VAL | ~CST2) is all ones, handle it as (X & CST2) < VAL. */ - if (tem == double_int::mask (prec)) + if (tem == double_int::mask (nprec)) { cst2n = false; valn = false; @@ -4929,8 +4949,9 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, goto lt_expr; } if (!cst2n - && cst2v.sext (prec).is_negative ()) - sgnbit = double_int_one.llshift (prec - 1, prec).zext (prec); + && cst2v.sext (nprec).is_negative ()) + sgnbit + = double_int_one.llshift (nprec - 1, nprec).zext (nprec); if (!sgnbit.is_zero ()) { if (valv == sgnbit) @@ -4939,7 +4960,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, valn = true; goto gt_expr; } - if (tem == double_int::mask (prec - 1)) + if (tem == double_int::mask (nprec - 1)) { cst2n = true; goto lt_expr; @@ -4958,22 +4979,22 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, { /* If (VAL & CST2) != VAL, X & CST2 can't be equal to VAL. */ - minv = masked_increment (valv, cst2v, sgnbit, prec); + minv = masked_increment (valv, cst2v, sgnbit, nprec); if (minv == valv) break; } - maxv = double_int::mask (prec - (cst2n ? 1 : 0)); + maxv = double_int::mask (nprec - (cst2n ? 1 : 0)); valid_p = true; break; case GT_EXPR: gt_expr: /* Find out smallest MINV where MINV > VAL && (MINV & CST2) == MINV, if any. If VAL is signed and - CST2 has MSB set, compute it biased by 1 << (prec - 1). */ - minv = masked_increment (valv, cst2v, sgnbit, prec); + CST2 has MSB set, compute it biased by 1 << (nprec - 1). */ + minv = masked_increment (valv, cst2v, sgnbit, nprec); if (minv == valv) break; - maxv = double_int::mask (prec - (cst2n ? 1 : 0)); + maxv = double_int::mask (nprec - (cst2n ? 1 : 0)); valid_p = true; break; case LE_EXPR: @@ -4989,13 +5010,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, maxv = valv; else { - maxv = masked_increment (valv, cst2v, sgnbit, prec); + maxv = masked_increment (valv, cst2v, sgnbit, nprec); if (maxv == valv) break; maxv -= double_int_one; } maxv |= ~cst2v; - maxv = maxv.zext (prec); + maxv = maxv.zext (nprec); minv = sgnbit; valid_p = true; break; @@ -5017,13 +5038,13 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, } else { - maxv = masked_increment (valv, cst2v, sgnbit, prec); + maxv = masked_increment (valv, cst2v, sgnbit, nprec); if (maxv == valv) break; } maxv -= double_int_one; maxv |= ~cst2v; - maxv = maxv.zext (prec); + maxv = maxv.zext (nprec); minv = sgnbit; valid_p = true; break; @@ -5031,7 +5052,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, break; } if (valid_p - && (maxv - minv).zext (prec) != double_int::mask (prec)) + && (maxv - minv).zext (nprec) != double_int::mask (nprec)) { tree tmp, new_val, type; int i; @@ -5044,7 +5065,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, type = TREE_TYPE (names[i]); if (!TYPE_UNSIGNED (type)) { - type = build_nonstandard_integer_type (prec, 1); + type = build_nonstandard_integer_type (nprec, 1); tmp = build1 (NOP_EXPR, type, names[i]); } if (!minv.is_zero ()) diff --git a/gcc/tree.c b/gcc/tree.c index 7f620e511be..8df1b86d2be 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -4350,7 +4350,7 @@ comp_type_attributes (const_tree type1, const_tree type2) const struct attribute_spec *as; const_tree attr; - as = lookup_attribute_spec (TREE_PURPOSE (a)); + as = lookup_attribute_spec (get_attribute_name (a)); if (!as || as->affects_type_identity == false) continue; @@ -4364,7 +4364,7 @@ comp_type_attributes (const_tree type1, const_tree type2) { const struct attribute_spec *as; - as = lookup_attribute_spec (TREE_PURPOSE (a)); + as = lookup_attribute_spec (get_attribute_name (a)); if (!as || as->affects_type_identity == false) continue; @@ -5287,11 +5287,12 @@ private_lookup_attribute (const char *attr_name, size_t attr_len, tree list) { while (list) { - size_t ident_len = IDENTIFIER_LENGTH (TREE_PURPOSE (list)); + size_t ident_len = IDENTIFIER_LENGTH (get_attribute_name (list)); if (ident_len == attr_len) { - if (strcmp (attr_name, IDENTIFIER_POINTER (TREE_PURPOSE (list))) == 0) + if (!strcmp (attr_name, + IDENTIFIER_POINTER (get_attribute_name (list)))) break; } /* TODO: If we made sure that attributes were stored in the @@ -5299,7 +5300,7 @@ private_lookup_attribute (const char *attr_name, size_t attr_len, tree list) to '__text__') then we could avoid the following case. */ else if (ident_len == attr_len + 4) { - const char *p = IDENTIFIER_POINTER (TREE_PURPOSE (list)); + const char *p = IDENTIFIER_POINTER (get_attribute_name (list)); if (p[0] == '_' && p[1] == '_' && p[ident_len - 2] == '_' && p[ident_len - 1] == '_' && strncmp (attr_name, p + 2, attr_len) == 0) @@ -5329,10 +5330,11 @@ lookup_ident_attribute (tree attr_identifier, tree list) while (list) { - gcc_checking_assert (TREE_CODE (TREE_PURPOSE (list)) == IDENTIFIER_NODE); + gcc_checking_assert (TREE_CODE (get_attribute_name (list)) + == IDENTIFIER_NODE); /* Identifiers can be compared directly for equality. */ - if (attr_identifier == TREE_PURPOSE (list)) + if (attr_identifier == get_attribute_name (list)) break; /* If they are not equal, they may still be one in the form @@ -5342,11 +5344,11 @@ lookup_ident_attribute (tree attr_identifier, tree list) the fact that we're comparing identifiers. :-) */ { size_t attr_len = IDENTIFIER_LENGTH (attr_identifier); - size_t ident_len = IDENTIFIER_LENGTH (TREE_PURPOSE (list)); + size_t ident_len = IDENTIFIER_LENGTH (get_attribute_name (list)); if (ident_len == attr_len + 4) { - const char *p = IDENTIFIER_POINTER (TREE_PURPOSE (list)); + const char *p = IDENTIFIER_POINTER (get_attribute_name (list)); const char *q = IDENTIFIER_POINTER (attr_identifier); if (p[0] == '_' && p[1] == '_' && p[ident_len - 2] == '_' && p[ident_len - 1] == '_' @@ -5355,7 +5357,7 @@ lookup_ident_attribute (tree attr_identifier, tree list) } else if (ident_len + 4 == attr_len) { - const char *p = IDENTIFIER_POINTER (TREE_PURPOSE (list)); + const char *p = IDENTIFIER_POINTER (get_attribute_name (list)); const char *q = IDENTIFIER_POINTER (attr_identifier); if (q[0] == '_' && q[1] == '_' && q[attr_len - 2] == '_' && q[attr_len - 1] == '_' @@ -5385,7 +5387,7 @@ remove_attribute (const char *attr_name, tree list) tree l = *p; /* TODO: If we were storing attributes in normalized form, here we could use a simple strcmp(). */ - if (private_is_attribute_p (attr_name, attr_len, TREE_PURPOSE (l))) + if (private_is_attribute_p (attr_name, attr_len, get_attribute_name (l))) *p = TREE_CHAIN (l); else p = &TREE_CHAIN (l); @@ -5422,9 +5424,11 @@ merge_attributes (tree a1, tree a2) for (; a2 != 0; a2 = TREE_CHAIN (a2)) { tree a; - for (a = lookup_ident_attribute (TREE_PURPOSE (a2), attributes); + for (a = lookup_ident_attribute (get_attribute_name (a2), + attributes); a != NULL_TREE && !attribute_value_equal (a, a2); - a = lookup_ident_attribute (TREE_PURPOSE (a2), TREE_CHAIN (a))) + a = lookup_ident_attribute (get_attribute_name (a2), + TREE_CHAIN (a))) ; if (a == NULL_TREE) { @@ -6346,7 +6350,7 @@ attribute_hash_list (const_tree list, hashval_t hashcode) for (tail = list; tail; tail = TREE_CHAIN (tail)) /* ??? Do we want to add in TREE_VALUE too? */ hashcode = iterative_hash_object - (IDENTIFIER_HASH_VALUE (TREE_PURPOSE (tail)), hashcode); + (IDENTIFIER_HASH_VALUE (get_attribute_name (tail)), hashcode); return hashcode; } @@ -6383,7 +6387,7 @@ attribute_list_contained (const_tree l1, const_tree l2) /* Maybe the lists are similar. */ for (t1 = l1, t2 = l2; t1 != 0 && t2 != 0 - && TREE_PURPOSE (t1) == TREE_PURPOSE (t2) + && get_attribute_name (t1) == get_attribute_name (t2) && TREE_VALUE (t1) == TREE_VALUE (t2); t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) ; @@ -6398,9 +6402,9 @@ attribute_list_contained (const_tree l1, const_tree l2) /* This CONST_CAST is okay because lookup_attribute does not modify its argument and the return value is assigned to a const_tree. */ - for (attr = lookup_ident_attribute (TREE_PURPOSE (t2), CONST_CAST_TREE(l1)); + for (attr = lookup_ident_attribute (get_attribute_name (t2), CONST_CAST_TREE(l1)); attr != NULL_TREE && !attribute_value_equal (t2, attr); - attr = lookup_ident_attribute (TREE_PURPOSE (t2), TREE_CHAIN (attr))) + attr = lookup_ident_attribute (get_attribute_name (t2), TREE_CHAIN (attr))) ; if (attr == NULL_TREE) diff --git a/gcc/tree.h b/gcc/tree.h index ff4ae52e237..e7cef185793 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4903,12 +4903,12 @@ struct attribute_spec { /* The name of the attribute (without any leading or trailing __), or NULL to mark the end of a table of attributes. */ - const char *const name; + const char *name; /* The minimum length of the list of arguments of the attribute. */ - const int min_length; + int min_length; /* The maximum length of the list of arguments of the attribute (-1 for no maximum). */ - const int max_length; + int max_length; /* Whether this attribute requires a DECL. If it does, it will be passed from types of DECLs, function return types and array element types to the DECLs, function types and array types respectively; but when @@ -4916,15 +4916,15 @@ struct attribute_spec a warning. (If greater control is desired for a given attribute, this should be false, and the flags argument to the handler may be used to gain greater control in that case.) */ - const bool decl_required; + bool decl_required; /* Whether this attribute requires a type. If it does, it will be passed from a DECL to the type of that DECL. */ - const bool type_required; + bool type_required; /* Whether this attribute requires a function (or method) type. If it does, it will be passed from a function pointer type to the target type, and from a function return type (which is not itself a function pointer type) to the function type. */ - const bool function_type_required; + bool function_type_required; /* Function to handle this attribute. NODE points to the node to which the attribute is to be applied. If a DECL, it should be modified in place; if a TYPE, a copy should be created. NAME is the name of the @@ -4939,10 +4939,10 @@ struct attribute_spec otherwise the return value should be NULL_TREE. This pointer may be NULL if no special handling is required beyond the checks implied by the rest of this structure. */ - tree (*const handler) (tree *node, tree name, tree args, - int flags, bool *no_add_attrs); + tree (*handler) (tree *node, tree name, tree args, + int flags, bool *no_add_attrs); /* Specifies if attribute affects type's identity. */ - const bool affects_type_identity; + bool affects_type_identity; }; /* Flags that may be passed in the third argument of decl_attributes, and @@ -4967,7 +4967,9 @@ enum attribute_flags /* The attributes are being applied by default to a library function whose name indicates known behavior, and should be silently ignored if they are not in fact compatible with the function type. */ - ATTR_FLAG_BUILT_IN = 16 + ATTR_FLAG_BUILT_IN = 16, + /* A given attribute has been parsed as a C++-11 attribute. */ + ATTR_FLAG_CXX11 = 32 }; /* Default versions of target-overridable functions. */ @@ -6054,6 +6056,8 @@ extern bool must_pass_in_stack_var_size_or_pad (enum machine_mode, const_tree); /* In attribs.c. */ extern const struct attribute_spec *lookup_attribute_spec (const_tree); +extern const struct attribute_spec *lookup_scoped_attribute_spec (const_tree, + const_tree); extern void init_attributes (void); @@ -6067,6 +6071,12 @@ extern void init_attributes (void); a decl attribute to the declaration rather than to its type). */ extern tree decl_attributes (tree *, tree, int); +extern bool cxx11_attribute_p (const_tree); + +extern tree get_attribute_name (const_tree); + +extern tree get_attribute_namespace (const_tree); + extern void apply_tm_attr (tree, tree); /* In stor-layout.c */ diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog index 528b4930204..16410566d9b 100644 --- a/libbacktrace/ChangeLog +++ b/libbacktrace/ChangeLog @@ -1,3 +1,7 @@ +2012-10-04 Gerald Pfeifer <gerald@pfeifer.com> + + * btest.c (f23): Avoid uninitialized variable warning. + 2012-10-04 Ian Lance Taylor <iant@google.com> * dwarf.c: If the system header files do not declare strnlen, diff --git a/libbacktrace/btest.c b/libbacktrace/btest.c index 085891a6e69..16f25b45013 100644 --- a/libbacktrace/btest.c +++ b/libbacktrace/btest.c @@ -486,7 +486,7 @@ f23 (int f1line, int f2line) case 2: expected = "test3"; break; - case 3: + default: assert (0); } diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 683d2d113aa..b09c22fe5f2 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,29 @@ +2012-10-07 Matthias Klose <doko@ubuntu.com> + + * config/arm/unwind-arm.h (__gnu_unwind_24bit): Mark parameters + as unused. + (_Unwind_decode_typeinfo_ptr): Mark base as unused. + +2012-10-06 Mark Kettenis <kettenis@openbsd.org> + + * config.host (*-*-openbsd*): Add t-eh-dw2-dip to tmake_file. + * unwind-dw2-fde-dip.c: Don't include <elf.h> on OpenBSD. + (USE_PT_GNU_EH_FRAME): Define for OpenBSD. + (ElfW): Likewise. + +2012-10-05 Jonathan Wakely <jwakely.gcc@gmail.com> + + PR other/53889 + * config/i386/gthr-win32.h (__gthread_recursive_mutex_destroy): + Fix parameter names. + +2012-10-04 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/33135 + * config/sh/t-sh (HOST_LIBGCC2_CFLAGS): Delete. + * config/sh/t-netbsd (HOST_LIBGCC2_CFLAGS): Delete. + * config/sh/t-linux (HOST_LIBGCC2_CFLAGS): Remove mieee option. + 2012-10-03 Oleg Endo <olegendo@gcc.gnu.org> PR target/50457 @@ -15,6 +41,8 @@ * gthr-single.h (__gthread_recursive_mutex_destroy): Likewise. * config/gthr-rtems.h (__gthread_recursive_mutex_destroy): Likewise. * config/gthr-vxworks.h (__gthread_recursive_mutex_destroy): Likewise. + * config/i386/gthr-win32.c (__gthread_win32_recursive_mutex_destroy): + Likewise. * config/i386/gthr-win32.h (__gthread_recursive_mutex_destroy): Likewise. * config/mips/gthr-mipssde.h (__gthread_recursive_mutex_destroy): diff --git a/libgcc/config.host b/libgcc/config.host index 368902467fb..763f6c3a252 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -213,7 +213,7 @@ case ${host} in esac ;; *-*-openbsd*) - tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic" + tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic t-eh-dw2-dip" case ${target_thread_file} in posix) tmake_file="$tmake_file t-openbsd-thread" diff --git a/libgcc/config/arm/unwind-arm.h b/libgcc/config/arm/unwind-arm.h index 4300c8e31c6..74f72b0fdde 100644 --- a/libgcc/config/arm/unwind-arm.h +++ b/libgcc/config/arm/unwind-arm.h @@ -39,7 +39,8 @@ extern "C" { #endif /* Decode an R_ARM_TARGET2 relocation. */ static inline _Unwind_Word - _Unwind_decode_typeinfo_ptr (_Unwind_Word base, _Unwind_Word ptr) + _Unwind_decode_typeinfo_ptr (_Unwind_Word base __attribute__ ((unused)), + _Unwind_Word ptr) { _Unwind_Word tmp; @@ -65,7 +66,9 @@ extern "C" { } static inline _Unwind_Reason_Code - __gnu_unwind_24bit (_Unwind_Context * context, _uw data, int compact) + __gnu_unwind_24bit (_Unwind_Context * context __attribute__ ((unused)), + _uw data __attribute__ ((unused)), + int compact __attribute__ ((unused))) { return _URC_FAILURE; } diff --git a/libgcc/config/i386/gthr-win32.h b/libgcc/config/i386/gthr-win32.h index 965614841c5..ecde94132d2 100644 --- a/libgcc/config/i386/gthr-win32.h +++ b/libgcc/config/i386/gthr-win32.h @@ -538,7 +538,7 @@ __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) } static inline int -__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *mutex) +__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex) { return __gthr_win32_recursive_mutex_destroy (__mutex); } @@ -769,9 +769,9 @@ __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) } static inline int -__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *mutex) +__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex) { - CloseHandle ((HANDLE) mutex->sema); + CloseHandle ((HANDLE) __mutex->sema); return 0; } diff --git a/libgcc/config/sh/t-linux b/libgcc/config/sh/t-linux index 60dee8de11a..d316db93708 100644 --- a/libgcc/config/sh/t-linux +++ b/libgcc/config/sh/t-linux @@ -2,7 +2,7 @@ LIB1ASMFUNCS_CACHE = _ic_invalidate _ic_invalidate_array LIB2ADD = $(srcdir)/config/sh/linux-atomic.c -HOST_LIBGCC2_CFLAGS += -mieee -DNO_FPSCR_VALUES +HOST_LIBGCC2_CFLAGS += -DNO_FPSCR_VALUES # Silence atomic built-in related warnings in linux-atomic.c. # Unfortunately the conflicting types warning can't be disabled selectively. diff --git a/libgcc/config/sh/t-netbsd b/libgcc/config/sh/t-netbsd index 3c5739e2ffc..93fe287e5c8 100644 --- a/libgcc/config/sh/t-netbsd +++ b/libgcc/config/sh/t-netbsd @@ -1,3 +1,2 @@ LIB1ASMFUNCS_CACHE = _ic_invalidate -HOST_LIBGCC2_CFLAGS += -mieee diff --git a/libgcc/config/sh/t-sh b/libgcc/config/sh/t-sh index efbaff8479e..61cfe79a6f8 100644 --- a/libgcc/config/sh/t-sh +++ b/libgcc/config/sh/t-sh @@ -59,5 +59,3 @@ div_table-4-300.o: $(srcdir)/config/sh/lib1funcs-4-300.S libgcc-4-300.a: div_table-4-300.o $(AR_CREATE_FOR_TARGET) $@ div_table-4-300.o -HOST_LIBGCC2_CFLAGS += -mieee - diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c index 92f8ab54644..2ce3af80b15 100644 --- a/libgcc/unwind-dw2-fde-dip.c +++ b/libgcc/unwind-dw2-fde-dip.c @@ -33,7 +33,7 @@ #include "tconfig.h" #include "tsystem.h" -#ifndef inhibit_libc +#if !defined(inhibit_libc) && !defined(__OpenBSD__) #include <elf.h> /* Get DT_CONFIG. */ #endif #include "coretypes.h" @@ -65,6 +65,12 @@ #endif #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \ + && defined(__OpenBSD__) +# define ElfW(type) Elf_##type +# define USE_PT_GNU_EH_FRAME +#endif + +#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \ && defined(TARGET_DL_ITERATE_PHDR) \ && defined(__sun__) && defined(__svr4__) # define USE_PT_GNU_EH_FRAME diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index feeb10a4146..74d6294b39d 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,19 @@ +2012-10-06 Janne Blomqvist <jb@gcc.gnu.org> + + * configure.ac: Check for presence of secure_getenv. + * libgfortran.h: Use HAVE_SECURE_GETENV. + * Makefile.in: Regenerated. + * aclocal.m4: Regenerated. + * config.h.in: Regenerated. + * configure: Regenerated. + +2012-10-06 Thomas König <tkoenig@gcc.gnu.org> + + PR libfortran/54736 + * runtime/environ.c (search_unit): Correct logic + for binary search. + (mark_single): Fix index errors. + 2012-09-29 Thomas König <tkoenig@gcc.gnu.org> PR fortran/52724 diff --git a/libgfortran/Makefile.in b/libgfortran/Makefile.in index aa23e85e37b..62b9f7abffa 100644 --- a/libgfortran/Makefile.in +++ b/libgfortran/Makefile.in @@ -1,9 +1,9 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -87,6 +87,12 @@ am__nobase_list = $(am__nobase_strip_setup); \ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } am__installdirs = "$(DESTDIR)$(cafexeclibdir)" \ "$(DESTDIR)$(myexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" \ "$(DESTDIR)$(toolexeclibdir)" @@ -1276,7 +1282,7 @@ all: $(BUILT_SOURCES) config.h .SUFFIXES: .SUFFIXES: .F90 .c .f90 .lo .o .obj -am--refresh: +am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ @@ -1312,10 +1318,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): config.h: stamp-h1 - @if test ! -f $@; then \ - rm -f stamp-h1; \ - $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ - else :; fi + @if test ! -f $@; then rm -f stamp-h1; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 @@ -1422,11 +1426,11 @@ clean-toolexeclibLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libcaf_single.la: $(libcaf_single_la_OBJECTS) $(libcaf_single_la_DEPENDENCIES) +libcaf_single.la: $(libcaf_single_la_OBJECTS) $(libcaf_single_la_DEPENDENCIES) $(EXTRA_libcaf_single_la_DEPENDENCIES) $(libcaf_single_la_LINK) -rpath $(cafexeclibdir) $(libcaf_single_la_OBJECTS) $(libcaf_single_la_LIBADD) $(LIBS) -libgfortran.la: $(libgfortran_la_OBJECTS) $(libgfortran_la_DEPENDENCIES) +libgfortran.la: $(libgfortran_la_OBJECTS) $(libgfortran_la_DEPENDENCIES) $(EXTRA_libgfortran_la_DEPENDENCIES) $(libgfortran_la_LINK) -rpath $(toolexeclibdir) $(libgfortran_la_OBJECTS) $(libgfortran_la_LIBADD) $(LIBS) -libgfortranbegin.la: $(libgfortranbegin_la_OBJECTS) $(libgfortranbegin_la_DEPENDENCIES) +libgfortranbegin.la: $(libgfortranbegin_la_OBJECTS) $(libgfortranbegin_la_DEPENDENCIES) $(EXTRA_libgfortranbegin_la_DEPENDENCIES) $(libgfortranbegin_la_LINK) -rpath $(myexeclibdir) $(libgfortranbegin_la_OBJECTS) $(libgfortranbegin_la_LIBADD) $(LIBS) mostlyclean-compile: @@ -5686,9 +5690,7 @@ uninstall-toolexeclibDATA: @$(NORMAL_UNINSTALL) @list='$(toolexeclib_DATA)'; test -n "$(toolexeclibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(toolexeclibdir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(toolexeclibdir)" && rm -f $$files + dir='$(DESTDIR)$(toolexeclibdir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -5760,10 +5762,15 @@ install-am: all-am installcheck: installcheck-am install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: diff --git a/libgfortran/aclocal.m4 b/libgfortran/aclocal.m4 index 8673daa1a9d..351be9d255a 100644 --- a/libgfortran/aclocal.m4 +++ b/libgfortran/aclocal.m4 @@ -1,7 +1,8 @@ -# generated automatically by aclocal 1.11.1 -*- Autoconf -*- +# generated automatically by aclocal 1.11.3 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, +# Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -19,12 +20,15 @@ You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) -# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 Free Software +# Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. +# serial 1 + # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been @@ -34,7 +38,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.11' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.11.1], [], +m4_if([$1], [1.11.3], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -50,19 +54,21 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.11.1])dnl +[AM_AUTOMAKE_VERSION([1.11.3])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. +# serial 1 + # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. @@ -144,14 +150,14 @@ AC_CONFIG_COMMANDS_PRE( Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 -# Free Software Foundation, Inc. +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, +# 2010, 2011 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 10 +# serial 12 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, @@ -191,6 +197,7 @@ AC_CACHE_CHECK([dependency style of $depcc], # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. + rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. @@ -255,7 +262,7 @@ AC_CACHE_CHECK([dependency style of $depcc], break fi ;; - msvisualcpp | msvcmsys) + msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. @@ -320,10 +327,13 @@ AC_DEFUN([AM_DEP_TRACK], if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' + am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- @@ -545,12 +555,15 @@ for _am_header in $config_headers :; do done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. +# Copyright (C) 2001, 2003, 2005, 2008, 2011 Free Software Foundation, +# Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. +# serial 1 + # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. @@ -569,8 +582,8 @@ AC_SUBST(install_sh)]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering -# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008 -# Free Software Foundation, Inc. +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008, +# 2011 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -590,7 +603,7 @@ AC_DEFUN([AM_MAINTAINER_MODE], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) -AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful @@ -736,12 +749,15 @@ else fi ]) -# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# Copyright (C) 2003, 2004, 2005, 2006, 2011 Free Software Foundation, +# Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. +# serial 1 + # AM_PROG_MKDIR_P # --------------- # Check for `mkdir -p'. @@ -764,13 +780,14 @@ esac # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. +# Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 Free Software +# Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 4 +# serial 5 # _AM_MANGLE_OPTION(NAME) # ----------------------- @@ -778,13 +795,13 @@ AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) -# ------------------------------ +# -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) -# ---------------------------------- +# ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) @@ -860,12 +877,14 @@ Check your system clock]) fi AC_MSG_RESULT(yes)]) -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. +# serial 1 + # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't @@ -888,13 +907,13 @@ fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006, 2008 Free Software Foundation, Inc. +# Copyright (C) 2006, 2008, 2010 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 2 +# serial 3 # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- @@ -903,13 +922,13 @@ AC_SUBST([INSTALL_STRIP_PROGRAM])]) AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) -# --------------------------- +# -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -931,10 +950,11 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], -[# Always define AMTAR for backward compatibility. -AM_MISSING_PROG([AMTAR], [tar]) +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) m4_if([$1], [v7], - [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in index 43ba0259862..ee4c14f52c3 100644 --- a/libgfortran/config.h.in +++ b/libgfortran/config.h.in @@ -648,6 +648,9 @@ /* Define to 1 if you have the `scalbnl' function. */ #undef HAVE_SCALBNL +/* Define to 1 if you have the `secure_getenv' function. */ +#undef HAVE_SECURE_GETENV + /* Define to 1 if you have the `setmode' function. */ #undef HAVE_SETMODE diff --git a/libgfortran/configure b/libgfortran/configure index 5ee6f23aa26..5ad56aa29b7 100755 --- a/libgfortran/configure +++ b/libgfortran/configure @@ -653,6 +653,7 @@ CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE +am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE @@ -2592,6 +2593,7 @@ as_fn_append ac_func_list " getuid" as_fn_append ac_func_list " geteuid" as_fn_append ac_func_list " umask" as_fn_append ac_func_list " getegid" +as_fn_append ac_func_list " secure_getenv" as_fn_append ac_func_list " __secure_getenv" as_fn_append ac_header_list " math.h" # Check that the precious variables saved in the cache have kept the same @@ -3383,11 +3385,11 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # We need awk for the "check" target. The system "awk" is bad on # some platforms. -# Always define AMTAR for backward compatibility. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' -AMTAR=${AMTAR-"${am_missing_run}tar"} - -am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' @@ -3520,6 +3522,7 @@ fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' + am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= @@ -4337,6 +4340,7 @@ else # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. + rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. @@ -4396,7 +4400,7 @@ else break fi ;; - msvisualcpp | msvcmsys) + msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. @@ -5512,6 +5516,7 @@ else # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. + rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. @@ -5571,7 +5576,7 @@ else break fi ;; - msvisualcpp | msvcmsys) + msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. @@ -12328,7 +12333,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12331 "configure" +#line 12336 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12434,7 +12439,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12437 "configure" +#line 12442 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -16548,6 +16553,8 @@ done + + # Check strerror_r, cannot be above as versions with two and three arguments exist ac_save_CFLAGS="$CFLAGS" diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac index 97b337e33ec..86cb330fee3 100644 --- a/libgfortran/configure.ac +++ b/libgfortran/configure.ac @@ -266,7 +266,8 @@ ftruncate chsize chdir getlogin gethostname kill link symlink sleep ttyname \ alarm access fork execl wait setmode execve pipe dup2 close \ strcasestr getrlimit gettimeofday stat fstat lstat getpwuid vsnprintf dup \ getcwd localtime_r gmtime_r getpwuid_r ttyname_r clock_gettime \ -readlink getgid getpid getppid getuid geteuid umask getegid __secure_getenv) +readlink getgid getpid getppid getuid geteuid umask getegid \ +secure_getenv __secure_getenv) # Check strerror_r, cannot be above as versions with two and three arguments exist LIBGFOR_CHECK_STRERROR_R diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h index 7dafd940e62..a8c33636171 100644 --- a/libgfortran/libgfortran.h +++ b/libgfortran/libgfortran.h @@ -772,6 +772,7 @@ unit_convert get_unformatted_convert (int); internal_proto(get_unformatted_convert); /* Secure getenv() which returns NULL if running as SUID/SGID. */ +#ifndef HAVE_SECURE_GETENV #ifdef HAVE___SECURE_GETENV #define secure_getenv __secure_getenv #elif defined(HAVE_GETUID) && defined(HAVE_GETEUID) \ @@ -782,6 +783,7 @@ internal_proto(secure_getenv); #else #define secure_getenv getenv #endif +#endif /* string.c */ diff --git a/libgfortran/runtime/environ.c b/libgfortran/runtime/environ.c index bcb91f44613..1f73397703d 100644 --- a/libgfortran/runtime/environ.c +++ b/libgfortran/runtime/environ.c @@ -459,21 +459,35 @@ search_unit (int unit, int *ip) { int low, high, mid; - low = -1; - high = n_elist; - while (high - low > 1) + if (n_elist == 0) + { + *ip = 0; + return 0; + } + + low = 0; + high = n_elist - 1; + + do { mid = (low + high) / 2; - if (unit <= elist[mid].unit) - high = mid; + if (unit == elist[mid].unit) + { + *ip = mid; + return 1; + } + else if (unit > elist[mid].unit) + low = mid + 1; else - low = mid; - } - *ip = high; - if (elist[high].unit == unit) - return 1; + high = mid - 1; + } while (low <= high); + + if (unit > elist[mid].unit) + *ip = mid + 1; else - return 0; + *ip = mid; + + return 0; } /* This matches a keyword. If it is found, return the token supplied, @@ -588,13 +602,13 @@ mark_single (int unit) } if (search_unit (unit, &i)) { - elist[unit].conv = endian; + elist[i].conv = endian; } else { - for (j=n_elist; j>=i; j--) + for (j=n_elist-1; j>=i; j--) elist[j+1] = elist[j]; - + n_elist += 1; elist[i].unit = unit; elist[i].conv = endian; diff --git a/libgo/runtime/go-caller.c b/libgo/runtime/go-caller.c index 8d8fe4c8797..8dcf9e4bee9 100644 --- a/libgo/runtime/go-caller.c +++ b/libgo/runtime/go-caller.c @@ -98,7 +98,12 @@ __go_get_backtrace_state () { runtime_lock (&back_state_lock); if (back_state == NULL) - back_state = backtrace_create_state (NULL, 1, error_callback, NULL); + { + const char *filename; + + filename = (const char *) runtime_progname (); + back_state = backtrace_create_state (filename, 1, error_callback, NULL); + } runtime_unlock (&back_state_lock); return back_state; } @@ -139,7 +144,7 @@ __go_symbol_value (uintptr_t pc, uintptr_t *val) { *val = 0; backtrace_syminfo (__go_get_backtrace_state (), pc, syminfo_callback, - error_callback, &val); + error_callback, val); return *val != 0; } diff --git a/libgo/runtime/runtime.c b/libgo/runtime/runtime.c index e0a7925aed1..86115965734 100644 --- a/libgo/runtime/runtime.c +++ b/libgo/runtime/runtime.c @@ -117,6 +117,12 @@ runtime_args(int32 c, byte **v) runtime_sysargs(c, v); } +byte* +runtime_progname() +{ + return argc == 0 ? nil : argv[0]; +} + void runtime_goargs(void) { diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index f96d740fb1c..74050da9e98 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -520,5 +520,6 @@ extern uintptr runtime_stacks_sys; struct backtrace_state; extern struct backtrace_state *__go_get_backtrace_state(void); extern _Bool __go_file_line(uintptr, String*, String*, int *); +extern byte* runtime_progname(); int32 getproccount(void); diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5f356407750..998e42924fe 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,59 @@ +2012-10-07 Matthias Klose <doko@ubuntu.com> + + * testsuite/28_regex/algorithms/match/basic: Remove empty directory. + * testsuite/28_regex/algorithms/match/extended: Likewise. + * testsuite/28_regex/algorithms/match: Likewise. + +2012-10-06 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/52764 + * include/c_global/cstdint: Remove __STDC_LIMIT_MACROS and + __STDC_CONSTANT_MACROS related macros. + +2012-10-06 Joe Seymour <jseymour@codesourcery.com> + + * include/tr2/dynamic_bitset: Fix cxxabi_forced.h include path. + +2012-10-05 Benjamin Kosnik <bkoz@redhat.com> + + * testsuite/28_regex/algorithms/match: Rename to... + * testsuite/28_regex/algorithms/regex_match: ...this. + * testsuite/28_regex/basic_regex/regex.cc: Rename to... + * testsuite/28_regex/basic_regex/ctors/basic/default.cc: ...this. + * testsuite/util/testsuite_regex.h: New. + * testsuite/28_regex/basic_regex/ctors/basic/raw_string.cc: New. + +2012-10-05 Jakub Jelinek <jakub@redhat.com> + + * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust line + numbers. + +2012-10-05 Marc Glisse <marc.glisse@inria.fr> + + PR libstdc++/54686 + * include/c_global/cstdlib (abs(long long)): Define with + __builtin_llabs when we have long long. + (abs(long)): Use __builtin_labs. + (abs(__int128)): Define when we have __int128. + +2012-10-05 Paolo Carlini <paolo.carlini@oracle.com> + + * include/c_global/cstdlib: Remove redundant pasto code protected + by __GXX_EXPERIMENTAL_CXX0X__. + * include/c_global/cwctype: Likewise. + * include/c_global/ccomplex: Remove uses of obsolete macro + _GLIBCXX_INCLUDE_AS_TR1. + * include/c_global/cfloat: Likewise. + +2012-10-05 Marc Glisse <marc.glisse@inria.fr> + + PR libstdc++/54686 + * include/c_std/cstdlib (abs(long long)): Define with + __builtin_llabs when we have long long. + (abs(long)): Use __builtin_labs. + (abs(__int128)): Define when we have __int128. + * testsuite/26_numerics/headers/cstdlib/54686.c: New file. + 2012-10-03 Paolo Carlini <paolo.carlini@oracle.com> PR libstdc++/53248 diff --git a/libstdc++-v3/include/c_global/ccomplex b/libstdc++-v3/include/c_global/ccomplex index b1117e8d42e..0109ec10e9a 100644 --- a/libstdc++-v3/include/c_global/ccomplex +++ b/libstdc++-v3/include/c_global/ccomplex @@ -1,6 +1,6 @@ // <ccomplex> -*- C++ -*- -// Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +// Copyright (C) 2007-2012 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -35,10 +35,6 @@ # include <bits/c++0x_warning.h> #endif -#if defined(_GLIBCXX_INCLUDE_AS_TR1) -# error C++0x header cannot be included from TR1 header -#endif - #include <complex> #endif diff --git a/libstdc++-v3/include/c_global/cfloat b/libstdc++-v3/include/c_global/cfloat index 1be81d34d68..2bc7883bfed 100644 --- a/libstdc++-v3/include/c_global/cfloat +++ b/libstdc++-v3/include/c_global/cfloat @@ -1,8 +1,6 @@ // -*- C++ -*- forwarding header. -// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -// 2006, 2007, 2008, 2009, 2010 -// Free Software Foundation, Inc. +// Copyright (C) 1997-2012 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -46,9 +44,6 @@ #define _GLIBCXX_CFLOAT 1 #ifdef __GXX_EXPERIMENTAL_CXX0X__ -# if defined(_GLIBCXX_INCLUDE_AS_TR1) -# error C++0x header cannot be included from TR1 header -# endif # ifndef DECIMAL_DIG # define DECIMAL_DIG __DECIMAL_DIG__ # endif diff --git a/libstdc++-v3/include/c_global/cstdint b/libstdc++-v3/include/c_global/cstdint index ce8143ea2bd..5ebee3bd793 100644 --- a/libstdc++-v3/include/c_global/cstdint +++ b/libstdc++-v3/include/c_global/cstdint @@ -1,6 +1,6 @@ // <cstdint> -*- C++ -*- -// Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +// Copyright (C) 2007-2012 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -37,25 +37,8 @@ #include <bits/c++config.h> -// For 8.22.1/1 (see C99, Notes 219, 220, 222) #if _GLIBCXX_HAVE_STDINT_H -# ifndef __STDC_LIMIT_MACROS -# define _UNDEF__STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS -# endif -# ifndef __STDC_CONSTANT_MACROS -# define _UNDEF__STDC_CONSTANT_MACROS -# define __STDC_CONSTANT_MACROS -# endif # include <stdint.h> -# ifdef _UNDEF__STDC_LIMIT_MACROS -# undef __STDC_LIMIT_MACROS -# undef _UNDEF__STDC_LIMIT_MACROS -# endif -# ifdef _UNDEF__STDC_CONSTANT_MACROS -# undef __STDC_CONSTANT_MACROS -# undef _UNDEF__STDC_CONSTANT_MACROS -# endif #endif #ifdef _GLIBCXX_USE_C99_STDINT_TR1 diff --git a/libstdc++-v3/include/c_global/cstdlib b/libstdc++-v3/include/c_global/cstdlib index f4785b4ad93..729a639c6e7 100644 --- a/libstdc++-v3/include/c_global/cstdlib +++ b/libstdc++-v3/include/c_global/cstdlib @@ -1,8 +1,6 @@ // -*- C++ -*- forwarding header. -// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -// 2006, 2007, 2008, 2009, 2010, 2011 -// Free Software Foundation, Inc. +// Copyright (C) 1997-2012 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -137,12 +135,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO inline long - abs(long __i) { return labs(__i); } + abs(long __i) { return __builtin_labs(__i); } inline ldiv_t div(long __i, long __j) { return ldiv(__i, __j); } #endif +#ifdef _GLIBCXX_USE_LONG_LONG + inline long long + abs(long long __x) { return __builtin_llabs (__x); } +#endif + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128) + inline __int128 + abs(__int128 __x) { return __x >= 0 ? __x : -__x; } +#endif + _GLIBCXX_END_NAMESPACE_VERSION } // namespace @@ -171,9 +179,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using ::_Exit; #endif - inline long long - abs(long long __x) { return __x >= 0 ? __x : -__x; } - #if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC using ::llabs; @@ -208,7 +213,6 @@ namespace std using ::__gnu_cxx::lldiv_t; #endif using ::__gnu_cxx::_Exit; - using ::__gnu_cxx::abs; #if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC using ::__gnu_cxx::llabs; using ::__gnu_cxx::div; @@ -221,35 +225,6 @@ namespace std using ::__gnu_cxx::strtold; } // namespace std -#ifdef __GXX_EXPERIMENTAL_CXX0X__ - -namespace std -{ -#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC - // types - using std::lldiv_t; - - // functions - using std::llabs; - using std::lldiv; -#endif - - using std::atoll; - using std::strtoll; - using std::strtoull; - - using std::strtof; - using std::strtold; - - // overloads - using std::abs; -#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC - using std::div; -#endif -} // namespace std - -#endif // __GXX_EXPERIMENTAL_CXX0X__ - #endif // _GLIBCXX_USE_C99 #endif // !_GLIBCXX_HOSTED diff --git a/libstdc++-v3/include/c_global/cwctype b/libstdc++-v3/include/c_global/cwctype index e417b687417..52fb440b21e 100644 --- a/libstdc++-v3/include/c_global/cwctype +++ b/libstdc++-v3/include/c_global/cwctype @@ -1,8 +1,6 @@ // -*- C++ -*- forwarding header. -// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -// 2006, 2007, 2008, 2009, 2010 -// Free Software Foundation, Inc. +// Copyright (C) 1997-2012 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -109,19 +107,4 @@ namespace std #endif //_GLIBCXX_USE_WCHAR_T -#ifdef __GXX_EXPERIMENTAL_CXX0X__ - -#ifdef _GLIBCXX_USE_WCHAR_T - -namespace std -{ -#if _GLIBCXX_HAVE_ISWBLANK - using std::iswblank; -#endif -} // namespace - -#endif // _GLIBCXX_USE_WCHAR_T - -#endif // __GXX_EXPERIMENTAL_CXX0X__ - #endif // _GLIBCXX_CWCTYPE diff --git a/libstdc++-v3/include/c_std/cstdlib b/libstdc++-v3/include/c_std/cstdlib index c3fe8aa4507..345920b76c2 100644 --- a/libstdc++-v3/include/c_std/cstdlib +++ b/libstdc++-v3/include/c_std/cstdlib @@ -135,7 +135,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif // _GLIBCXX_USE_WCHAR_T inline long - abs(long __i) { return labs(__i); } + abs(long __i) { return __builtin_labs(__i); } + +#ifdef _GLIBCXX_USE_LONG_LONG + inline long long + abs(long long __x) { return __builtin_llabs (__x); } +#endif + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128) + inline __int128 + abs(__int128 __x) { return __x >= 0 ? __x : -__x; } +#endif inline ldiv_t div(long __i, long __j) { return ldiv(__i, __j); } @@ -168,9 +178,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using ::_Exit; #endif - inline long long - abs(long long __x) { return __x >= 0 ? __x : -__x; } - #if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC using ::llabs; @@ -205,7 +212,6 @@ namespace std using ::__gnu_cxx::lldiv_t; #endif using ::__gnu_cxx::_Exit; - using ::__gnu_cxx::abs; #if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC using ::__gnu_cxx::llabs; using ::__gnu_cxx::div; diff --git a/libstdc++-v3/include/tr2/dynamic_bitset b/libstdc++-v3/include/tr2/dynamic_bitset index 5ca56470bd2..53b696f0ebd 100644 --- a/libstdc++-v3/include/tr2/dynamic_bitset +++ b/libstdc++-v3/include/tr2/dynamic_bitset @@ -1,6 +1,6 @@ // TR2 <dynamic_bitset> -*- C++ -*- -// Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc. +// Copyright (C) 2009-2012 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -39,7 +39,7 @@ #include <bits/functexcept.h> // For invalid_argument, out_of_range, // overflow_error #include <iosfwd> -#include <cxxabi_forced.h> +#include <bits/cxxabi_forced.h> namespace std _GLIBCXX_VISIBILITY(default) { diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc index dc9d80383f8..a2ceeb5c277 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc @@ -32,9 +32,9 @@ void test01() { X* px = 0; std::shared_ptr<X> p1(px); // { dg-error "here" } - // { dg-error "incomplete" "" { target *-*-* } 776 } + // { dg-error "incomplete" "" { target *-*-* } 775 } std::shared_ptr<X> p9(ap()); // { dg-error "here" } - // { dg-error "incomplete" "" { target *-*-* } 310 } + // { dg-error "incomplete" "" { target *-*-* } 307 } } diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cstdlib/54686.c b/libstdc++-v3/testsuite/26_numerics/headers/cstdlib/54686.c new file mode 100644 index 00000000000..fd723c89e7c --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/headers/cstdlib/54686.c @@ -0,0 +1,32 @@ +// { dg-do compile } +// { dg-options "-std=c++11" } + +// Copyright (C) 2012 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <cmath> +#include <cstdlib> +#include <type_traits> +#include <utility> + +#ifdef _GLIBCXX_USE_LONG_LONG +void test01() +{ + static_assert (std::is_same<decltype (std::abs (std::declval<long long> ())), + long long>::value, "Missing abs(long long)"); +} +#endif diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/match/basic/string_01.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_01.cc index 4a7161a7967..4a7161a7967 100644 --- a/libstdc++-v3/testsuite/28_regex/algorithms/match/basic/string_01.cc +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_01.cc diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/match/basic/string_range_00_03.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_00_03.cc index 6c0fdd76f2c..6c0fdd76f2c 100644 --- a/libstdc++-v3/testsuite/28_regex/algorithms/match/basic/string_range_00_03.cc +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_00_03.cc diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/match/basic/string_range_01_03.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_01_03.cc index 3439b544b63..3439b544b63 100644 --- a/libstdc++-v3/testsuite/28_regex/algorithms/match/basic/string_range_01_03.cc +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_01_03.cc diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/match/basic/string_range_02_03.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_02_03.cc index dfd00a0f3d7..dfd00a0f3d7 100644 --- a/libstdc++-v3/testsuite/28_regex/algorithms/match/basic/string_range_02_03.cc +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/basic/string_range_02_03.cc diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/match/extended/cstring_plus.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_plus.cc index ad0f57e221d..ad0f57e221d 100644 --- a/libstdc++-v3/testsuite/28_regex/algorithms/match/extended/cstring_plus.cc +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_plus.cc diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/match/extended/cstring_questionmark.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_questionmark.cc index 21abea456a9..21abea456a9 100644 --- a/libstdc++-v3/testsuite/28_regex/algorithms/match/extended/cstring_questionmark.cc +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/cstring_questionmark.cc diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/match/extended/string_any.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_any.cc index 8d3716b1edf..8d3716b1edf 100644 --- a/libstdc++-v3/testsuite/28_regex/algorithms/match/extended/string_any.cc +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_any.cc diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/match/extended/string_range_00_03.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_00_03.cc index a0a2e1fa9d8..a0a2e1fa9d8 100644 --- a/libstdc++-v3/testsuite/28_regex/algorithms/match/extended/string_range_00_03.cc +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_00_03.cc diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/match/extended/string_range_01_03.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_01_03.cc index b50e07645ab..b50e07645ab 100644 --- a/libstdc++-v3/testsuite/28_regex/algorithms/match/extended/string_range_01_03.cc +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_01_03.cc diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/match/extended/string_range_02_03.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_02_03.cc index ca322a8d4cd..ca322a8d4cd 100644 --- a/libstdc++-v3/testsuite/28_regex/algorithms/match/extended/string_range_02_03.cc +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/extended/string_range_02_03.cc diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/regex.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/default.cc index 8a803ede81f..8a803ede81f 100644 --- a/libstdc++-v3/testsuite/28_regex/basic_regex/regex.cc +++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/default.cc diff --git a/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/raw_string.cc b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/raw_string.cc new file mode 100644 index 00000000000..0ab42ebaca6 --- /dev/null +++ b/libstdc++-v3/testsuite/28_regex/basic_regex/ctors/basic/raw_string.cc @@ -0,0 +1,52 @@ +// { dg-options "-std=c++0x" } +// { dg-do run { xfail *-*-* } } + +// 2012-08-20 Benjamin Kosnik <bkoz@redhat.com> +// +// Copyright (C) 2012 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// basic_regex constructors + raw string literals + +#include <regex> +#include <testsuite_regex.h> + +void +test01() +{ + using namespace __gnu_test; + + // raw string literals + + //string_type sre0(R"(\d{3}-\d{3}-\d{4})"); // expected fail + + string_type sre1(R"( this\n and new : forms\n )"); + + string_type sre2(R"([:num:]{3}-[:num:]{3}-[:num:]{4})"); + + // 1 + regex_type re(R"( this\n and new : forms\n )", std::regex::basic); + + // 2 + regex_sanity_check(sre1); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/util/testsuite_regex.h b/libstdc++-v3/testsuite/util/testsuite_regex.h new file mode 100644 index 00000000000..dbf4b34553d --- /dev/null +++ b/libstdc++-v3/testsuite/util/testsuite_regex.h @@ -0,0 +1,130 @@ +// -*- C++ -*- +// regex utils for the C++ library testsuite. +// +// Copyright (C) 2012 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. +// + +#include <regex> +#include <stdexcept> +#include <iostream> + +#ifndef _TESTSUITE_REGEX_H +#define _TESTSUITE_REGEX_H 1 + +namespace __gnu_test +{ + // Test on a compilation of simple expressions, throw regex_error on error. + typedef std::regex regex_type; + typedef regex_type::flag_type flag_type; + typedef std::regex_constants::error_type error_type; + typedef std::size_t size_type; + typedef std::string string_type; + + // Utilities + struct regex_expected_fail { }; + + const error_type regex_error_internal(static_cast<error_type>(-1)); + + // Stringify error codes for text logging. + const char* regex_error_codes[] = + { + "error_collate", + "error_ctype", + "error_escape", + "error_backref", + "error_brack", + "error_paren", + "error_brace", + "error_badbrace", + "error_range", + "error_space", + "error_badrepeat", + "error_complexity", + "error_stack" + }; + + void + show_regex_error_codes() + { + using namespace std; + using namespace std::regex_constants; + const char tab('\t'); + cout << "error_collate = " << tab << error_collate << endl; + cout << "error_ctype = " << tab << error_ctype << endl; + cout << "error_escape = " << tab << error_escape << endl; + cout << "error_backref = " << tab << error_backref << endl; + cout << "error_brack = " << tab << error_brack << endl; + cout << "error_paren = " << tab << error_paren << endl; + cout << "error_brace = " << tab << error_brace << endl; + cout << "error_badbrace = " << tab << error_badbrace << endl; + cout << "error_range = " << tab << error_range << endl; + cout << "error_space = " << tab << error_space << endl; + cout << "error_badrepeat = " << tab << error_badrepeat << endl; + cout << "error_complexity =" << tab << error_complexity << endl; + cout << "error_stack = " << tab << error_stack << endl; + } + + // Arguments + // string __res: the regular expression string + // flag_type __f: flag + // __error: expected error, if any + void + regex_sanity_check(const string_type& __res, + flag_type __f = regex_type::basic, + error_type __error = regex_error_internal) + { + using namespace std; + + try + { + regex_type reo(__res, __f); + auto n = reo.mark_count(); + cout << "regex_type::mark_count " << n << endl; + } + catch (const regex_error& e) + { + cout << "regex_sanity_check: " << __res << endl; + cout << "regex_error::what " << e.what() << endl; + + show_regex_error_codes(); + cout << "regex_error::code " << regex_error_codes[e.code()] << endl; + + if (__error != regex_error_internal) + { + // Then expected error_type is __error. Check. + if (__error != e.code()) + { + throw regex_expected_fail(); + } + } + throw; + } + catch (const logic_error& e) + { + cout << "logic_error::what " << e.what() << endl; + throw; + } + catch (const std::exception& e) + { + cout << "exception: " << endl; + throw; + } + } + +} // namespace __gnu_test +#endif |