diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-02-22 11:51:54 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-02-22 11:51:54 +0000 |
commit | 8564db8424b6988dd1b665e29f579c732a6001dc (patch) | |
tree | c203317dc88ea9f1a0fdb079333a2e6086f51b0e | |
parent | 49e6b159a6b2225a0198f8e261c6b6f3772fba3f (diff) | |
download | gcc-8564db8424b6988dd1b665e29f579c732a6001dc.tar.gz |
2013-02-22 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 196218 using svnmerge.py
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@196219 138bc75d-0d04-0410-961f-82ee72b054a4
176 files changed, 2695 insertions, 782 deletions
diff --git a/ChangeLog b/ChangeLog index f9c8f298233..6ef875812c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-02-20 Andrew Sutton <andrew.n.sutton@gmail.com> + + * MAINTAINERS (Write After Approval): Add myself. + 2013-02-15 Yufeng Zhang <yufeng.zhang@arm.com> * configure.ac: Set libgloss_dir for the aarch64*-*-* targets. diff --git a/ChangeLog.MELT b/ChangeLog.MELT index 2fcc3e9e4eb..c2969a2ba7f 100644 --- a/ChangeLog.MELT +++ b/ChangeLog.MELT @@ -1,4 +1,8 @@ +2013-02-22 Basile Starynkevitch <basile@starynkevitch.net> + + MELT branch merged with trunk rev 196218 using svnmerge.py + 2013-02-18 Basile Starynkevitch <basile@starynkevitch.net> MELT branch merged with trunk rev 196123 using svnmerge.py diff --git a/MAINTAINERS b/MAINTAINERS index 3f57f2fdefc..9affec84353 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -523,6 +523,7 @@ Graham Stott graham.stott@btinternet.com Andrew Stubbs ams@codesourcery.com Mike Stump mikestump@comcast.net Jeff Sturm jsturm@gcc.gnu.org +Andrew Sutton andrew.n.sutton@gmail.com Gabriele Svelto gabriele.svelto@st.com Sriraman Tallam tmsriram@google.com Chung-Lin Tang cltang@codesourcery.com diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e8be788a8c7..c2b35d3538c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,223 @@ +2013-02-21 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/56420 + * expmed.c (EXACT_POWER_OF_2_OR_ZERO_P): Do subtraction in uhwi, to + avoid signed wrapping. + (expand_mult): Handle properly multiplication by + ((dword_type) -1) << (BITS_PER_WORD - 1). Improve multiplication by + ((dword_type) 1) << (BITS_PER_WORD - 1). Avoid undefined behavior + in the compiler if coeff is HOST_WIDE_INT_MIN. + (expand_divmod): Don't make ext_op1 static, change it's type to + uhwi. Avoid undefined behavior in -INTVAL (op1). + + PR rtl-optimization/50339 + * lower-subreg.h (struct lower_subreg_choices): Add splitting_ashiftrt + field. + * lower-subreg.c (compute_splitting_shift): Handle ASHIFTRT. + (compute_costs): Call compute_splitting_shift also for ASHIFTRT + into splitting_ashiftrt field. + (find_decomposable_shift_zext, resolve_shift_zext): Handle also + ASHIFTRT. + (dump_choices): Fix up printing LSHIFTRT choices, print ASHIFTRT + choices. + +2013-02-20 Aldy Hernandez <aldyh@redhat.com> + + PR middle-end/56108 + * trans-mem.c (execute_tm_mark): Do not expand transactions that + are sure to go irrevocable. + +2013-02-21 Hans-Peter Nilsson <hp@axis.com> + + * doc/rtl.texi (vec_concat, vec_duplicate): Mention that + scalars are valid operands. + +2013-02-21 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/56310 + * ipa-cp.c (agg_replacements_to_vector): New parameter index, copy + only matching indices and non-negative final offsets. + (intersect_aggregates_with_edge): Pass src_idx to + agg_replacements_to_vector. Pass src_idx insstead of index to + intersect_with_agg_replacements. + +2013-02-21 Martin Jambor <mjambor@suse.cz> + + * ipa-cp.c (good_cloning_opportunity_p): Dump the real threshold + instead of hard-wired defaults. + +2013-02-21 Maciej W. Rozycki <macro@codesourcery.com> + + * doc/invoke.texi (MIPS Options): Update documentation of the + floating-point multiply-accumulate instruction restrictions. + +2013-02-21 Kostya Serebryany <kcc@google.com> + + * config/i386/i386.c (ix86_asan_shadow_offset): Use 0x7fff8000 as + asan_shadow_offset on x86_64 linux. + +2013-02-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/56415 + Revert + 2013-02-11 Richard Biener <rguenther@suse.de> + + PR tree-optimization/56273 + * tree-vrp.c (simplify_cond_using_ranges): Disable for the + first VRP run. + +2013-02-21 Jakub Jelinek <jakub@redhat.com> + + PR bootstrap/56258 + * doc/invoke.texi (-fdump-rtl-pro_and_epilogue): Use @item + instead of @itemx. + + PR inline-asm/56405 + * expr.c (expand_expr_real_1) <case TARGET_MEM_REF, MEM_REF>: Don't + use movmisalign or extract_bit_field for EXPAND_MEMORY modifier. + +2013-02-20 Jan Hubicka <jh@suse.cz> + + PR tree-optimization/56265 + * ipa-prop.c (ipa_make_edge_direct_to_target): Fixup callgraph when target is + referenced for firs ttime. + +2013-02-20 Richard Biener <rguenther@suse.de> + + * tree-call-cdce.c (tree_call_cdce): Do not remove unused locals. + * tree-ssa-forwprop.c (ssa_forward_propagate_and_combine): Likewise. + * tree-ssa-dce.c (perform_tree_ssa_dce): Likewise. + * tree-ssa-copyrename.c (copy_rename_partition_coalesce): Do + not return anything. + (rename_ssa_copies): Do not remove unused locals. + * tree-ssa-ccp.c (do_ssa_ccp): Likewise. + * tree-ssanames.c (pass_release_ssa_names): Remove unused + locals first. + * passes.c (execute_function_todo): Do not schedule unused locals + removal if cleanup_tree_cfg did something. + * tree-ssa-live.c (remove_unused_locals): Dump statistics + about the number of removed locals. + +2013-02-20 Richard Biener <rguenther@suse.de> + + PR tree-optimization/56398 + * tree-vect-loop-manip.c (adjust_debug_stmts): Skip + SSA default defs. + +2013-02-20 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/55334 + * ipa-cp.c (initialize_node_lattices): Disable IPA-CP through and to + restricted pointers to arrays. + +2013-02-20 Richard Biener <rguenther@suse.de> + Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/56396 + * tree-ssa-ccp.c (n_const_val): New static variable. + (get_value): Return NULL for SSA names we don't have a lattice + entry for. + (ccp_initialize): Initialize n_const_val. + * tree-ssa-copy.c (n_copy_of): New static variable. + (init_copy_prop): Initialize n_copy_of. + (get_value): Return NULL_TREE for SSA names we don't have a + lattice entry for. + +2013-02-20 Martin Jambor <mjambor@suse.cz> + + * ipa-cp.c (initialize_node_lattices): Fix dumping condition. + +2013-02-20 Richard Biener <rguenther@suse.de> + + * genpreds.c (write_lookup_constraint): Do not compare first + letter of the constraint again. + +2013-02-20 Richard Biener <rguenther@suse.de> + + * tree-ssa-loop-ivopts.c (alloc_use_cost_map): Use bitmap_count_bits + and ceil_log2. + (get_use_iv_cost): Terminate hashtable walk when coming across + an empty entry. + +2013-02-20 Igor Zamyatin <igor.zamyatin@intel.com> + + * config/i386/i386.c (initial_ix86_tune_features): Turn on fp + reassociation for avx2 targets. + +2012-02-19 Edgar E. Iglesias <edgar.iglesias@gmail.com> + + * config/microblaze/microblaze.c: microblaze_has_clz = 0 + Add version check for v8.10.a to enable microblaze_has_clz + * config/microblaze/microblaze.h: Add TARGET_HAS_CLZ as combined + version and TARGET_PATTERN_COMPARE check + * config/microblaze/microblaze.md: New clzsi2 instruction + +2012-02-19 Edgar E. Iglesias <edgar.iglesias@gmail.com> + + * config/microblaze/microblaze.md (call_value_intern): Check symbol is + function before branching. + +2012-02-19 Andrey Belevantsev <abel@ispras.ru> + + * sel-sched-dump.c (dump_insn_rtx_flags): Explicitly set + DUMP_INSN_RTX_UID. + (dump_insn_rtx_1): Pass PATTERN (insn) to str_pattern_slim. + +2012-02-19 Andrey Belevantsev <abel@ispras.ru> + + PR middle-end/55889 + + * sel-sched.c: Include ira.h. + (implicit_clobber_conflict_p): New function. + (moveup_expr): Use it. + * Makefile.in (sel-sched.o): Depend on ira.h. + +2013-02-19 Richard Biener <rguenther@suse.de> + + PR tree-optimization/56384 + * tree-ssa-sccvn.h (struct vn_phi_s): Add type member. + (vn_hash_type): Split out from ... + (vn_hash_constant_with_type): ... here. + * tree-ssa-sccvn.c (vn_phi_compute_hash): Use vn_hash_type. + (vn_phi_eq): Compare types from vn_phi_s structure. + (vn_phi_lookup): Populate vn_phi_s type. + (vn_phi_insert): Likewise. + +2013-02-19 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/56350 + * tree-vect-loop.c (vectorizable_reduction): If orig_stmt, return false + if haven't found reduction or nested cycle operand, rather than + asserting we must find it. + + PR tree-optimization/56381 + * tree-ssa-pre.c (create_expression_by_pieces): Fix up last argument + to fold_build3. + +2013-02-18 Aldy Hernandez <aldyh@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + PR target/52555 + * genopinit.c (raw_optab_handler): Use this_fn_optabs. + (swap_optab_enable): Same. + (init_all_optabs): Use argument instead of global. + * tree.h (struct tree_optimization_option): New field + target_optabs. + * expr.h (init_all_optabs): Add argument to prototype. + (TREE_OPTIMIZATION_OPTABS): New. + (save_optabs_if_changed): Protoize. + * optabs.h: Declare this_fn_optabs. + * optabs.c (save_optabs_if_changed): New. + Declare this_fn_optabs. + (init_optabs): Add argument to init_all_optabs() call. + * function.c (invoke_set_current_function_hook): Handle per + function optabs. + * function.h (struct function): New field optabs. + * config/mips/mips.c (mips_set_mips16_mode): Handle when + optimization_current_node has changed. + * target-globals.h (save_target_globals_default_opts): Protoize. + * target-globals.c (save_target_globals_default_opts): New. + 2013-02-18 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> PR target/56347 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 9e056c92577..cea0916f9b7 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20130218 +20130222 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index ce34c04792b..c6bdac88e3b 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -3443,7 +3443,7 @@ sel-sched.o : sel-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(FUNCTION_H) $(INSN_ATTR_H) $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \ $(TM_P_H) output.h $(TARGET_H) $(TREE_PASS_H) \ $(SCHED_INT_H) $(GGC_H) $(TREE_H) langhooks.h rtlhooks-def.h \ - $(SEL_SCHED_IR_H) $(SEL_SCHED_DUMP_H) sel-sched.h $(DBGCNT_H) $(EMIT_RTL_H) + $(SEL_SCHED_IR_H) $(SEL_SCHED_DUMP_H) sel-sched.h $(DBGCNT_H) $(EMIT_RTL_H) ira.h sel-sched-dump.o : sel-sched-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \ $(FUNCTION_H) $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \ diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 385e77118a3..d23568fedd6 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2013-02-21 Jakub Jelinek <jakub@redhat.com> + + PR bootstrap/56258 + * gnat-style.texi (@title): Remove @hfill. + * projects.texi: Avoid line wrapping inside of @pxref or + @xref. + 2013-02-14 Rainer Emrich <rainer@emrich-ebersheim.de> PR target/52123 diff --git a/gcc/ada/gnat-style.texi b/gcc/ada/gnat-style.texi index 43e6b4310a1..df2d491e14f 100644 --- a/gcc/ada/gnat-style.texi +++ b/gcc/ada/gnat-style.texi @@ -42,7 +42,7 @@ Texts. A copy of the license is included in the section entitled @titlepage @titlefont{GNAT Coding Style:} @sp 1 -@title @hfill A Guide for GNAT Developers +@title A Guide for GNAT Developers @subtitle GNAT, The GNU Ada Compiler @versionsubtitle @author Ada Core Technologies, Inc. diff --git a/gcc/ada/projects.texi b/gcc/ada/projects.texi index 6bf1e0c7c20..32ae8f66c5f 100644 --- a/gcc/ada/projects.texi +++ b/gcc/ada/projects.texi @@ -48,8 +48,7 @@ project files allow you to specify: @item Source file naming conventions; you can specify these either globally or for individual compilation units (@pxref{Naming Schemes}). @item Change any of the above settings depending on external values, thus enabling - the reuse of the projects in various @b{scenarios} (@pxref{Scenarios - in Projects}). + the reuse of the projects in various @b{scenarios} (@pxref{Scenarios in Projects}). @item Automatically build libraries as part of the build process (@pxref{Library Projects}). @@ -360,8 +359,8 @@ locating the specified source files in the specified source directories. @item For various reasons, it is sometimes useful to have a project with no sources (most of the time because the attributes defined in the project - file will be reused in other projects, as explained in @pxref{Organizing - Projects into Subsystems}. To do this, the attribute + file will be reused in other projects, as explained in + @pxref{Organizing Projects into Subsystems}. To do this, the attribute @emph{Source_Files} is set to the empty list, i.e. @code{()}. Alternatively, @emph{Source_Dirs} can be set to the empty list, with the same result. @@ -388,8 +387,9 @@ locating the specified source files in the specified source directories. This can be done thanks to the attribute @b{Excluded_Source_Files} (or its synonym @b{Locally_Removed_Files}). Its value is the list of file names that should not be taken into account. - This attribute is often used when extending a project, @xref{Project - Extension}. A similar attribute @b{Excluded_Source_List_File} plays the same + This attribute is often used when extending a project, + @xref{Project Extension}. A similar attribute + @b{Excluded_Source_List_File} plays the same role but takes the name of file containing file names similarly to @code{Source_List_File}. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 16ef84a3634..50ad1016f7c 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,17 @@ +2013-02-18 Aldy Hernandez <aldyh@redhat.com> + + PR target/52555 + * c-common.c (handle_optimize_attribute): Call + save_optabs_if_changed. + +2013-02-18 Jakub Jelinek <jakub@redhat.com> + Steven Bosscher <steven@gcc.gnu.org> + + PR pch/54117 + * c-opts.c (c_common_post_options): If debug info is enabled + and non-dwarf*, refuse to load PCH files and when writing PCH + file warn. + 2013-02-05 Jakub Jelinek <jakub@redhat.com> PR middle-end/56167 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 1e6afaa77f2..a1d47a68045 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -8925,6 +8925,8 @@ handle_optimize_attribute (tree *node, tree name, tree args, DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = build_optimization_node (); + save_optabs_if_changed (*node); + /* Restore current options. */ cl_optimization_restore (&global_options, &cur_opts); } diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index 1a922a81c35..4b6990a60c1 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -945,6 +945,16 @@ c_common_post_options (const char **pfilename) because the default address space slot then can't be used for the output PCH file. */ if (pch_file) + { + c_common_no_more_pch (); + /* Only -g0 and -gdwarf* are supported with PCH, for other + debug formats we warn here and refuse to load any PCH files. */ + if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG) + warning (OPT_Wdeprecated, + "the \"%s\" debug format cannot be used with " + "pre-compiled headers", debug_type_names[write_symbols]); + } + else if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG) c_common_no_more_pch (); /* Yuk. WTF is this? I do know ObjC relies on it somewhere. */ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 9a94c36bea9..b835c5da2ab 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2021,7 +2021,7 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = { /* X86_TUNE_REASSOC_FP_TO_PARALLEL: Try to produce parallel computations during reassociation of fp computation. */ - m_ATOM, + m_ATOM | m_HASWELL, /* X86_TUNE_GENERAL_REGS_SSE_SPILL: Try to spill general regs to SSE regs instead of memory. */ @@ -5436,7 +5436,8 @@ ix86_legitimate_combined_insn (rtx insn) static unsigned HOST_WIDE_INT ix86_asan_shadow_offset (void) { - return TARGET_LP64 ? (HOST_WIDE_INT_1 << 44) + return TARGET_LP64 ? (TARGET_MACHO ? (HOST_WIDE_INT_1 << 44) + : HOST_WIDE_INT_C (0x7fff8000)) : (HOST_WIDE_INT_1 << 29); } diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c index 449626b2e38..fc0296e2c15 100644 --- a/gcc/config/microblaze/microblaze.c +++ b/gcc/config/microblaze/microblaze.c @@ -143,6 +143,9 @@ int microblaze_section_threshold = -1; delay slots. -mcpu=v3.00.a or v4.00.a turns this on. */ int microblaze_no_unsafe_delay; +/* Set to one if the targeted core has the CLZ insn. */ +int microblaze_has_clz = 0; + /* Which CPU pipeline do we use. We haven't really standardized on a CPU version having only a particular type of pipeline. There can still be options on the CPU to scale pipeline features up or down. :( @@ -1369,6 +1372,14 @@ microblaze_option_override (void) "-mxl-multiply-high can be used only with -mcpu=v6.00.a or greater"); } + ver = MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v8.10.a"); + microblaze_has_clz = 1; + if (ver < 0) + { + /* MicroBlaze prior to 8.10.a didn't have clz. */ + microblaze_has_clz = 0; + } + if (TARGET_MULTIPLY_HIGH && TARGET_SOFT_MUL) error ("-mxl-multiply-high requires -mno-xl-soft-mul"); diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h index b552665ac63..a188a2eb113 100644 --- a/gcc/config/microblaze/microblaze.h +++ b/gcc/config/microblaze/microblaze.h @@ -42,6 +42,7 @@ extern int microblaze_section_threshold; extern int microblaze_dbx_regno[]; extern int microblaze_no_unsafe_delay; +extern int microblaze_has_clz; extern enum pipeline_type microblaze_pipe; #define OBJECT_FORMAT_ELF @@ -58,6 +59,9 @@ extern enum pipeline_type microblaze_pipe; #define TARGET_DEFAULT (MASK_SOFT_MUL | MASK_SOFT_DIV | MASK_SOFT_FLOAT \ | TARGET_ENDIAN_DEFAULT) +/* Do we have CLZ? */ +#define TARGET_HAS_CLZ (TARGET_PATTERN_COMPARE && microblaze_has_clz) + /* The default is to support PIC. */ #define TARGET_SUPPORTS_PIC 1 diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md index 1d55a167be4..1b4200307cb 100644 --- a/gcc/config/microblaze/microblaze.md +++ b/gcc/config/microblaze/microblaze.md @@ -2128,9 +2128,17 @@ register rtx target = operands[1]; register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM); - if (GET_CODE (target) == SYMBOL_REF){ - gen_rtx_CLOBBER (VOIDmode,target2); - return "brlid\tr15,%1\;%#"; + if (GET_CODE (target) == SYMBOL_REF) + { + gen_rtx_CLOBBER (VOIDmode,target2); + if (SYMBOL_REF_FLAGS (target) & SYMBOL_FLAG_FUNCTION) + { + return "brlid\tr15,%1\;%#"; + } + else + { + return "bralid\tr15,%1\;%#"; + } } else if (GET_CODE (target) == CONST_INT) return "la\t%@,r0,%1\;brald\tr15,%@\;%#"; @@ -2192,3 +2200,13 @@ [(set_attr "type" "multi") (set_attr "length" "12")]) +;; This insn gives the count of leading number of zeros for the second +;; operand and stores the result in first operand. +(define_insn "clzsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (clz:SI (match_operand:SI 1 "register_operand" "r")))] + "TARGET_HAS_CLZ" + "clz\t%0,%1" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "4")]) diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index b203cdd1ed2..252e828480e 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -16313,7 +16313,7 @@ mips_set_mips16_mode (int mips16_p) if (mips16_p) { if (!mips16_globals) - mips16_globals = save_target_globals (); + mips16_globals = save_target_globals_default_opts (); else restore_target_globals (mips16_globals); } diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 52fac3af74c..b7816a90339 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2013-02-20 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/56373 + * tree.c (maybe_warn_zero_as_null_pointer_constant): Add. + * cvt.c (ocp_convert): Use the latter. + (cp_convert_to_pointer): Likewise. + * decl.c (check_default_argument): Likewise. + * typeck.c (cp_build_binary_op): Likewise. + * cp-tree.h (maybe_warn_zero_as_null_pointer_constant): Declare. + 2013-02-15 Jonathan Wakely <jwakely.gcc@gmail.com> Paolo Carlini <paolo.carlini@oracle.com> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d9270e2270d..4a597d8b3a6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5834,6 +5834,7 @@ extern bool cast_valid_in_integral_constant_expression_p (tree); extern bool cxx_type_hash_eq (const_tree, const_tree); extern void cxx_print_statistics (void); +extern bool maybe_warn_zero_as_null_pointer_constant (tree, location_t); /* in ptree.c */ extern void cxx_print_xnode (FILE *, tree, int); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 8e8ce53325e..348e6082ceb 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -203,11 +203,8 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain) if (null_ptr_cst_p (expr)) { - if ((complain & tf_warning) - && c_inhibit_evaluation_warnings == 0 - && !NULLPTR_TYPE_P (TREE_TYPE (expr))) - warning_at (loc, OPT_Wzero_as_null_pointer_constant, - "zero as null pointer constant"); + if (complain & tf_warning) + maybe_warn_zero_as_null_pointer_constant (expr, loc); if (TYPE_PTRMEMFUNC_P (type)) return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0, @@ -783,7 +780,11 @@ ocp_convert (tree type, tree expr, int convtype, int flags, return ignore_overflows (converted, e); } if (NULLPTR_TYPE_P (type) && e && null_ptr_cst_p (e)) - return nullptr_node; + { + if (complain & tf_warning) + maybe_warn_zero_as_null_pointer_constant (e, loc); + return nullptr_node; + } if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type)) return fold_if_not_in_template (cp_convert_to_pointer (type, e, complain)); if (code == VECTOR_TYPE) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 3d63389e404..661969f441c 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -10861,15 +10861,10 @@ check_default_argument (tree decl, tree arg) --cp_unevaluated_operand; if (warn_zero_as_null_pointer_constant - && c_inhibit_evaluation_warnings == 0 && TYPE_PTR_OR_PTRMEM_P (decl_type) && null_ptr_cst_p (arg) - && !NULLPTR_TYPE_P (TREE_TYPE (arg))) - { - warning (OPT_Wzero_as_null_pointer_constant, - "zero as null pointer constant"); - return nullptr_node; - } + && maybe_warn_zero_as_null_pointer_constant (arg, input_location)) + return nullptr_node; /* [dcl.fct.default] diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 0b033c2bfb4..41c8759096c 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -3939,6 +3939,21 @@ cp_tree_operand_length (const_tree t) return TREE_OPERAND_LENGTH (t); } } + +/* Implement -Wzero_as_null_pointer_constant. Return true if the + conditions for the warning hold, false otherwise. */ +bool +maybe_warn_zero_as_null_pointer_constant (tree expr, location_t loc) +{ + if (c_inhibit_evaluation_warnings == 0 + && !NULLPTR_TYPE_P (TREE_TYPE (expr))) + { + warning_at (loc, OPT_Wzero_as_null_pointer_constant, + "zero as null pointer constant"); + return true; + } + return false; +} #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) /* Complain that some language-specific thing hanging off a tree diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 688c2665b4f..58295d73d15 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4293,12 +4293,9 @@ cp_build_binary_op (location_t location, delta0, integer_one_node, complain); - - if ((complain & tf_warning) - && c_inhibit_evaluation_warnings == 0 - && !NULLPTR_TYPE_P (TREE_TYPE (op1))) - warning (OPT_Wzero_as_null_pointer_constant, - "zero as null pointer constant"); + + if (complain & tf_warning) + maybe_warn_zero_as_null_pointer_constant (op1, input_location); e2 = cp_build_binary_op (location, EQ_EXPR, e2, integer_zero_node, diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index a444dbafb75..49a04ccc262 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -5617,7 +5617,7 @@ Dump after the peephole pass. @opindex fdump-rtl-postreload Dump after post-reload optimizations. -@itemx -fdump-rtl-pro_and_epilogue +@item -fdump-rtl-pro_and_epilogue @opindex fdump-rtl-pro_and_epilogue Dump after generating the function prologues and epilogues. @@ -16445,10 +16445,12 @@ Enable (disable) use of the floating-point multiply-accumulate instructions, when they are available. The default is @option{-mfused-madd}. -When multiply-accumulate instructions are used, the intermediate -product is calculated to infinite precision and is not subject to -the FCSR Flush to Zero bit. This may be undesirable in some -circumstances. +On the R8000 CPU when multiply-accumulate instructions are used, +the intermediate product is calculated to infinite precision +and is not subject to the FCSR Flush to Zero bit. This may be +undesirable in some circumstances. On other processors the result +is numerically identical to the equivalent computation using +separate multiply, add, subtract and negate instructions. @item -nocpp @opindex nocpp diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index b0b0723af2e..aa33d1cd80d 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -2627,17 +2627,18 @@ The result mode @var{m} is either the submode for a single element of with that element submode (if multiple subparts are selected). @findex vec_concat -@item (vec_concat:@var{m} @var{vec1} @var{vec2}) +@item (vec_concat:@var{m} @var{x1} @var{x2}) Describes a vector concat operation. The result is a concatenation of the -vectors @var{vec1} and @var{vec2}; its length is the sum of the lengths of -the two inputs. +vectors or scalars @var{x1} and @var{x2}; its length is the sum of the +lengths of the two inputs. @findex vec_duplicate -@item (vec_duplicate:@var{m} @var{vec}) -This operation converts a small vector into a larger one by duplicating the -input values. The output vector mode must have the same submodes as the -input vector mode, and the number of output parts must be an integer multiple -of the number of input parts. +@item (vec_duplicate:@var{m} @var{x}) +This operation converts a scalar into a vector or a small vector into a +larger one by duplicating the input values. The output vector mode must have +the same submodes as the input vector mode or the scalar modes, and the +number of output parts must be an integer multiple of the number of input +parts. @end table diff --git a/gcc/expmed.c b/gcc/expmed.c index 954a360c7b2..d66c6e667fb 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -64,7 +64,8 @@ static rtx expand_smod_pow2 (enum machine_mode, rtx, HOST_WIDE_INT); static rtx expand_sdiv_pow2 (enum machine_mode, rtx, HOST_WIDE_INT); /* Test whether a value is zero of a power of two. */ -#define EXACT_POWER_OF_2_OR_ZERO_P(x) (((x) & ((x) - 1)) == 0) +#define EXACT_POWER_OF_2_OR_ZERO_P(x) \ + (((x) & ((x) - (unsigned HOST_WIDE_INT) 1)) == 0) struct init_expmed_rtl { @@ -3079,7 +3080,10 @@ expand_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, /* If we are multiplying in DImode, it may still be a win to try to work with shifts and adds. */ if (CONST_DOUBLE_HIGH (scalar_op1) == 0 - && CONST_DOUBLE_LOW (scalar_op1) > 0) + && (CONST_DOUBLE_LOW (scalar_op1) > 0 + || (CONST_DOUBLE_LOW (scalar_op1) < 0 + && EXACT_POWER_OF_2_OR_ZERO_P + (CONST_DOUBLE_LOW (scalar_op1))))) { coeff = CONST_DOUBLE_LOW (scalar_op1); is_neg = false; @@ -3109,7 +3113,8 @@ expand_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, use synth_mult. */ /* Special case powers of two. */ - if (EXACT_POWER_OF_2_OR_ZERO_P (coeff)) + if (EXACT_POWER_OF_2_OR_ZERO_P (coeff) + && !(is_neg && mode_bitsize > HOST_BITS_PER_WIDE_INT)) return expand_shift (LSHIFT_EXPR, mode, op0, floor_log2 (coeff), target, unsignedp); @@ -3124,13 +3129,24 @@ expand_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, result is interpreted as an unsigned coefficient. Exclude cost of op0 from max_cost to match the cost calculation of the synth_mult. */ + coeff = -(unsigned HOST_WIDE_INT) coeff; max_cost = (set_src_cost (gen_rtx_MULT (mode, fake_reg, op1), speed) - neg_cost(speed, mode)); - if (max_cost > 0 - && choose_mult_variant (mode, -coeff, &algorithm, - &variant, max_cost)) + if (max_cost <= 0) + goto skip_synth; + + /* Special case powers of two. */ + if (EXACT_POWER_OF_2_OR_ZERO_P (coeff)) + { + rtx temp = expand_shift (LSHIFT_EXPR, mode, op0, + floor_log2 (coeff), target, unsignedp); + return expand_unop (mode, neg_optab, temp, target, 0); + } + + if (choose_mult_variant (mode, coeff, &algorithm, &variant, + max_cost)) { - rtx temp = expand_mult_const (mode, op0, -coeff, NULL_RTX, + rtx temp = expand_mult_const (mode, op0, coeff, NULL_RTX, &algorithm, variant); return expand_unop (mode, neg_optab, temp, target, 0); } @@ -3813,13 +3829,12 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode, int op1_is_constant, op1_is_pow2 = 0; int max_cost, extra_cost; static HOST_WIDE_INT last_div_const = 0; - static HOST_WIDE_INT ext_op1; bool speed = optimize_insn_for_speed_p (); op1_is_constant = CONST_INT_P (op1); if (op1_is_constant) { - ext_op1 = INTVAL (op1); + unsigned HOST_WIDE_INT ext_op1 = UINTVAL (op1); if (unsignedp) ext_op1 &= GET_MODE_MASK (mode); op1_is_pow2 = ((EXACT_POWER_OF_2_OR_ZERO_P (ext_op1) @@ -3967,7 +3982,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode, op1_is_pow2 = (op1_is_constant && ((EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1)) || (! unsignedp - && EXACT_POWER_OF_2_OR_ZERO_P (-INTVAL (op1)))))) ; + && EXACT_POWER_OF_2_OR_ZERO_P (-UINTVAL (op1)))))); } /* If one of the operands is a volatile MEM, copy it into a register. */ diff --git a/gcc/expr.c b/gcc/expr.c index 08c5c9d0c58..d225479e84e 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -9551,6 +9551,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, set_mem_addr_space (temp, as); align = get_object_alignment (exp); if (modifier != EXPAND_WRITE + && modifier != EXPAND_MEMORY && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode) /* If the target does not have special handling for unaligned @@ -9639,6 +9640,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, if (TREE_THIS_VOLATILE (exp)) MEM_VOLATILE_P (temp) = 1; if (modifier != EXPAND_WRITE + && modifier != EXPAND_MEMORY && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode)) { diff --git a/gcc/expr.h b/gcc/expr.h index f5063b47cdd..15fcb471d8d 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -718,7 +718,7 @@ extern bool split_comparison (enum rtx_code, enum machine_mode, /* Call this once to initialize the contents of the optabs appropriately for the current target machine. */ extern void init_optabs (void); -extern void init_all_optabs (void); +extern void init_all_optabs (struct target_optabs *); /* Call this to initialize an optab function entry. */ extern rtx init_one_libfunc (const char *); diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 277ad3ef595..8aeded26d16 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,17 @@ +2013-02-21 Janus Weil <janus@gcc.gnu.org> + + PR fortran/56385 + * trans-array.c (structure_alloc_comps): Handle procedure-pointer + components with allocatable result. + +2012-02-21 Tobias Burnus <burnus@net-b.de> + + PR fortran/56416 + * gfortran.texi (Part II: Language Reference, Extensions, + Non-Fortran Main Program): Sort @menu to match actual section order. + * intrinsic.texi (Intrinsic Procedures): Ditto. + (C_F_POINTER, PRECISION): Move to the alphabetically correct place. + 2013-02-15 Tobias Burnus <burnus@net-b.de> Mikael Morin <mikael@gcc.gnu.org> diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index 2dccb16d81a..462b4436615 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -182,8 +182,8 @@ Part I: Invoking GNU Fortran Part II: Language Reference * Fortran 2003 and 2008 status:: Fortran 2003 and 2008 features supported by GNU Fortran. * Compiler Characteristics:: User-visible implementation details. +* Extensions:: Language extensions implemented by GNU Fortran. * Mixed-Language Programming:: Interoperability with C -* Extensions:: Language extensions implemented by GNU Fortran. * Intrinsic Procedures:: Intrinsic procedures supported by GNU Fortran. * Intrinsic Modules:: Intrinsic modules supported by GNU Fortran. @@ -1348,8 +1348,8 @@ without warning. * Commas in FORMAT specifications:: * Missing period in FORMAT specifications:: * I/O item lists:: -* BOZ literal constants:: * @code{Q} exponent-letter:: +* BOZ literal constants:: * Real array indices:: * Unary operators:: * Implicitly convert LOGICAL and INTEGER values:: @@ -2698,8 +2698,8 @@ the same declaration part as the variable or procedure pointer. * _gfortran_set_options:: Set library option flags * _gfortran_set_convert:: Set endian conversion * _gfortran_set_record_marker:: Set length of record markers -* _gfortran_set_max_subrecord_length:: Set subrecord length * _gfortran_set_fpe:: Set when a Floating Point Exception should be raised +* _gfortran_set_max_subrecord_length:: Set subrecord length @end menu Even if you are doing mixed-language programming, it is very diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi index 91f2fea8320..4a48425cd83 100644 --- a/gcc/fortran/intrinsic.texi +++ b/gcc/fortran/intrinsic.texi @@ -87,9 +87,9 @@ Some basic guidelines for editing this document: * @code{CHMOD}: CHMOD, Change access permissions of files * @code{CMPLX}: CMPLX, Complex conversion function * @code{COMMAND_ARGUMENT_COUNT}: COMMAND_ARGUMENT_COUNT, Get number of command line arguments -* @code{COMPLEX}: COMPLEX, Complex conversion function -* @code{COMPILER_VERSION}: COMPILER_VERSION, Compiler version string * @code{COMPILER_OPTIONS}: COMPILER_OPTIONS, Options passed to the compiler +* @code{COMPILER_VERSION}: COMPILER_VERSION, Compiler version string +* @code{COMPLEX}: COMPLEX, Complex conversion function * @code{CONJG}: CONJG, Complex conjugate function * @code{COS}: COS, Cosine function * @code{COSH}: COSH, Hyperbolic cosine function @@ -234,12 +234,12 @@ Some basic guidelines for editing this document: * @code{PRESENT}: PRESENT, Determine whether an optional dummy argument is specified * @code{PRODUCT}: PRODUCT, Product of array elements * @code{RADIX}: RADIX, Base of a data model +* @code{RAN}: RAN, Real pseudo-random number +* @code{RAND}: RAND, Real pseudo-random number * @code{RANDOM_NUMBER}: RANDOM_NUMBER, Pseudo-random number * @code{RANDOM_SEED}: RANDOM_SEED, Initialize a pseudo-random number sequence -* @code{RAND}: RAND, Real pseudo-random number * @code{RANGE}: RANGE, Decimal exponent range * @code{RANK} : RANK, Rank of a data object -* @code{RAN}: RAN, Real pseudo-random number * @code{REAL}: REAL, Convert to real type * @code{RENAME}: RENAME, Rename a file * @code{REPEAT}: REPEAT, Repeated string concatenation @@ -2271,60 +2271,57 @@ end subroutine association_test @end table -@node C_FUNLOC -@section @code{C_FUNLOC} --- Obtain the C address of a procedure -@fnindex C_FUNLOC -@cindex pointer, C address of procedures +@node C_F_POINTER +@section @code{C_F_POINTER} --- Convert C into Fortran pointer +@fnindex C_F_POINTER +@cindex pointer, convert C to Fortran @table @asis @item @emph{Description}: -@code{C_FUNLOC(x)} determines the C address of the argument. +@code{C_F_POINTER(CPTR, FPTR[, SHAPE])} assigns the target of the C pointer +@var{CPTR} to the Fortran pointer @var{FPTR} and specifies its shape. @item @emph{Standard}: Fortran 2003 and later @item @emph{Class}: -Inquiry function +Subroutine @item @emph{Syntax}: -@code{RESULT = C_FUNLOC(x)} +@code{CALL C_F_POINTER(CPTR, FPTR[, SHAPE])} @item @emph{Arguments}: @multitable @columnfractions .15 .70 -@item @var{x} @tab Interoperable function or pointer to such function. +@item @var{CPTR} @tab scalar of the type @code{C_PTR}. It is +@code{INTENT(IN)}. +@item @var{FPTR} @tab pointer interoperable with @var{cptr}. It is +@code{INTENT(OUT)}. +@item @var{SHAPE} @tab (Optional) Rank-one array of type @code{INTEGER} +with @code{INTENT(IN)}. It shall be present +if and only if @var{fptr} is an array. The size +must be equal to the rank of @var{fptr}. @end multitable -@item @emph{Return value}: -The return value is of type @code{C_FUNPTR} and contains the C address -of the argument. - @item @emph{Example}: @smallexample -module x - use iso_c_binding - implicit none -contains - subroutine sub(a) bind(c) - real(c_float) :: a - a = sqrt(a)+5.0 - end subroutine sub -end module x program main use iso_c_binding - use x implicit none interface subroutine my_routine(p) bind(c,name='myC_func') - import :: c_funptr - type(c_funptr), intent(in) :: p + import :: c_ptr + type(c_ptr), intent(out) :: p end subroutine end interface - call my_routine(c_funloc(sub)) + type(c_ptr) :: cptr + real,pointer :: a(:) + call my_routine(cptr) + call c_f_pointer(cptr, a, [12]) end program main @end smallexample @item @emph{See also}: -@ref{C_ASSOCIATED}, @ref{C_LOC}, @ref{C_F_POINTER}, @ref{C_F_PROCPOINTER} +@ref{C_LOC}, @ref{C_F_PROCPOINTER} @end table @@ -2385,57 +2382,60 @@ end program main @end table -@node C_F_POINTER -@section @code{C_F_POINTER} --- Convert C into Fortran pointer -@fnindex C_F_POINTER -@cindex pointer, convert C to Fortran +@node C_FUNLOC +@section @code{C_FUNLOC} --- Obtain the C address of a procedure +@fnindex C_FUNLOC +@cindex pointer, C address of procedures @table @asis @item @emph{Description}: -@code{C_F_POINTER(CPTR, FPTR[, SHAPE])} assigns the target of the C pointer -@var{CPTR} to the Fortran pointer @var{FPTR} and specifies its shape. +@code{C_FUNLOC(x)} determines the C address of the argument. @item @emph{Standard}: Fortran 2003 and later @item @emph{Class}: -Subroutine +Inquiry function @item @emph{Syntax}: -@code{CALL C_F_POINTER(CPTR, FPTR[, SHAPE])} +@code{RESULT = C_FUNLOC(x)} @item @emph{Arguments}: @multitable @columnfractions .15 .70 -@item @var{CPTR} @tab scalar of the type @code{C_PTR}. It is -@code{INTENT(IN)}. -@item @var{FPTR} @tab pointer interoperable with @var{cptr}. It is -@code{INTENT(OUT)}. -@item @var{SHAPE} @tab (Optional) Rank-one array of type @code{INTEGER} -with @code{INTENT(IN)}. It shall be present -if and only if @var{fptr} is an array. The size -must be equal to the rank of @var{fptr}. +@item @var{x} @tab Interoperable function or pointer to such function. @end multitable +@item @emph{Return value}: +The return value is of type @code{C_FUNPTR} and contains the C address +of the argument. + @item @emph{Example}: @smallexample +module x + use iso_c_binding + implicit none +contains + subroutine sub(a) bind(c) + real(c_float) :: a + a = sqrt(a)+5.0 + end subroutine sub +end module x program main use iso_c_binding + use x implicit none interface subroutine my_routine(p) bind(c,name='myC_func') - import :: c_ptr - type(c_ptr), intent(out) :: p + import :: c_funptr + type(c_funptr), intent(in) :: p end subroutine end interface - type(c_ptr) :: cptr - real,pointer :: a(:) - call my_routine(cptr) - call c_f_pointer(cptr, a, [12]) + call my_routine(c_funloc(sub)) end program main @end smallexample @item @emph{See also}: -@ref{C_LOC}, @ref{C_F_PROCPOINTER} +@ref{C_ASSOCIATED}, @ref{C_LOC}, @ref{C_F_POINTER}, @ref{C_F_PROCPOINTER} @end table @@ -9749,51 +9749,6 @@ default kind. -@node PRECISION -@section @code{PRECISION} --- Decimal precision of a real kind -@fnindex PRECISION -@cindex model representation, precision - -@table @asis -@item @emph{Description}: -@code{PRECISION(X)} returns the decimal precision in the model of the -type of @code{X}. - -@item @emph{Standard}: -Fortran 95 and later - -@item @emph{Class}: -Inquiry function - -@item @emph{Syntax}: -@code{RESULT = PRECISION(X)} - -@item @emph{Arguments}: -@multitable @columnfractions .15 .70 -@item @var{X} @tab Shall be of type @code{REAL} or @code{COMPLEX}. -@end multitable - -@item @emph{Return value}: -The return value is of type @code{INTEGER} and of the default integer -kind. - -@item @emph{See also}: -@ref{SELECTED_REAL_KIND}, @ref{RANGE} - -@item @emph{Example}: -@smallexample -program prec_and_range - real(kind=4) :: x(2) - complex(kind=8) :: y - - print *, precision(x), range(x) - print *, precision(y), range(y) -end program prec_and_range -@end smallexample -@end table - - - @node POPCNT @section @code{POPCNT} --- Number of bits set @fnindex POPCNT @@ -9883,6 +9838,51 @@ end program test_population +@node PRECISION +@section @code{PRECISION} --- Decimal precision of a real kind +@fnindex PRECISION +@cindex model representation, precision + +@table @asis +@item @emph{Description}: +@code{PRECISION(X)} returns the decimal precision in the model of the +type of @code{X}. + +@item @emph{Standard}: +Fortran 95 and later + +@item @emph{Class}: +Inquiry function + +@item @emph{Syntax}: +@code{RESULT = PRECISION(X)} + +@item @emph{Arguments}: +@multitable @columnfractions .15 .70 +@item @var{X} @tab Shall be of type @code{REAL} or @code{COMPLEX}. +@end multitable + +@item @emph{Return value}: +The return value is of type @code{INTEGER} and of the default integer +kind. + +@item @emph{See also}: +@ref{SELECTED_REAL_KIND}, @ref{RANGE} + +@item @emph{Example}: +@smallexample +program prec_and_range + real(kind=4) :: x(2) + complex(kind=8) :: y + + print *, precision(x), range(x) + print *, precision(y), range(y) +end program prec_and_range +@end smallexample +@end table + + + @node PRESENT @section @code{PRESENT} --- Determine whether an optional dummy argument is specified @fnindex PRESENT diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index ee2954e5bca..75fed2f651c 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -7547,8 +7547,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, called_dealloc_with_status = false; gfc_init_block (&tmpblock); - if (c->attr.allocatable - && (c->attr.dimension || c->attr.codimension)) + if (c->attr.allocatable && (c->attr.dimension || c->attr.codimension) + && !c->attr.proc_pointer) { comp = fold_build3_loc (input_location, COMPONENT_REF, ctype, decl, cdecl, NULL_TREE); @@ -7730,7 +7730,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, continue; } - if (c->attr.allocatable && !cmp_has_alloc_comps) + if (c->attr.allocatable && !c->attr.proc_pointer + && !cmp_has_alloc_comps) { rank = c->as ? c->as->rank : 0; tmp = gfc_duplicate_allocatable (dcmp, comp, ctype, rank); diff --git a/gcc/function.c b/gcc/function.c index 4ce2259ef71..1b41cf2cb34 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4400,6 +4400,26 @@ invoke_set_current_function_hook (tree fndecl) } targetm.set_current_function (fndecl); + + if (opts == optimization_default_node) + this_fn_optabs = this_target_optabs; + else + { + struct function *fn = DECL_STRUCT_FUNCTION (fndecl); + if (fn->optabs == NULL) + { + if (this_target_optabs == &default_target_optabs) + fn->optabs = TREE_OPTIMIZATION_OPTABS (opts); + else + { + fn->optabs = (unsigned char *) + ggc_alloc_atomic (sizeof (struct target_optabs)); + init_all_optabs ((struct target_optabs *) fn->optabs); + } + } + this_fn_optabs = fn->optabs ? (struct target_optabs *) fn->optabs + : this_target_optabs; + } } } diff --git a/gcc/function.h b/gcc/function.h index 89d71e592dd..53e28b768c0 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -580,6 +580,9 @@ struct GTY(()) function { a string describing the reason for failure. */ const char * GTY((skip)) cannot_be_copied_reason; + /* Optabs for this function. This is of type `struct target_optabs *'. */ + unsigned char *GTY ((atomic)) optabs; + /* Collected bit flags. */ /* Number of units of general registers that need saving in stdarg diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 1bb2f770d22..fb8071765dd 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -422,8 +422,8 @@ main (int argc, char **argv) fprintf (s_file, " { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name); fprintf (s_file, "};\n\n"); - fprintf (s_file, "void\ninit_all_optabs (void)\n{\n"); - fprintf (s_file, " bool *ena = this_target_optabs->pat_enable;\n"); + fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n"); + fprintf (s_file, " bool *ena = optabs->pat_enable;\n"); for (i = 0; patterns.iterate (i, &p); ++i) fprintf (s_file, " ena[%u] = HAVE_%s;\n", i, p->name); fprintf (s_file, "}\n\n"); @@ -456,7 +456,7 @@ main (int argc, char **argv) "raw_optab_handler (unsigned scode)\n" "{\n" " int i = lookup_handler (scode);\n" - " return (i >= 0 && this_target_optabs->pat_enable[i]\n" + " return (i >= 0 && this_fn_optabs->pat_enable[i]\n" " ? pats[i].icode : CODE_FOR_nothing);\n" "}\n\n"); @@ -468,8 +468,8 @@ main (int argc, char **argv) " int i = lookup_handler (scode);\n" " if (i >= 0)\n" " {\n" - " bool ret = this_target_optabs->pat_enable[i];\n" - " this_target_optabs->pat_enable[i] = set;\n" + " bool ret = this_fn_optabs->pat_enable[i];\n" + " this_fn_optabs->pat_enable[i] = set;\n" " return ret;\n" " }\n" " else\n" diff --git a/gcc/genpreds.c b/gcc/genpreds.c index 09fc87b3dd1..98488e30b8b 100644 --- a/gcc/genpreds.c +++ b/gcc/genpreds.c @@ -945,9 +945,10 @@ write_lookup_constraint (void) { do { - printf (" if (!strncmp (str, \"%s\", %lu))\n" + printf (" if (!strncmp (str + 1, \"%s\", %lu))\n" " return CONSTRAINT_%s;\n", - c->name, (unsigned long int) c->namelen, c->c_name); + c->name + 1, (unsigned long int) c->namelen - 1, + c->c_name); c = c->next_this_letter; } while (c); diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 332e623f41a..9a67f3c0be3 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -725,11 +725,27 @@ initialize_node_lattices (struct cgraph_node *node) set_all_contains_variable (plats); } if (dump_file && (dump_flags & TDF_DETAILS) - && node->alias && node->thunk.thunk_p) + && !node->alias && !node->thunk.thunk_p) fprintf (dump_file, "Marking all lattices of %s/%i as %s\n", cgraph_node_name (node), node->uid, disable ? "BOTTOM" : "VARIABLE"); } + if (!disable) + for (i = 0; i < ipa_get_param_count (info) ; i++) + { + struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); + tree t = TREE_TYPE (ipa_get_param(info, i)); + + if (POINTER_TYPE_P (t) && TYPE_RESTRICT (t) + && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) + { + set_lattice_to_bottom (&plats->itself); + if (dump_file && (dump_flags & TDF_DETAILS) + && !node->alias && !node->thunk.thunk_p) + fprintf (dump_file, "Going to ignore param %i of of %s/%i.\n", + i, cgraph_node_name (node), node->uid); + } + } for (ie = node->indirect_calls; ie; ie = ie->next_callee) if (ie->indirect_info->polymorphic) @@ -1638,7 +1654,7 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit, ") -> evaluation: " HOST_WIDEST_INT_PRINT_DEC ", threshold: %i\n", time_benefit, size_cost, (HOST_WIDE_INT) count_sum, - evaluation, 500); + evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD)); return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD); } @@ -1652,7 +1668,7 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit, "size: %i, freq_sum: %i) -> evaluation: " HOST_WIDEST_INT_PRINT_DEC ", threshold: %i\n", time_benefit, size_cost, freq_sum, evaluation, - CGRAPH_FREQ_BASE /2); + PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD)); return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD); } @@ -2791,12 +2807,15 @@ intersect_with_plats (struct ipcp_param_lattices *plats, vector result while subtracting OFFSET from the individual value offsets. */ static vec<ipa_agg_jf_item_t> -agg_replacements_to_vector (struct cgraph_node *node, HOST_WIDE_INT offset) +agg_replacements_to_vector (struct cgraph_node *node, int index, + HOST_WIDE_INT offset) { struct ipa_agg_replacement_value *av; vec<ipa_agg_jf_item_t> res = vNULL; for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next) + if (av->index == index + && (av->offset - offset) >= 0) { struct ipa_agg_jf_item item; gcc_checking_assert (av->value); @@ -2876,7 +2895,7 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, if (agg_pass_through_permissible_p (orig_plats, jfunc)) { if (!inter.exists ()) - inter = agg_replacements_to_vector (cs->caller, 0); + inter = agg_replacements_to_vector (cs->caller, src_idx, 0); else intersect_with_agg_replacements (cs->caller, src_idx, &inter, 0); @@ -2909,9 +2928,9 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, if (caller_info->ipcp_orig_node) { if (!inter.exists ()) - inter = agg_replacements_to_vector (cs->caller, delta); + inter = agg_replacements_to_vector (cs->caller, src_idx, delta); else - intersect_with_agg_replacements (cs->caller, index, &inter, + intersect_with_agg_replacements (cs->caller, src_idx, &inter, delta); } else diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 5cc222d49f7..f68349363b0 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -2100,10 +2100,65 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target) if (TREE_CODE (target) == ADDR_EXPR) target = TREE_OPERAND (target, 0); if (TREE_CODE (target) != FUNCTION_DECL) - return NULL; + { + target = canonicalize_constructor_val (target, NULL); + if (!target || TREE_CODE (target) != FUNCTION_DECL) + { + if (dump_file) + fprintf (dump_file, "ipa-prop: Discovered direct call to non-function" + " in (%s/%i).\n", + cgraph_node_name (ie->caller), ie->caller->uid); + return NULL; + } + } callee = cgraph_get_node (target); - if (!callee) - return NULL; + + /* Because may-edges are not explicitely represented and vtable may be external, + we may create the first reference to the object in the unit. */ + if (!callee || callee->global.inlined_to) + { + struct cgraph_node *first_clone = callee; + + /* We are better to ensure we can refer to it. + In the case of static functions we are out of luck, since we already + removed its body. In the case of public functions we may or may + not introduce the reference. */ + if (!canonicalize_constructor_val (target, NULL) + || !TREE_PUBLIC (target)) + { + if (dump_file) + fprintf (dump_file, "ipa-prop: Discovered call to a known target " + "(%s/%i -> %s/%i) but can not refer to it. Giving up.\n", + xstrdup (cgraph_node_name (ie->caller)), ie->caller->uid, + xstrdup (cgraph_node_name (ie->callee)), ie->callee->uid); + return NULL; + } + + /* Create symbol table node. Even if inline clone exists, we can not take + it as a target of non-inlined call. */ + callee = cgraph_create_node (target); + + /* OK, we previously inlined the function, then removed the offline copy and + now we want it back for external call. This can happen when devirtualizing + while inlining function called once that happens after extern inlined and + virtuals are already removed. In this case introduce the external node + and make it available for call. */ + if (first_clone) + { + first_clone->clone_of = callee; + callee->clones = first_clone; + symtab_prevail_in_asm_name_hash ((symtab_node)callee); + symtab_insert_node_to_hashtable ((symtab_node)callee); + if (dump_file) + fprintf (dump_file, "ipa-prop: Introduced new external node " + "(%s/%i) and turned into root of the clone tree.\n", + xstrdup (cgraph_node_name (callee)), callee->uid); + } + else if (dump_file) + fprintf (dump_file, "ipa-prop: Introduced new external node " + "(%s/%i).\n", + xstrdup (cgraph_node_name (callee)), callee->uid); + } ipa_check_create_node_params (); /* We can not make edges to inline clones. It is bug that someone removed diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c index 228d3a28eae..05927e13b08 100644 --- a/gcc/lower-subreg.c +++ b/gcc/lower-subreg.c @@ -57,9 +57,9 @@ along with GCC; see the file COPYING3. If not see to do this. This pass only splits moves with modes that are wider than - word_mode and ASHIFTs, LSHIFTRTs and ZERO_EXTENDs with integer - modes that are twice the width of word_mode. The latter could be - generalized if there was a need to do this, but the trend in + word_mode and ASHIFTs, LSHIFTRTs, ASHIFTRTs and ZERO_EXTENDs with + integer modes that are twice the width of word_mode. The latter + could be generalized if there was a need to do this, but the trend in architectures is to not need this. There are two useful preprocessor defines for use by maintainers: @@ -152,7 +152,7 @@ compute_splitting_shift (bool speed_p, struct cost_rtxes *rtxes, bool *splitting, enum rtx_code code, int word_move_zero_cost, int word_move_cost) { - int wide_cost, narrow_cost, i; + int wide_cost, narrow_cost, upper_cost, i; for (i = 0; i < BITS_PER_WORD; i++) { @@ -163,13 +163,20 @@ compute_splitting_shift (bool speed_p, struct cost_rtxes *rtxes, else narrow_cost = shift_cost (speed_p, rtxes, code, word_mode, i); + if (code != ASHIFTRT) + upper_cost = word_move_zero_cost; + else if (i == BITS_PER_WORD - 1) + upper_cost = word_move_cost; + else + upper_cost = shift_cost (speed_p, rtxes, code, word_mode, + BITS_PER_WORD - 1); + if (LOG_COSTS) fprintf (stderr, "%s %s by %d: original cost %d, split cost %d + %d\n", GET_MODE_NAME (twice_word_mode), GET_RTX_NAME (code), - i + BITS_PER_WORD, wide_cost, narrow_cost, - word_move_zero_cost); + i + BITS_PER_WORD, wide_cost, narrow_cost, upper_cost); - if (FORCE_LOWERING || wide_cost >= narrow_cost + word_move_zero_cost) + if (FORCE_LOWERING || wide_cost >= narrow_cost + upper_cost) splitting[i] = true; } } @@ -248,6 +255,9 @@ compute_costs (bool speed_p, struct cost_rtxes *rtxes) compute_splitting_shift (speed_p, rtxes, choices[speed_p].splitting_lshiftrt, LSHIFTRT, word_move_zero_cost, word_move_cost); + compute_splitting_shift (speed_p, rtxes, + choices[speed_p].splitting_ashiftrt, ASHIFTRT, + word_move_zero_cost, word_move_cost); } } @@ -1153,6 +1163,7 @@ find_decomposable_shift_zext (rtx insn, bool speed_p) op = SET_SRC (set); if (GET_CODE (op) != ASHIFT && GET_CODE (op) != LSHIFTRT + && GET_CODE (op) != ASHIFTRT && GET_CODE (op) != ZERO_EXTEND) return false; @@ -1173,6 +1184,8 @@ find_decomposable_shift_zext (rtx insn, bool speed_p) { bool *splitting = (GET_CODE (op) == ASHIFT ? choices[speed_p].splitting_ashift + : GET_CODE (op) == ASHIFTRT + ? choices[speed_p].splitting_ashiftrt : choices[speed_p].splitting_lshiftrt); if (!CONST_INT_P (XEXP (op, 1)) || !IN_RANGE (INTVAL (XEXP (op, 1)), BITS_PER_WORD, @@ -1200,7 +1213,7 @@ resolve_shift_zext (rtx insn) rtx op; rtx op_operand; rtx insns; - rtx src_reg, dest_reg, dest_zero; + rtx src_reg, dest_reg, dest_upper, upper_src = NULL_RTX; int src_reg_num, dest_reg_num, offset1, offset2, src_offset; set = single_set (insn); @@ -1210,6 +1223,7 @@ resolve_shift_zext (rtx insn) op = SET_SRC (set); if (GET_CODE (op) != ASHIFT && GET_CODE (op) != LSHIFTRT + && GET_CODE (op) != ASHIFTRT && GET_CODE (op) != ZERO_EXTEND) return NULL_RTX; @@ -1223,7 +1237,8 @@ resolve_shift_zext (rtx insn) /* src_reg_num is the number of the word mode register which we are operating on. For a left shift and a zero_extend on little endian machines this is register 0. */ - src_reg_num = GET_CODE (op) == LSHIFTRT ? 1 : 0; + src_reg_num = (GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFTRT) + ? 1 : 0; if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (op_operand)) > UNITS_PER_WORD) @@ -1243,12 +1258,17 @@ resolve_shift_zext (rtx insn) dest_reg = simplify_gen_subreg_concatn (word_mode, SET_DEST (set), GET_MODE (SET_DEST (set)), offset1); - dest_zero = simplify_gen_subreg_concatn (word_mode, SET_DEST (set), - GET_MODE (SET_DEST (set)), - offset2); + dest_upper = simplify_gen_subreg_concatn (word_mode, SET_DEST (set), + GET_MODE (SET_DEST (set)), + offset2); src_reg = simplify_gen_subreg_concatn (word_mode, op_operand, GET_MODE (op_operand), src_offset); + if (GET_CODE (op) == ASHIFTRT + && INTVAL (XEXP (op, 1)) != 2 * BITS_PER_WORD - 1) + upper_src = expand_shift (RSHIFT_EXPR, word_mode, copy_rtx (src_reg), + BITS_PER_WORD - 1, NULL_RTX, 0); + if (GET_CODE (op) != ZERO_EXTEND) { int shift_count = INTVAL (XEXP (op, 1)); @@ -1257,12 +1277,17 @@ resolve_shift_zext (rtx insn) LSHIFT_EXPR : RSHIFT_EXPR, word_mode, src_reg, shift_count - BITS_PER_WORD, - dest_reg, 1); + dest_reg, GET_CODE (op) != ASHIFTRT); } if (dest_reg != src_reg) emit_move_insn (dest_reg, src_reg); - emit_move_insn (dest_zero, CONST0_RTX (word_mode)); + if (GET_CODE (op) != ASHIFTRT) + emit_move_insn (dest_upper, CONST0_RTX (word_mode)); + else if (INTVAL (XEXP (op, 1)) == 2 * BITS_PER_WORD - 1) + emit_move_insn (dest_upper, copy_rtx (src_reg)); + else + emit_move_insn (dest_upper, upper_src); insns = get_insns (); end_sequence (); @@ -1328,7 +1353,8 @@ dump_choices (bool speed_p, const char *description) GET_MODE_NAME (twice_word_mode)); dump_shift_choices (ASHIFT, choices[speed_p].splitting_ashift); - dump_shift_choices (LSHIFTRT, choices[speed_p].splitting_ashift); + dump_shift_choices (LSHIFTRT, choices[speed_p].splitting_lshiftrt); + dump_shift_choices (ASHIFTRT, choices[speed_p].splitting_ashiftrt); fprintf (dump_file, "\n"); } diff --git a/gcc/lower-subreg.h b/gcc/lower-subreg.h index b4320826a28..16c48bf8cd8 100644 --- a/gcc/lower-subreg.h +++ b/gcc/lower-subreg.h @@ -34,6 +34,7 @@ struct lower_subreg_choices { should be split. */ bool splitting_ashift[MAX_BITS_PER_WORD]; bool splitting_lshiftrt[MAX_BITS_PER_WORD]; + bool splitting_ashiftrt[MAX_BITS_PER_WORD]; /* True if there is at least one mode that is worth splitting. */ bool something_to_do; diff --git a/gcc/optabs.c b/gcc/optabs.c index c1dacf487a0..c5778d1928b 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see struct target_optabs default_target_optabs; struct target_libfuncs default_target_libfuncs; +struct target_optabs *this_fn_optabs = &default_target_optabs; #if SWITCHABLE_TARGET struct target_optabs *this_target_optabs = &default_target_optabs; struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs; @@ -6150,7 +6151,7 @@ init_optabs (void) libfunc_hash = htab_create_ggc (10, hash_libfunc, eq_libfunc, NULL); /* Fill in the optabs with the insns we support. */ - init_all_optabs (); + init_all_optabs (this_fn_optabs); /* The ffs function operates on `int'. Fall back on it if we do not have a libgcc2 function for that width. */ @@ -6207,6 +6208,38 @@ init_optabs (void) targetm.init_libfuncs (); } +/* Recompute the optabs and save them if they have changed. */ + +void +save_optabs_if_changed (tree fndecl) +{ + /* ?? If this fails, we should temporarily restore the default + target first (set_cfun (NULL) ??), do the rest of this function, + and then restore it. */ + gcc_assert (this_target_optabs == &default_target_optabs); + + struct target_optabs *tmp_optabs = (struct target_optabs *) + ggc_alloc_atomic (sizeof (struct target_optabs)); + tree optnode = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); + + /* Generate a new set of optabs into tmp_optabs. */ + init_all_optabs (tmp_optabs); + + /* If the optabs changed, record it. */ + if (memcmp (tmp_optabs, this_target_optabs, sizeof (struct target_optabs))) + { + if (TREE_OPTIMIZATION_OPTABS (optnode)) + ggc_free (TREE_OPTIMIZATION_OPTABS (optnode)); + + TREE_OPTIMIZATION_OPTABS (optnode) = (unsigned char *) tmp_optabs; + } + else + { + TREE_OPTIMIZATION_OPTABS (optnode) = NULL; + ggc_free (tmp_optabs); + } +} + /* A helper function for init_sync_libfuncs. Using the basename BASE, install libfuncs into TAB for BASE_N for 1 <= N <= MAX. */ diff --git a/gcc/optabs.h b/gcc/optabs.h index c08adcf454f..4de4409342d 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -76,6 +76,7 @@ struct target_optabs { }; extern struct target_optabs default_target_optabs; +extern struct target_optabs *this_fn_optabs; #if SWITCHABLE_TARGET extern struct target_optabs *this_target_optabs; #else diff --git a/gcc/passes.c b/gcc/passes.c index d31f6e4dd81..cc2e9ca38f1 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1918,10 +1918,7 @@ execute_function_todo (void *data) /* Always cleanup the CFG before trying to update SSA. */ if (flags & TODO_cleanup_cfg) { - bool cleanup = cleanup_tree_cfg (); - - if (cleanup && (cfun->curr_properties & PROP_ssa)) - flags |= TODO_remove_unused_locals; + cleanup_tree_cfg (); /* When cleanup_tree_cfg merges consecutive blocks, it may perform some simplistic propagation when removing single diff --git a/gcc/sel-sched-dump.c b/gcc/sel-sched-dump.c index 4b2be37796a..0dafe497add 100644 --- a/gcc/sel-sched-dump.c +++ b/gcc/sel-sched-dump.c @@ -91,7 +91,7 @@ restore_dump (void) /* Functions for dumping instructions, av sets, and exprs. */ /* Default flags for dumping insns. */ -static int dump_insn_rtx_flags = DUMP_INSN_RTX_PATTERN; +static int dump_insn_rtx_flags = DUMP_INSN_RTX_UID | DUMP_INSN_RTX_PATTERN; /* Default flags for dumping vinsns. */ static int dump_vinsn_flags = (DUMP_VINSN_INSN_RTX | DUMP_VINSN_TYPE @@ -136,7 +136,7 @@ dump_insn_rtx_1 (rtx insn, int flags) sel_print ("%d;", INSN_UID (insn)); if (flags & DUMP_INSN_RTX_PATTERN) - sel_print ("%s;", str_pattern_slim (insn)); + sel_print ("%s;", str_pattern_slim (PATTERN (insn))); if (flags & DUMP_INSN_RTX_BBN) { diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c index 6f60d7063a3..11bf2e62c31 100644 --- a/gcc/sel-sched.c +++ b/gcc/sel-sched.c @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "rtlhooks-def.h" #include "emit-rtl.h" +#include "ira.h" #ifdef INSN_SCHEDULING #include "sel-sched-ir.h" @@ -2101,6 +2102,61 @@ moving_insn_creates_bookkeeping_block_p (insn_t insn, return TRUE; } +/* Return true when the conflict with newly created implicit clobbers + between EXPR and THROUGH_INSN is found because of renaming. */ +static bool +implicit_clobber_conflict_p (insn_t through_insn, expr_t expr) +{ + HARD_REG_SET temp; + rtx insn, reg, rhs, pat; + hard_reg_set_iterator hrsi; + unsigned regno; + bool valid; + + /* Make a new pseudo register. */ + reg = gen_reg_rtx (GET_MODE (EXPR_LHS (expr))); + max_regno = max_reg_num (); + maybe_extend_reg_info_p (); + + /* Validate a change and bail out early. */ + insn = EXPR_INSN_RTX (expr); + validate_change (insn, &SET_DEST (PATTERN (insn)), reg, true); + valid = verify_changes (0); + cancel_changes (0); + if (!valid) + { + if (sched_verbose >= 6) + sel_print ("implicit clobbers failed validation, "); + return true; + } + + /* Make a new insn with it. */ + rhs = copy_rtx (VINSN_RHS (EXPR_VINSN (expr))); + pat = gen_rtx_SET (VOIDmode, reg, rhs); + start_sequence (); + insn = emit_insn (pat); + end_sequence (); + + /* Calculate implicit clobbers. */ + extract_insn (insn); + preprocess_constraints (); + ira_implicitly_set_insn_hard_regs (&temp); + AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs); + + /* If any implicit clobber registers intersect with regular ones in + through_insn, we have a dependency and thus bail out. */ + EXECUTE_IF_SET_IN_HARD_REG_SET (temp, 0, regno, hrsi) + { + vinsn_t vi = INSN_VINSN (through_insn); + if (bitmap_bit_p (VINSN_REG_SETS (vi), regno) + || bitmap_bit_p (VINSN_REG_CLOBBERS (vi), regno) + || bitmap_bit_p (VINSN_REG_USES (vi), regno)) + return true; + } + + return false; +} + /* Modifies EXPR so it can be moved through the THROUGH_INSN, performing necessary transformations. Record the type of transformation made in PTRANS_TYPE, when it is not NULL. When INSIDE_INSN_GROUP, @@ -2233,6 +2289,17 @@ moveup_expr (expr_t expr, insn_t through_insn, bool inside_insn_group, if (!enable_schedule_as_rhs_p || !EXPR_SEPARABLE_P (expr)) return MOVEUP_EXPR_NULL; + /* When renaming a hard register to a pseudo before reload, extra + dependencies can occur from the implicit clobbers of the insn. + Filter out such cases here. */ + if (!reload_completed && REG_P (EXPR_LHS (expr)) + && HARD_REGISTER_P (EXPR_LHS (expr)) + && implicit_clobber_conflict_p (through_insn, expr)) + { + if (sched_verbose >= 6) + sel_print ("implicit clobbers conflict detected, "); + return MOVEUP_EXPR_NULL; + } EXPR_TARGET_AVAILABLE (expr) = false; was_target_conflict = true; as_rhs = true; diff --git a/gcc/target-globals.c b/gcc/target-globals.c index 533a8e58374..d72495da26d 100644 --- a/gcc/target-globals.c +++ b/gcc/target-globals.c @@ -91,4 +91,33 @@ save_target_globals (void) return g; } +/* Like save_target_globals() above, but set *this_target_optabs + correctly when a previous function has changed + *this_target_optabs. */ + +struct target_globals * +save_target_globals_default_opts () +{ + struct target_globals *globals; + + if (optimization_current_node != optimization_default_node) + { + tree opts = optimization_current_node; + /* Temporarily switch to the default optimization node, so that + *this_target_optabs is set to the default, not reflecting + whatever a previous function used for the optimize + attribute. */ + optimization_current_node = optimization_default_node; + cl_optimization_restore + (&global_options, + TREE_OPTIMIZATION (optimization_default_node)); + globals = save_target_globals (); + optimization_current_node = opts; + cl_optimization_restore (&global_options, + TREE_OPTIMIZATION (opts)); + return globals; + } + return save_target_globals (); +} + #endif diff --git a/gcc/target-globals.h b/gcc/target-globals.h index 110f879cd7b..04eba530abe 100644 --- a/gcc/target-globals.h +++ b/gcc/target-globals.h @@ -60,6 +60,7 @@ struct GTY(()) target_globals { extern struct target_globals default_target_globals; extern struct target_globals *save_target_globals (void); +extern struct target_globals *save_target_globals_default_opts (void); static inline void restore_target_globals (struct target_globals *g) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fe995e8e0ea..7df8623d288 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,98 @@ +2013-02-21 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/56420 + * gcc.dg/torture/pr56420.c: New test. + +2013-02-20 Aldy Hernandez <aldyh@redhat.com> + + PR middle-end/56108 + * gcc.dg/tm/memopt-1.c: Declare functions transaction_safe. + +2013-02-21 Martin Jambor <mjambor@suse.cz> + + PR tree-optimization/56310 + * g++.dg/ipa/pr56310.C: New test. + +2013-02-21 Janus Weil <janus@gcc.gnu.org> + + PR fortran/56385 + * gfortran.dg/proc_ptr_comp_37.f90: New. + +2013-02-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/56415 + Revert + 2013-02-11 Richard Biener <rguenther@suse.de> + + PR tree-optimization/56273 + * g++.dg/warn/Warray-bounds-6.C: New testcase. + * gcc.dg/tree-ssa/pr21559.c: Adjust. + * gcc.dg/tree-ssa/vrp17.c: Likewise. + * gcc.dg/tree-ssa/vrp18.c: Likewise. + * gcc.dg/tree-ssa/vrp23.c: Likewise. + * gcc.dg/tree-ssa/vrp24.c: Likewise. + +2013-02-21 Marek Polacek <polacek@redhat.com> + + PR tree-optimization/56398 + * g++.dg/torture/pr56398.C: New test. + +2013-02-21 Jakub Jelinek <jakub@redhat.com> + + PR inline-asm/56405 + * gcc.c-torture/compile/pr56405.c: New test. + +2013-02-20 Jan Hubicka <jh@suse.cz> + + PR tree-optimization/56265 + * testsuite/g++.dg/ipa/devirt-11.C: New testcase. + +2013-02-20 Richard Biener <rguenther@suse.de> + + * gcc.dg/tree-ssa/forwprop-8.c: Adjust. + +2013-02-20 Richard Biener <rguenther@suse.de> + Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/56396 + * gcc.dg/pr56396.c: New testcase. + +2013-02-20 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/56373 + * g++.dg/cpp0x/Wzero-as-null-pointer-constant-2.C: New. + +2013-02-19 Richard Biener <rguenther@suse.de> + + PR tree-optimization/56384 + * gcc.dg/torture/pr56384.c: New testcase. + +2013-02-19 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/56350 + * gcc.dg/pr56350.c: New test. + + PR tree-optimization/56381 + * g++.dg/opt/pr56381.C: New test. + +2013-02-18 Jakub Jelinek <jakub@redhat.com> + + PR pch/54117 + * lib/dg-pch.exp (pch-init, pch-finish, + check_effective_target_pch_supported_debug): New procs. + (dg-flags-pch): If $pch_unsupported, make tests UNSUPPORTED. + Likewise if $pch_unsupported_debug and $flags include -g. + Skip FAILs about missing *.gch file if $pch_unsupported_debug + and dg-require-effective-target pch_unsupported_debug. + * g++.dg/pch/pch.exp: Call pch-init and pch-finish. + * objc.dg/pch/pch.exp: Likewise. + * gcc.dg/pch/pch.exp: Likewise. + * gcc.dg/pch/valid-1.c: Add dg-require-effective-target + pch_unsupported_debug. + * gcc.dg/pch/valid-1.hs: Likewise. + * gcc.dg/pch/valid-1b.c: Likewise. + * gcc.dg/pch/valid-1b.hs: Likewise. + 2013-02-18 Richard Biener <rguenther@suse.de> PR tree-optimization/56366 diff --git a/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-2.C b/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-2.C new file mode 100644 index 00000000000..eea2c2fcf31 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-2.C @@ -0,0 +1,14 @@ +// PR c++/56373 +// { dg-options "-std=c++11 -Wzero-as-null-pointer-constant" } + +struct shared_ptr +{ + shared_ptr(decltype(nullptr)); +}; + +void f() +{ + shared_ptr a = 0; // { dg-warning "zero as null pointer" } + shared_ptr b(0); // { dg-warning "zero as null pointer" } + shared_ptr c{0}; // { dg-warning "zero as null pointer" } +} diff --git a/gcc/testsuite/g++.dg/ipa/devirt-11.C b/gcc/testsuite/g++.dg/ipa/devirt-11.C new file mode 100644 index 00000000000..c139f8f9633 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/devirt-11.C @@ -0,0 +1,50 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-ipa-inline" } */ +int baz (); +struct A +{ + virtual int fn2 () = 0; + virtual int *fn3 (); + double *fn4 (); + int fn5 (int); + template <class T> + void fn1 (A &, T) { fn3 (); fn4 (); fn2 (); } +}; +struct B : A +{ + int fn2 () { return 6; } + void fn3 (int, double); + B (bool = true); + B (int, int); +}; +template <typename T> +void +foo (B &x, A &y, A &z) +{ + y.fn2 (); + z.fn2 (); + int i = baz (); + int j = (y.fn3 ())[i]; + x.fn3 (j, (y.fn4 ())[i] + (z.fn4 ())[z.fn5 (j)]); +} +inline B +operator+ (A &y, A &z) +{ + B x; + foo<int> (x, y, z); + return x; +} +void +bar () +{ + B a, b, c (4, 0), d; + a.fn1 (b, .6); + baz (); + c + d; +} +/* While inlining function called once we should devirtualize a new call to fn2 + and two to fn3. While doing so the new symbol for fn2 needs to be + introduced. */ +/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 3 "inline" } } */ +/* { dg-final { scan-ipa-dump-times "and turned into root of the clone tree" 1 "inline" } } */ +/* { dg-final { cleanup-ipa-dump "inline" } } */ diff --git a/gcc/testsuite/g++.dg/ipa/pr56310.C b/gcc/testsuite/g++.dg/ipa/pr56310.C new file mode 100644 index 00000000000..af6979c8fd3 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr56310.C @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fipa-cp -std=gnu++0x -fno-early-inlining -fipa-cp-clone --param=ipa-cp-eval-threshold=1" } */ + +void bar (void *, void *); + +struct C +{ + constexpr C ():p (0) + { + } + void *get () + { + return p; + } + void *p; +}; + +struct B:C +{ +}; + +struct A +{ + void f (B * x, B * y) + { + bar (x->get (), y->get ()); + } +}; + +void +foo () +{ + A a; + B b; + a.f (&b, &b); +} diff --git a/gcc/testsuite/g++.dg/opt/pr56381.C b/gcc/testsuite/g++.dg/opt/pr56381.C new file mode 100644 index 00000000000..38a121d979a --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr56381.C @@ -0,0 +1,156 @@ +// PR tree-optimization/56381 +// { dg-do compile } +// { dg-options "-std=c++11 -O2 -w" } + +template <class> +class intrusive_ptr {}; +class BasicReferenceCounted +{ +}; +template <class T> +class ReferenceCountingPointer : intrusive_ptr <T> +{ +}; +typedef BasicReferenceCounted ReferenceCountedInConditions; +class PointTag; +template <typename T, typename> +struct PreciseFloatType +{ + typedef T Type; +}; +template <typename T, int N> +struct ExtVecTraits +{ + typedef T __attribute__ ((vector_size (N * sizeof (T)))) type; +}; +template <typename T, int N> +using ExtVec = typename ExtVecTraits <T, N>::type; +template <typename T> using Vec4 = ExtVec <T, 4>; +template <typename Vec> +Vec cross3 (Vec x, Vec y) +{ + Vec x1200 = (Vec) { x[2], x[0] }; + Vec y2010 { y[2], y[0], y[1], y[0] }; + Vec x2010 = (Vec) { x[2], x[0], x[1], x[0] }; + Vec y1200 = (Vec) { y[1], y[0] }; + return x1200 * y2010 - x2010 * y1200; +} +template <typename T> +struct Rot3 +{ + typedef Vec4 <T> Vec; + Vec axis[3]; +}; +class Basic2DVector +{ +}; +template <typename T> +struct Basic3DVector +{ + typedef Vec4 <T> MathVector; + Basic3DVector (MathVector iv) : v { (iv[0]), (iv[1]), (iv[2]), (iv[3]) } {} + T mag2 () {} + Basic3DVector unit () + { + T my_mag = mag2 (); + return (my_mag) ? (*this) * (T () / (my_mag)) : *this; + } + Basic3DVector + cross (Basic3DVector lh) { return cross3 (v, lh.v); } + Vec4 <T> v; +}; +template <class T> +Basic3DVector <T> operator * (Basic3DVector <T>, T); +template <class T, class, class> +struct PV3DBase +{ + typedef Basic3DVector <T> BasicVectorType; + template <class U> + PV3DBase (Basic3DVector <U> v) : theVector (v) {} + BasicVectorType basicVector () { return theVector; } + T x (); + T y (); + BasicVectorType theVector; +}; +class VectorTag; +template <class T, class FrameTag> +struct Vector3DBase:public PV3DBase <T, VectorTag, FrameTag> +{ + typedef PV3DBase <T, VectorTag, FrameTag> BaseClass; + template <class U> + Vector3DBase (Basic3DVector <U> v) : BaseClass (v) {} + Vector3DBase unit () { return (this->basicVector ().unit ()); } + template <class U> + Vector3DBase <typename PreciseFloatType <T, U>::Type, FrameTag> cross (Vector3DBase <U, FrameTag> v) + { + return (this->theVector.cross (v.basicVector ())); + } +}; +template <class T, class FrameTag> +class Point3DBase : public PV3DBase <T, PointTag, FrameTag> +{ +}; +template <typename T, typename U, class Frame> +Vector3DBase <typename PreciseFloatType <T, U>::Type, Frame> operator - (Point3DBase <T, Frame>, Point3DBase <U, Frame>); +class GlobalTag; +template <class T> +struct TkRotation +{ + typedef Vector3DBase <T, GlobalTag> GlobalVector; + TkRotation (GlobalVector aX, GlobalVector aY) + { + GlobalVector uX = aX.unit (); + GlobalVector uY = aY.unit (); + GlobalVector uZ (uX.cross (uY)); + rot.axis[2] = uZ.basicVector ().v; + } + Basic3DVector <T> z (); + Rot3 <T> rot; +}; +template <class T> +struct GloballyPositioned +{ + typedef Point3DBase <T, GlobalTag> PositionType; + typedef TkRotation <T> RotationType; + typedef Point3DBase <T, GlobalTag> GlobalPoint; + typedef Vector3DBase <T, GlobalTag> GlobalVector; + T iniPhi () { return 999.9978; } + GloballyPositioned (PositionType pos, RotationType rot) : thePos (pos), theRot (rot) { resetCache (); } + PositionType position () const; + RotationType rotation () const; + PositionType thePos; + RotationType theRot; + void resetCache () + { + if ((thePos.x () == 0.) && (thePos.y () == 0.)) + thePhi = 0.; + else + thePhi = iniPhi (); + } + T thePhi; +}; +class Plane; +using TangentPlane = Plane; +struct Surface : public GloballyPositioned <float>, ReferenceCountedInConditions +{ + typedef GloballyPositioned <float> Base; + Surface (PositionType pos, RotationType rot): + Base (pos, rot) {} +}; +struct Plane : Surface +{ + template <typename ... Args> + Plane (Args ... args): + Surface ((args) ...) {} +}; +class Cylinder : Surface +{ + void tangentPlane (const GlobalPoint &) const; +}; +void +Cylinder::tangentPlane (const GlobalPoint & aPoint) const +{ + GlobalVector yPlane (rotation ().z ()); + GlobalVector xPlane (yPlane.cross (aPoint - position ())); + new TangentPlane (aPoint, RotationType (xPlane, yPlane)); +} diff --git a/gcc/testsuite/g++.dg/pch/pch.exp b/gcc/testsuite/g++.dg/pch/pch.exp index 0c5e13319ee..db67c24f5b9 100644 --- a/gcc/testsuite/g++.dg/pch/pch.exp +++ b/gcc/testsuite/g++.dg/pch/pch.exp @@ -23,6 +23,7 @@ load_lib dg-pch.exp # Initialize `dg'. dg-init +pch-init set old_dg_do_what_default "${dg-do-what-default}" @@ -36,4 +37,5 @@ foreach test [lsort [glob -nocomplain $srcdir/$subdir/*.C]] { set dg-do-what-default "$old_dg_do_what_default" # All done. +pch-finish dg-finish diff --git a/gcc/testsuite/g++.dg/torture/pr56398.C b/gcc/testsuite/g++.dg/torture/pr56398.C new file mode 100644 index 00000000000..5b7bcf279b2 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr56398.C @@ -0,0 +1,22 @@ +// { dg-do compile } +// { dg-options "-g" } + +namespace +{ +#0 "/usr/include/c/4.8/bits/postypes.h" 3 +} + +vtkpow (int b) +{ + int a1; + int b1; + int c; + while (b1) + { + while (b) + b1 = 0; + b1 = b1 - 1; + c = c * a1; + } + return c; +} diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-6.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-6.C deleted file mode 100644 index ee2862f1ec1..00000000000 --- a/gcc/testsuite/g++.dg/warn/Warray-bounds-6.C +++ /dev/null @@ -1,30 +0,0 @@ -// { dg-do compile } -// { dg-options "-O3 -Warray-bounds" } - -struct type { - bool a, b; - bool get_b() { return b; } -}; - -type stuff[9u]; - -void bar(); - -void foo() { - - for(unsigned i = 0u; i < 9u; i++) { - - if(!stuff[i].a) { - continue; - } - - bar(); - - for(unsigned j = i + 1u; j < 9u; j++) { - if(stuff[j].a && stuff[j].get_b()) { // { dg-bogus "array bounds" } - return; - } - } - - } -} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr52555.c b/gcc/testsuite/gcc.c-torture/compile/pr52555.c new file mode 100644 index 00000000000..701683488df --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr52555.c @@ -0,0 +1,10 @@ +/* { dg-options "-ffast-math" } */ + +float farg; +unsigned val; + +void __attribute__((optimize("O"))) +test() +{ + val = __builtin_ceilf(farg); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr56405.c b/gcc/testsuite/gcc.c-torture/compile/pr56405.c new file mode 100644 index 00000000000..6e6a56e156c --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr56405.c @@ -0,0 +1,7 @@ +/* PR inline-asm/56405 */ + +void +foo (void) +{ + asm volatile ("" : "+m" (*(volatile unsigned short *) 0x1001UL)); +} diff --git a/gcc/testsuite/gcc.dg/pch/pch.exp b/gcc/testsuite/gcc.dg/pch/pch.exp index 4144243a7a1..7bf64df172c 100644 --- a/gcc/testsuite/gcc.dg/pch/pch.exp +++ b/gcc/testsuite/gcc.dg/pch/pch.exp @@ -26,6 +26,7 @@ load_lib torture-options.exp dg-init torture-init set-torture-options $DG_TORTURE_OPTIONS +pch-init set old_dg_do_what_default "${dg-do-what-default}" @@ -59,5 +60,6 @@ file delete $testh set dg-do-what-default "$old_dg_do_what_default" # All done. +pch-finish torture-finish dg-finish diff --git a/gcc/testsuite/gcc.dg/pch/valid-1.c b/gcc/testsuite/gcc.dg/pch/valid-1.c index b7f22d0dc17..d445c47d6f3 100644 --- a/gcc/testsuite/gcc.dg/pch/valid-1.c +++ b/gcc/testsuite/gcc.dg/pch/valid-1.c @@ -1,3 +1,4 @@ +/* { dg-require-effective-target pch_supported_debug } */ /* { dg-options "-I. -Winvalid-pch -g" } */ #include "valid-1.h"/* { dg-warning "created with -gnone, but used with -g" } */ diff --git a/gcc/testsuite/gcc.dg/pch/valid-1.hs b/gcc/testsuite/gcc.dg/pch/valid-1.hs index e1ed11df4cc..20d9f65dd72 100644 --- a/gcc/testsuite/gcc.dg/pch/valid-1.hs +++ b/gcc/testsuite/gcc.dg/pch/valid-1.hs @@ -1,3 +1,4 @@ +/* { dg-require-effective-target pch_supported_debug } */ /* { dg-options "-I. -Winvalid-pch -g0" } */ extern int x; diff --git a/gcc/testsuite/gcc.dg/pch/valid-1b.c b/gcc/testsuite/gcc.dg/pch/valid-1b.c index a2709967c07..3113d0f744d 100644 --- a/gcc/testsuite/gcc.dg/pch/valid-1b.c +++ b/gcc/testsuite/gcc.dg/pch/valid-1b.c @@ -1,3 +1,4 @@ +/* { dg-require-effective-target pch_supported_debug } */ /* { dg-options "-I. -Winvalid-pch -g0" } */ #include "valid-1b.h" diff --git a/gcc/testsuite/gcc.dg/pch/valid-1b.hs b/gcc/testsuite/gcc.dg/pch/valid-1b.hs index 6dc358735a7..93b2256e355 100644 --- a/gcc/testsuite/gcc.dg/pch/valid-1b.hs +++ b/gcc/testsuite/gcc.dg/pch/valid-1b.hs @@ -1,3 +1,4 @@ +/* { dg-require-effective-target pch_supported_debug } */ /* { dg-options "-I. -Winvalid-pch -g" } */ extern int x; diff --git a/gcc/testsuite/gcc.dg/pr56350.c b/gcc/testsuite/gcc.dg/pr56350.c new file mode 100644 index 00000000000..899a507ee8b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr56350.c @@ -0,0 +1,13 @@ +/* PR tree-optimization/56350 */ +/* { dg-do compile } */ +/* { dg-options "-O -ftree-vectorize" } */ + +int a, b, c; + +void +f (void) +{ + for (; c; c++) + for (b = 0; b < 2; b++) + a /= 8; +} diff --git a/gcc/testsuite/gcc.dg/pr56396.c b/gcc/testsuite/gcc.dg/pr56396.c new file mode 100644 index 00000000000..d2ec8fa9bff --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr56396.c @@ -0,0 +1,22 @@ +/* PR tree-optimization/56396 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fpic -g" } */ + +struct S { char *s; int z; }; +struct T { int t; } *c, u; +void bar (int, const char *); + +inline void * +foo (void *x, char *y, int z) +{ + struct S s; + char b[256]; + s.s = b; + s.z = __builtin___sprintf_chk (s.s, 1, __builtin_object_size (s.s, 2), "Require"); + if (s.z < 0) + bar (u.t | c->t, "rls"); + if (foo (x, s.s, s.z)) + { + } + return (void *) 0; +} diff --git a/gcc/testsuite/gcc.dg/tm/memopt-1.c b/gcc/testsuite/gcc.dg/tm/memopt-1.c index b78a6d417dc..c5ac5ced56c 100644 --- a/gcc/testsuite/gcc.dg/tm/memopt-1.c +++ b/gcc/testsuite/gcc.dg/tm/memopt-1.c @@ -2,8 +2,8 @@ /* { dg-options "-fgnu-tm -O -fdump-tree-tmmemopt" } */ long g, xxx, yyy; -extern george() __attribute__((transaction_callable)); -extern ringo(long int); +extern george() __attribute__((transaction_safe)); +extern ringo(long int) __attribute__((transaction_safe)); int i; f() diff --git a/gcc/testsuite/gcc.dg/tm/pr56108.c b/gcc/testsuite/gcc.dg/tm/pr56108.c new file mode 100644 index 00000000000..81ff574cd47 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/pr56108.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O" } */ + +int +main() +{ + __transaction_relaxed { __asm__(""); } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr56384.c b/gcc/testsuite/gcc.dg/torture/pr56384.c new file mode 100644 index 00000000000..ef3cf0536bd --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr56384.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ + +int a, c; + +void f(void) +{ + unsigned char b; + + if(a) + { + for(; b < 1; b++); +lbl1: + c = (b |= 0) ^ (b || a); + } + + if((a = b)) + { + b = c; + goto lbl1; + } + + b = 5; + goto lbl1; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr56420.c b/gcc/testsuite/gcc.dg/torture/pr56420.c new file mode 100644 index 00000000000..6fa1a803dd6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr56420.c @@ -0,0 +1,37 @@ +/* PR middle-end/56420 */ +/* { dg-do run { target int128 } } */ + +extern void abort (void); + +__attribute__((noinline, noclone)) __uint128_t +foo (__uint128_t x) +{ + return x * (((__uint128_t) -1) << 63); +} + +__attribute__((noinline, noclone)) __uint128_t +bar (__uint128_t x) +{ + return x * (((__uint128_t) 1) << 63); +} + +__attribute__((noinline, noclone)) __uint128_t +baz (__uint128_t x) +{ + return x * -(((__uint128_t) 1) << 62); +} + +int +main () +{ + if (foo (1) != (((__uint128_t) -1) << 63) + || foo (8) != (((__uint128_t) -1) << 66)) + abort (); + if (bar (1) != (((__uint128_t) 1) << 63) + || bar (8) != (((__uint128_t) 1) << 66)) + abort (); + if (baz (1) != -(((__uint128_t) 1) << 62) + || baz (8) != ((-(((__uint128_t) 1) << 62)) << 3)) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-8.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-8.c index fc74297242c..1c780c834c5 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-8.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-8.c @@ -11,6 +11,5 @@ int foo(struct X *q) /* We should have propragated &q->a into (*pointer). */ -/* { dg-final { scan-tree-dump-times "pointer" 0 "forwprop1"} } */ -/* { dg-final { scan-tree-dump "\\\[0\\\]" "forwprop1" } } */ +/* { dg-final { scan-tree-dump "q_.\\\(D\\\)\\\]\\\[0\\\];" "forwprop1" } } */ /* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c index d7d3bab154d..34f4a01db00 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp-details" } */ +/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ static int blocksize = 4096; @@ -32,7 +32,7 @@ void foo (void) /* First, we should simplify the bits < 0 test within the loop. */ -/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp2" } } */ +/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */ /* Second, we should thread the edge out of the loop via the break statement. We also realize that the final bytes == 0 test is useless, @@ -40,4 +40,4 @@ void foo (void) /* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp1" } } */ /* { dg-final { cleanup-tree-dump "vrp1" } } */ -/* { dg-final { cleanup-tree-dump "vrp2" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp17.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp17.c index 2f112ae268d..c04b9ba7843 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp17.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp17.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fno-tree-tail-merge -fdump-tree-vrp2" } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ extern void abort (void) __attribute__ ((__noreturn__)); union tree_node; @@ -27,5 +27,6 @@ gimplify_for_stmt (tree stmt) abort (); } -/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp2" } } */ -/* { dg-final { cleanup-tree-dump "vrp2" } } */ +/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp18.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp18.c index 610dd44cf2f..a3cc536ae56 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp18.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp18.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp2" } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ static int blocksize = 4096; @@ -30,5 +30,5 @@ void foo (void) eof_reached = 1; } -/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp2" } } */ -/* { dg-final { cleanup-tree-dump "vrp2" } } */ +/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp23.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp23.c index 6bca02b44e1..77899a65fca 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp23.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp23.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp2-details" } */ +/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ blah (int code1, int code2) { @@ -40,5 +40,6 @@ L8: /* The n_sets > 0 test can be simplified into n_sets == 1 since the only way to reach the test is when n_sets <= 1, and the only value which satisfies both conditions is n_sets == 1. */ -/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp2" } } */ -/* { dg-final { cleanup-tree-dump "vrp2" } } */ +/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp24.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp24.c index 28e1a924f54..85e5b62d148 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp24.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp24.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp2-details" } */ +/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ + struct rtx_def; typedef struct rtx_def *rtx; @@ -85,5 +86,6 @@ L7: The second n_sets > 0 test can also be simplified into n_sets == 1 as the only way to reach the tests is when n_sets <= 1 and the only value which satisfies both conditions is n_sets == 1. */ -/* { dg-final { scan-tree-dump-times "Simplified relational" 2 "vrp2" } } */ -/* { dg-final { cleanup-tree-dump "vrp2" } } */ +/* { dg-final { scan-tree-dump-times "Simplified relational" 2 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_comp_37.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_comp_37.f90 new file mode 100644 index 00000000000..9695b96066c --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_comp_37.f90 @@ -0,0 +1,25 @@ +! { dg-do compile } +! +! PR 56385: [4.6/4.7/4.8 Regression] [OOP] ICE with allocatable function result in a procedure-pointer component +! +! Contributed by Vladimir Fuka <vladimir.fuka@gmail.com> + + implicit none + + type :: TGeometricShape + end type + + type :: TVolumeSourceBody + class(TGeometricShape), allocatable :: GeometricShape + procedure(scalar_flux_interface), pointer :: get_scalar_flux + end type + + abstract interface + function scalar_flux_interface(self) result(res) + import + real, allocatable :: res(:) + class(TVolumeSourceBody), intent(in) :: self + end function + end interface + +end diff --git a/gcc/testsuite/lib/dg-pch.exp b/gcc/testsuite/lib/dg-pch.exp index d6a55d89e12..1b3591a7506 100644 --- a/gcc/testsuite/lib/dg-pch.exp +++ b/gcc/testsuite/lib/dg-pch.exp @@ -16,8 +16,49 @@ load_lib copy-file.exp +proc pch-init { args } { + global pch_unsupported_debug pch_unsupported + + if [info exists pch_unsupported_debug] { + error "pch-init: pch_unsupported_debug is not empty as expected" + } + if [info exists pch_unsupported] { + error "pch-init: pch_unsupported is not empty as expected" + } + + set result [check_compile pchtest object "int i;" "-g -x c-header"] + set pch_unsupported_debug \ + [regexp "debug format cannot be used with pre-compiled headers" \ + [lindex $result 0]] + + set pch_unsupported 0 + if { $pch_unsupported_debug } { + verbose -log "pch is unsupported with the debug info format" + + set result [check_compile pchtest object "int i;" "-x c-header"] + set pch_unsupported \ + [regexp "debug format cannot be used with pre-compiled headers" \ + [lindex $result 0]] + } +} + +proc pch-finish { args } { + global pch_unsupported_debug pch_unsupported + unset pch_unsupported_debug + unset pch_unsupported +} + +proc check_effective_target_pch_supported_debug { } { + global pch_unsupported_debug + if { $pch_unsupported_debug } { + return 0 + } + return 1 +} + proc dg-flags-pch { subdir test otherflags options suffix } { global runtests dg-do-what-default + global pch_unsupported_debug pch_unsupported # If we're only testing specific files and this isn't one of them, skip it. if ![runtest_file_p $runtests $test] { @@ -35,6 +76,13 @@ proc dg-flags-pch { subdir test otherflags options suffix } { foreach flags $options { verbose "Testing $nshort, $otherflags $flags" 1 + if { $pch_unsupported != 0 \ + || ( $pch_unsupported_debug != 0 && [regexp " -g" " $flags"] ) } { + verbose -log "$nshort unsupported because debug format conflicts with PCH" + unsupported "$nshort $flags" + continue + } + # For the header files, the default is to precompile. set dg-do-what-default precompile catch { file_on_host delete "$bname$suffix" } @@ -78,7 +126,8 @@ proc dg-flags-pch { subdir test otherflags options suffix } { fail "$nshort $flags assembly comparison" } } - } else { + } elseif { $pch_unsupported_debug == 0 \ + || [llength [grep $test "{\[ \t\]\+dg-require-effective-target\[ \t\]\+pch_supported_debug\[ \t\]\+.*\[ \t\]\+}"]] > 0 } { verbose -log "pch file '$bname$suffix.gch' missing" fail "$nshort $flags" if { !$have_errs } { diff --git a/gcc/testsuite/objc.dg/pch/pch.exp b/gcc/testsuite/objc.dg/pch/pch.exp index 90b5b17d2a9..e380390bba6 100644 --- a/gcc/testsuite/objc.dg/pch/pch.exp +++ b/gcc/testsuite/objc.dg/pch/pch.exp @@ -24,8 +24,8 @@ load_lib torture-options.exp # Initialize `dg'. dg-init - torture-init +pch-init set-torture-options $DG_TORTURE_OPTIONS @@ -59,5 +59,6 @@ if [istarget "*-*-darwin*" ] { set dg-do-what-default "$old_dg_do_what_default" # All done. +pch-finish torture-finish dg-finish diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c index dd3918edb1b..71eaa4464e0 100644 --- a/gcc/trans-mem.c +++ b/gcc/trans-mem.c @@ -2859,8 +2859,23 @@ execute_tm_mark (void) // Expand memory operations into calls into the runtime. // This collects log entries as well. FOR_EACH_VEC_ELT (bb_regions, i, r) - if (r != NULL) - expand_block_tm (r, BASIC_BLOCK (i)); + { + if (r != NULL) + { + if (r->transaction_stmt) + { + unsigned sub = gimple_transaction_subcode (r->transaction_stmt); + + /* If we're sure to go irrevocable, there won't be + anything to expand, since the run-time will go + irrevocable right away. */ + if (sub & GTMA_DOES_GO_IRREVOCABLE + && sub & GTMA_MAY_ENTER_IRREVOCABLE) + continue; + } + expand_block_tm (r, BASIC_BLOCK (i)); + } + } bb_regions.release (); diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c index bc7e23f786a..9b6186e3393 100644 --- a/gcc/tree-call-cdce.c +++ b/gcc/tree-call-cdce.c @@ -898,11 +898,10 @@ tree_call_cdce (void) /* As we introduced new control-flow we need to insert PHI-nodes for the call-clobbers of the remaining call. */ mark_virtual_operands_for_renaming (cfun); - return (TODO_update_ssa | TODO_cleanup_cfg | TODO_ggc_collect - | TODO_remove_unused_locals); + return TODO_update_ssa; } - else - return 0; + + return 0; } static bool diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index d8f03a1a343..a64bffcaec7 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -162,6 +162,7 @@ typedef struct prop_value_d prop_value_t; memory reference used to store (i.e., the LHS of the assignment doing the store). */ static prop_value_t *const_val; +static unsigned n_const_val; static void canonicalize_float_value (prop_value_t *); static bool ccp_fold_stmt (gimple_stmt_iterator *); @@ -295,7 +296,8 @@ get_value (tree var) { prop_value_t *val; - if (const_val == NULL) + if (const_val == NULL + || SSA_NAME_VERSION (var) >= n_const_val) return NULL; val = &const_val[SSA_NAME_VERSION (var)]; @@ -713,7 +715,8 @@ ccp_initialize (void) { basic_block bb; - const_val = XCNEWVEC (prop_value_t, num_ssa_names); + n_const_val = num_ssa_names; + const_val = XCNEWVEC (prop_value_t, n_const_val); /* Initialize simulation flags for PHI nodes and statements. */ FOR_EACH_BB (bb) @@ -2105,7 +2108,7 @@ do_ssa_ccp (void) ccp_initialize (); ssa_propagate (ccp_visit_stmt, ccp_visit_phi_node); if (ccp_finalize ()) - todo = (TODO_cleanup_cfg | TODO_update_ssa | TODO_remove_unused_locals); + todo = (TODO_cleanup_cfg | TODO_update_ssa); free_dominance_info (CDI_DOMINATORS); return todo; } diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c index 551ebe3f0ed..75a415454de 100644 --- a/gcc/tree-ssa-copy.c +++ b/gcc/tree-ssa-copy.c @@ -280,6 +280,7 @@ struct prop_value_d { typedef struct prop_value_d prop_value_t; static prop_value_t *copy_of; +static unsigned n_copy_of; /* Return true if this statement may generate a useful copy. */ @@ -664,7 +665,8 @@ init_copy_prop (void) { basic_block bb; - copy_of = XCNEWVEC (prop_value_t, num_ssa_names); + n_copy_of = num_ssa_names; + copy_of = XCNEWVEC (prop_value_t, n_copy_of); FOR_EACH_BB (bb) { @@ -728,7 +730,10 @@ init_copy_prop (void) static tree get_value (tree name) { - tree val = copy_of[SSA_NAME_VERSION (name)].value; + tree val; + if (SSA_NAME_VERSION (name) >= n_copy_of) + return NULL_TREE; + val = copy_of[SSA_NAME_VERSION (name)].value; if (val && val != name) return val; return NULL_TREE; diff --git a/gcc/tree-ssa-copyrename.c b/gcc/tree-ssa-copyrename.c index 5348c57434f..6f49b7ecf5a 100644 --- a/gcc/tree-ssa-copyrename.c +++ b/gcc/tree-ssa-copyrename.c @@ -113,7 +113,7 @@ static struct /* Coalesce the partitions in MAP representing VAR1 and VAR2 if it is valid. Choose a representative for the partition, and send debug info to DEBUG. */ -static bool +static void copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) { int p1, p2, p3; @@ -146,7 +146,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) { if (debug) fprintf (debug, " : Already coalesced.\n"); - return false; + return; } rep1 = partition_to_var (map, p1); @@ -154,7 +154,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) root1 = SSA_NAME_VAR (rep1); root2 = SSA_NAME_VAR (rep2); if (!root1 && !root2) - return false; + return; /* Don't coalesce if one of the variables occurs in an abnormal PHI. */ abnorm = (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rep1) @@ -163,7 +163,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) { if (debug) fprintf (debug, " : Abnormal PHI barrier. No coalesce.\n"); - return false; + return; } /* Partitions already have the same root, simply merge them. */ @@ -172,7 +172,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) p1 = partition_union (map->var_partition, p1, p2); if (debug) fprintf (debug, " : Same root, coalesced --> P%d.\n", p1); - return false; + return; } /* Never attempt to coalesce 2 different parameters. */ @@ -181,7 +181,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) { if (debug) fprintf (debug, " : 2 different PARM_DECLS. No coalesce.\n"); - return false; + return; } if ((root1 && TREE_CODE (root1) == RESULT_DECL) @@ -189,7 +189,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) { if (debug) fprintf (debug, " : One root a RESULT_DECL. No coalesce.\n"); - return false; + return; } ign1 = !root1 || (TREE_CODE (root1) == VAR_DECL && DECL_IGNORED_P (root1)); @@ -206,7 +206,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) { if (debug) fprintf (debug, " : 2 different USER vars. No coalesce.\n"); - return false; + return; } else ign2 = true; @@ -220,7 +220,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) { if (debug) fprintf (debug, " : 2 default defs. No coalesce.\n"); - return false; + return; } else { @@ -240,7 +240,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) { if (debug) fprintf (debug, " : Choosen variable has no root. No coalesce.\n"); - return false; + return; } /* Don't coalesce if the new chosen root variable would be read-only. @@ -253,7 +253,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) { if (debug) fprintf (debug, " : Readonly variable. No coalesce.\n"); - return false; + return; } /* Don't coalesce if the two variables aren't type compatible . */ @@ -266,7 +266,7 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) { if (debug) fprintf (debug, " : Incompatible types. No coalesce.\n"); - return false; + return; } /* Merge the two partitions. */ @@ -288,7 +288,6 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug) TDF_SLIM); fprintf (debug, "\n"); } - return true; } @@ -308,7 +307,6 @@ rename_ssa_copies (void) gimple stmt, phi; unsigned x; FILE *debug; - bool updated = false; memset (&stats, 0, sizeof (stats)); @@ -330,7 +328,7 @@ rename_ssa_copies (void) tree lhs = gimple_assign_lhs (stmt); tree rhs = gimple_assign_rhs1 (stmt); - updated |= copy_rename_partition_coalesce (map, lhs, rhs, debug); + copy_rename_partition_coalesce (map, lhs, rhs, debug); } } } @@ -358,8 +356,8 @@ rename_ssa_copies (void) { tree arg = PHI_ARG_DEF (phi, i); if (TREE_CODE (arg) == SSA_NAME) - updated |= copy_rename_partition_coalesce (map, res, arg, - debug); + copy_rename_partition_coalesce (map, res, arg, + debug); } /* Else if all arguments are in the same partition try to merge it with the result. */ @@ -390,9 +388,9 @@ rename_ssa_copies (void) } } if (all_p_same == 1) - updated |= copy_rename_partition_coalesce (map, res, - PHI_ARG_DEF (phi, 0), - debug); + copy_rename_partition_coalesce (map, res, + PHI_ARG_DEF (phi, 0), + debug); } } } @@ -426,7 +424,7 @@ rename_ssa_copies (void) statistics_counter_event (cfun, "copies coalesced", stats.coalesced); delete_var_map (map); - return updated ? TODO_remove_unused_locals : 0; + return 0; } /* Return true if copy rename is to be performed. */ diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index 28e3486157d..05c58feca5d 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -1607,10 +1607,8 @@ perform_tree_ssa_dce (bool aggressive) free_edge_list (el); if (something_changed) - return (TODO_update_ssa | TODO_cleanup_cfg | TODO_ggc_collect - | TODO_remove_unused_locals); - else - return 0; + return TODO_update_ssa | TODO_cleanup_cfg; + return 0; } /* Pass entry points. */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 8bb783708b8..855c212b0ca 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -2936,7 +2936,6 @@ ssa_forward_propagate_and_combine (void) && forward_propagate_addr_expr (lhs, rhs)) { release_defs (stmt); - todoflags |= TODO_remove_unused_locals; gsi_remove (&gsi, true); } else @@ -2961,7 +2960,6 @@ ssa_forward_propagate_and_combine (void) off))))) { release_defs (stmt); - todoflags |= TODO_remove_unused_locals; gsi_remove (&gsi, true); } else if (is_gimple_min_invariant (rhs)) diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index 9055d91ddb3..a72e9d5a6b6 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -889,7 +889,10 @@ remove_unused_locals (void) dstidx++; } if (dstidx != num) - cfun->local_decls->truncate (dstidx); + { + statistics_counter_event (cfun, "unused VAR_DECLs removed", num - dstidx); + cfun->local_decls->truncate (dstidx); + } remove_unused_scope_block_p (DECL_INITIAL (current_function_decl)); clear_unused_block_pointer (); diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index d30bfec5062..2940bf10044 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -2574,26 +2574,20 @@ record_important_candidates (struct ivopts_data *data) static void alloc_use_cost_map (struct ivopts_data *data) { - unsigned i, size, s, j; + unsigned i, size, s; for (i = 0; i < n_iv_uses (data); i++) { struct iv_use *use = iv_use (data, i); - bitmap_iterator bi; if (data->consider_all_candidates) size = n_iv_cands (data); else { - s = 0; - EXECUTE_IF_SET_IN_BITMAP (use->related_cands, 0, j, bi) - { - s++; - } + s = bitmap_count_bits (use->related_cands); /* Round up to the power of two, so that moduling by it is fast. */ - for (size = 1; size < s; size <<= 1) - continue; + size = s ? (1 << ceil_log2 (s)) : 1; } use->n_map_members = size; @@ -2731,10 +2725,13 @@ get_use_iv_cost (struct ivopts_data *data, struct iv_use *use, for (i = s; i < use->n_map_members; i++) if (use->cost_map[i].cand == cand) return use->cost_map + i; - + else if (use->cost_map[i].cand == NULL) + return NULL; for (i = 0; i < s; i++) if (use->cost_map[i].cand == cand) return use->cost_map + i; + else if (use->cost_map[i].cand == NULL) + return NULL; return NULL; } diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 9ccec2156eb..10c8091758e 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -2923,7 +2923,7 @@ create_expression_by_pieces (basic_block block, pre_expr expr, break; case 3: folded = fold_build3 (nary->opcode, nary->type, - genop[0], genop[1], genop[3]); + genop[0], genop[1], genop[2]); break; default: gcc_unreachable (); diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 81a07aefb4f..202980c19ef 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2401,10 +2401,8 @@ vn_phi_compute_hash (vn_phi_t vp1) /* If all PHI arguments are constants we need to distinguish the PHI node via its type. */ - type = TREE_TYPE (vp1->phiargs[0]); - result += (INTEGRAL_TYPE_P (type) - + (INTEGRAL_TYPE_P (type) - ? TYPE_PRECISION (type) + TYPE_UNSIGNED (type) : 0)); + type = vp1->type; + result += vn_hash_type (type); FOR_EACH_VEC_ELT (vp1->phiargs, i, phi1op) { @@ -2443,8 +2441,7 @@ vn_phi_eq (const void *p1, const void *p2) /* If the PHI nodes do not have compatible types they are not the same. */ - if (!types_compatible_p (TREE_TYPE (vp1->phiargs[0]), - TREE_TYPE (vp2->phiargs[0]))) + if (!types_compatible_p (vp1->type, vp2->type)) return false; /* Any phi in the same block will have it's arguments in the @@ -2484,6 +2481,7 @@ vn_phi_lookup (gimple phi) def = TREE_CODE (def) == SSA_NAME ? SSA_VAL (def) : def; shared_lookup_phiargs.safe_push (def); } + vp1.type = TREE_TYPE (gimple_phi_result (phi)); vp1.phiargs = shared_lookup_phiargs; vp1.block = gimple_bb (phi); vp1.hashcode = vn_phi_compute_hash (&vp1); @@ -2516,6 +2514,7 @@ vn_phi_insert (gimple phi, tree result) args.safe_push (def); } vp1->value_id = VN_INFO (result)->value_id; + vp1->type = TREE_TYPE (gimple_phi_result (phi)); vp1->phiargs = args; vp1->block = gimple_bb (phi); vp1->result = result; diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h index ea9020de21f..072f7ddf65e 100644 --- a/gcc/tree-ssa-sccvn.h +++ b/gcc/tree-ssa-sccvn.h @@ -67,6 +67,7 @@ typedef struct vn_phi_s hashval_t hashcode; vec<tree> phiargs; basic_block block; + tree type; tree result; } *vn_phi_t; typedef const struct vn_phi_s *const_vn_phi_t; @@ -122,17 +123,25 @@ typedef struct vn_constant_s enum vn_kind { VN_NONE, VN_CONSTANT, VN_NARY, VN_REFERENCE, VN_PHI }; enum vn_kind vn_get_stmt_kind (gimple); +/* Hash the type TYPE using bits that distinguishes it in the + types_compatible_p sense. */ + +static inline hashval_t +vn_hash_type (tree type) +{ + return (INTEGRAL_TYPE_P (type) + + (INTEGRAL_TYPE_P (type) + ? TYPE_PRECISION (type) + TYPE_UNSIGNED (type) : 0)); +} + /* Hash the constant CONSTANT with distinguishing type incompatible constants in the types_compatible_p sense. */ static inline hashval_t vn_hash_constant_with_type (tree constant) { - tree type = TREE_TYPE (constant); return (iterative_hash_expr (constant, 0) - + INTEGRAL_TYPE_P (type) - + (INTEGRAL_TYPE_P (type) - ? TYPE_PRECISION (type) + TYPE_UNSIGNED (type) : 0)); + + vn_hash_type (TREE_TYPE (constant))); } /* Compare the constants C1 and C2 with distinguishing type incompatible diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index be078ce96ce..0a405ce2a30 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -455,7 +455,7 @@ struct gimple_opt_pass pass_release_ssa_names = PROP_ssa, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ + TODO_remove_unused_locals, /* todo_flags_start */ + 0 /* todo_flags_finish */ } }; diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c index 8a8982ad2e0..559f6e9e997 100644 --- a/gcc/tree-vect-loop-manip.c +++ b/gcc/tree-vect-loop-manip.c @@ -187,6 +187,7 @@ adjust_debug_stmts (tree from, tree to, basic_block bb) if (MAY_HAVE_DEBUG_STMTS && TREE_CODE (from) == SSA_NAME + && ! SSA_NAME_IS_DEFAULT_DEF (from) && ! virtual_operand_p (from)) { ai.from = from; diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index a2f90138fc9..3693cd27a96 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -4707,7 +4707,7 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi, The last use is the reduction variable. In case of nested cycle this assumption is not true: we use reduc_index to record the index of the reduction variable. */ - for (i = 0; i < op_type-1; i++) + for (i = 0; i < op_type - 1; i++) { /* The condition of COND_EXPR is checked in vectorizable_condition(). */ if (i == 0 && code == COND_EXPR) @@ -4739,11 +4739,18 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi, if (!vectype_in) vectype_in = tem; gcc_assert (is_simple_use); - gcc_assert (dt == vect_reduction_def - || dt == vect_nested_cycle - || ((dt == vect_internal_def || dt == vect_external_def - || dt == vect_constant_def || dt == vect_induction_def) - && nested_cycle && found_nested_cycle_def)); + if (!(dt == vect_reduction_def + || dt == vect_nested_cycle + || ((dt == vect_internal_def || dt == vect_external_def + || dt == vect_constant_def || dt == vect_induction_def) + && nested_cycle && found_nested_cycle_def))) + { + /* For pattern recognized stmts, orig_stmt might be a reduction, + but some helper statements for the pattern might not, or + might be COND_EXPRs with reduction uses in the condition. */ + gcc_assert (orig_stmt); + return false; + } if (!found_nested_cycle_def) reduc_def_stmt = def_stmt; diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index a023a460371..a38b14d4956 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -8503,8 +8503,9 @@ test_for_singularity (enum tree_code cond_code, tree op0, return NULL; } -/* Simplify the conditional stmt STMT using final range information. - Return true if we simplified the statement. */ +/* Simplify a conditional using a relational operator to an equality + test if the range information indicates only one value can satisfy + the original conditional. */ static bool simplify_cond_using_ranges (gimple stmt) @@ -8513,13 +8514,7 @@ simplify_cond_using_ranges (gimple stmt) tree op1 = gimple_cond_rhs (stmt); enum tree_code cond_code = gimple_cond_code (stmt); - /* Simplify a conditional using a relational operator to an equality - test if the range information indicates only one value can satisfy - the original conditional. - Do that only in the second VRP pass as otherwise assertions derived - from this predicate are weakened. */ - if (!first_pass_instance - && cond_code != NE_EXPR + if (cond_code != NE_EXPR && cond_code != EQ_EXPR && TREE_CODE (op0) == SSA_NAME && INTEGRAL_TYPE_P (TREE_TYPE (op0)) diff --git a/gcc/tree.h b/gcc/tree.h index c3c814ca33a..740d4382712 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3586,14 +3586,25 @@ struct GTY(()) tree_optimization_option { /* The optimization options used by the user. */ struct cl_optimization opts; + + /* Target optabs for this set of optimization options. This is of + type `struct target_optabs *'. */ + unsigned char *GTY ((atomic)) target_optabs; }; #define TREE_OPTIMIZATION(NODE) \ (&OPTIMIZATION_NODE_CHECK (NODE)->optimization.opts) +#define TREE_OPTIMIZATION_OPTABS(NODE) \ + (OPTIMIZATION_NODE_CHECK (NODE)->optimization.target_optabs) + /* Return a tree node that encapsulates the current optimization options. */ extern tree build_optimization_node (void); +/* Save a new set of target_optabs in a TREE_OPTIMIZATION node if the + current set of optabs has changed. */ +extern void save_optabs_if_changed (tree); + /* Target options used by a function. */ struct GTY(()) tree_target_option { diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index d4bc8109e7d..6032f6f1a6a 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,7 @@ +2012-02-19 Edgar E. Iglesias <edgar.iglesias@gmail.com> + * config/microblaze/modsi3.S (modsi3): Fix case with 0x80000000 + as dividend. + 2013-02-16 Alan Modra <amodra@gmail.com> PR target/55431 diff --git a/libgcc/config/microblaze/modsi3.S b/libgcc/config/microblaze/modsi3.S index ed28acf8f63..93d0c30b688 100644 --- a/libgcc/config/microblaze/modsi3.S +++ b/libgcc/config/microblaze/modsi3.S @@ -55,6 +55,8 @@ $LaR5_Pos: $LaR6_Pos: ADDIK r3,r0,0 # Clear mod ADDIK r30,r0,0 # clear div + BLTId r5,$LaDIV2 # If r5 is still negative (0x80000000), skip + # the first bit search. ADDIK r29,r0,32 # Initialize the loop count # First part try to find the first '1' in the r5 $LaDIV1: diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 1a42a8449a9..54ac5738c01 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,20 @@ +2013-02-21 Janne Blomqvist <jb@gcc.gnu.org> + + PR libfortran/30162 + * io/open.c (test_endfile): Call stell only if size != 0. + * io/unix.c (raw_tell): Revert r194679. + (raw_size): Return size field only for regular files, otherwise 0. + +2013-02-19 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> + + PR target/56347 + * acinclude.m4 (LIBGFOR_CHECK_FOR_BROKEN_POWF): Remove check for + broken powf. + * configure.ac (LIBGFOR_CHECK_FOR_BROKEN_POWF): Likewise. + * intrinsics/c99_functions.c: Likewise. + * configure: Rebuilt. + * config.h.in: Rebuilt. + 2013-02-06 Janus Weil <janus@gcc.gnu.org> PR fortran/55978 diff --git a/libgfortran/acinclude.m4 b/libgfortran/acinclude.m4 index d10126150ea..35698ec00f6 100644 --- a/libgfortran/acinclude.m4 +++ b/libgfortran/acinclude.m4 @@ -257,18 +257,6 @@ __mingw_snprintf (NULL, 0, "%d\n", 1); fi ]) -dnl Check whether we have a broken powf implementation -AC_DEFUN([LIBGFOR_CHECK_FOR_BROKEN_POWF], [ - AC_CACHE_CHECK([whether powf is broken], libgfor_cv_have_broken_powf, [ -case "${target}" in - hppa*64*-*-hpux*) libgfor_cv_have_broken_powf=yes ;; - *) libgfor_cv_have_broken_powf=no;; -esac]) - if test x"$libgfor_cv_have_broken_powf" = xyes; then - AC_DEFINE(HAVE_BROKEN_POWF, 1, [Define if powf is broken.]) - fi -]) - dnl Check whether we have a __float128 type AC_DEFUN([LIBGFOR_CHECK_FLOAT128], [ LIBQUADSPEC= diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in index ee4c14f52c3..fb5026fc0da 100644 --- a/libgfortran/config.h.in +++ b/libgfortran/config.h.in @@ -81,9 +81,6 @@ /* Define to 1 if the target supports __attribute__((visibility(...))). */ #undef HAVE_ATTRIBUTE_VISIBILITY -/* Define if powf is broken. */ -#undef HAVE_BROKEN_POWF - /* Define to 1 if you have the `cabs' function. */ #undef HAVE_CABS diff --git a/libgfortran/configure b/libgfortran/configure index 5ad56aa29b7..8385e968458 100755 --- a/libgfortran/configure +++ b/libgfortran/configure @@ -25592,28 +25592,6 @@ $as_echo "#define HAVE_MINGW_SNPRINTF 1" >>confdefs.h fi -# Check for a broken powf implementation - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether powf is broken" >&5 -$as_echo_n "checking whether powf is broken... " >&6; } -if test "${libgfor_cv_have_broken_powf+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - -case "${target}" in - hppa*64*-*-hpux*) libgfor_cv_have_broken_powf=yes ;; - *) libgfor_cv_have_broken_powf=no;; -esac -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgfor_cv_have_broken_powf" >&5 -$as_echo "$libgfor_cv_have_broken_powf" >&6; } - if test x"$libgfor_cv_have_broken_powf" = xyes; then - -$as_echo "#define HAVE_BROKEN_POWF 1" >>confdefs.h - - fi - - # Check whether libquadmath should be used # Check whether --enable-libquadmath-support was given. if test "${enable_libquadmath_support+set}" = set; then : diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac index 86cb330fee3..7d97fed1b0b 100644 --- a/libgfortran/configure.ac +++ b/libgfortran/configure.ac @@ -468,9 +468,6 @@ LIBGFOR_CHECK_WORKING_STAT # Check whether __mingw_snprintf() is present LIBGFOR_CHECK_MINGW_SNPRINTF -# Check for a broken powf implementation -LIBGFOR_CHECK_FOR_BROKEN_POWF - # Check whether libquadmath should be used AC_ARG_ENABLE(libquadmath-support, AS_HELP_STRING([--disable-libquadmath-support], diff --git a/libgfortran/intrinsics/c99_functions.c b/libgfortran/intrinsics/c99_functions.c index f6acf2d1d0f..ee74b115ea7 100644 --- a/libgfortran/intrinsics/c99_functions.c +++ b/libgfortran/intrinsics/c99_functions.c @@ -518,10 +518,8 @@ nextafterf (float x, float y) #endif -#if !defined(HAVE_POWF) || defined(HAVE_BROKEN_POWF) #ifndef HAVE_POWF #define HAVE_POWF 1 -#endif float powf (float x, float y); float diff --git a/libgfortran/io/open.c b/libgfortran/io/open.c index 28957673eff..d9cfde853f5 100644 --- a/libgfortran/io/open.c +++ b/libgfortran/io/open.c @@ -152,8 +152,12 @@ static const st_option async_opt[] = static void test_endfile (gfc_unit * u) { - if (u->endfile == NO_ENDFILE && ssize (u->s) == stell (u->s)) - u->endfile = AT_ENDFILE; + if (u->endfile == NO_ENDFILE) + { + gfc_offset sz = ssize (u->s); + if (sz == 0 || sz == stell (u->s)) + u->endfile = AT_ENDFILE; + } } diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c index ba8392d21a1..8b9d7a77342 100644 --- a/libgfortran/io/unix.c +++ b/libgfortran/io/unix.c @@ -342,15 +342,7 @@ raw_seek (unix_stream * s, gfc_offset offset, int whence) static gfc_offset raw_tell (unix_stream * s) { - gfc_offset x; - x = lseek (s->fd, 0, SEEK_CUR); - - /* Non-seekable files should always be assumed to be at - current position. */ - if (x == -1 && errno == ESPIPE) - x = 0; - - return x; + return lseek (s->fd, 0, SEEK_CUR); } static gfc_offset @@ -360,7 +352,10 @@ raw_size (unix_stream * s) int ret = fstat (s->fd, &statbuf); if (ret == -1) return ret; - return statbuf.st_size; + if (S_ISREG (statbuf.st_mode)) + return statbuf.st_size; + else + return 0; } static int diff --git a/libgo/Makefile.am b/libgo/Makefile.am index c153ae22227..ea90318cee1 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -1656,6 +1656,13 @@ endif endif endif +# Define socket functions. +if LIBGO_IS_SOLARIS +syscall_socket_os_file = go/syscall/socket_xnet.go +else +syscall_socket_os_file = go/syscall/socket_posix.go +endif + # Support for uname. if LIBGO_IS_SOLARIS if LIBGO_IS_386 @@ -1722,6 +1729,7 @@ go_base_syscall_files = \ $(syscall_errstr_file) \ $(syscall_size_file) \ $(syscall_socket_file) \ + $(syscall_socket_os_file) \ $(syscall_uname_file) \ $(syscall_netlink_file) \ $(syscall_lsf_file) \ @@ -1746,13 +1754,20 @@ go_syscall_test_files = \ go/syscall/passfd_test.go libcalls.go: s-libcalls; @true -s-libcalls: Makefile go/syscall/mksyscall.awk $(go_base_syscall_files) +s-libcalls: libcalls-list go/syscall/mksyscall.awk $(go_base_syscall_files) rm -f libcalls.go.tmp - files=`echo $^ | sed -e 's/Makefile//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \ + files=`echo $^ | sed -e 's/libcalls-list//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \ $(AWK) -f $(srcdir)/go/syscall/mksyscall.awk $${files} > libcalls.go.tmp $(SHELL) $(srcdir)/../move-if-change libcalls.go.tmp libcalls.go $(STAMP) $@ +libcalls-list: s-libcalls-list; @true +s-libcalls-list: Makefile + rm -f libcalls-list.tmp + echo $(go_base_syscall_files) > libcalls-list.tmp + $(SHELL) $(srcdir)/../move-if-change libcalls-list.tmp libcalls-list + $(STAMP) $@ + syscall_arch.go: s-syscall_arch; @true s-syscall_arch: Makefile rm -f syscall_arch.go.tmp diff --git a/libgo/Makefile.in b/libgo/Makefile.in index fe780b13f22..c22a4ea47fc 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -1877,6 +1877,10 @@ go_unicode_utf8_files = \ # Define socket sizes and types. @LIBGO_IS_LINUX_TRUE@syscall_socket_file = go/syscall/socket_linux.go epoll.go +@LIBGO_IS_SOLARIS_FALSE@syscall_socket_os_file = go/syscall/socket_posix.go + +# Define socket functions. +@LIBGO_IS_SOLARIS_TRUE@syscall_socket_os_file = go/syscall/socket_xnet.go @LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file = go/syscall/libcall_uname.go # Support for uname. @@ -1922,6 +1926,7 @@ go_base_syscall_files = \ $(syscall_errstr_file) \ $(syscall_size_file) \ $(syscall_socket_file) \ + $(syscall_socket_os_file) \ $(syscall_uname_file) \ $(syscall_netlink_file) \ $(syscall_lsf_file) \ @@ -4512,13 +4517,20 @@ s-version: Makefile $(STAMP) $@ libcalls.go: s-libcalls; @true -s-libcalls: Makefile go/syscall/mksyscall.awk $(go_base_syscall_files) +s-libcalls: libcalls-list go/syscall/mksyscall.awk $(go_base_syscall_files) rm -f libcalls.go.tmp - files=`echo $^ | sed -e 's/Makefile//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \ + files=`echo $^ | sed -e 's/libcalls-list//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \ $(AWK) -f $(srcdir)/go/syscall/mksyscall.awk $${files} > libcalls.go.tmp $(SHELL) $(srcdir)/../move-if-change libcalls.go.tmp libcalls.go $(STAMP) $@ +libcalls-list: s-libcalls-list; @true +s-libcalls-list: Makefile + rm -f libcalls-list.tmp + echo $(go_base_syscall_files) > libcalls-list.tmp + $(SHELL) $(srcdir)/../move-if-change libcalls-list.tmp libcalls-list + $(STAMP) $@ + syscall_arch.go: s-syscall_arch; @true s-syscall_arch: Makefile rm -f syscall_arch.go.tmp diff --git a/libgo/go/syscall/sockcmsg_unix.go b/libgo/go/syscall/sockcmsg_unix.go index fc83df123db..951bc18fcdf 100644 --- a/libgo/go/syscall/sockcmsg_unix.go +++ b/libgo/go/syscall/sockcmsg_unix.go @@ -8,7 +8,10 @@ package syscall -import "unsafe" +import ( + "runtime" + "unsafe" +) // Round the length of a raw sockaddr up to align it propery. func cmsgAlignOf(salen int) int { @@ -18,6 +21,11 @@ func cmsgAlignOf(salen int) int { if darwinAMD64 { salign = 4 } + // NOTE: Solaris always uses 32-bit alignment, + // cf. _CMSG_DATA_ALIGNMENT in <sys/socket.h>. + if runtime.GOOS == "solaris" { + salign = 4 + } if salen == 0 { return salign } diff --git a/libgo/go/syscall/socket.go b/libgo/go/syscall/socket.go index 3aa92012f08..a625eb69851 100644 --- a/libgo/go/syscall/socket.go +++ b/libgo/go/syscall/socket.go @@ -177,9 +177,6 @@ func Getpeername(fd int) (sa Sockaddr, err error) { return anyToSockaddr(&rsa) } -//sys bind(fd int, sa *RawSockaddrAny, len Socklen_t) (err error) -//bind(fd _C_int, sa *RawSockaddrAny, len Socklen_t) _C_int - func Bind(fd int, sa Sockaddr) (err error) { ptr, n, err := sa.sockaddr() if err != nil { @@ -188,9 +185,6 @@ func Bind(fd int, sa Sockaddr) (err error) { return bind(fd, ptr, n) } -//sys connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) (err error) -//connect(s _C_int, addr *RawSockaddrAny, addrlen Socklen_t) _C_int - func Connect(fd int, sa Sockaddr) (err error) { ptr, n, err := sa.sockaddr() if err != nil { @@ -199,9 +193,6 @@ func Connect(fd int, sa Sockaddr) (err error) { return connect(fd, ptr, n) } -//sysnb socket(domain int, typ int, proto int) (fd int, err error) -//socket(domain _C_int, typ _C_int, protocol _C_int) _C_int - func Socket(domain, typ, proto int) (fd int, err error) { if domain == AF_INET6 && SocketDisableIPv6 { return -1, EAFNOSUPPORT @@ -210,9 +201,6 @@ func Socket(domain, typ, proto int) (fd int, err error) { return } -//sysnb socketpair(domain int, typ int, proto int, fd *[2]_C_int) (err error) -//socketpair(domain _C_int, typ _C_int, protocol _C_int, fd *[2]_C_int) _C_int - func Socketpair(domain, typ, proto int) (fd [2]int, err error) { var fdx [2]_C_int err = socketpair(domain, typ, proto, &fdx) @@ -223,9 +211,6 @@ func Socketpair(domain, typ, proto int) (fd [2]int, err error) { return } -//sys getsockopt(s int, level int, name int, val uintptr, vallen *Socklen_t) (err error) -//getsockopt(s _C_int, level _C_int, name _C_int, val *byte, vallen *Socklen_t) _C_int - func GetsockoptByte(fd, level, opt int) (value byte, err error) { var n byte vallen := Socklen_t(1) @@ -326,9 +311,6 @@ func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { return } -//sys sendto(s int, buf []byte, flags int, to *RawSockaddrAny, tolen Socklen_t) (err error) -//sendto(s _C_int, buf *byte, len Size_t, flags _C_int, to *RawSockaddrAny, tolen Socklen_t) Ssize_t - func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { ptr, n, err := to.sockaddr() if err != nil { @@ -337,9 +319,6 @@ func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) { return sendto(fd, p, flags, ptr, n) } -//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) -//recvmsg(s _C_int, msg *Msghdr, flags _C_int) Ssize_t - func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { var msg Msghdr var rsa RawSockaddrAny @@ -374,9 +353,6 @@ func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from return } -//sys sendmsg(s int, msg *Msghdr, flags int) (err error) -//sendmsg(s _C_int, msg *Msghdr, flags _C_int) Ssize_t - func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { var ptr *RawSockaddrAny var salen Socklen_t diff --git a/libgo/go/syscall/socket_posix.go b/libgo/go/syscall/socket_posix.go new file mode 100644 index 00000000000..06d7dab464a --- /dev/null +++ b/libgo/go/syscall/socket_posix.go @@ -0,0 +1,31 @@ +// socket_posix.go -- Socket handling for generic POSIX systems. + +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package syscall + +//sys bind(fd int, sa *RawSockaddrAny, len Socklen_t) (err error) +//bind(fd _C_int, sa *RawSockaddrAny, len Socklen_t) _C_int + +//sys connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) (err error) +//connect(s _C_int, addr *RawSockaddrAny, addrlen Socklen_t) _C_int + +//sysnb socket(domain int, typ int, proto int) (fd int, err error) +//socket(domain _C_int, typ _C_int, protocol _C_int) _C_int + +//sysnb socketpair(domain int, typ int, proto int, fd *[2]_C_int) (err error) +//socketpair(domain _C_int, typ _C_int, protocol _C_int, fd *[2]_C_int) _C_int + +//sys getsockopt(s int, level int, name int, val uintptr, vallen *Socklen_t) (err error) +//getsockopt(s _C_int, level _C_int, name _C_int, val *byte, vallen *Socklen_t) _C_int + +//sys sendto(s int, buf []byte, flags int, to *RawSockaddrAny, tolen Socklen_t) (err error) +//sendto(s _C_int, buf *byte, len Size_t, flags _C_int, to *RawSockaddrAny, tolen Socklen_t) Ssize_t + +//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) +//recvmsg(s _C_int, msg *Msghdr, flags _C_int) Ssize_t + +//sys sendmsg(s int, msg *Msghdr, flags int) (err error) +//sendmsg(s _C_int, msg *Msghdr, flags _C_int) Ssize_t diff --git a/libgo/go/syscall/socket_xnet.go b/libgo/go/syscall/socket_xnet.go new file mode 100644 index 00000000000..8f86c622b9f --- /dev/null +++ b/libgo/go/syscall/socket_xnet.go @@ -0,0 +1,32 @@ +// socket_xnet.go -- Socket handling specific to Solaris. +// Enforce use of XPG 4.2 versions of socket functions. + +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package syscall + +//sys bind(fd int, sa *RawSockaddrAny, len Socklen_t) (err error) +//__xnet_bind(fd _C_int, sa *RawSockaddrAny, len Socklen_t) _C_int + +//sys connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) (err error) +//__xnet_connect(s _C_int, addr *RawSockaddrAny, addrlen Socklen_t) _C_int + +//sysnb socket(domain int, typ int, proto int) (fd int, err error) +//__xnet_socket(domain _C_int, typ _C_int, protocol _C_int) _C_int + +//sysnb socketpair(domain int, typ int, proto int, fd *[2]_C_int) (err error) +//__xnet_socketpair(domain _C_int, typ _C_int, protocol _C_int, fd *[2]_C_int) _C_int + +//sys getsockopt(s int, level int, name int, val uintptr, vallen *Socklen_t) (err error) +//__xnet_getsockopt(s _C_int, level _C_int, name _C_int, val *byte, vallen *Socklen_t) _C_int + +//sys sendto(s int, buf []byte, flags int, to *RawSockaddrAny, tolen Socklen_t) (err error) +//__xnet_sendto(s _C_int, buf *byte, len Size_t, flags _C_int, to *RawSockaddrAny, tolen Socklen_t) Ssize_t + +//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) +//__xnet_recvmsg(s _C_int, msg *Msghdr, flags _C_int) Ssize_t + +//sys sendmsg(s int, msg *Msghdr, flags int) (err error) +//__xnet_sendmsg(s _C_int, msg *Msghdr, flags _C_int) Ssize_t diff --git a/libgo/runtime/lfstack.c b/libgo/runtime/lfstack.c index 00b60081e88..230ed87c43f 100644 --- a/libgo/runtime/lfstack.c +++ b/libgo/runtime/lfstack.c @@ -17,9 +17,10 @@ #define PTR_MASK ((1ull<<PTR_BITS)-1) #define CNT_MASK (0ull-1) -#if __SIZEOF_POINTER__ == 8 && defined(__sparc__) -// SPARC64 uses all 64 bits of virtual addresses. Use low-order three -// bits as ABA counter. +#if __SIZEOF_POINTER__ == 8 && (defined(__sparc__) || (defined(__sun__) && defined(__amd64__))) +// SPARC64 and Solaris on AMD64 uses all 64 bits of virtual addresses. +// Use low-order three bits as ABA counter. +// http://docs.oracle.com/cd/E19120-01/open.solaris/816-5138/6mba6ua5p/index.html #undef PTR_BITS #undef CNT_MASK #undef PTR_MASK diff --git a/libjava/classpath/ChangeLog.gcj b/libjava/classpath/ChangeLog.gcj index 98ce4382983..62105e26968 100644 --- a/libjava/classpath/ChangeLog.gcj +++ b/libjava/classpath/ChangeLog.gcj @@ -1,3 +1,9 @@ +2013-02-21 Jakub Jelinek <jakub@redhat.com> + + PR bootstrap/56258 + * doc/cp-tools.texinfo (Virtual Machine Options): Use just + one @gccoptlist instead of 3 separate ones. + 2013-01-03 Jakub Jelinek <jakub@redhat.com> * gnu/java/rmi/registry/RegistryImpl.java (version): Update diff --git a/libjava/classpath/doc/cp-tools.texinfo b/libjava/classpath/doc/cp-tools.texinfo index ec186dee778..c3cc5ff8cdf 100644 --- a/libjava/classpath/doc/cp-tools.texinfo +++ b/libjava/classpath/doc/cp-tools.texinfo @@ -2025,7 +2025,7 @@ Doclet, grouped by type. Explanations are in the following sections. @item Virtual Machine Options @xref{Virtual Machine Options,,Options Controlling Gjdoc Behavior}. -@gccoptlist{-classpath} @gccoptlist{-bootclasspath} @gccoptlist{-J}@var{vmopt} +@gccoptlist{-classpath -bootclasspath -J @var{vmopt}} @end table diff --git a/libquadmath/ChangeLog b/libquadmath/ChangeLog index 3c293cfac5e..15c0739319d 100644 --- a/libquadmath/ChangeLog +++ b/libquadmath/ChangeLog @@ -1,3 +1,9 @@ +2013-02-19 Jakub Jelinek <jakub@redhat.com> + + PR libquadmath/56379 + * strtod/strtod_l.c (mpn_lshift_1): Rewritten as function-like + macro. + 2013-02-17 Tobias Burnus <burnus@net-b.de> * math/cacoshq.c (cacoshq): Call signbitq instead of signbit. diff --git a/libquadmath/strtod/strtod_l.c b/libquadmath/strtod/strtod_l.c index d1845a8039c..0b0e85a3cf7 100644 --- a/libquadmath/strtod/strtod_l.c +++ b/libquadmath/strtod/strtod_l.c @@ -421,28 +421,30 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize, /* Shift {PTR, SIZE} COUNT bits to the left, and fill the vacated bits with the COUNT most significant bits of LIMB. - Tege doesn't like this function so I have to write it here myself. :) + Implemented as a macro, so that __builtin_constant_p works even at -O0. + + Tege doesn't like this macro so I have to write it here myself. :) --drepper */ -static inline void -__attribute ((always_inline)) -mpn_lshift_1 (mp_limb_t *ptr, mp_size_t size, unsigned int count, - mp_limb_t limb) -{ - if (__builtin_constant_p (count) && count == BITS_PER_MP_LIMB) - { - /* Optimize the case of shifting by exactly a word: - just copy words, with no actual bit-shifting. */ - mp_size_t i; - for (i = size - 1; i > 0; --i) - ptr[i] = ptr[i - 1]; - ptr[0] = limb; - } - else - { - (void) mpn_lshift (ptr, ptr, size, count); - ptr[0] |= limb >> (BITS_PER_MP_LIMB - count); - } -} +#define mpn_lshift_1(ptr, size, count, limb) \ + do \ + { \ + mp_limb_t *__ptr = (ptr); \ + if (__builtin_constant_p (count) && count == BITS_PER_MP_LIMB) \ + { \ + mp_size_t i; \ + for (i = (size) - 1; i > 0; --i) \ + __ptr[i] = __ptr[i - 1]; \ + __ptr[0] = (limb); \ + } \ + else \ + { \ + /* We assume count > 0 && count < BITS_PER_MP_LIMB here. */ \ + unsigned int __count = (count); \ + (void) mpn_lshift (__ptr, __ptr, size, __count); \ + __ptr[0] |= (limb) >> (BITS_PER_MP_LIMB - __count); \ + } \ + } \ + while (0) #define INTERNAL(x) INTERNAL1(x) diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index eb6a3456e47..7f8f6ad7758 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,21 @@ +2013-02-21 Jack Howarth <howarth@bromo.med.uc.edu> + + * asan/Makefile.am (libasan_la_SOURCES): Remove deprecated + dynamic/asan_interceptors_dynamic.cc. + * asan/Makefile.in: Regenerated. + * merge.sh: Remove merge of deprecated lib/asan/dynamic. + +2013-02-21 Jakub Jelinek <jakub@redhat.com> + + * asan/asan_rtl.cc (__asan_preinit): Don't add if PIC macro is + defined. Add used attribute. + +2013-02-21 Kostya Serebryany <kcc@google.com> + + * All source files: Merge from upstream r175733. + * sanitizer_common/Makefile.am: Added a new file. + * sanitizer_common/Makefile.in: Regenerated. + 2013-02-14 H.J. Lu <hongjiu.lu@intel.com> PR bootstrap/56327 diff --git a/libsanitizer/MERGE b/libsanitizer/MERGE index 02d2bfcf512..28d1e49ab77 100644 --- a/libsanitizer/MERGE +++ b/libsanitizer/MERGE @@ -1,4 +1,4 @@ -175049 +175733 The first line of this file holds the svn revision number of the last merge done from the master library sources. diff --git a/libsanitizer/asan/Makefile.am b/libsanitizer/asan/Makefile.am index bfd9e2e5524..b3ca3df31e1 100644 --- a/libsanitizer/asan/Makefile.am +++ b/libsanitizer/asan/Makefile.am @@ -37,7 +37,6 @@ asan_files = \ libasan_la_SOURCES = $(asan_files) if USING_MAC_INTERPOSE -libasan_la_SOURCES += dynamic/asan_interceptors_dynamic.cc libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la else libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la diff --git a/libsanitizer/asan/Makefile.in b/libsanitizer/asan/Makefile.in index 848f0df1e83..28dad181415 100644 --- a/libsanitizer/asan/Makefile.in +++ b/libsanitizer/asan/Makefile.in @@ -53,7 +53,6 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ @USING_MAC_INTERPOSE_TRUE@am__append_1 = -DMAC_INTERPOSE_FUNCTIONS -DMISSING_BLOCKS_SUPPORT -@USING_MAC_INTERPOSE_TRUE@am__append_2 = dynamic/asan_interceptors_dynamic.cc subdir = asan DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -107,13 +106,6 @@ am__DEPENDENCIES_1 = @USING_MAC_INTERPOSE_FALSE@ $(am__DEPENDENCIES_1) @USING_MAC_INTERPOSE_TRUE@libasan_la_DEPENDENCIES = $(top_builddir)/sanitizer_common/libsanitizer_common.la \ @USING_MAC_INTERPOSE_TRUE@ $(am__DEPENDENCIES_1) -am__libasan_la_SOURCES_DIST = asan_allocator.cc asan_allocator2.cc \ - asan_interceptors.cc asan_mac.cc asan_malloc_mac.cc \ - asan_new_delete.cc asan_posix.cc asan_rtl.cc asan_stats.cc \ - asan_thread_registry.cc asan_fake_stack.cc asan_globals.cc \ - asan_linux.cc asan_malloc_linux.cc asan_malloc_win.cc \ - asan_poisoning.cc asan_report.cc asan_stack.cc asan_thread.cc \ - asan_win.cc dynamic/asan_interceptors_dynamic.cc am__objects_1 = asan_allocator.lo asan_allocator2.lo \ asan_interceptors.lo asan_mac.lo asan_malloc_mac.lo \ asan_new_delete.lo asan_posix.lo asan_rtl.lo asan_stats.lo \ @@ -121,9 +113,7 @@ am__objects_1 = asan_allocator.lo asan_allocator2.lo \ asan_linux.lo asan_malloc_linux.lo asan_malloc_win.lo \ asan_poisoning.lo asan_report.lo asan_stack.lo asan_thread.lo \ asan_win.lo -@USING_MAC_INTERPOSE_TRUE@am__objects_2 = \ -@USING_MAC_INTERPOSE_TRUE@ asan_interceptors_dynamic.lo -am_libasan_la_OBJECTS = $(am__objects_1) $(am__objects_2) +am_libasan_la_OBJECTS = $(am__objects_1) libasan_la_OBJECTS = $(am_libasan_la_OBJECTS) libasan_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ @@ -142,7 +132,7 @@ CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libasan_la_SOURCES) -DIST_SOURCES = $(am__libasan_la_SOURCES_DIST) +DIST_SOURCES = $(libasan_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -317,7 +307,7 @@ asan_files = \ asan_thread.cc \ asan_win.cc -libasan_la_SOURCES = $(asan_files) $(am__append_2) +libasan_la_SOURCES = $(asan_files) @USING_MAC_INTERPOSE_FALSE@libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la \ @USING_MAC_INTERPOSE_FALSE@ $(top_builddir)/interception/libinterception.la \ @USING_MAC_INTERPOSE_FALSE@ $(LIBSTDCXX_RAW_CXX_LDFLAGS) @@ -444,7 +434,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_fake_stack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_globals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_interceptors.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_interceptors_dynamic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_linux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_mac.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_malloc_linux.Plo@am__quote@ @@ -482,13 +471,6 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< -asan_interceptors_dynamic.lo: dynamic/asan_interceptors_dynamic.cc -@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT asan_interceptors_dynamic.lo -MD -MP -MF $(DEPDIR)/asan_interceptors_dynamic.Tpo -c -o asan_interceptors_dynamic.lo `test -f 'dynamic/asan_interceptors_dynamic.cc' || echo '$(srcdir)/'`dynamic/asan_interceptors_dynamic.cc -@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/asan_interceptors_dynamic.Tpo $(DEPDIR)/asan_interceptors_dynamic.Plo -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dynamic/asan_interceptors_dynamic.cc' object='asan_interceptors_dynamic.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o asan_interceptors_dynamic.lo `test -f 'dynamic/asan_interceptors_dynamic.cc' || echo '$(srcdir)/'`dynamic/asan_interceptors_dynamic.cc - mostlyclean-libtool: -rm -f *.lo diff --git a/libsanitizer/asan/asan_flags.h b/libsanitizer/asan/asan_flags.h index b05fdc3acc6..b880896c7a3 100644 --- a/libsanitizer/asan/asan_flags.h +++ b/libsanitizer/asan/asan_flags.h @@ -15,11 +15,13 @@ #include "sanitizer_common/sanitizer_internal_defs.h" -// ASan flag values can be defined in three ways: +// ASan flag values can be defined in four ways: // 1) initialized with default values at startup. -// 2) overriden from string returned by user-specified function +// 2) overriden during compilation of ASan runtime by providing +// compile definition ASAN_DEFAULT_OPTIONS. +// 3) overriden from string returned by user-specified function // __asan_default_options(). -// 3) overriden from env variable ASAN_OPTIONS. +// 4) overriden from env variable ASAN_OPTIONS. namespace __asan { diff --git a/libsanitizer/asan/asan_intercepted_functions.h b/libsanitizer/asan/asan_intercepted_functions.h index 45c913c1894..ed75c428439 100644 --- a/libsanitizer/asan/asan_intercepted_functions.h +++ b/libsanitizer/asan/asan_intercepted_functions.h @@ -77,9 +77,36 @@ using __sanitizer::uptr; # define ASAN_INTERCEPT___CXA_THROW 0 #endif +#define INTERPOSE_FUNCTION(function) \ + { reinterpret_cast<const uptr>(WRAP(function)), \ + reinterpret_cast<const uptr>(function) } + +#define INTERPOSE_FUNCTION_2(function, wrapper) \ + { reinterpret_cast<const uptr>(wrapper), \ + reinterpret_cast<const uptr>(function) } + +struct interpose_substitution { + const uptr replacement; + const uptr original; +}; + +#define INTERPOSER(func) __attribute__((used)) \ +const interpose_substitution substitution_##func[] \ + __attribute__((section("__DATA, __interpose"))) = { \ + INTERPOSE_FUNCTION(func), \ +} + +#define INTERPOSER_2(func, wrapper) __attribute__((used)) \ +const interpose_substitution substitution_##func[] \ + __attribute__((section("__DATA, __interpose"))) = { \ + INTERPOSE_FUNCTION_2(func, wrapper), \ +} + + #define DECLARE_FUNCTION_AND_WRAPPER(ret_type, func, ...) \ ret_type func(__VA_ARGS__); \ - ret_type WRAP(func)(__VA_ARGS__) + ret_type WRAP(func)(__VA_ARGS__); \ + INTERPOSER(func) // Use extern declarations of intercepted functions on Mac and Windows // to avoid including system headers. @@ -139,7 +166,8 @@ DECLARE_FUNCTION_AND_WRAPPER(char*, strdup, const char *s); DECLARE_FUNCTION_AND_WRAPPER(uptr, strnlen, const char *s, uptr maxlen); # endif # if ASAN_INTERCEPT_INDEX -DECLARE_FUNCTION_AND_WRAPPER(char*, index, const char *string, int c); +char* index(const char *string, int c); +INTERPOSER_2(index, WRAP(strchr)); # endif // stdlib.h @@ -193,6 +221,20 @@ DECLARE_FUNCTION_AND_WRAPPER(int, pthread_create, void *(*start_routine)(void*), void *arg); # endif +# if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS +DECLARE_FUNCTION_AND_WRAPPER(void *, localtime, unsigned long *timep); +DECLARE_FUNCTION_AND_WRAPPER(void *, localtime_r, unsigned long *timep, + void *result); +DECLARE_FUNCTION_AND_WRAPPER(void *, gmtime, unsigned long *timep); +DECLARE_FUNCTION_AND_WRAPPER(void *, gmtime_r, unsigned long *timep, + void *result); +DECLARE_FUNCTION_AND_WRAPPER(char *, ctime, unsigned long *timep); +DECLARE_FUNCTION_AND_WRAPPER(char *, ctime_r, unsigned long *timep, + char *result); +DECLARE_FUNCTION_AND_WRAPPER(char *, asctime, void *tm); +DECLARE_FUNCTION_AND_WRAPPER(char *, asctime_r, void *tm, char *result); +# endif + // stdio.h # if SANITIZER_INTERCEPT_SCANF DECLARE_FUNCTION_AND_WRAPPER(int, vscanf, const char *format, va_list ap); @@ -205,17 +247,6 @@ DECLARE_FUNCTION_AND_WRAPPER(int, fscanf, void* stream, const char *format, ...); DECLARE_FUNCTION_AND_WRAPPER(int, sscanf, // NOLINT const char *str, const char *format, ...); -DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_vscanf, const char *format, - va_list ap); -DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_vsscanf, const char *str, - const char *format, va_list ap); -DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_vfscanf, void *stream, - const char *format, va_list ap); -DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_scanf, const char *format, ...); -DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_fscanf, - void* stream, const char *format, ...); -DECLARE_FUNCTION_AND_WRAPPER(int, __isoc99_sscanf, // NOLINT - const char *str, const char *format, ...); # endif # if defined(__APPLE__) @@ -278,9 +309,11 @@ DECLARE_FUNCTION_AND_WRAPPER(void *, valloc, size_t size); DECLARE_FUNCTION_AND_WRAPPER(size_t, malloc_good_size, size_t size); DECLARE_FUNCTION_AND_WRAPPER(int, posix_memalign, void **memptr, size_t alignment, size_t size); +#if 0 DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_prepare, void); DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_parent, void); DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_child, void); +#endif diff --git a/libsanitizer/asan/asan_interceptors.cc b/libsanitizer/asan/asan_interceptors.cc index f4c56830d8a..064fc6261b0 100644 --- a/libsanitizer/asan/asan_interceptors.cc +++ b/libsanitizer/asan/asan_interceptors.cc @@ -24,6 +24,16 @@ namespace __asan { +// Return true if we can quickly decide that the region is unpoisoned. +static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) { + if (size == 0) return true; + if (size <= 32) + return !AddressIsPoisoned(beg) && + !AddressIsPoisoned(beg + size - 1) && + !AddressIsPoisoned(beg + size / 2); + return false; +} + // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, // and ASAN_WRITE_RANGE as macro instead of function so // that no extra frames are created, and stack trace contains @@ -32,7 +42,8 @@ namespace __asan { #define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ uptr __offset = (uptr)(offset); \ uptr __size = (uptr)(size); \ - if (__asan_region_is_poisoned(__offset, __size)) { \ + if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \ + __asan_region_is_poisoned(__offset, __size)) { \ GET_CURRENT_PC_BP_SP; \ __asan_report_error(pc, bp, sp, __offset, isWrite, __size); \ } \ diff --git a/libsanitizer/asan/asan_internal.h b/libsanitizer/asan/asan_internal.h index 0fe620e2e4c..1ccbf108647 100644 --- a/libsanitizer/asan/asan_internal.h +++ b/libsanitizer/asan/asan_internal.h @@ -52,7 +52,7 @@ #define ASAN_POSIX (ASAN_LINUX || ASAN_MAC) -#if __has_feature(address_sanitizer) +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) # error "The AddressSanitizer run-time should not be" " instrumented by AddressSanitizer" #endif @@ -89,6 +89,10 @@ # endif #endif +#ifndef ASAN_USE_PREINIT_ARRAY +# define ASAN_USE_PREINIT_ARRAY (ASAN_LINUX && !ASAN_ANDROID) +#endif + // All internal functions in asan reside inside the __asan namespace // to avoid namespace collisions with the user programs. // Seperate namespace also makes it simpler to distinguish the asan run-time diff --git a/libsanitizer/asan/asan_mac.cc b/libsanitizer/asan/asan_mac.cc index c5fc7de10c0..dd2657df1e2 100644 --- a/libsanitizer/asan/asan_mac.cc +++ b/libsanitizer/asan/asan_mac.cc @@ -86,6 +86,39 @@ extern "C" void __asan_init(); static const char kDyldInsertLibraries[] = "DYLD_INSERT_LIBRARIES"; +LowLevelAllocator allocator_for_env; + +// Change the value of the env var |name|, leaking the original value. +// If |name_value| is NULL, the variable is deleted from the environment, +// otherwise the corresponding "NAME=value" string is replaced with +// |name_value|. +void LeakyResetEnv(const char *name, const char *name_value) { + char ***env_ptr = _NSGetEnviron(); + CHECK(env_ptr); + char **environ = *env_ptr; + CHECK(environ); + uptr name_len = internal_strlen(name); + while (*environ != 0) { + uptr len = internal_strlen(*environ); + if (len > name_len) { + const char *p = *environ; + if (!internal_memcmp(p, name, name_len) && p[name_len] == '=') { + // Match. + if (name_value) { + // Replace the old value with the new one. + *environ = const_cast<char*>(name_value); + } else { + // Shift the subsequent pointers back. + char **del = environ; + do { + del[0] = del[1]; + } while (*del++); + } + } + } + environ++; + } +} void MaybeReexec() { if (!flags()->allow_reexec) return; @@ -94,7 +127,11 @@ void MaybeReexec() { // ourselves. Dl_info info; CHECK(dladdr((void*)((uptr)__asan_init), &info)); - const char *dyld_insert_libraries = GetEnv(kDyldInsertLibraries); + char *dyld_insert_libraries = + const_cast<char*>(GetEnv(kDyldInsertLibraries)); + uptr old_env_len = dyld_insert_libraries ? + internal_strlen(dyld_insert_libraries) : 0; + uptr fname_len = internal_strlen(info.dli_fname); if (!dyld_insert_libraries || !REAL(strstr)(dyld_insert_libraries, info.dli_fname)) { // DYLD_INSERT_LIBRARIES is not set or does not contain the runtime @@ -102,16 +139,79 @@ void MaybeReexec() { char program_name[1024]; uint32_t buf_size = sizeof(program_name); _NSGetExecutablePath(program_name, &buf_size); - // Ok to use setenv() since the wrappers don't depend on the value of - // asan_inited. - setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); + char *new_env = const_cast<char*>(info.dli_fname); + if (dyld_insert_libraries) { + // Append the runtime dylib name to the existing value of + // DYLD_INSERT_LIBRARIES. + new_env = (char*)allocator_for_env.Allocate(old_env_len + fname_len + 2); + internal_strncpy(new_env, dyld_insert_libraries, old_env_len); + new_env[old_env_len] = ':'; + // Copy fname_len and add a trailing zero. + internal_strncpy(new_env + old_env_len + 1, info.dli_fname, + fname_len + 1); + // Ok to use setenv() since the wrappers don't depend on the value of + // asan_inited. + setenv(kDyldInsertLibraries, new_env, /*overwrite*/1); + } else { + // Set DYLD_INSERT_LIBRARIES equal to the runtime dylib name. + setenv(kDyldInsertLibraries, info.dli_fname, /*overwrite*/0); + } if (flags()->verbosity >= 1) { Report("exec()-ing the program with\n"); - Report("%s=%s\n", kDyldInsertLibraries, info.dli_fname); + Report("%s=%s\n", kDyldInsertLibraries, new_env); Report("to enable ASan wrappers.\n"); Report("Set ASAN_OPTIONS=allow_reexec=0 to disable this.\n"); } execv(program_name, *_NSGetArgv()); + } else { + // DYLD_INSERT_LIBRARIES is set and contains the runtime library. + if (old_env_len == fname_len) { + // It's just the runtime library name - fine to unset the variable. + LeakyResetEnv(kDyldInsertLibraries, NULL); + } else { + uptr env_name_len = internal_strlen(kDyldInsertLibraries); + // Allocate memory to hold the previous env var name, its value, the '=' + // sign and the '\0' char. + char *new_env = (char*)allocator_for_env.Allocate( + old_env_len + 2 + env_name_len); + CHECK(new_env); + internal_memset(new_env, '\0', old_env_len + 2 + env_name_len); + internal_strncpy(new_env, kDyldInsertLibraries, env_name_len); + new_env[env_name_len] = '='; + char *new_env_pos = new_env + env_name_len + 1; + + // Iterate over colon-separated pieces of |dyld_insert_libraries|. + char *piece_start = dyld_insert_libraries; + char *piece_end = NULL; + char *old_env_end = dyld_insert_libraries + old_env_len; + do { + if (piece_start[0] == ':') piece_start++; + piece_end = REAL(strchr)(piece_start, ':'); + if (!piece_end) piece_end = dyld_insert_libraries + old_env_len; + if ((uptr)(piece_start - dyld_insert_libraries) > old_env_len) break; + uptr piece_len = piece_end - piece_start; + + // If the current piece isn't the runtime library name, + // append it to new_env. + if ((piece_len != fname_len) || + (internal_strncmp(piece_start, info.dli_fname, fname_len) != 0)) { + if (new_env_pos != new_env + env_name_len + 1) { + new_env_pos[0] = ':'; + new_env_pos++; + } + internal_strncpy(new_env_pos, piece_start, piece_len); + } + // Move on to the next piece. + new_env_pos += piece_len; + piece_start = piece_end; + } while (piece_start < old_env_end); + + // Can't use setenv() here, because it requires the allocator to be + // initialized. + // FIXME: instead of filtering DYLD_INSERT_LIBRARIES here, do it in + // a separate function called after InitializeAllocator(). + LeakyResetEnv(kDyldInsertLibraries, new_env); + } } } diff --git a/libsanitizer/asan/asan_mapping.h b/libsanitizer/asan/asan_mapping.h index 48b24545b99..df952363893 100644 --- a/libsanitizer/asan/asan_mapping.h +++ b/libsanitizer/asan/asan_mapping.h @@ -1,7 +1,5 @@ //===-- asan_mapping.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // @@ -18,6 +16,37 @@ // The full explanation of the memory mapping could be found here: // http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm +// +// Typical shadow mapping on Linux/x86_64 with SHADOW_OFFSET == 0x00007fff8000: +// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || +// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || +// || `[0x00008fff7000, 0x02008fff6fff]` || ShadowGap || +// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || +// || `[0x000000000000, 0x00007fff7fff]` || LowMem || +// +// When SHADOW_OFFSET is zero (-pie): +// || `[0x100000000000, 0x7fffffffffff]` || HighMem || +// || `[0x020000000000, 0x0fffffffffff]` || HighShadow || +// || `[0x000000040000, 0x01ffffffffff]` || ShadowGap || +// +// Special case when something is already mapped between +// 0x003000000000 and 0x004000000000 (e.g. when prelink is installed): +// || `[0x10007fff8000, 0x7fffffffffff]` || HighMem || +// || `[0x02008fff7000, 0x10007fff7fff]` || HighShadow || +// || `[0x004000000000, 0x02008fff6fff]` || ShadowGap3 || +// || `[0x003000000000, 0x003fffffffff]` || MidMem || +// || `[0x00087fff8000, 0x002fffffffff]` || ShadowGap2 || +// || `[0x00067fff8000, 0x00087fff7fff]` || MidShadow || +// || `[0x00008fff7000, 0x00067fff7fff]` || ShadowGap || +// || `[0x00007fff8000, 0x00008fff6fff]` || LowShadow || +// || `[0x000000000000, 0x00007fff7fff]` || LowMem || +// +// Default Linux/i386 mapping: +// || `[0x40000000, 0xffffffff]` || HighMem || +// || `[0x28000000, 0x3fffffff]` || HighShadow || +// || `[0x24000000, 0x27ffffff]` || ShadowGap || +// || `[0x20000000, 0x23ffffff]` || LowShadow || +// || `[0x00000000, 0x1fffffff]` || LowMem || #if ASAN_FLEXIBLE_MAPPING_AND_OFFSET == 1 extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_scale; @@ -36,7 +65,11 @@ extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset; # if defined(__powerpc64__) # define SHADOW_OFFSET (1ULL << 41) # else -# define SHADOW_OFFSET (1ULL << 44) +# if ASAN_MAC +# define SHADOW_OFFSET (1ULL << 44) +# else +# define SHADOW_OFFSET 0x7fff8000ULL +# endif # endif # endif # endif @@ -57,49 +90,105 @@ extern SANITIZER_INTERFACE_ATTRIBUTE uptr __asan_mapping_offset; #define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) #define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd) +# define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg) +# define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd) + // With the zero shadow base we can not actually map pages starting from 0. // This constant is somewhat arbitrary. #define kZeroBaseShadowStart (1 << 18) #define kShadowGapBeg (kLowShadowEnd ? kLowShadowEnd + 1 \ : kZeroBaseShadowStart) -#define kShadowGapEnd (kHighShadowBeg - 1) +#define kShadowGapEnd ((kMidMemBeg ? kMidShadowBeg : kHighShadowBeg) - 1) + +#define kShadowGap2Beg (kMidMemBeg ? kMidShadowEnd + 1 : 0) +#define kShadowGap2End (kMidMemBeg ? kMidMemBeg - 1 : 0) + +#define kShadowGap3Beg (kMidMemBeg ? kMidMemEnd + 1 : 0) +#define kShadowGap3End (kMidMemBeg ? kHighShadowBeg - 1 : 0) + +#define DO_ASAN_MAPPING_PROFILE 0 // Set to 1 to profile the functions below. + +#if DO_ASAN_MAPPING_PROFILE +# define PROFILE_ASAN_MAPPING() AsanMappingProfile[__LINE__]++; +#else +# define PROFILE_ASAN_MAPPING() +#endif + +// If 1, all shadow boundaries are constants. +// Don't set to 1 other than for testing. +#define ASAN_FIXED_MAPPING 0 namespace __asan { +extern uptr AsanMappingProfile[]; + +#if ASAN_FIXED_MAPPING +// Fixed mapping for 64-bit Linux. Mostly used for performance comparison +// with non-fixed mapping. As of r175253 (Feb 2013) the performance +// difference between fixed and non-fixed mapping is below the noise level. +static uptr kHighMemEnd = 0x7fffffffffffULL; +static uptr kMidMemBeg = 0x3000000000ULL; +static uptr kMidMemEnd = 0x3fffffffffULL; +#else SANITIZER_INTERFACE_ATTRIBUTE -extern uptr kHighMemEnd; // Initialized in __asan_init. +extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init. +#endif static inline bool AddrIsInLowMem(uptr a) { + PROFILE_ASAN_MAPPING(); return a < kLowMemEnd; } static inline bool AddrIsInLowShadow(uptr a) { + PROFILE_ASAN_MAPPING(); return a >= kLowShadowBeg && a <= kLowShadowEnd; } static inline bool AddrIsInHighMem(uptr a) { + PROFILE_ASAN_MAPPING(); return a >= kHighMemBeg && a <= kHighMemEnd; } +static inline bool AddrIsInMidMem(uptr a) { + PROFILE_ASAN_MAPPING(); + return kMidMemBeg && a >= kMidMemBeg && a <= kMidMemEnd; +} + static inline bool AddrIsInMem(uptr a) { - return AddrIsInLowMem(a) || AddrIsInHighMem(a); + PROFILE_ASAN_MAPPING(); + return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a); } static inline uptr MemToShadow(uptr p) { + PROFILE_ASAN_MAPPING(); CHECK(AddrIsInMem(p)); return MEM_TO_SHADOW(p); } static inline bool AddrIsInHighShadow(uptr a) { - return a >= kHighShadowBeg && a <= kHighMemEnd; + PROFILE_ASAN_MAPPING(); + return a >= kHighShadowBeg && a <= kHighMemEnd; +} + +static inline bool AddrIsInMidShadow(uptr a) { + PROFILE_ASAN_MAPPING(); + return kMidMemBeg && a >= kMidShadowBeg && a <= kMidMemEnd; } static inline bool AddrIsInShadow(uptr a) { - return AddrIsInLowShadow(a) || AddrIsInHighShadow(a); + PROFILE_ASAN_MAPPING(); + return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a); } static inline bool AddrIsInShadowGap(uptr a) { + PROFILE_ASAN_MAPPING(); + if (kMidMemBeg) { + if (a <= kShadowGapEnd) + return SHADOW_OFFSET == 0 || a >= kShadowGapBeg; + return (a >= kShadowGap2Beg && a <= kShadowGap2End) || + (a >= kShadowGap3Beg && a <= kShadowGap3End); + } // In zero-based shadow mode we treat addresses near zero as addresses // in shadow gap as well. if (SHADOW_OFFSET == 0) @@ -108,12 +197,14 @@ static inline bool AddrIsInShadowGap(uptr a) { } static inline bool AddrIsAlignedByGranularity(uptr a) { + PROFILE_ASAN_MAPPING(); return (a & (SHADOW_GRANULARITY - 1)) == 0; } static inline bool AddressIsPoisoned(uptr a) { + PROFILE_ASAN_MAPPING(); const uptr kAccessSize = 1; - u8 *shadow_address = (u8*)MemToShadow(a); + u8 *shadow_address = (u8*)MEM_TO_SHADOW(a); s8 shadow_value = *shadow_address; if (shadow_value) { u8 last_accessed_byte = (a & (SHADOW_GRANULARITY - 1)) @@ -123,6 +214,9 @@ static inline bool AddressIsPoisoned(uptr a) { return false; } +// Must be after all calls to PROFILE_ASAN_MAPPING(). +static const uptr kAsanMappingProfileSize = __LINE__; + } // namespace __asan #endif // ASAN_MAPPING_H diff --git a/libsanitizer/asan/asan_report.cc b/libsanitizer/asan/asan_report.cc index 663e8f3b748..13e94c421b5 100644 --- a/libsanitizer/asan/asan_report.cc +++ b/libsanitizer/asan/asan_report.cc @@ -433,9 +433,9 @@ class ScopedInErrorReport { // an error report will finish doing it. SleepForSeconds(Max(100, flags()->sleep_before_dying + 1)); } - // If we're still not dead for some reason, use raw Exit() instead of + // If we're still not dead for some reason, use raw _exit() instead of // Die() to bypass any additional checks. - Exit(flags()->exitcode); + internal__exit(flags()->exitcode); } ASAN_ON_ERROR(); reporting_thread_tid = asanThreadRegistry().GetCurrentTidOrInvalid(); diff --git a/libsanitizer/asan/asan_rtl.cc b/libsanitizer/asan/asan_rtl.cc index 175d37788c2..4b0afd2731a 100644 --- a/libsanitizer/asan/asan_rtl.cc +++ b/libsanitizer/asan/asan_rtl.cc @@ -25,6 +25,8 @@ namespace __asan { +uptr AsanMappingProfile[kAsanMappingProfileSize]; + static void AsanDie() { static atomic_uint32_t num_calls; if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { @@ -35,13 +37,19 @@ static void AsanDie() { Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying); SleepForSeconds(flags()->sleep_before_dying); } - if (flags()->unmap_shadow_on_exit) - UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); + if (flags()->unmap_shadow_on_exit) { + if (kMidMemBeg) { + UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); + UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); + } else { + UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); + } + } if (death_callback) death_callback(); if (flags()->abort_on_error) Abort(); - Exit(flags()->exitcode); + internal__exit(flags()->exitcode); } static void AsanCheckFailed(const char *file, int line, const char *cond, @@ -66,6 +74,17 @@ static const char *MaybeCallAsanDefaultOptions() { return (&__asan_default_options) ? __asan_default_options() : ""; } +static const char *MaybeUseAsanDefaultOptionsCompileDefiniton() { +#ifdef ASAN_DEFAULT_OPTIONS +// Stringize the macro value. +# define ASAN_STRINGIZE(x) #x +# define ASAN_STRINGIZE_OPTIONS(options) ASAN_STRINGIZE(options) + return ASAN_STRINGIZE_OPTIONS(ASAN_DEFAULT_OPTIONS); +#else + return ""; +#endif +} + static void ParseFlagsFromString(Flags *f, const char *str) { ParseFlag(str, &f->quarantine_size, "quarantine_size"); ParseFlag(str, &f->symbolize, "symbolize"); @@ -146,6 +165,9 @@ void InitializeFlags(Flags *f, const char *env) { f->alloc_dealloc_mismatch = true; f->use_stack_depot = true; // Only affects allocator2. + // Override from compile definition. + ParseFlagsFromString(f, MaybeUseAsanDefaultOptionsCompileDefiniton()); + // Override from user-specified string. ParseFlagsFromString(f, MaybeCallAsanDefaultOptions()); if (flags()->verbosity) { @@ -161,7 +183,10 @@ void InitializeFlags(Flags *f, const char *env) { int asan_inited; bool asan_init_is_running; void (*death_callback)(void); -uptr kHighMemEnd; + +#if !ASAN_FIXED_MAPPING +uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; +#endif // -------------------------- Misc ---------------- {{{1 void ShowStatsAndAbort() { @@ -209,6 +234,17 @@ ASAN_REPORT_ERROR(store, true, 4) ASAN_REPORT_ERROR(store, true, 8) ASAN_REPORT_ERROR(store, true, 16) +#define ASAN_REPORT_ERROR_N(type, is_write) \ +extern "C" NOINLINE INTERFACE_ATTRIBUTE \ +void __asan_report_ ## type ## _n(uptr addr, uptr size); \ +void __asan_report_ ## type ## _n(uptr addr, uptr size) { \ + GET_CALLER_PC_BP_SP; \ + __asan_report_error(pc, bp, sp, addr, is_write, size); \ +} + +ASAN_REPORT_ERROR_N(load, false) +ASAN_REPORT_ERROR_N(store, true) + // Force the linker to keep the symbols for various ASan interface functions. // We want to keep those in the executable in order to let the instrumented // dynamic libraries access the symbol even if it is not used by the executable @@ -259,9 +295,15 @@ static NOINLINE void force_interface_symbols() { static void asan_atexit() { Printf("AddressSanitizer exit stats:\n"); __asan_print_accumulated_stats(); + // Print AsanMappingProfile. + for (uptr i = 0; i < kAsanMappingProfileSize; i++) { + if (AsanMappingProfile[i] == 0) continue; + Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]); + } } static void InitializeHighMemEnd() { +#if !ASAN_FIXED_MAPPING #if SANITIZER_WORDSIZE == 64 # if defined(__powerpc64__) // FIXME: @@ -277,6 +319,58 @@ static void InitializeHighMemEnd() { #else // SANITIZER_WORDSIZE == 32 kHighMemEnd = (1ULL << 32) - 1; // 0xffffffff; #endif // SANITIZER_WORDSIZE +#endif // !ASAN_FIXED_MAPPING +} + +static void ProtectGap(uptr a, uptr size) { + CHECK_EQ(a, (uptr)Mprotect(a, size)); +} + +static void PrintAddressSpaceLayout() { + Printf("|| `[%p, %p]` || HighMem ||\n", + (void*)kHighMemBeg, (void*)kHighMemEnd); + Printf("|| `[%p, %p]` || HighShadow ||\n", + (void*)kHighShadowBeg, (void*)kHighShadowEnd); + if (kMidMemBeg) { + Printf("|| `[%p, %p]` || ShadowGap3 ||\n", + (void*)kShadowGap3Beg, (void*)kShadowGap3End); + Printf("|| `[%p, %p]` || MidMem ||\n", + (void*)kMidMemBeg, (void*)kMidMemEnd); + Printf("|| `[%p, %p]` || ShadowGap2 ||\n", + (void*)kShadowGap2Beg, (void*)kShadowGap2End); + Printf("|| `[%p, %p]` || MidShadow ||\n", + (void*)kMidShadowBeg, (void*)kMidShadowEnd); + } + Printf("|| `[%p, %p]` || ShadowGap ||\n", + (void*)kShadowGapBeg, (void*)kShadowGapEnd); + if (kLowShadowBeg) { + Printf("|| `[%p, %p]` || LowShadow ||\n", + (void*)kLowShadowBeg, (void*)kLowShadowEnd); + Printf("|| `[%p, %p]` || LowMem ||\n", + (void*)kLowMemBeg, (void*)kLowMemEnd); + } + Printf("MemToShadow(shadow): %p %p %p %p", + (void*)MEM_TO_SHADOW(kLowShadowBeg), + (void*)MEM_TO_SHADOW(kLowShadowEnd), + (void*)MEM_TO_SHADOW(kHighShadowBeg), + (void*)MEM_TO_SHADOW(kHighShadowEnd)); + if (kMidMemBeg) { + Printf(" %p %p", + (void*)MEM_TO_SHADOW(kMidShadowBeg), + (void*)MEM_TO_SHADOW(kMidShadowEnd)); + } + Printf("\n"); + Printf("red_zone=%zu\n", (uptr)flags()->redzone); + Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size); + + Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE); + Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY); + Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET); + CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); + if (kMidMemBeg) + CHECK(kMidShadowBeg > kLowShadowEnd && + kMidMemBeg > kMidShadowEnd && + kHighShadowBeg > kMidMemEnd); } } // namespace __asan @@ -352,49 +446,48 @@ void __asan_init() { ReplaceSystemMalloc(); ReplaceOperatorsNewAndDelete(); - if (flags()->verbosity) { - Printf("|| `[%p, %p]` || HighMem ||\n", - (void*)kHighMemBeg, (void*)kHighMemEnd); - Printf("|| `[%p, %p]` || HighShadow ||\n", - (void*)kHighShadowBeg, (void*)kHighShadowEnd); - Printf("|| `[%p, %p]` || ShadowGap ||\n", - (void*)kShadowGapBeg, (void*)kShadowGapEnd); - Printf("|| `[%p, %p]` || LowShadow ||\n", - (void*)kLowShadowBeg, (void*)kLowShadowEnd); - Printf("|| `[%p, %p]` || LowMem ||\n", - (void*)kLowMemBeg, (void*)kLowMemEnd); - Printf("MemToShadow(shadow): %p %p %p %p\n", - (void*)MEM_TO_SHADOW(kLowShadowBeg), - (void*)MEM_TO_SHADOW(kLowShadowEnd), - (void*)MEM_TO_SHADOW(kHighShadowBeg), - (void*)MEM_TO_SHADOW(kHighShadowEnd)); - Printf("red_zone=%zu\n", (uptr)flags()->redzone); - Printf("malloc_context_size=%zu\n", (uptr)flags()->malloc_context_size); - - Printf("SHADOW_SCALE: %zx\n", (uptr)SHADOW_SCALE); - Printf("SHADOW_GRANULARITY: %zx\n", (uptr)SHADOW_GRANULARITY); - Printf("SHADOW_OFFSET: %zx\n", (uptr)SHADOW_OFFSET); - CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); + uptr shadow_start = kLowShadowBeg; + if (kLowShadowBeg) shadow_start -= GetMmapGranularity(); + uptr shadow_end = kHighShadowEnd; + bool full_shadow_is_available = + MemoryRangeIsAvailable(shadow_start, shadow_end); + +#if ASAN_LINUX && defined(__x86_64__) && !ASAN_FIXED_MAPPING + if (!full_shadow_is_available) { + kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0; + kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x3fffffffffULL : 0; } +#endif + + if (flags()->verbosity) + PrintAddressSpaceLayout(); if (flags()->disable_core) { DisableCoreDumper(); } - uptr shadow_start = kLowShadowBeg; - if (kLowShadowBeg > 0) shadow_start -= GetMmapGranularity(); - uptr shadow_end = kHighShadowEnd; - if (MemoryRangeIsAvailable(shadow_start, shadow_end)) { - if (kLowShadowBeg != kLowShadowEnd) { - // mmap the low shadow plus at least one page. - ReserveShadowMemoryRange(kLowShadowBeg - GetMmapGranularity(), - kLowShadowEnd); - } + if (full_shadow_is_available) { + // mmap the low shadow plus at least one page at the left. + if (kLowShadowBeg) + ReserveShadowMemoryRange(shadow_start, kLowShadowEnd); + // mmap the high shadow. + ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd); + // protect the gap. + ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); + } else if (kMidMemBeg && + MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) && + MemoryRangeIsAvailable(kMidMemEnd + 1, shadow_end)) { + CHECK(kLowShadowBeg != kLowShadowEnd); + // mmap the low shadow plus at least one page at the left. + ReserveShadowMemoryRange(shadow_start, kLowShadowEnd); + // mmap the mid shadow. + ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd); // mmap the high shadow. ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd); - // protect the gap - void *prot = Mprotect(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); - CHECK(prot == (void*)kShadowGapBeg); + // protect the gaps. + ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); + ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1); + ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1); } else { Report("Shadow memory range interleaves with an existing memory mapping. " "ASan cannot proceed correctly. ABORTING.\n"); @@ -427,12 +520,12 @@ void __asan_init() { } } -#if defined(ASAN_USE_PREINIT_ARRAY) +#if ASAN_USE_PREINIT_ARRAY && !defined (PIC) // On Linux, we force __asan_init to be called before anyone else // by placing it into .preinit_array section. // FIXME: do we have anything like this on Mac? - __attribute__((section(".preinit_array"))) - typeof(__asan_init) *__asan_preinit =__asan_init; + __attribute__((section(".preinit_array"), used)) + void (*__asan_preinit)(void) =__asan_init; #elif defined(_WIN32) && defined(_DLL) // On Windows, when using dynamic CRT (/MD), we can put a pointer // to __asan_init into the global list of C initializers. diff --git a/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc b/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc deleted file mode 100644 index 727edf2b43b..00000000000 --- a/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc +++ /dev/null @@ -1,114 +0,0 @@ -//===-- asan_interceptors_dynamic.cc --------------------------------------===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -// __DATA,__interpose section of the dynamic runtime library for Mac OS. -//===----------------------------------------------------------------------===// - -#if defined(__APPLE__) - -#include "../asan_interceptors.h" -#include "../asan_intercepted_functions.h" - -namespace __asan { - -#define INTERPOSE_FUNCTION(function) \ - { reinterpret_cast<const uptr>(WRAP(function)), \ - reinterpret_cast<const uptr>(function) } - -#define INTERPOSE_FUNCTION_2(function, wrapper) \ - { reinterpret_cast<const uptr>(wrapper), \ - reinterpret_cast<const uptr>(function) } - -struct interpose_substitution { - const uptr replacement; - const uptr original; -}; - -__attribute__((used)) -const interpose_substitution substitutions[] - __attribute__((section("__DATA, __interpose"))) = { - INTERPOSE_FUNCTION(strlen), - INTERPOSE_FUNCTION(memcmp), - INTERPOSE_FUNCTION(memcpy), - INTERPOSE_FUNCTION(memmove), - INTERPOSE_FUNCTION(memset), - INTERPOSE_FUNCTION(strchr), - INTERPOSE_FUNCTION(strcat), - INTERPOSE_FUNCTION(strncat), - INTERPOSE_FUNCTION(strcpy), - INTERPOSE_FUNCTION(strncpy), - INTERPOSE_FUNCTION(pthread_create), - INTERPOSE_FUNCTION(longjmp), -#if ASAN_INTERCEPT__LONGJMP - INTERPOSE_FUNCTION(_longjmp), -#endif -#if ASAN_INTERCEPT_SIGLONGJMP - INTERPOSE_FUNCTION(siglongjmp), -#endif -#if ASAN_INTERCEPT_STRDUP - INTERPOSE_FUNCTION(strdup), -#endif -#if ASAN_INTERCEPT_STRNLEN - INTERPOSE_FUNCTION(strnlen), -#endif -#if ASAN_INTERCEPT_INDEX - INTERPOSE_FUNCTION_2(index, WRAP(strchr)), -#endif - INTERPOSE_FUNCTION(strcmp), - INTERPOSE_FUNCTION(strncmp), -#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP - INTERPOSE_FUNCTION(strcasecmp), - INTERPOSE_FUNCTION(strncasecmp), -#endif - INTERPOSE_FUNCTION(atoi), - INTERPOSE_FUNCTION(atol), - INTERPOSE_FUNCTION(strtol), -#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL - INTERPOSE_FUNCTION(atoll), - INTERPOSE_FUNCTION(strtoll), -#endif -#if ASAN_INTERCEPT_MLOCKX - INTERPOSE_FUNCTION(mlock), - INTERPOSE_FUNCTION(munlock), - INTERPOSE_FUNCTION(mlockall), - INTERPOSE_FUNCTION(munlockall), -#endif - INTERPOSE_FUNCTION(dispatch_async_f), - INTERPOSE_FUNCTION(dispatch_sync_f), - INTERPOSE_FUNCTION(dispatch_after_f), - INTERPOSE_FUNCTION(dispatch_barrier_async_f), - INTERPOSE_FUNCTION(dispatch_group_async_f), -#ifndef MISSING_BLOCKS_SUPPORT - INTERPOSE_FUNCTION(dispatch_group_async), - INTERPOSE_FUNCTION(dispatch_async), - INTERPOSE_FUNCTION(dispatch_after), - INTERPOSE_FUNCTION(dispatch_source_set_event_handler), - INTERPOSE_FUNCTION(dispatch_source_set_cancel_handler), -#endif - INTERPOSE_FUNCTION(signal), - INTERPOSE_FUNCTION(sigaction), - - INTERPOSE_FUNCTION(malloc_create_zone), - INTERPOSE_FUNCTION(malloc_default_zone), - INTERPOSE_FUNCTION(malloc_default_purgeable_zone), - INTERPOSE_FUNCTION(malloc_make_purgeable), - INTERPOSE_FUNCTION(malloc_make_nonpurgeable), - INTERPOSE_FUNCTION(malloc_set_zone_name), - INTERPOSE_FUNCTION(malloc), - INTERPOSE_FUNCTION(free), - INTERPOSE_FUNCTION(realloc), - INTERPOSE_FUNCTION(calloc), - INTERPOSE_FUNCTION(valloc), - INTERPOSE_FUNCTION(malloc_good_size), - INTERPOSE_FUNCTION(posix_memalign), -}; - -} // namespace __asan - -#endif // __APPLE__ diff --git a/libsanitizer/include/sanitizer/asan_interface.h b/libsanitizer/include/sanitizer/asan_interface.h index 18696a681ed..0016339e486 100644 --- a/libsanitizer/include/sanitizer/asan_interface.h +++ b/libsanitizer/include/sanitizer/asan_interface.h @@ -35,8 +35,8 @@ extern "C" { // (un)poison memory in the same memory region simultaneously. void __asan_unpoison_memory_region(void const volatile *addr, size_t size); - // User code should use macro instead of functions. -#if __has_feature(address_sanitizer) +// User code should use macros instead of functions. +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) #define ASAN_POISON_MEMORY_REGION(addr, size) \ __asan_poison_memory_region((addr), (size)) #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ diff --git a/libsanitizer/include/sanitizer/common_interface_defs.h b/libsanitizer/include/sanitizer/common_interface_defs.h index b61b8a1a636..c218b5b5654 100644 --- a/libsanitizer/include/sanitizer/common_interface_defs.h +++ b/libsanitizer/include/sanitizer/common_interface_defs.h @@ -14,6 +14,11 @@ #include <stddef.h> #include <stdint.h> +// GCC does not understand __has_feature. +#if !defined(__has_feature) +# define __has_feature(x) 0 +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/libsanitizer/merge.sh b/libsanitizer/merge.sh index d2e622aeb1a..9c29b319829 100755 --- a/libsanitizer/merge.sh +++ b/libsanitizer/merge.sh @@ -66,7 +66,6 @@ CUR_REV=$(get_current_rev) echo Current upstream revision: $CUR_REV merge include/sanitizer include/sanitizer merge lib/asan asan -merge lib/asan/dynamic asan/dynamic merge lib/tsan/rtl tsan merge lib/sanitizer_common sanitizer_common merge lib/interception interception diff --git a/libsanitizer/sanitizer_common/Makefile.am b/libsanitizer/sanitizer_common/Makefile.am index 79585e48ed2..c53a3c6bfc5 100644 --- a/libsanitizer/sanitizer_common/Makefile.am +++ b/libsanitizer/sanitizer_common/Makefile.am @@ -17,6 +17,7 @@ sanitizer_common_files = \ sanitizer_libc.cc \ sanitizer_linux.cc \ sanitizer_mac.cc \ + sanitizer_platform_limits_posix.cc \ sanitizer_posix.cc \ sanitizer_printf.cc \ sanitizer_stackdepot.cc \ diff --git a/libsanitizer/sanitizer_common/Makefile.in b/libsanitizer/sanitizer_common/Makefile.in index ce68d5e02f6..32e0dc8cac6 100644 --- a/libsanitizer/sanitizer_common/Makefile.in +++ b/libsanitizer/sanitizer_common/Makefile.in @@ -74,11 +74,12 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) libsanitizer_common_la_LIBADD = am__objects_1 = sanitizer_allocator.lo sanitizer_common.lo \ sanitizer_flags.lo sanitizer_libc.lo sanitizer_linux.lo \ - sanitizer_mac.lo sanitizer_posix.lo sanitizer_printf.lo \ - sanitizer_stackdepot.lo sanitizer_stacktrace.lo \ - sanitizer_symbolizer.lo sanitizer_symbolizer_itanium.lo \ - sanitizer_symbolizer_linux.lo sanitizer_symbolizer_mac.lo \ - sanitizer_symbolizer_win.lo sanitizer_win.lo + sanitizer_mac.lo sanitizer_platform_limits_posix.lo \ + sanitizer_posix.lo sanitizer_printf.lo sanitizer_stackdepot.lo \ + sanitizer_stacktrace.lo sanitizer_symbolizer.lo \ + sanitizer_symbolizer_itanium.lo sanitizer_symbolizer_linux.lo \ + sanitizer_symbolizer_mac.lo sanitizer_symbolizer_win.lo \ + sanitizer_win.lo am_libsanitizer_common_la_OBJECTS = $(am__objects_1) libsanitizer_common_la_OBJECTS = $(am_libsanitizer_common_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ @@ -252,6 +253,7 @@ sanitizer_common_files = \ sanitizer_libc.cc \ sanitizer_linux.cc \ sanitizer_mac.cc \ + sanitizer_platform_limits_posix.cc \ sanitizer_posix.cc \ sanitizer_printf.cc \ sanitizer_stackdepot.cc \ @@ -362,6 +364,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_libc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_linux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_mac.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_platform_limits_posix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_posix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_printf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_stackdepot.Plo@am__quote@ diff --git a/libsanitizer/sanitizer_common/sanitizer_common.cc b/libsanitizer/sanitizer_common/sanitizer_common.cc index 4447c346eba..f8d2d0e3fe5 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common.cc +++ b/libsanitizer/sanitizer_common/sanitizer_common.cc @@ -43,7 +43,7 @@ void NORETURN Die() { if (DieCallback) { DieCallback(); } - Exit(1); + internal__exit(1); } static CheckFailedCallbackType CheckFailedCallback; diff --git a/libsanitizer/sanitizer_common/sanitizer_common.h b/libsanitizer/sanitizer_common/sanitizer_common.h index 109966ba360..302dc742769 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common.h +++ b/libsanitizer/sanitizer_common/sanitizer_common.h @@ -124,6 +124,7 @@ void DumpProcessMap(); bool FileExists(const char *filename); const char *GetEnv(const char *name); const char *GetPwd(); +u32 GetUid(); void ReExec(); bool StackSizeIsUnlimited(); void SetStackSizeLimitInBytes(uptr limit); @@ -137,7 +138,6 @@ void SortArray(uptr *array, uptr size); // Exit void NORETURN Abort(); -void NORETURN Exit(int exitcode); void NORETURN Die(); void NORETURN SANITIZER_INTERFACE_ATTRIBUTE CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2); diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc index 4ba7b8fee9f..af27603ebdd 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc +++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc @@ -124,8 +124,8 @@ INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count, #endif #if SANITIZER_INTERCEPT_PRCTL -INTERCEPTOR(int, prctl, int option, unsigned long arg2, - unsigned long arg3, // NOLINT +INTERCEPTOR(int, prctl, int option, + unsigned long arg2, unsigned long arg3, // NOLINT unsigned long arg4, unsigned long arg5) { // NOLINT void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5); @@ -144,6 +144,100 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, #define INIT_PRCTL #endif // SANITIZER_INTERCEPT_PRCTL +#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS +INTERCEPTOR(void *, localtime, unsigned long *timep) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep); + void *res = REAL(localtime)(timep); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz); + } + return res; +} +INTERCEPTOR(void *, localtime_r, unsigned long *timep, void *result) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result); + void *res = REAL(localtime_r)(timep, result); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz); + } + return res; +} +INTERCEPTOR(void *, gmtime, unsigned long *timep) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep); + void *res = REAL(gmtime)(timep); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz); + } + return res; +} +INTERCEPTOR(void *, gmtime_r, unsigned long *timep, void *result) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result); + void *res = REAL(gmtime_r)(timep, result); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, struct_tm_sz); + } + return res; +} +INTERCEPTOR(char *, ctime, unsigned long *timep) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep); + char *res = REAL(ctime)(timep); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + } + return res; +} +INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result); + char *res = REAL(ctime_r)(timep, result); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + } + return res; +} +INTERCEPTOR(char *, asctime, void *tm) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm); + char *res = REAL(asctime)(tm); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + } + return res; +} +INTERCEPTOR(char *, asctime_r, void *tm, char *result) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result); + char *res = REAL(asctime_r)(tm, result); + if (res) { + COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, struct_tm_sz); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + } + return res; +} +#define INIT_LOCALTIME_AND_FRIENDS \ + INTERCEPT_FUNCTION(localtime); \ + INTERCEPT_FUNCTION(localtime_r); \ + INTERCEPT_FUNCTION(gmtime); \ + INTERCEPT_FUNCTION(gmtime_r); \ + INTERCEPT_FUNCTION(ctime); \ + INTERCEPT_FUNCTION(ctime_r); \ + INTERCEPT_FUNCTION(asctime); \ + INTERCEPT_FUNCTION(asctime_r); +#else +#define INIT_LOCALTIME_AND_FRIENDS +#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS + #if SANITIZER_INTERCEPT_SCANF #include "sanitizer_common_interceptors_scanf.inc" @@ -170,6 +264,7 @@ VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap) INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap) VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap) +#if SANITIZER_INTERCEPT_ISOC99_SCANF INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap) VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap) @@ -179,6 +274,7 @@ VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap) INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap) VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap) +#endif // SANITIZER_INTERCEPT_ISOC99_SCANF #define SCANF_INTERCEPTOR_IMPL(name, vname, ...) \ { \ @@ -200,6 +296,7 @@ SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format) INTERCEPTOR(int, sscanf, const char *str, const char *format, ...) SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format) +#if SANITIZER_INTERCEPT_ISOC99_SCANF INTERCEPTOR(int, __isoc99_scanf, const char *format, ...) SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format) @@ -208,6 +305,7 @@ SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format) INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...) SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format) +#endif #define INIT_SCANF \ INTERCEPT_FUNCTION(scanf); \ @@ -235,4 +333,5 @@ SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format) INIT_WRITE; \ INIT_PWRITE; \ INIT_PWRITE64; \ + INIT_LOCALTIME_AND_FRIENDS; \ INIT_SCANF; diff --git a/libsanitizer/sanitizer_common/sanitizer_flags.cc b/libsanitizer/sanitizer_common/sanitizer_flags.cc index 837738ceb81..2152c7bdff4 100644 --- a/libsanitizer/sanitizer_common/sanitizer_flags.cc +++ b/libsanitizer/sanitizer_common/sanitizer_flags.cc @@ -36,7 +36,8 @@ static bool GetFlagValue(const char *env, const char *name, pos += 1; end = internal_strchr(pos, '\''); } else { - end = internal_strchr(pos, ' '); + // Read until the next space or colon. + end = pos + internal_strcspn(pos, " :"); } if (end == 0) end = pos + internal_strlen(pos); diff --git a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h index 1a25b70c23e..577c9a9c17f 100644 --- a/libsanitizer/sanitizer_common/sanitizer_internal_defs.h +++ b/libsanitizer/sanitizer_common/sanitizer_internal_defs.h @@ -29,7 +29,7 @@ # define SANITIZER_SUPPORTS_WEAK_HOOKS 0 #endif -// __has_feature +// GCC does not understand __has_feature #if !defined(__has_feature) # define __has_feature(x) 0 #endif diff --git a/libsanitizer/sanitizer_common/sanitizer_libc.h b/libsanitizer/sanitizer_common/sanitizer_libc.h index 7a9774406fa..16239413356 100644 --- a/libsanitizer/sanitizer_common/sanitizer_libc.h +++ b/libsanitizer/sanitizer_common/sanitizer_libc.h @@ -43,6 +43,7 @@ char *internal_strrchr(const char *s, int c); char *internal_strstr(const char *haystack, const char *needle); // Works only for base=10 and doesn't set errno. s64 internal_simple_strtoll(const char *nptr, char **endptr, int base); +int internal_snprintf(char *buffer, uptr length, const char *format, ...); // Return true if all bytes in [mem, mem+size) are zero. // Optimized for the case when the result is true. @@ -68,14 +69,15 @@ fd_t internal_open(const char *filename, int flags, u32 mode); uptr internal_read(fd_t fd, void *buf, uptr count); uptr internal_write(fd_t fd, const void *buf, uptr count); + +// OS uptr internal_filesize(fd_t fd); // -1 on error. int internal_stat(const char *path, void *buf); int internal_lstat(const char *path, void *buf); int internal_fstat(fd_t fd, void *buf); - int internal_dup2(int oldfd, int newfd); uptr internal_readlink(const char *path, char *buf, uptr bufsize); -int internal_snprintf(char *buffer, uptr length, const char *format, ...); +void NORETURN internal__exit(int exitcode); // Threading int internal_sched_yield(); diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_linux.cc index 3d3aa0b00bd..06e5a0a6441 100644 --- a/libsanitizer/sanitizer_common/sanitizer_linux.cc +++ b/libsanitizer/sanitizer_common/sanitizer_linux.cc @@ -138,6 +138,11 @@ int internal_sched_yield() { return syscall(__NR_sched_yield); } +void internal__exit(int exitcode) { + syscall(__NR_exit_group, exitcode); + Die(); // Unreachable. +} + // ----------------- sanitizer_common.h bool FileExists(const char *filename) { #if SANITIZER_LINUX_USES_64BIT_SYSCALLS @@ -232,6 +237,21 @@ const char *GetEnv(const char *name) { return 0; // Not found. } +#ifdef __GLIBC__ + +extern "C" { + extern void *__libc_stack_end; +} + +static void GetArgsAndEnv(char ***argv, char ***envp) { + uptr *stack_end = (uptr *)__libc_stack_end; + int argc = *stack_end; + *argv = (char**)(stack_end + 1); + *envp = (char**)(stack_end + argc + 2); +} + +#else // __GLIBC__ + static void ReadNullSepFileToArray(const char *path, char ***arr, int arr_size) { char *buff; @@ -251,12 +271,20 @@ static void ReadNullSepFileToArray(const char *path, char ***arr, (*arr)[count] = 0; } +static void GetArgsAndEnv(char ***argv, char ***envp) { + static const int kMaxArgv = 2000, kMaxEnvp = 2000; + ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv); + ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); +} + +#endif // __GLIBC__ + void ReExec() { - static const int kMaxArgv = 100, kMaxEnvp = 1000; char **argv, **envp; - ReadNullSepFileToArray("/proc/self/cmdline", &argv, kMaxArgv); - ReadNullSepFileToArray("/proc/self/environ", &envp, kMaxEnvp); - execve(argv[0], argv, envp); + GetArgsAndEnv(&argv, &envp); + execve("/proc/self/exe", argv, envp); + Printf("execve failed, errno %d\n", errno); + Die(); } void PrepareForSandboxing() { diff --git a/libsanitizer/sanitizer_common/sanitizer_mac.cc b/libsanitizer/sanitizer_common/sanitizer_mac.cc index 309b5a94005..d7885bb3509 100644 --- a/libsanitizer/sanitizer_common/sanitizer_mac.cc +++ b/libsanitizer/sanitizer_common/sanitizer_mac.cc @@ -104,6 +104,10 @@ int internal_sched_yield() { return sched_yield(); } +void internal__exit(int exitcode) { + _exit(exitcode); +} + // ----------------- sanitizer_common.h bool FileExists(const char *filename) { struct stat st; diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h index 2c60253c533..9b40c0cc523 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h +++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h @@ -14,6 +14,7 @@ #if !defined(_WIN32) # define SI_NOT_WINDOWS 1 +# include "sanitizer_platform_limits_posix.h" #else # define SI_NOT_WINDOWS 0 #endif @@ -24,6 +25,12 @@ # define SI_LINUX_NOT_ANDROID 0 #endif +#if defined(__linux__) +# define SI_LINUX 1 +#else +# define SI_LINUX 0 +#endif + # define SANITIZER_INTERCEPT_READ SI_NOT_WINDOWS # define SANITIZER_INTERCEPT_PREAD SI_NOT_WINDOWS # define SANITIZER_INTERCEPT_WRITE SI_NOT_WINDOWS @@ -33,4 +40,7 @@ # define SANITIZER_INTERCEPT_PWRITE64 SI_LINUX_NOT_ANDROID # define SANITIZER_INTERCEPT_PRCTL SI_LINUX_NOT_ANDROID +# define SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS SI_NOT_WINDOWS + # define SANITIZER_INTERCEPT_SCANF SI_NOT_WINDOWS +# define SANITIZER_INTERCEPT_ISOC99_SCANF SI_LINUX diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc new file mode 100644 index 00000000000..c4be1aa42da --- /dev/null +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -0,0 +1,68 @@ +//===-- sanitizer_platform_limits_posix.cc --------------------------------===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of Sanitizer common code. +// +// Sizes and layouts of platform-specific POSIX data structures. +//===----------------------------------------------------------------------===// + +#if defined(__linux__) || defined(__APPLE__) + +#include "sanitizer_internal_defs.h" +#include "sanitizer_platform_limits_posix.h" + +#include <dirent.h> +#include <sys/utsname.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/socket.h> +#include <time.h> + +#if defined(__linux__) +#include <sys/vfs.h> +#include <sys/epoll.h> +#endif // __linux__ + +namespace __sanitizer { + unsigned struct_utsname_sz = sizeof(struct utsname); + unsigned struct_stat_sz = sizeof(struct stat); + unsigned struct_stat64_sz = sizeof(struct stat64); + unsigned struct_rusage_sz = sizeof(struct rusage); + unsigned struct_tm_sz = sizeof(struct tm); + +#if defined(__linux__) + unsigned struct_rlimit_sz = sizeof(struct rlimit); + unsigned struct_dirent_sz = sizeof(struct dirent); + unsigned struct_statfs_sz = sizeof(struct statfs); + unsigned struct_epoll_event_sz = sizeof(struct epoll_event); +#endif // __linux__ + +#if defined(__linux__) && !defined(__ANDROID__) + unsigned struct_rlimit64_sz = sizeof(struct rlimit64); + unsigned struct_statfs64_sz = sizeof(struct statfs64); +#endif // __linux__ && !__ANDROID__ + + void* __sanitizer_get_msghdr_iov_iov_base(void* msg, int idx) { + return ((struct msghdr *)msg)->msg_iov[idx].iov_base; + } + + uptr __sanitizer_get_msghdr_iov_iov_len(void* msg, int idx) { + return ((struct msghdr *)msg)->msg_iov[idx].iov_len; + } + + uptr __sanitizer_get_msghdr_iovlen(void* msg) { + return ((struct msghdr *)msg)->msg_iovlen; + } + + uptr __sanitizer_get_socklen_t(void* socklen_ptr) { + return *(socklen_t*)socklen_ptr; + } +} // namespace __sanitizer + +#endif // __linux__ || __APPLE__ diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h new file mode 100644 index 00000000000..dd53da94be6 --- /dev/null +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h @@ -0,0 +1,41 @@ +//===-- sanitizer_platform_limits_posix.h ---------------------------------===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of Sanitizer common code. +// +// Sizes and layouts of platform-specific POSIX data structures. +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_PLATFORM_LIMITS_POSIX_H +#define SANITIZER_PLATFORM_LIMITS_POSIX_H + +namespace __sanitizer { + extern unsigned struct_utsname_sz; + extern unsigned struct_stat_sz; + extern unsigned struct_stat64_sz; + extern unsigned struct_rusage_sz; + extern unsigned struct_tm_sz; + +#if defined(__linux__) + extern unsigned struct_rlimit_sz; + extern unsigned struct_dirent_sz; + extern unsigned struct_statfs_sz; + extern unsigned struct_epoll_event_sz; +#endif // __linux__ + +#if defined(__linux__) && !defined(__ANDROID__) + extern unsigned struct_rlimit64_sz; + extern unsigned struct_statfs64_sz; +#endif // __linux__ && !__ANDROID__ + + void* __sanitizer_get_msghdr_iov_iov_base(void* msg, int idx); + uptr __sanitizer_get_msghdr_iov_iov_len(void* msg, int idx); + uptr __sanitizer_get_msghdr_iovlen(void* msg); + uptr __sanitizer_get_socklen_t(void* socklen_ptr); +} // namespace __sanitizer + +#endif diff --git a/libsanitizer/sanitizer_common/sanitizer_posix.cc b/libsanitizer/sanitizer_common/sanitizer_posix.cc index 48c5ebaef3e..1c6ff0a2ebb 100644 --- a/libsanitizer/sanitizer_common/sanitizer_posix.cc +++ b/libsanitizer/sanitizer_common/sanitizer_posix.cc @@ -42,6 +42,10 @@ int GetPid() { return getpid(); } +u32 GetUid() { + return getuid(); +} + uptr GetThreadSelf() { return (uptr)pthread_self(); } @@ -203,10 +207,6 @@ void SleepForMillis(int millis) { usleep(millis * 1000); } -void Exit(int exitcode) { - _exit(exitcode); -} - void Abort() { abort(); } diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc index 259da0082e3..e14ea447264 100644 --- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc +++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc @@ -129,8 +129,9 @@ void StackTrace::FastUnwindStack(uptr pc, uptr bp, CHECK(size == 0 && trace[0] == pc); size = 1; uhwptr *frame = (uhwptr *)bp; - uhwptr *prev_frame = frame; - while (frame >= prev_frame && + uhwptr *prev_frame = frame - 1; + // Avoid infinite loop when frame == frame[0] by using frame > prev_frame. + while (frame > prev_frame && frame < (uhwptr *)stack_top - 2 && frame > (uhwptr *)stack_bottom && size < max_size) { diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc index bb1c40f9613..01f1e4588da 100644 --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_linux.cc @@ -97,7 +97,7 @@ bool StartSymbolizerSubprocess(const char *path_to_symbolizer, for (int fd = getdtablesize(); fd > 2; fd--) internal_close(fd); execl(path_to_symbolizer, path_to_symbolizer, (char*)0); - Exit(1); + internal__exit(1); } // Continue execution in parent process. diff --git a/libsanitizer/sanitizer_common/sanitizer_win.cc b/libsanitizer/sanitizer_common/sanitizer_win.cc index 3d5cde11cf8..695265594b3 100644 --- a/libsanitizer/sanitizer_common/sanitizer_win.cc +++ b/libsanitizer/sanitizer_common/sanitizer_win.cc @@ -129,6 +129,10 @@ const char *GetPwd() { UNIMPLEMENTED(); } +u32 GetUid() { + UNIMPLEMENTED(); +} + void DumpProcessMap() { UNIMPLEMENTED(); } @@ -161,10 +165,6 @@ void SleepForMillis(int millis) { Sleep(millis); } -void Exit(int exitcode) { - _exit(exitcode); -} - void Abort() { abort(); _exit(-1); // abort is not NORETURN on Windows. @@ -251,6 +251,10 @@ int internal_sched_yield() { return 0; } +void internal__exit(int exitcode) { + _exit(exitcode); +} + // ---------------------- BlockingMutex ---------------- {{{1 const uptr LOCK_UNINITIALIZED = 0; const uptr LOCK_READY = (uptr)-1; diff --git a/libsanitizer/tsan/tsan_platform_linux.cc b/libsanitizer/tsan/tsan_platform_linux.cc index def91559d5e..f7b05f2bf8f 100644 --- a/libsanitizer/tsan/tsan_platform_linux.cc +++ b/libsanitizer/tsan/tsan_platform_linux.cc @@ -241,7 +241,7 @@ const char *InitializePlatform() { g_tls_size = (uptr)InitTlsSize(); InitDataSeg(); #endif - return getenv(kTsanOptionsEnv); + return GetEnv(kTsanOptionsEnv); } void FinalizePlatform() { diff --git a/libsanitizer/tsan/tsan_platform_mac.cc b/libsanitizer/tsan/tsan_platform_mac.cc index 808d99c0207..b247468c829 100644 --- a/libsanitizer/tsan/tsan_platform_mac.cc +++ b/libsanitizer/tsan/tsan_platform_mac.cc @@ -80,7 +80,7 @@ const char *InitializePlatform() { setrlimit(RLIMIT_CORE, (rlimit*)&lim); } - return getenv(kTsanOptionsEnv); + return GetEnv(kTsanOptionsEnv); } void FinalizePlatform() { diff --git a/libsanitizer/tsan/tsan_platform_windows.cc b/libsanitizer/tsan/tsan_platform_windows.cc index 74b9020d077..376dc08688b 100644 --- a/libsanitizer/tsan/tsan_platform_windows.cc +++ b/libsanitizer/tsan/tsan_platform_windows.cc @@ -32,7 +32,7 @@ void FlushShadowMemory() { } const char *InitializePlatform() { - return getenv(kTsanOptionsEnv); + return GetEnv(kTsanOptionsEnv); } void FinalizePlatform() { diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h index 717f4599705..e939921049a 100644 --- a/libsanitizer/tsan/tsan_rtl.h +++ b/libsanitizer/tsan/tsan_rtl.h @@ -590,6 +590,8 @@ void MemoryAccessImpl(ThreadState *thr, uptr addr, u64 *shadow_mem, Shadow cur); void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size, bool is_write); +void MemoryAccessRangeStep(ThreadState *thr, uptr pc, uptr addr, + uptr size, uptr step, bool is_write); const int kSizeLog1 = 0; const int kSizeLog2 = 1; diff --git a/libsanitizer/tsan/tsan_rtl_thread.cc b/libsanitizer/tsan/tsan_rtl_thread.cc index 9c89417ad68..e30916dc627 100644 --- a/libsanitizer/tsan/tsan_rtl_thread.cc +++ b/libsanitizer/tsan/tsan_rtl_thread.cc @@ -420,4 +420,26 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, shadow_mem, cur); } } + +void MemoryAccessRangeStep(ThreadState *thr, uptr pc, uptr addr, + uptr size, uptr step, bool is_write) { + if (size == 0) + return; + FastState fast_state = thr->fast_state; + if (fast_state.GetIgnoreBit()) + return; + StatInc(thr, StatMopRange); + fast_state.IncrementEpoch(); + thr->fast_state = fast_state; + TraceAddEvent(thr, fast_state, EventTypeMop, pc); + + for (uptr addr_end = addr + size; addr < addr_end; addr += step) { + u64 *shadow_mem = (u64*)MemToShadow(addr); + Shadow cur(fast_state); + cur.SetWrite(is_write); + cur.SetAddr0AndSizeLog(addr & (kShadowCell - 1), kSizeLog1); + MemoryAccessImpl(thr, addr, kSizeLog1, is_write, false, + shadow_mem, cur); + } +} } // namespace __tsan diff --git a/libsanitizer/tsan/tsan_stat.cc b/libsanitizer/tsan/tsan_stat.cc index cd88d2df928..fbec4225d9c 100644 --- a/libsanitizer/tsan/tsan_stat.cc +++ b/libsanitizer/tsan/tsan_stat.cc @@ -263,6 +263,14 @@ void StatOutput(u64 *stat) { name[StatInt___isoc99_fscanf] = " fscanf "; name[StatInt_on_exit] = " on_exit "; name[StatInt___cxa_atexit] = " __cxa_atexit "; + name[StatInt_localtime] = " localtime "; + name[StatInt_localtime_r] = " localtime_r "; + name[StatInt_gmtime] = " gmtime "; + name[StatInt_gmtime_r] = " gmtime_r "; + name[StatInt_ctime] = " ctime "; + name[StatInt_ctime_r] = " ctime_r "; + name[StatInt_asctime] = " asctime "; + name[StatInt_asctime_r] = " asctime_r "; name[StatAnnotation] = "Dynamic annotations "; name[StatAnnotateHappensBefore] = " HappensBefore "; diff --git a/libsanitizer/tsan/tsan_stat.h b/libsanitizer/tsan/tsan_stat.h index 1d6c54cdd4f..8b08a024be2 100644 --- a/libsanitizer/tsan/tsan_stat.h +++ b/libsanitizer/tsan/tsan_stat.h @@ -262,6 +262,14 @@ enum StatType { StatInt___isoc99_fscanf, StatInt_on_exit, StatInt___cxa_atexit, + StatInt_localtime, + StatInt_localtime_r, + StatInt_gmtime, + StatInt_gmtime_r, + StatInt_ctime, + StatInt_ctime_r, + StatInt_asctime, + StatInt_asctime_r, // Dynamic annotations. StatAnnotation, diff --git a/libsanitizer/tsan/tsan_suppressions.cc b/libsanitizer/tsan/tsan_suppressions.cc index b6c54db2c51..8ee8de7c278 100644 --- a/libsanitizer/tsan/tsan_suppressions.cc +++ b/libsanitizer/tsan/tsan_suppressions.cc @@ -138,7 +138,7 @@ void InitializeSuppressions() { g_suppressions = SuppressionParse(0, supp); #ifndef TSAN_GO supp = __tsan_default_suppressions(); - g_suppressions = SuppressionParse(0, supp); + g_suppressions = SuppressionParse(g_suppressions, supp); #endif } diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 8d61a2d6e7d..8e4d68f77b5 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,41 @@ +2013-02-20 Jonathan Wakely <jwakely.gcc@gmail.com> + + * include/std/streambuf (basic_streambuf): Use injected class name + instead of non-standard __streambuf_type typedef. Fix unclosed Doxygen + group. + +2013-02-20 Jonathan Wakely <jwakely.gcc@gmail.com> + + * doc/html/faq.html: Fix spelling. + * doc/xml/faq.xml: Likewise. + * include/bits/basic_ios.h: Likewise. + * include/bits/regex.h: Likewise. + * include/std/istream: Likewise. + * include/std/streambuf: Likewise. + +2013-02-20 Jonathan Wakely <jwakely.gcc@gmail.com> + + * testsuite/23_containers/unordered_set/55043.cc: Add missing + namespace qualification. + * testsuite/23_containers/unordered_multiset/55043.cc: Likewise. + +2013-02-19 Benjamin Kosnik <bkoz@redhat.com> + + * doc/doxygen/user.cfg.in: Set __cplusplus to 201103L. Change to + _GLIBCXX_INCLUDE_AS_CXX11. DIRECTORY_GRAPH, MARKDOWN_SUPPORT, + AUTOLINK_SUPPORT to NO. Update to doxygen 1.8.3.1. + * include/bits/stl_pair.h: Add to utilities group. + * include/std/tuple: Same. + * include/std/typeindex: Same. + + * include/bits/stringfwd.h: Fix markup. + * include/std/limits: Same. + * include/std/type_traits: Same. + * include/tr1/memory: Same. + * include/tr1/regex: Same. + * scripts/run_doxygen: Comment. + * testsuite/20_util/uses_allocator/cons_neg.cc: Fixup line numbers. + 2013-02-14 Jason Merrill <jason@redhat.com> * testsuite/18_support/quick_exit/quick_exit.cc: #if out the whole diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in index 5af636bfe92..4a3afc4de93 100644 --- a/libstdc++-v3/doc/doxygen/user.cfg.in +++ b/libstdc++-v3/doc/doxygen/user.cfg.in @@ -1,4 +1,4 @@ -# Doxyfile 1.8.2 +# Doxyfile 1.8.3.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -252,14 +252,15 @@ EXTENSION_MAPPING = # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. -MARKDOWN_SUPPORT = YES +MARKDOWN_SUPPORT = NO -# When enabled doxygen tries to link words that correspond to documented classes, -# or namespaces to their corresponding documentation. Such a link can be -# prevented in individual cases by by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. +# When enabled doxygen tries to link words that correspond to +# documented classes, or namespaces to their corresponding +# documentation. Such a link can be prevented in individual cases by +# by putting a % sign in front of the word or globally by setting +# AUTOLINK_SUPPORT to NO. -AUTOLINK_SUPPORT = YES +AUTOLINK_SUPPORT = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should @@ -281,7 +282,12 @@ CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO -# For Microsoft's IDL there are propget and propput attributes to indicate getter and setter methods for a property. Setting this option to YES (the default) will make doxygen replace the get and set methods by a property in the documentation. This will only work if the methods are indeed getting or setting a simple type. If this is not the case, or you want to show the methods anyway, you should set this option to NO. +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES (the +# default) will make doxygen replace the get and set methods by a property in +# the documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = NO @@ -305,8 +311,7 @@ SUBGROUPING = YES # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). -#INLINE_GROUPED_CLASSES = NO -INLINE_GROUPED_CLASSES = YES +INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation @@ -314,7 +319,7 @@ INLINE_GROUPED_CLASSES = YES # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). - + INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum @@ -542,7 +547,8 @@ GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. +# documentation sections, marked by \if section-label ... \endif +# and \cond section-label ... \endcond blocks. ENABLED_SECTIONS = @enabled_sections@ @@ -600,7 +606,8 @@ LAYOUT_FILE = # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this -# feature you need bibtex and perl available in the search path. +# feature you need bibtex and perl available in the search path. Do not use +# file names with spaces, bibtex cannot handle them. CITE_BIB_FILES = @@ -952,6 +959,13 @@ FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = +# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page (index.html). +# This can be useful if you have a project on for instance GitHub and want reuse +# the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- @@ -1134,7 +1148,7 @@ HTML_TIMESTAMP = NO # documentation will contain sections that can be hidden and shown after the # page has loaded. -HTML_DYNAMIC_SECTIONS = YES +HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # entries shown in the various tree structured indices initially; the user @@ -1145,7 +1159,7 @@ HTML_DYNAMIC_SECTIONS = YES # default. 0 is a special value representing an infinite number of entries # and will result in a full expanded tree by default. -HTML_INDEX_NUM_ENTRIES = 100 +HTML_INDEX_NUM_ENTRIES = 0 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 @@ -1361,6 +1375,13 @@ FORMULA_TRANSPARENT = YES USE_MATHJAX = NO +# When MathJax is enabled you can set the default output format to be used for +# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and +# SVG. The default value is HTML-CSS, which is slower, but has the best +# compatibility. + +MATHJAX_FORMAT = HTML-CSS + # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax @@ -1389,15 +1410,55 @@ MATHJAX_EXTENSIONS = SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvantages are that it is more difficult to setup -# and does not have live searching capabilities. +# implemented using a web server instead of a web client using Javascript. +# There are two flavours of web server based search depending on the +# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for +# searching and an index file used by the script. When EXTERNAL_SEARCH is +# enabled the indexing and searching needs to be provided by external tools. +# See the manual for details. SERVER_BASED_SEARCH = NO +# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain +# the search results. Doxygen ships with an example indexer (doxyindexer) and +# search engine (doxysearch.cgi) which are based on the open source search engine +# library Xapian. See the manual for configuration details. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will returned the search results when EXTERNAL_SEARCH is enabled. +# Doxygen ships with an example search engine (doxysearch) which is based on +# the open source search engine library Xapian. See the manual for configuration +# details. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id +# of to a relative location where the documentation can be found. +# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... + +EXTRA_SEARCH_MAPPINGS = + #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- @@ -1431,7 +1492,7 @@ MAKEINDEX_CMD_NAME = makeindex # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. -COMPACT_LATEX = YES +COMPACT_LATEX = YES # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and @@ -1698,10 +1759,10 @@ INCLUDE_FILE_PATTERNS = # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = __cplusplus \ +PREDEFINED = __cplusplus=201103L \ __GTHREADS \ _GLIBCXX_HAS_GTHREADS \ - _GLIBCXX_INCLUDE_AS_CXX0X \ + _GLIBCXX_INCLUDE_AS_CXX11 \ "_GLIBCXX_PURE= " \ "_GLIBCXX_CONST= " \ "_GLIBCXX_NORETURN= " \ @@ -1938,7 +1999,7 @@ GRAPHICAL_HIERARCHY = YES # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. -DIRECTORY_GRAPH = YES +DIRECTORY_GRAPH = NO # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. diff --git a/libstdc++-v3/doc/html/faq.html b/libstdc++-v3/doc/html/faq.html index 0c1d3280a85..91952071e87 100644 --- a/libstdc++-v3/doc/html/faq.html +++ b/libstdc++-v3/doc/html/faq.html @@ -503,7 +503,7 @@ Short answer: Pretty much everything <span class="emphasis"><em>works</em></span> except for some corner cases. Support for localization in <code class="classname">locale</code> may be incomplete on non-GNU - platforms. Also dependant on the underlying platform is support + platforms. Also dependent on the underlying platform is support for <span class="type">wchar_t</span> and <span class="type">long long</span> specializations, and details of thread support. </p><p> diff --git a/libstdc++-v3/doc/xml/faq.xml b/libstdc++-v3/doc/xml/faq.xml index 1408bd24610..4e3339260ee 100644 --- a/libstdc++-v3/doc/xml/faq.xml +++ b/libstdc++-v3/doc/xml/faq.xml @@ -685,7 +685,7 @@ Short answer: Pretty much everything <emphasis>works</emphasis> except for some corner cases. Support for localization in <classname>locale</classname> may be incomplete on non-GNU - platforms. Also dependant on the underlying platform is support + platforms. Also dependent on the underlying platform is support for <type>wchar_t</type> and <type>long long</type> specializations, and details of thread support. </para> diff --git a/libstdc++-v3/include/bits/basic_ios.h b/libstdc++-v3/include/bits/basic_ios.h index b78b464ba02..5325800df90 100644 --- a/libstdc++-v3/include/bits/basic_ios.h +++ b/libstdc++-v3/include/bits/basic_ios.h @@ -69,7 +69,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION //@{ /** * These are standard types. They permit a standardized way of - * referring to names of (or names dependant on) the template + * referring to names of (or names dependent on) the template * parameters, which are specific to the implementation. */ typedef _CharT char_type; diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h index 39704bee716..101925a66f8 100644 --- a/libstdc++-v3/include/bits/regex.h +++ b/libstdc++-v3/include/bits/regex.h @@ -135,7 +135,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } /** - * @brief Gets a sort key for a character sequence, independant of case. + * @brief Gets a sort key for a character sequence, independent of case. * * @param __first beginning of the character sequence. * @param __last one-past-the-end of the character sequence. @@ -185,7 +185,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * the returned mask identifies the classification regardless of * the case of the characters to be matched (for example, * [[:lower:]] is the same as [[:alpha:]]), otherwise a - * case-dependant classification is returned. The value + * case-dependent classification is returned. The value * returned shall be independent of the case of the characters * in the character sequence. If the name is not recognized then * returns a value that compares equal to 0. diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index 967951cfecc..92250166b40 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -66,6 +66,11 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION + /** + * @addtogroup utilities + * @{ + */ + #if __cplusplus >= 201103L /// piecewise_construct_t struct piecewise_construct_t { }; @@ -282,7 +287,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return pair<_T1, _T2>(__x, __y); } #endif + /// @} + _GLIBCXX_END_NAMESPACE_VERSION -} // namespace +} // namespace std #endif /* _STL_PAIR_H */ diff --git a/libstdc++-v3/include/bits/stringfwd.h b/libstdc++-v3/include/bits/stringfwd.h index e204b08940e..5d5b83f5e96 100644 --- a/libstdc++-v3/include/bits/stringfwd.h +++ b/libstdc++-v3/include/bits/stringfwd.h @@ -60,12 +60,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<> struct char_traits<char>; - typedef basic_string<char> string; /// A string of @c char + /// A string of @c char + typedef basic_string<char> string; #ifdef _GLIBCXX_USE_WCHAR_T template<> struct char_traits<wchar_t>; - typedef basic_string<wchar_t> wstring; /// A string of @c wchar_t + /// A string of @c wchar_t + typedef basic_string<wchar_t> wstring; #endif #if ((__cplusplus >= 201103L) \ @@ -74,13 +76,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<> struct char_traits<char16_t>; template<> struct char_traits<char32_t>; - typedef basic_string<char16_t> u16string; /// A string of @c char16_t - typedef basic_string<char32_t> u32string; /// A string of @c char32_t + /// A string of @c char16_t + typedef basic_string<char16_t> u16string; + + /// A string of @c char32_t + typedef basic_string<char32_t> u32string; #endif /** @} */ _GLIBCXX_END_NAMESPACE_VERSION -} // namespace +} // namespace std #endif // _STRINGFWD_H diff --git a/libstdc++-v3/include/std/istream b/libstdc++-v3/include/std/istream index ae1485f5f43..861bca53adf 100644 --- a/libstdc++-v3/include/std/istream +++ b/libstdc++-v3/include/std/istream @@ -660,7 +660,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool _M_ok; public: - /// Easy access to dependant types. + /// Easy access to dependent types. typedef _Traits traits_type; typedef basic_streambuf<_CharT, _Traits> __streambuf_type; typedef basic_istream<_CharT, _Traits> __istream_type; diff --git a/libstdc++-v3/include/std/limits b/libstdc++-v3/include/std/limits index 13ad660aeca..a137d0b1210 100644 --- a/libstdc++-v3/include/std/limits +++ b/libstdc++-v3/include/std/limits @@ -211,14 +211,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** True if the type is signed. */ static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; - /** True if the type is integer. - * Is this supposed to be <em>if the type is integral?</em> */ + /** True if the type is integer. */ static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; - /** True if the type uses an exact representation. <em>All integer types are + /** True if the type uses an exact representation. All integer types are exact, but not all exact types are integer. For example, rational and - fixed-exponent representations are exact but not integer.</em> - [18.2.1.2]/15 */ + fixed-exponent representations are exact but not integer. */ static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; /** For integer types, specifies the base of the representation. For @@ -246,27 +244,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; /** True if the type has a representation for a quiet (non-signaling) - <em>Not a Number</em>. */ + Not a Number. */ static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; /** True if the type has a representation for a signaling - <em>Not a Number</em>. */ + Not a Number. */ static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; /** See std::float_denorm_style for more information. */ static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm = denorm_absent; - /** <em>True if loss of accuracy is detected as a denormalization loss, - rather than as an inexact result.</em> [18.2.1.2]/42 */ + /** True if loss of accuracy is detected as a denormalization loss, + rather than as an inexact result. */ static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; /** True if-and-only-if the type adheres to the IEC 559 standard, also known as IEEE 754. (Only makes sense for floating point types.) */ static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - /** <em>True if the set of values representable by the type is + /** True if the set of values representable by the type is finite. All built-in types are bounded, this member would be - false for arbitrary precision types.</em> [18.2.1.2]/54 */ + false for arbitrary precision types. */ static _GLIBCXX_USE_CONSTEXPR bool is_bounded = false; /** True if the type is @e modulo. A type is modulo if, for any @@ -334,12 +332,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _GLIBCXX_CONSTEXPR _Tp infinity() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } - /** The representation of a quiet <em>Not a Number</em>, + /** The representation of a quiet Not a Number, if @c has_quiet_NaN. */ static _GLIBCXX_CONSTEXPR _Tp quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } - /** The representation of a signaling <em>Not a Number</em>, if + /** The representation of a signaling Not a Number, if @c has_signaling_NaN. */ static _GLIBCXX_CONSTEXPR _Tp signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } diff --git a/libstdc++-v3/include/std/streambuf b/libstdc++-v3/include/std/streambuf index 0fb2f07cc90..26a3871471c 100644 --- a/libstdc++-v3/include/std/streambuf +++ b/libstdc++-v3/include/std/streambuf @@ -123,7 +123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION //@{ /** * These are standard types. They permit a standardized way of - * referring to names of (or names dependant on) the template + * referring to names of (or names dependent on) the template * parameters, which are specific to the implementation. */ typedef _CharT char_type; @@ -145,7 +145,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION friend class ostreambuf_iterator<char_type, traits_type>; friend streamsize - __copy_streambufs_eof<>(__streambuf_type*, __streambuf_type*, bool&); + __copy_streambufs_eof<>(basic_streambuf*, basic_streambuf*, bool&); template<bool _IsMove, typename _CharT2> friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, @@ -174,20 +174,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION basic_string<_CharT2, _Traits2, _Alloc>&, _CharT2); protected: - //@{ - /** + /* * This is based on _IO_FILE, just reordered to be more consistent, * and is intended to be the most minimal abstraction for an * internal buffer. * - get == input == read * - put == output == write */ - char_type* _M_in_beg; // Start of get area. - char_type* _M_in_cur; // Current read area. - char_type* _M_in_end; // End of get area. - char_type* _M_out_beg; // Start of put area. - char_type* _M_out_cur; // Current put area. - char_type* _M_out_end; // End of put area. + char_type* _M_in_beg; ///< Start of get area. + char_type* _M_in_cur; ///< Current read area. + char_type* _M_in_end; ///< End of get area. + char_type* _M_out_beg; ///< Start of put area. + char_type* _M_out_cur; ///< Current put area. + char_type* _M_out_end; ///< End of put area. /// Current locale setting. locale _M_buf_locale; @@ -236,7 +235,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * derived @c foo member functions, passing the arguments (if any) * and returning the result unchanged. */ - __streambuf_type* + basic_streambuf* pubsetbuf(char_type* __s, streamsize __n) { return this->setbuf(__s, __n); } @@ -800,15 +799,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: // _GLIBCXX_RESOLVE_LIB_DEFECTS // Side effect of DR 50. - basic_streambuf(const __streambuf_type& __sb) + basic_streambuf(const basic_streambuf& __sb) : _M_in_beg(__sb._M_in_beg), _M_in_cur(__sb._M_in_cur), _M_in_end(__sb._M_in_end), _M_out_beg(__sb._M_out_beg), _M_out_cur(__sb._M_out_cur), _M_out_end(__sb._M_out_cur), _M_buf_locale(__sb._M_buf_locale) { } - __streambuf_type& - operator=(const __streambuf_type&) { return *this; }; + basic_streambuf& + operator=(const basic_streambuf&) { return *this; }; }; // Explicit specialization declarations, defined in src/streambuf.cc. diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 80b136a2c61..ee2b2e1d4c2 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -43,6 +43,11 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION + /** + * @addtogroup utilities + * @{ + */ + // Adds a const reference to a non-reference type. template<typename _Tp> struct __add_c_ref @@ -1018,6 +1023,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; + /// tuple_cat template<typename... _Tpls, typename = typename enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type> constexpr auto @@ -1030,11 +1036,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __concater::_S_do(std::forward<_Tpls>(__tpls)...); } + /// tie template<typename... _Elements> inline tuple<_Elements&...> tie(_Elements&... __args) noexcept { return tuple<_Elements&...>(__args...); } + /// swap template<typename... _Elements> inline void swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y) @@ -1080,8 +1088,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...) { } + /// @} + _GLIBCXX_END_NAMESPACE_VERSION -} // namespace +} // namespace std #endif // C++11 diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index cfc45390454..62d59128f9f 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -1,4 +1,4 @@ -// C++11 type_traits -*- C++ -*- +// C++11 <type_traits> -*- C++ -*- // Copyright (C) 2007-2013 Free Software Foundation, Inc. // @@ -42,7 +42,7 @@ namespace std _GLIBCXX_VISIBILITY(default) _GLIBCXX_BEGIN_NAMESPACE_VERSION /** - * @defgroup metaprogramming Metaprogramming and type traits + * @defgroup metaprogramming Metaprogramming * @ingroup utilities * * Template utilities for compile-time introspection and modification, @@ -62,15 +62,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr operator value_type() { return value; } }; + template<typename _Tp, _Tp __v> + constexpr _Tp integral_constant<_Tp, __v>::value; + /// The type used as a compile-time boolean with true value. typedef integral_constant<bool, true> true_type; /// The type used as a compile-time boolean with false value. typedef integral_constant<bool, false> false_type; - template<typename _Tp, _Tp __v> - constexpr _Tp integral_constant<_Tp, __v>::value; - // Meta programming helper types. template<bool, typename, typename> @@ -145,7 +145,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __failure_type { }; - // primary type categories. + // Primary type categories. template<typename> struct remove_cv; @@ -426,7 +426,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION remove_cv<_Tp>::type>::value)> { }; - // composite type categories. + // Composite type categories. /// is_reference template<typename _Tp> @@ -484,7 +484,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename remove_cv<_Tp>::type>::value)> { }; - // type properties. + // Type properties. /// is_const template<typename> @@ -577,7 +577,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { }; - // destructible and constructible type properties + // Destructible and constructible type properties. template<typename> struct add_rvalue_reference; @@ -1271,7 +1271,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { }; - // type relations. + // Type relations. /// is_same template<typename, typename> @@ -1320,7 +1320,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { }; - // const-volatile modifications. + // Const-volatile modifications. /// remove_const template<typename _Tp> @@ -1420,7 +1420,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { }; - // sign modifications. + // Sign modifications. // Utility for constructing identically cv-qualified types. template<typename _Unqualified, bool _IsConst, bool _IsVol> @@ -1617,7 +1617,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct make_signed<bool>; - // array modifications. + // Array modifications. /// remove_extent template<typename _Tp> @@ -1646,7 +1646,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef typename remove_all_extents<_Tp>::type type; }; - // pointer modifications. + // Pointer modifications. template<typename _Tp, typename> struct __remove_pointer_helper @@ -1789,7 +1789,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename... _Tp> struct common_type; - // sfinae-friendly common_type implementation: + // Sfinae-friendly common_type implementation: struct __do_common_type_impl { @@ -1877,7 +1877,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Signature> class result_of; - // sfinae-friendly result_of implementation: + // Sfinae-friendly result_of implementation: // [func.require] paragraph 1 bullet 1: struct __result_of_memfun_ref_impl @@ -2034,6 +2034,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Functor, _ArgTypes... >::type { }; + + /// @} group metaprogramming /** * Use SFINAE to determine if the type _Tp has a publicly-accessible @@ -2064,9 +2066,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION <typename remove_cv<_Tp>::type>::value> \ { }; - /// @} group metaprogramming _GLIBCXX_END_NAMESPACE_VERSION -} // namespace +} // namespace std #endif // C++11 diff --git a/libstdc++-v3/include/std/typeindex b/libstdc++-v3/include/std/typeindex index 793894f3f80..9e6db30a72a 100644 --- a/libstdc++-v3/include/std/typeindex +++ b/libstdc++-v3/include/std/typeindex @@ -1,4 +1,4 @@ -// C++0x typeindex -*- C++ -*- +// C++11 <typeindex> -*- C++ -*- // Copyright (C) 2010-2013 Free Software Foundation, Inc. // @@ -42,9 +42,12 @@ namespace std _GLIBCXX_VISIBILITY(default) _GLIBCXX_BEGIN_NAMESPACE_VERSION /** - @brief The class type_index provides a simple wrapper for type_info - which can be used as an index type in associative containers (23.6) - and in unordered associative containers (23.7). + * @brief Class type_index + * @ingroup utilities + * + * The class type_index provides a simple wrapper for type_info + * which can be used as an index type in associative containers + * (23.6) and in unordered associative containers (23.7). */ struct type_index { @@ -102,7 +105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; _GLIBCXX_END_NAMESPACE_VERSION -} // namespace +} // namespace std #endif // C++11 diff --git a/libstdc++-v3/include/tr1/memory b/libstdc++-v3/include/tr1/memory index d04f86b8030..7f4ce513777 100644 --- a/libstdc++-v3/include/tr1/memory +++ b/libstdc++-v3/include/tr1/memory @@ -32,8 +32,8 @@ #pragma GCC system_header -#if defined(_GLIBCXX_INCLUDE_AS_CXX0X) -# error TR1 header cannot be included from C++0x header +#if defined(_GLIBCXX_INCLUDE_AS_CXX11) +# error TR1 header cannot be included from C++11 header #endif #include <memory> diff --git a/libstdc++-v3/include/tr1/regex b/libstdc++-v3/include/tr1/regex index 15f56af41c9..dfcc3a90467 100644 --- a/libstdc++-v3/include/tr1/regex +++ b/libstdc++-v3/include/tr1/regex @@ -847,7 +847,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_flags(__f), _M_pattern(__first, __last), _M_mark_count(0) { _M_compile(); } -#ifdef _GLIBCXX_INCLUDE_AS_CXX0X +#ifdef _GLIBCXX_INCLUDE_AS_CXX11 /** * @brief Constructs a basic regular expression from an initializer list. * @@ -986,7 +986,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION flag_type __flags = regex_constants::ECMAScript) { return this->assign(string_type(__first, __last), __flags); } -#ifdef _GLIBCXX_INCLUDE_AS_CXX0X +#ifdef _GLIBCXX_INCLUDE_AS_CXX11 /** * @brief Assigns a new regular expression to a regex object. * @@ -1966,7 +1966,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION begin() const { return _Base_type::begin(); } -#ifdef _GLIBCXX_INCLUDE_AS_CXX0X +#ifdef _GLIBCXX_INCLUDE_AS_CXX11 /** * @brief Gets an iterator to the start of the %sub_match collection. */ @@ -1982,7 +1982,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION end() const { return _Base_type::end(); } -#ifdef _GLIBCXX_INCLUDE_AS_CXX0X +#ifdef _GLIBCXX_INCLUDE_AS_CXX11 /** * @brief Gets an iterator to one-past-the-end of the collection. */ diff --git a/libstdc++-v3/scripts/run_doxygen b/libstdc++-v3/scripts/run_doxygen index 0f65d3af05c..75b2f4f9758 100644 --- a/libstdc++-v3/scripts/run_doxygen +++ b/libstdc++-v3/scripts/run_doxygen @@ -205,6 +205,8 @@ if $do_html; then cd ${outdir}/${mode} #doxytag -t libstdc++.tag . > /dev/null 2>&1 + + # Strip pathnames from tag file. sed -e '/<path>/d' libstdc++.tag > TEMP mv TEMP libstdc++.tag diff --git a/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc index 2fbc4568123..e5f015fa146 100644 --- a/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc +++ b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc @@ -44,4 +44,4 @@ void test01() tuple<Type> t(allocator_arg, a, 1); } -// { dg-error "no matching function" "" { target *-*-* } 113 } +// { dg-error "no matching function" "" { target *-*-* } 118 } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc index 445e4e48bc3..9d71cff8583 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/55043.cc @@ -33,7 +33,7 @@ struct equal { bool operator()(const MoveOnly&, const MoveOnly) const { return true; } }; struct hash { - size_t operator()(const MoveOnly&) const { return 0; } + std::size_t operator()(const MoveOnly&) const { return 0; } }; template<typename Alloc> diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/55043.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/55043.cc index e5ba065f5d5..152489042f7 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_set/55043.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/55043.cc @@ -33,7 +33,7 @@ struct equal { bool operator()(const MoveOnly&, const MoveOnly) const { return true; } }; struct hash { - size_t operator()(const MoveOnly&) const { return 0; } + std::size_t operator()(const MoveOnly&) const { return 0; } }; template<typename Alloc> |