diff options
author | Martin Liska <mliska@suse.cz> | 2021-08-19 12:03:21 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2021-08-19 12:03:21 +0200 |
commit | 0b6c24dd10ff426108f737551067085d0af42ca8 (patch) | |
tree | 50bc9dfc7aaf11d1325281485908fb5bf0bcb54b /gcc | |
parent | 60ae041aae40e239fda5fbf6f4c4ec047ce50962 (diff) | |
parent | 301dc6011cbceb7ea9debd86aaec7cadb37213c8 (diff) | |
download | gcc-0b6c24dd10ff426108f737551067085d0af42ca8.zip gcc-0b6c24dd10ff426108f737551067085d0af42ca8.tar.gz gcc-0b6c24dd10ff426108f737551067085d0af42ca8.tar.bz2 |
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
66 files changed, 1685 insertions, 133 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b26f256..4fd8ff7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,54 @@ +2021-08-18 Iain Sandoe <iain@sandoe.co.uk> + + * config.gcc: Include rpath.opt for Darwin. + * config/darwin.h (DRIVER_SELF_SPECS): Handle -rpath. + +2021-08-18 Thomas Schwinge <thomas@codesourcery.com> + + PR bootstrap/101959 + * hash-map-tests.c (test_map_of_type_with_ctor_and_dtor_expand): + Use an 'int_hash'. + +2021-08-18 Jonathan Wright <jonathan.wright@arm.com> + + * config/aarch64/arm_neon.h (vld3_lane_f64): Use float RTL + pattern and type cast. + (vld4_lane_f32): Use float RTL pattern. + (vld4q_lane_f64): Use float type cast. + +2021-08-18 Jan Hubicka <hubicka@ucw.cz> + + * tree-ssa-uninit.c (maybe_warn_pass_by_reference): Check also + EAF_NOREAD. + +2021-08-18 Thomas Schwinge <thomas@codesourcery.com> + + * hash-map-tests.c (test_map_of_type_with_ctor_and_dtor): Extend. + (test_map_of_type_with_ctor_and_dtor_expand): Add function. + (hash_map_tests_c_tests): Call it. + +2021-08-18 Thomas Schwinge <thomas@codesourcery.com> + + * ggc.h (enum ggc_collect): New. + (ggc_collect): Use it. + * ggc-page.c: Adjust. + * ggc-common.c: Likewise. + * ggc-tests.c: Likewise. + * read-rtl-function.c: Likewise. + * selftest-run-tests.c: Likewise. + * doc/gty.texi (Invoking the garbage collector): Likewise. + +2021-08-18 liuhongt <hongtao.liu@intel.com> + + PR target/97147 + * config/i386/i386.h (TARGET_V2DF_REDUCTION_PREFER_HADDPD): + New macro. + * config/i386/sse.md (*sse3_haddv2df3_low): Add + TARGET_V2DF_REDUCTION_PREFER_HADDPD. + (*sse3_hsubv2df3_low): Ditto. + * config/i386/x86-tune.def + (X86_TUNE_V2DF_REDUCTION_PREFER_HADDPD): New tune. + 2021-08-17 Andrew MacLeod <amacleod@redhat.com> * gimple-range-gori.cc (gori_compute::gori_compute): Enable tracing. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 70b09db..30a51b9 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210818 +20210819 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 8e19ca4..63a04b1 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2021-08-18 Eric Botcazou <ebotcazou@gcc.gnu.org> + + * gcc-interface/decl.c (gnat_to_gnu_entity) <discrete_type>: Fix + thinko in latest change. + 2021-08-11 Bernd Edlinger <bernd.edlinger@hotmail.de> PR debug/101598 diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index 43e3c63..0b483cc 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,54 @@ +2021-08-18 Ankur Saini <arsenic@sourceware.org> + + PR analyzer/97114 + * region-model.cc (region_model::get_rvalue_1): Add case for + OBJ_TYPE_REF. + +2021-08-18 Ankur Saini <arsenic@sourceware.org> + + PR analyzer/100546 + * analysis-plan.cc (analysis_plan::use_summary_p): Don't use call + summaries if there is no callgraph edge + * checker-path.cc (call_event::call_event): Handle calls events that + are not represented by a supergraph call edge + (return_event::return_event): Likewise. + (call_event::get_desc): Work with new call_event structure. + (return_event::get_desc): Likeise. + * checker-path.h (call_event::m_src_snode): New field. + (call_event::m_dest_snode): New field. + (return_event::m_src_snode): New field. + (return_event::m_dest_snode): New field. + * diagnostic-manager.cc + (diagnostic_manager::prune_for_sm_diagnostic)<case EK_CALL_EDGE>: + Refactor to work with edges without callgraph edge. + (diagnostic_manager::prune_for_sm_diagnostic)<case EK_RETURN_EDGE>: + Likewise. + * engine.cc (dynamic_call_info_t::update_model): New function. + (dynamic_call_info_t::add_events_to_path): New function. + (exploded_graph::create_dynamic_call): New function. + (exploded_graph::process_node): Work with dynamically discovered calls. + * exploded-graph.h (class dynamic_call_info_t): New class. + (exploded_graph::create_dynamic_call): New decl. + * program-point.cc (program_point::push_to_call_stack): New function. + (program_point::pop_from_call_stack): New function. + * program-point.h (program_point::push_to_call_stack): New decl. + (program_point::pop_from_call_stack): New decl. + * program-state.cc (program_state::push_call): New function. + (program_state::returning_call): New function. + * program-state.h (program_state::push_call): New decl. + (program_state::returning_call): New decl. + * region-model.cc (region_model::update_for_gcall) New function. + (region_model::update_for_return_gcall): New function. + (egion_model::update_for_call_superedge): Get the underlying gcall and + update for gcall. + (region_model::update_for_return_superedge): Likewise. + * region-model.h (region_model::update_for_gcall): New decl. + (region_model::update_for_return_gcall): New decl. + * state-purge.cc (state_purge_per_ssa_name::process_point): Update to + work with calls without underlying cgraph edge. + * supergraph.cc (supergraph::supergraph) Split snodes at every callsite. + * supergraph.h (supernode::get_returning_call) New accessor. + 2021-08-04 David Malcolm <dmalcolm@redhat.com> PR analyzer/101570 diff --git a/gcc/analyzer/analysis-plan.cc b/gcc/analyzer/analysis-plan.cc index 7dfc48e..57a6dcb 100644 --- a/gcc/analyzer/analysis-plan.cc +++ b/gcc/analyzer/analysis-plan.cc @@ -109,6 +109,10 @@ analysis_plan::use_summary_p (const cgraph_edge *edge) const if (!flag_analyzer_call_summaries) return false; + /* Don't use call summaries if there is no callgraph edge */ + if (!edge || !edge->callee) + return false; + /* TODO: don't count callsites each time. */ int num_call_sites = 0; const cgraph_node *callee = edge->callee; diff --git a/gcc/analyzer/checker-path.cc b/gcc/analyzer/checker-path.cc index e10c8e2..e132f00 100644 --- a/gcc/analyzer/checker-path.cc +++ b/gcc/analyzer/checker-path.cc @@ -614,7 +614,11 @@ call_event::call_event (const exploded_edge &eedge, location_t loc, tree fndecl, int depth) : superedge_event (EK_CALL_EDGE, eedge, loc, fndecl, depth) { - gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CALL); + if (eedge.m_sedge) + gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_CALL); + + m_src_snode = eedge.m_src->get_supernode (); + m_dest_snode = eedge.m_dest->get_supernode (); } /* Implementation of diagnostic_event::get_desc vfunc for @@ -638,8 +642,8 @@ call_event::get_desc (bool can_colorize) const label_text custom_desc = m_pending_diagnostic->describe_call_with_state (evdesc::call_with_state (can_colorize, - m_sedge->m_src->m_fun->decl, - m_sedge->m_dest->m_fun->decl, + m_src_snode->m_fun->decl, + m_dest_snode->m_fun->decl, var, m_critical_state)); if (custom_desc.m_buffer) @@ -648,8 +652,8 @@ call_event::get_desc (bool can_colorize) const return make_label_text (can_colorize, "calling %qE from %qE", - m_sedge->m_dest->m_fun->decl, - m_sedge->m_src->m_fun->decl); + m_dest_snode->m_fun->decl, + m_src_snode->m_fun->decl); } /* Override of checker_event::is_call_p for calls. */ @@ -668,7 +672,11 @@ return_event::return_event (const exploded_edge &eedge, location_t loc, tree fndecl, int depth) : superedge_event (EK_RETURN_EDGE, eedge, loc, fndecl, depth) { - gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_RETURN); + if (eedge.m_sedge) + gcc_assert (eedge.m_sedge->m_kind == SUPEREDGE_RETURN); + + m_src_snode = eedge.m_src->get_supernode (); + m_dest_snode = eedge.m_dest->get_supernode (); } /* Implementation of diagnostic_event::get_desc vfunc for @@ -694,16 +702,16 @@ return_event::get_desc (bool can_colorize) const label_text custom_desc = m_pending_diagnostic->describe_return_of_state (evdesc::return_of_state (can_colorize, - m_sedge->m_dest->m_fun->decl, - m_sedge->m_src->m_fun->decl, + m_dest_snode->m_fun->decl, + m_src_snode->m_fun->decl, m_critical_state)); if (custom_desc.m_buffer) return custom_desc; } return make_label_text (can_colorize, "returning to %qE from %qE", - m_sedge->m_dest->m_fun->decl, - m_sedge->m_src->m_fun->decl); + m_dest_snode->m_fun->decl, + m_src_snode->m_fun->decl); } /* Override of checker_event::is_return_p for returns. */ diff --git a/gcc/analyzer/checker-path.h b/gcc/analyzer/checker-path.h index 1843c4b..27634c2 100644 --- a/gcc/analyzer/checker-path.h +++ b/gcc/analyzer/checker-path.h @@ -338,6 +338,9 @@ public: label_text get_desc (bool can_colorize) const FINAL OVERRIDE; bool is_call_p () const FINAL OVERRIDE; + + const supernode *m_src_snode; + const supernode *m_dest_snode; }; /* A concrete event subclass for an interprocedural return. */ @@ -351,6 +354,9 @@ public: label_text get_desc (bool can_colorize) const FINAL OVERRIDE; bool is_return_p () const FINAL OVERRIDE; + + const supernode *m_src_snode; + const supernode *m_dest_snode; }; /* A concrete event subclass for the start of a consolidated run of CFG diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index ef3df32..06e7510 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -2093,18 +2093,13 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path, case EK_CALL_EDGE: { call_event *event = (call_event *)base_event; - const callgraph_superedge& cg_superedge - = event->get_callgraph_superedge (); const region_model *callee_model = event->m_eedge.m_dest->get_state ().m_region_model; + const region_model *caller_model + = event->m_eedge.m_src->get_state ().m_region_model; tree callee_var = callee_model->get_representative_tree (sval); - /* We could just use caller_model->get_representative_tree (sval); - to get the caller_var, but for now use - map_expr_from_callee_to_caller so as to only record critical - state for parms and the like. */ callsite_expr expr; - tree caller_var - = cg_superedge.map_expr_from_callee_to_caller (callee_var, &expr); + tree caller_var = caller_model->get_representative_tree (sval); if (caller_var) { if (get_logger ()) @@ -2126,15 +2121,11 @@ diagnostic_manager::prune_for_sm_diagnostic (checker_path *path, if (sval) { return_event *event = (return_event *)base_event; - const callgraph_superedge& cg_superedge - = event->get_callgraph_superedge (); - const region_model *caller_model - = event->m_eedge.m_dest->get_state ().m_region_model; - tree caller_var = caller_model->get_representative_tree (sval); callsite_expr expr; - tree callee_var - = cg_superedge.map_expr_from_caller_to_callee (caller_var, - &expr); + + const region_model *callee_model + = event->m_eedge.m_src->get_state ().m_region_model; + tree callee_var = callee_model->get_representative_tree (sval); if (callee_var) { if (get_logger ()) diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index ecd4265..461de9c 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -1627,6 +1627,50 @@ exploded_node::dump_succs_and_preds (FILE *outf) const } } +/* class dynamic_call_info_t : public exploded_edge::custom_info_t. */ + +/* Implementation of exploded_edge::custom_info_t::update_model vfunc + for dynamic_call_info_t. + + Update state for the dynamically discorverd calls */ + +void +dynamic_call_info_t::update_model (region_model *model, + const exploded_edge &eedge) +{ + const program_state &dest_state = eedge.m_dest->get_state (); + *model = *dest_state.m_region_model; +} + +/* Implementation of exploded_edge::custom_info_t::add_events_to_path vfunc + for dynamic_call_info_t. */ + +void +dynamic_call_info_t::add_events_to_path (checker_path *emission_path, + const exploded_edge &eedge) +{ + const exploded_node *src_node = eedge.m_src; + const program_point &src_point = src_node->get_point (); + const int src_stack_depth = src_point.get_stack_depth (); + const exploded_node *dest_node = eedge.m_dest; + const program_point &dest_point = dest_node->get_point (); + const int dest_stack_depth = dest_point.get_stack_depth (); + + if (m_is_returning_call) + emission_path->add_event (new return_event (eedge, (m_dynamic_call + ? m_dynamic_call->location + : UNKNOWN_LOCATION), + dest_point.get_fndecl (), + dest_stack_depth)); + else + emission_path->add_event (new call_event (eedge, (m_dynamic_call + ? m_dynamic_call->location + : UNKNOWN_LOCATION), + src_point.get_fndecl (), + src_stack_depth)); + +} + /* class rewind_info_t : public exploded_edge::custom_info_t. */ /* Implementation of exploded_edge::custom_info_t::update_model vfunc @@ -2980,6 +3024,61 @@ state_change_requires_new_enode_p (const program_state &old_state, return false; } +/* Create enodes and eedges for the function calls that doesn't have an + underlying call superedge. + + Such case occurs when GCC's middle end didn't know which function to + call but the analyzer does (with the help of current state). + + Some example such calls are dynamically dispatched calls to virtual + functions or calls that happen via function pointer. */ + +void +exploded_graph::create_dynamic_call (const gcall *call, + tree fn_decl, + exploded_node *node, + program_state next_state, + program_point &next_point, + uncertainty_t *uncertainty, + logger *logger) +{ + LOG_FUNC (logger); + + const program_point *this_point = &node->get_point (); + function *fun = DECL_STRUCT_FUNCTION (fn_decl); + if (fun) + { + const supergraph &sg = this->get_supergraph (); + supernode * sn_entry = sg.get_node_for_function_entry (fun); + supernode * sn_exit = sg.get_node_for_function_exit (fun); + + program_point new_point + = program_point::before_supernode (sn_entry, + NULL, + this_point->get_call_string ()); + + new_point.push_to_call_stack (sn_exit, + next_point.get_supernode()); + next_state.push_call (*this, node, call, uncertainty); + + if (next_state.m_valid) + { + if (logger) + logger->log ("Discovered call to %s [SN: %i -> SN: %i]", + function_name(fun), + this_point->get_supernode ()->m_index, + sn_entry->m_index); + + exploded_node *enode = get_or_create_node (new_point, + next_state, + node); + if (enode) + add_edge (node,enode, NULL, + new dynamic_call_info_t (call)); + } + } +} + /* The core of exploded_graph::process_worklist (the main analysis loop), handling one node in the worklist. @@ -3174,10 +3273,13 @@ exploded_graph::process_node (exploded_node *node) break; case PK_AFTER_SUPERNODE: { + bool found_a_superedge = false; + bool is_an_exit_block = false; /* If this is an EXIT BB, detect leaks, and potentially create a function summary. */ if (point.get_supernode ()->return_p ()) { + is_an_exit_block = true; node->detect_leaks (*this); if (flag_analyzer_call_summaries && point.get_call_string ().empty_p ()) @@ -3205,6 +3307,7 @@ exploded_graph::process_node (exploded_node *node) superedge *succ; FOR_EACH_VEC_ELT (point.get_supernode ()->m_succs, i, succ) { + found_a_superedge = true; if (logger) logger->log ("considering SN: %i -> SN: %i", succ->m_src->m_index, succ->m_dest->m_index); @@ -3214,6 +3317,54 @@ exploded_graph::process_node (exploded_node *node) point.get_call_string ()); program_state next_state (state); uncertainty_t uncertainty; + + /* Make use the current state and try to discover and analyse + indirect function calls (a call that doesn't have an underlying + cgraph edge representing call). + + Some examples of such calls are virtual function calls + and calls that happen via a function pointer. */ + if (succ->m_kind == SUPEREDGE_INTRAPROCEDURAL_CALL + && !(succ->get_any_callgraph_edge ())) + { + const gcall *call + = point.get_supernode ()->get_final_call (); + + impl_region_model_context ctxt (*this, + node, + &state, + &next_state, + &uncertainty, + point.get_stmt()); + + region_model *model = state.m_region_model; + + if (tree fn_decl = model->get_fndecl_for_call(call,&ctxt)) + create_dynamic_call (call, + fn_decl, + node, + next_state, + next_point, + &uncertainty, + logger); + else + { + /* An unknown function was called at this point, in such + case, don't terminate the analysis of the current + function. + + The analyzer handles calls to unknown functions while + analysing the stmt itself, so the the function call + must have been handled by the anlyzer till now. */ + exploded_node *next + = get_or_create_node (next_point, + next_state, + node); + if (next) + add_edge (node, next, succ); + } + } + if (!node->on_edge (*this, succ, &next_point, &next_state, &uncertainty)) { @@ -3227,6 +3378,38 @@ exploded_graph::process_node (exploded_node *node) if (next) add_edge (node, next, succ); } + + /* Return from the calls which doesn't have a return superedge. + Such case occurs when GCC's middle end didn't knew which function to + call but analyzer did. */ + if((is_an_exit_block && !found_a_superedge) + && (!point.get_call_string ().empty_p ())) + { + const call_string cs = point.get_call_string (); + program_point next_point + = program_point::before_supernode (cs.get_caller_node (), + NULL, + cs); + program_state next_state (state); + uncertainty_t uncertainty; + + const gcall *call + = next_point.get_supernode ()->get_returning_call (); + + if(call) + next_state.returning_call (*this, node, call, &uncertainty); + + if (next_state.m_valid) + { + next_point.pop_from_call_stack (); + exploded_node *enode = get_or_create_node (next_point, + next_state, + node); + if (enode) + add_edge (node, enode, NULL, + new dynamic_call_info_t (call, true)); + } + } } break; } diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h index 8f48d8a..192a4b3 100644 --- a/gcc/analyzer/exploded-graph.h +++ b/gcc/analyzer/exploded-graph.h @@ -362,6 +362,37 @@ private: DISABLE_COPY_AND_ASSIGN (exploded_edge); }; +/* Extra data for an exploded_edge that represents dynamic call info ( calls + that doesn't have an underlying superedge representing the call ). */ + +class dynamic_call_info_t : public exploded_edge::custom_info_t +{ +public: + dynamic_call_info_t (const gcall *dynamic_call, + const bool is_returning_call = false) + : m_dynamic_call (dynamic_call), + m_is_returning_call (is_returning_call) + {} + + void print (pretty_printer *pp) FINAL OVERRIDE + { + if (m_is_returning_call) + pp_string (pp, "dynamic_return"); + else + pp_string (pp, "dynamic_call"); + } + + void update_model (region_model *model, + const exploded_edge &eedge) FINAL OVERRIDE; + + void add_events_to_path (checker_path *emission_path, + const exploded_edge &eedge) FINAL OVERRIDE; +private: + const gcall *m_dynamic_call; + const bool m_is_returning_call; +}; + + /* Extra data for an exploded_edge that represents a rewind from a longjmp to a setjmp (or from a siglongjmp to a sigsetjmp). */ @@ -785,6 +816,14 @@ public: bool maybe_process_run_of_before_supernode_enodes (exploded_node *node); void process_node (exploded_node *node); + void create_dynamic_call (const gcall *call, + tree fn_decl, + exploded_node *node, + program_state next_state, + program_point &next_point, + uncertainty_t *uncertainty, + logger *logger); + exploded_node *get_or_create_node (const program_point &point, const program_state &state, exploded_node *enode_for_diag); diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc index d9f50da..25d56af 100644 --- a/gcc/analyzer/program-point.cc +++ b/gcc/analyzer/program-point.cc @@ -330,6 +330,24 @@ program_point::to_json () const return point_obj; } +/* Update the callstack to represent a call from caller to callee. + + Generally used to push a custom call to a perticular program point + where we don't have a superedge representing the call. */ +void +program_point::push_to_call_stack (const supernode *caller, + const supernode *callee) +{ + m_call_string.push_call (callee, caller); +} + +/* Pop the topmost call from the current callstack. */ +void +program_point::pop_from_call_stack () +{ + m_call_string.pop (); +} + /* Generate a hash value for this program_point. */ hashval_t diff --git a/gcc/analyzer/program-point.h b/gcc/analyzer/program-point.h index 5f86745..6bae29b 100644 --- a/gcc/analyzer/program-point.h +++ b/gcc/analyzer/program-point.h @@ -293,7 +293,8 @@ public: } bool on_edge (exploded_graph &eg, const superedge *succ); - + void push_to_call_stack (const supernode *caller, const supernode *callee); + void pop_from_call_stack (); void validate () const; /* For before_stmt, go to next stmt. */ diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc index 5bb8676..ea53c61 100644 --- a/gcc/analyzer/program-state.cc +++ b/gcc/analyzer/program-state.cc @@ -1034,6 +1034,50 @@ program_state::on_edge (exploded_graph &eg, return true; } +/* Update this program_state to reflect a call to function + represented by CALL_STMT. + currently used only when the call doesn't have a superedge representing + the call ( like call via a function pointer ) */ +void +program_state::push_call (exploded_graph &eg, + exploded_node *enode, + const gcall *call_stmt, + uncertainty_t *uncertainty) +{ + /* Update state. */ + const program_point &point = enode->get_point (); + const gimple *last_stmt = point.get_supernode ()->get_last_stmt (); + + impl_region_model_context ctxt (eg, enode, + &enode->get_state (), + this, + uncertainty, + last_stmt); + m_region_model->update_for_gcall (call_stmt, &ctxt); +} + +/* Update this program_state to reflect a return from function + call to which is represented by CALL_STMT. + currently used only when the call doesn't have a superedge representing + the return */ +void +program_state::returning_call (exploded_graph &eg, + exploded_node *enode, + const gcall *call_stmt, + uncertainty_t *uncertainty) +{ + /* Update state. */ + const program_point &point = enode->get_point (); + const gimple *last_stmt = point.get_supernode ()->get_last_stmt (); + + impl_region_model_context ctxt (eg, enode, + &enode->get_state (), + this, + uncertainty, + last_stmt); + m_region_model->update_for_return_gcall (call_stmt, &ctxt); +} + /* Generate a simpler version of THIS, discarding state that's no longer relevant at POINT. The idea is that we're more likely to be able to consolidate diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h index 8dee930..eb49006 100644 --- a/gcc/analyzer/program-state.h +++ b/gcc/analyzer/program-state.h @@ -218,6 +218,17 @@ public: void push_frame (const extrinsic_state &ext_state, function *fun); function * get_current_function () const; + void push_call (exploded_graph &eg, + exploded_node *enode, + const gcall *call_stmt, + uncertainty_t *uncertainty); + + void returning_call (exploded_graph &eg, + exploded_node *enode, + const gcall *call_stmt, + uncertainty_t *uncertainty); + + bool on_edge (exploded_graph &eg, exploded_node *enode, const superedge *succ, diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 58da7e3..822e893 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -1841,6 +1841,11 @@ region_model::get_rvalue_1 (path_var pv, region_model_context *ctxt) const const region *ref_reg = get_lvalue (pv, ctxt); return get_store_value (ref_reg, ctxt); } + case OBJ_TYPE_REF: + { + tree expr = OBJ_TYPE_REF_EXPR (pv.m_tree); + return get_rvalue (expr, ctxt); + } } } @@ -3172,12 +3177,11 @@ region_model::maybe_update_for_edge (const superedge &edge, caller's frame. */ void -region_model::update_for_call_superedge (const call_superedge &call_edge, - region_model_context *ctxt) +region_model::update_for_gcall (const gcall *call_stmt, + region_model_context *ctxt) { /* Build a vec of argument svalues, using the current top frame for resolving tree expressions. */ - const gcall *call_stmt = call_edge.get_call_stmt (); auto_vec<const svalue *> arg_svals (gimple_call_num_args (call_stmt)); for (unsigned i = 0; i < gimple_call_num_args (call_stmt); i++) @@ -3186,33 +3190,58 @@ region_model::update_for_call_superedge (const call_superedge &call_edge, arg_svals.quick_push (get_rvalue (arg, ctxt)); } - push_frame (call_edge.get_callee_function (), &arg_svals, ctxt); + /* Get the function * from the call. */ + tree fn_decl = get_fndecl_for_call (call_stmt,ctxt); + function *fun = DECL_STRUCT_FUNCTION (fn_decl); + push_frame (fun, &arg_svals, ctxt); } /* Pop the top-most frame_region from the stack, and copy the return region's values (if any) into the region for the lvalue of the LHS of the call (if any). */ + void -region_model::update_for_return_superedge (const return_superedge &return_edge, - region_model_context *ctxt) +region_model::update_for_return_gcall (const gcall *call_stmt, + region_model_context *ctxt) { /* Get the region for the result of the call, within the caller frame. */ const region *result_dst_reg = NULL; - const gcall *call_stmt = return_edge.get_call_stmt (); tree lhs = gimple_call_lhs (call_stmt); if (lhs) { /* Normally we access the top-level frame, which is: - path_var (expr, get_stack_depth () - 1) - whereas here we need the caller frame, hence "- 2" here. */ + path_var (expr, get_stack_depth () - 1) + whereas here we need the caller frame, hence "- 2" here. */ gcc_assert (get_stack_depth () >= 2); result_dst_reg = get_lvalue (path_var (lhs, get_stack_depth () - 2), - ctxt); + ctxt); } pop_frame (result_dst_reg, NULL, ctxt); } +/* Extract calling information from the superedge and update the model for the + call */ + +void +region_model::update_for_call_superedge (const call_superedge &call_edge, + region_model_context *ctxt) +{ + const gcall *call_stmt = call_edge.get_call_stmt (); + update_for_gcall (call_stmt,ctxt); +} + +/* Extract calling information from the return superedge and update the model + for the returning call */ + +void +region_model::update_for_return_superedge (const return_superedge &return_edge, + region_model_context *ctxt) +{ + const gcall *call_stmt = return_edge.get_call_stmt (); + update_for_return_gcall (call_stmt, ctxt); +} + /* Update this region_model with a summary of the effect of calling and returning from CG_SEDGE. diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index 30f02a0..e40264e 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -608,6 +608,12 @@ class region_model region_model_context *ctxt, rejected_constraint **out); + void update_for_gcall (const gcall *call_stmt, + region_model_context *ctxt); + + void update_for_return_gcall (const gcall *call_stmt, + region_model_context *ctxt); + const region *push_frame (function *fun, const vec<const svalue *> *arg_sids, region_model_context *ctxt); const frame_region *get_current_frame () const { return m_current_frame; } diff --git a/gcc/analyzer/state-purge.cc b/gcc/analyzer/state-purge.cc index bfa48a9..8800570 100644 --- a/gcc/analyzer/state-purge.cc +++ b/gcc/analyzer/state-purge.cc @@ -383,18 +383,31 @@ state_purge_per_ssa_name::process_point (const function_point &point, { /* Add any intraprocedually edge for a call. */ if (snode->m_returning_call) - { - cgraph_edge *cedge + { + gcall *returning_call = snode->m_returning_call; + cgraph_edge *cedge = supergraph_call_edge (snode->m_fun, - snode->m_returning_call); - gcc_assert (cedge); - superedge *sedge - = map.get_sg ().get_intraprocedural_edge_for_call (cedge); - gcc_assert (sedge); - add_to_worklist - (function_point::after_supernode (sedge->m_src), - worklist, logger); - } + returning_call); + if(cedge) + { + superedge *sedge + = map.get_sg ().get_intraprocedural_edge_for_call (cedge); + gcc_assert (sedge); + add_to_worklist + (function_point::after_supernode (sedge->m_src), + worklist, logger); + } + else + { + supernode *callernode + = map.get_sg ().get_supernode_for_stmt (returning_call); + + gcc_assert (callernode); + add_to_worklist + (function_point::after_supernode (callernode), + worklist, logger); + } + } } } break; diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc index 1eb2543..66ef765 100644 --- a/gcc/analyzer/supergraph.cc +++ b/gcc/analyzer/supergraph.cc @@ -183,11 +183,33 @@ supergraph::supergraph (logger *logger) m_stmt_to_node_t.put (stmt, node_for_stmts); m_stmt_uids.make_uid_unique (stmt); if (cgraph_edge *edge = supergraph_call_edge (fun, stmt)) - { - m_cgraph_edge_to_caller_prev_node.put(edge, node_for_stmts); - node_for_stmts = add_node (fun, bb, as_a <gcall *> (stmt), NULL); - m_cgraph_edge_to_caller_next_node.put (edge, node_for_stmts); - } + { + m_cgraph_edge_to_caller_prev_node.put(edge, node_for_stmts); + node_for_stmts = add_node (fun, bb, as_a <gcall *> (stmt), + NULL); + m_cgraph_edge_to_caller_next_node.put (edge, node_for_stmts); + } + else + { + // maybe call is via a function pointer + if (gcall *call = dyn_cast<gcall *> (stmt)) + { + cgraph_edge *edge + = cgraph_node::get (fun->decl)->get_edge (stmt); + if (!edge || !edge->callee) + { + supernode *old_node_for_stmts = node_for_stmts; + node_for_stmts = add_node (fun, bb, call, NULL); + + superedge *sedge + = new callgraph_superedge (old_node_for_stmts, + node_for_stmts, + SUPEREDGE_INTRAPROCEDURAL_CALL, + NULL); + add_edge (sedge); + } + } + } } m_bb_to_final_node.put (bb, node_for_stmts); @@ -1139,6 +1161,17 @@ callgraph_superedge::get_callee_decl () const return get_callee_function ()->decl; } +/* Get the gcall * of this interprocedural call/return edge. */ + +gcall * +callgraph_superedge::get_call_stmt () const +{ + if (m_cedge) + return m_cedge->call_stmt; + + return m_src->get_final_call (); +} + /* Get the calling fndecl at this interprocedural call/return edge. */ tree diff --git a/gcc/analyzer/supergraph.h b/gcc/analyzer/supergraph.h index 877958f..335f513 100644 --- a/gcc/analyzer/supergraph.h +++ b/gcc/analyzer/supergraph.h @@ -268,6 +268,11 @@ class supernode : public dnode<supergraph_traits> return i; } + gcall *get_returning_call () const + { + return m_returning_call; + } + gimple *get_last_stmt () const { if (m_stmts.length () == 0) @@ -400,7 +405,7 @@ class callgraph_superedge : public superedge function *get_caller_function () const; tree get_callee_decl () const; tree get_caller_decl () const; - gcall *get_call_stmt () const { return m_cedge->call_stmt; } + gcall *get_call_stmt () const; tree get_arg_for_parm (tree parm, callsite_expr *out) const; tree get_parm_for_arg (tree arg, callsite_expr *out) const; tree map_expr_from_caller_to_callee (tree caller_expr, diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 5595994..ab566ba 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2021-08-18 Jakub Jelinek <jakub@redhat.com> + + * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_NOTHING. + * c-pragma.c (omp_pragmas): Add nothing directive. + * c-omp.c (omp_directives): Uncomment nothing directive entry. + 2021-08-17 Jakub Jelinek <jakub@redhat.com> PR c++/101539 diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index caeac5b..53abd1a 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,32 @@ +2021-08-18 Jakub Jelinek <jakub@redhat.com> + + * c-parser.c (c_parser_omp_nothing): New function. + (c_parser_pragma): Handle PRAGMA_OMP_NOTHING. + +2021-08-18 Jakub Jelinek <jakub@redhat.com> + + * c-parser.c (c_parser_statement_after_labels): Add restart label + near the start of the function. If c_parser_pragma returns false, + goto restart. + (c_parser_pragma): For PRAGMA_OMP_CANCELLATION_POINT return what + c_parser_omp_cancellation_point returned. For PRAGMA_OMP_DECLARE + return what c_parser_omp_declare returned. Return true instead of + false after emitting errors that the directive is not allowed in + pragma_stmt context. + (c_parser_omp_ordered): Return true instead of + false after emitting errors that the directive is not allowed in + pragma_stmt context. + (c_parser_omp_target_update): Likewise. + (c_parser_omp_target_enter_data, c_parser_omp_target_exit_data): + Change return type from tree to bool, return false if the + directive should be ignored in pragma_stmt contexts. + (c_parser_omp_target): Adjust callers of c_parser_omp_target_*_data, + return their result directly. + (c_parser_omp_cancellation_point): Change return type from void to + bool, return false if the directive should be ignored in pragma_stmt + contexts. + (c_parser_omp_declare): Likewise. + 2021-08-17 Jakub Jelinek <jakub@redhat.com> * c-parser.c (OMP_SCOPE_CLAUSE_MASK): Define. diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index d5f51b1..407f279 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -21710,9 +21710,18 @@ c_parser_omp_requires (c_parser *parser) error_at (c_parser_peek_token (parser)->location, "expected %<seq_cst%>, %<relaxed%> or " "%<acq_rel%>"); - if (c_parser_peek_2nd_token (parser)->type - == CPP_CLOSE_PAREN) - c_parser_consume_token (parser); + switch (c_parser_peek_token (parser)->type) + { + case CPP_EOF: + case CPP_PRAGMA_EOL: + case CPP_CLOSE_PAREN: + break; + default: + if (c_parser_peek_2nd_token (parser)->type + == CPP_CLOSE_PAREN) + c_parser_consume_token (parser); + break; + } } else c_parser_consume_token (parser); diff --git a/gcc/config.gcc b/gcc/config.gcc index d9bfbfd..eb232df 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -700,7 +700,7 @@ case ${target} in tm_file="${tm_file} ${cpu_type}/darwin.h" tm_p_file="${tm_p_file} darwin-protos.h" target_gtfiles="$target_gtfiles \$(srcdir)/config/darwin.c" - extra_options="${extra_options} darwin.opt" + extra_options="${extra_options} rpath.opt darwin.opt" c_target_objs="${c_target_objs} darwin-c.o" cxx_target_objs="${cxx_target_objs} darwin-c.o" d_target_objs="${d_target_objs} darwin-d.o" diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h index d8b2970..635a223 100644 --- a/gcc/config/aarch64/arm_neon.h +++ b/gcc/config/aarch64/arm_neon.h @@ -20546,8 +20546,8 @@ vld3_lane_f64 (const float64_t * __ptr, float64x1x3_t __b, const int __c) __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) __temp.val[0], 0); __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) __temp.val[1], 1); __o = __builtin_aarch64_set_qregciv2df (__o, (float64x2_t) __temp.val[2], 2); - __o = __builtin_aarch64_ld3_lanedi ( - (__builtin_aarch64_simd_di *) __ptr, __o, __c); + __o = __builtin_aarch64_ld3_lanedf ( + (__builtin_aarch64_simd_df *) __ptr, __o, __c); __b.val[0] = (float64x1_t) __builtin_aarch64_get_dregcidi (__o, 0); __b.val[1] = (float64x1_t) __builtin_aarch64_get_dregcidi (__o, 1); __b.val[2] = (float64x1_t) __builtin_aarch64_get_dregcidi (__o, 2); @@ -21077,7 +21077,7 @@ vld4_lane_f32 (const float32_t * __ptr, float32x2x4_t __b, const int __c) __o = __builtin_aarch64_set_qregxiv4sf (__o, (float32x4_t) __temp.val[1], 1); __o = __builtin_aarch64_set_qregxiv4sf (__o, (float32x4_t) __temp.val[2], 2); __o = __builtin_aarch64_set_qregxiv4sf (__o, (float32x4_t) __temp.val[3], 3); - __o = __builtin_aarch64_ld4_lanev2si ( + __o = __builtin_aarch64_ld4_lanev2sf ( (__builtin_aarch64_simd_sf *) __ptr, __o, __c); __b.val[0] = (float32x2_t) __builtin_aarch64_get_dregxidi (__o, 0); __b.val[1] = (float32x2_t) __builtin_aarch64_get_dregxidi (__o, 1); @@ -21381,7 +21381,7 @@ vld4q_lane_f64 (const float64_t * __ptr, float64x2x4_t __b, const int __c) __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) __b.val[2], 2); __o = __builtin_aarch64_set_qregxiv4si (__o, (int32x4_t) __b.val[3], 3); __o = __builtin_aarch64_ld4_lanev2df ( - (__builtin_aarch64_simd_di *) __ptr, __o, __c); + (__builtin_aarch64_simd_df *) __ptr, __o, __c); ret.val[0] = (float64x2_t) __builtin_aarch64_get_qregxiv4si (__o, 0); ret.val[1] = (float64x2_t) __builtin_aarch64_get_qregxiv4si (__o, 1); ret.val[2] = (float64x2_t) __builtin_aarch64_get_qregxiv4si (__o, 2); diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index 20d6b1e..b1be561 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -132,6 +132,7 @@ extern GTY(()) int darwin_ms_struct; "%{gsplit-dwarf:%ngsplit-dwarf is not supported on this platform} \ %<gsplit-dwarf", \ "%{gused:-g -feliminate-unused-debug-symbols} %<gused", \ +"%{rpath*: -Xlinker -rpath -Xlinker %*}", \ "%{shared:-Zdynamiclib} %<shared", \ "%{static:%{Zdynamic:%e conflicting code gen style switches are used}}",\ "%{y*:%nthe y option is obsolete and ignored} %<y*", \ @@ -238,7 +239,7 @@ extern GTY(()) int darwin_ms_struct; DARWIN_NOPIE_SPEC \ DARWIN_RDYNAMIC \ DARWIN_NOCOMPACT_UNWIND \ - "}}}}}}} %<pie %<no-pie %<rdynamic %<X " + "}}}}}}} %<pie %<no-pie %<rdynamic %<X %<rpath " /* Spec that controls whether the debug linker is run automatically for a link step. This needs to be done if there is a source file on the diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 4d4ab6a..46844fa 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -22203,11 +22203,7 @@ ix86_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost, case vec_construct: { /* N element inserts into SSE vectors. */ - int cost - = TYPE_VECTOR_SUBPARTS (vectype) * (fp ? - ix86_cost->sse_op - : ix86_cost->integer_to_sse); - + int cost = TYPE_VECTOR_SUBPARTS (vectype) * ix86_cost->sse_op; /* One vinserti128 for combining two SSE vectors for AVX256. */ if (GET_MODE_BITSIZE (mode) == 256) cost += ix86_vec_cost (mode, ix86_cost->addss); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index b3e57a8..8aba86d 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -165,7 +165,6 @@ struct processor_costs { const int xmm_move, ymm_move, /* cost of moving XMM and YMM register. */ zmm_move; const int sse_to_integer; /* cost of moving SSE register to integer. */ - const int integer_to_sse; /* cost of moving integer to SSE register. */ const int gather_static, gather_per_elt; /* Cost of gather load is computed as static + per_item * nelts. */ const int scatter_static, scatter_per_elt; /* Cost of gather store is diff --git a/gcc/config/i386/x86-tune-costs.h b/gcc/config/i386/x86-tune-costs.h index 67cfa00..ffe810f 100644 --- a/gcc/config/i386/x86-tune-costs.h +++ b/gcc/config/i386/x86-tune-costs.h @@ -102,7 +102,6 @@ struct processor_costs ix86_size_cost = {/* costs for tuning for size */ in 128bit, 256bit and 512bit */ 3, 3, 3, /* cost of moving XMM,YMM,ZMM register */ 3, /* cost of moving SSE register to integer. */ - COSTS_N_BYTES (2), /* cost of moving integer to sse register. */ 5, 0, /* Gather load static, per_elt. */ 5, 0, /* Gather store static, per_elt. */ 0, /* size of l1 cache */ @@ -212,7 +211,6 @@ struct processor_costs i386_cost = { /* 386 specific costs */ {4, 8, 16, 32, 64}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 3, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 4, 4, /* Gather load static, per_elt. */ 4, 4, /* Gather store static, per_elt. */ 0, /* size of l1 cache */ @@ -321,7 +319,6 @@ struct processor_costs i486_cost = { /* 486 specific costs */ {4, 8, 16, 32, 64}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 3, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 4, 4, /* Gather load static, per_elt. */ 4, 4, /* Gather store static, per_elt. */ 4, /* size of l1 cache. 486 has 8kB cache @@ -432,7 +429,6 @@ struct processor_costs pentium_cost = { {4, 8, 16, 32, 64}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 3, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 4, 4, /* Gather load static, per_elt. */ 4, 4, /* Gather store static, per_elt. */ 8, /* size of l1 cache. */ @@ -534,7 +530,6 @@ struct processor_costs lakemont_cost = { {4, 8, 16, 32, 64}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 3, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 4, 4, /* Gather load static, per_elt. */ 4, 4, /* Gather store static, per_elt. */ 8, /* size of l1 cache. */ @@ -651,7 +646,6 @@ struct processor_costs pentiumpro_cost = { {4, 8, 16, 32, 64}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 3, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 4, 4, /* Gather load static, per_elt. */ 4, 4, /* Gather store static, per_elt. */ 8, /* size of l1 cache. */ @@ -759,7 +753,6 @@ struct processor_costs geode_cost = { {2, 2, 8, 16, 32}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 6, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 2, 2, /* Gather load static, per_elt. */ 2, 2, /* Gather store static, per_elt. */ 64, /* size of l1 cache. */ @@ -867,7 +860,6 @@ struct processor_costs k6_cost = { {2, 2, 8, 16, 32}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 6, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 2, 2, /* Gather load static, per_elt. */ 2, 2, /* Gather store static, per_elt. */ 32, /* size of l1 cache. */ @@ -981,7 +973,6 @@ struct processor_costs athlon_cost = { {4, 4, 10, 10, 20}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 5, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (2), /* cost of moving integer to sse register. */ 4, 4, /* Gather load static, per_elt. */ 4, 4, /* Gather store static, per_elt. */ 64, /* size of l1 cache. */ @@ -1097,7 +1088,6 @@ struct processor_costs k8_cost = { {4, 4, 10, 10, 20}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 5, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (2), /* cost of moving integer to sse register. */ 4, 4, /* Gather load static, per_elt. */ 4, 4, /* Gather store static, per_elt. */ 64, /* size of l1 cache. */ @@ -1226,7 +1216,6 @@ struct processor_costs amdfam10_cost = { {4, 4, 5, 10, 20}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 3, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (2), /* cost of moving integer to sse register. */ 4, 4, /* Gather load static, per_elt. */ 4, 4, /* Gather store static, per_elt. */ 64, /* size of l1 cache. */ @@ -1347,7 +1336,6 @@ const struct processor_costs bdver_cost = { {10, 10, 10, 40, 60}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 16, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (2), /* cost of moving integer to sse register. */ 12, 12, /* Gather load static, per_elt. */ 10, 10, /* Gather store static, per_elt. */ 16, /* size of l1 cache. */ @@ -1489,7 +1477,6 @@ struct processor_costs znver1_cost = { {8, 8, 8, 16, 32}, /* cost of unaligned stores. */ 2, 3, 6, /* cost of moving XMM,YMM,ZMM register. */ 6, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ /* VGATHERDPD is 23 uops and throughput is 9, VGATHERDPD is 35 uops, throughput 12. Approx 9 uops do not depend on vector size and every load is 7 uops. */ @@ -1646,7 +1633,6 @@ struct processor_costs znver2_cost = { 2, 2, 3, /* cost of moving XMM,YMM,ZMM register. */ 6, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ /* VGATHERDPD is 23 uops and throughput is 9, VGATHERDPD is 35 uops, throughput 12. Approx 9 uops do not depend on vector size and every load is 7 uops. */ @@ -1779,7 +1765,6 @@ struct processor_costs znver3_cost = { 2, 2, 3, /* cost of moving XMM,YMM,ZMM register. */ 6, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ /* VGATHERDPD is 15 uops and throughput is 4, VGATHERDPS is 23 uops, throughput 9. Approx 7 uops do not depend on vector size and every load is 4 uops. */ @@ -1924,7 +1909,6 @@ struct processor_costs skylake_cost = { {8, 8, 8, 8, 16}, /* cost of unaligned stores. */ 2, 2, 4, /* cost of moving XMM,YMM,ZMM register */ 6, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (2)+1, /* cost of moving integer to sse register. */ 20, 8, /* Gather load static, per_elt. */ 22, 10, /* Gather store static, per_elt. */ 64, /* size of l1 cache. */ @@ -2051,7 +2035,6 @@ struct processor_costs icelake_cost = { {8, 8, 8, 8, 16}, /* cost of unaligned stores. */ 2, 2, 4, /* cost of moving XMM,YMM,ZMM register */ 6, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 20, 8, /* Gather load static, per_elt. */ 22, 10, /* Gather store static, per_elt. */ 64, /* size of l1 cache. */ @@ -2165,7 +2148,6 @@ const struct processor_costs btver1_cost = { {10, 10, 12, 48, 96}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 14, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 10, 10, /* Gather load static, per_elt. */ 10, 10, /* Gather store static, per_elt. */ 32, /* size of l1 cache. */ @@ -2276,7 +2258,6 @@ const struct processor_costs btver2_cost = { {10, 10, 12, 48, 96}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 14, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 10, 10, /* Gather load static, per_elt. */ 10, 10, /* Gather store static, per_elt. */ 32, /* size of l1 cache. */ @@ -2386,7 +2367,6 @@ struct processor_costs pentium4_cost = { {32, 32, 32, 64, 128}, /* cost of unaligned stores. */ 12, 24, 48, /* cost of moving XMM,YMM,ZMM register */ 20, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (2), /* cost of moving integer to sse register. */ 16, 16, /* Gather load static, per_elt. */ 16, 16, /* Gather store static, per_elt. */ 8, /* size of l1 cache. */ @@ -2499,7 +2479,6 @@ struct processor_costs nocona_cost = { {24, 24, 24, 48, 96}, /* cost of unaligned stores. */ 6, 12, 24, /* cost of moving XMM,YMM,ZMM register */ 20, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (2), /* cost of moving integer to sse register. */ 12, 12, /* Gather load static, per_elt. */ 12, 12, /* Gather store static, per_elt. */ 8, /* size of l1 cache. */ @@ -2610,7 +2589,6 @@ struct processor_costs atom_cost = { {16, 16, 16, 32, 64}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 8, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 8, 8, /* Gather load static, per_elt. */ 8, 8, /* Gather store static, per_elt. */ 32, /* size of l1 cache. */ @@ -2721,7 +2699,6 @@ struct processor_costs slm_cost = { {16, 16, 16, 32, 64}, /* cost of unaligned stores. */ 2, 4, 8, /* cost of moving XMM,YMM,ZMM register */ 8, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 8, 8, /* Gather load static, per_elt. */ 8, 8, /* Gather store static, per_elt. */ 32, /* size of l1 cache. */ @@ -2832,7 +2809,6 @@ struct processor_costs intel_cost = { {10, 10, 10, 10, 10}, /* cost of unaligned loads. */ 2, 2, 2, /* cost of moving XMM,YMM,ZMM register */ 4, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 6, 6, /* Gather load static, per_elt. */ 6, 6, /* Gather store static, per_elt. */ 32, /* size of l1 cache. */ @@ -2950,7 +2926,6 @@ struct processor_costs generic_cost = { {6, 6, 6, 10, 15}, /* cost of unaligned storess. */ 2, 3, 4, /* cost of moving XMM,YMM,ZMM register */ 6, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ 18, 6, /* Gather load static, per_elt. */ 18, 6, /* Gather store static, per_elt. */ 32, /* size of l1 cache. */ @@ -3074,7 +3049,6 @@ struct processor_costs core_cost = { {6, 6, 6, 6, 12}, /* cost of unaligned stores. */ 2, 2, 4, /* cost of moving XMM,YMM,ZMM register */ 2, /* cost of moving SSE register to integer. */ - COSTS_N_INSNS (1), /* cost of moving integer to sse register. */ /* VGATHERDPD is 7 uops, rec throughput 5, while VGATHERDPD is 9 uops, rec. throughput 6. So 5 uops statically and one uops per load. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a2d47b3..a06a496 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,42 @@ +2021-08-18 Patrick Palka <ppalka@redhat.com> + + PR c++/101344 + PR c++/101820 + * cp-tree.h (CONSTRUCTOR_BRACES_ELIDED_P): Define. + * decl.c (reshape_init_r): Set it. + * pt.c (collect_ctor_idx_types): Recurse into a sub-CONSTRUCTOR + iff CONSTRUCTOR_BRACES_ELIDED_P. + +2021-08-18 Patrick Palka <ppalka@redhat.com> + + PR c++/101883 + * pt.c (convert_template_argument): Pass LOOKUP_IMPLICIT to + do_auto_deduction. + +2021-08-18 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_omp_nothing): New function. + (cp_parser_pragma): Handle PRAGMA_OMP_NOTHING. + +2021-08-18 Jakub Jelinek <jakub@redhat.com> + + * parser.c (cp_parser_omp_ordered): Return true instead of + false after emitting errors that the directive is not allowed in + pragma_stmt context. + (cp_parser_omp_target_update): Likewise. + (cp_parser_omp_cancellation_point): Change return type from void to + bool, return false if the directive should be ignored in pragma_stmt + contexts. + (cp_parser_omp_target_enter_data, cp_parser_omp_target_exit_data): + Change return type from tree to bool, return false if the + directive should be ignored in pragma_stmt contexts. + (cp_parser_omp_target): Adjust callers of cp_parser_omp_target_*_data, + return their result directly. + (cp_parser_pragma): For PRAGMA_OMP_CANCELLATION_POINT return what + cp_parser_omp_cancellation_point returned. Return true instead of + false after emitting errors that the directive is not allowed in + pragma_stmt context. + 2021-08-17 Jakub Jelinek <jakub@redhat.com> PR c++/101539 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 04116fb..0af1a2c 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -45479,9 +45479,18 @@ cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok) error_at (cp_lexer_peek_token (parser->lexer)->location, "expected %<seq_cst%>, %<relaxed%> or " "%<acq_rel%>"); - if (cp_lexer_nth_token_is (parser->lexer, 2, - CPP_CLOSE_PAREN)) - cp_lexer_consume_token (parser->lexer); + switch (cp_lexer_peek_token (parser->lexer)->type) + { + case CPP_EOF: + case CPP_PRAGMA_EOL: + case CPP_CLOSE_PAREN: + break; + default: + if (cp_lexer_nth_token_is (parser->lexer, 2, + CPP_CLOSE_PAREN)) + cp_lexer_consume_token (parser->lexer); + break; + } } else cp_lexer_consume_token (parser->lexer); @@ -45570,7 +45579,7 @@ cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok) static void cp_parser_omp_nothing (cp_parser *parser, cp_token *pragma_tok) { - cp_parser_skip_to_pragma_eol (parser, pragma_tok); + cp_parser_require_pragma_eol (parser, pragma_tok); } diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 86a2bda..90a3e53 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2021-08-18 Tobias Burnus <tobias@codesourcery.com> + + * match.h (gfc_match_omp_nothing): New. + * openmp.c (gfc_match_omp_nothing): New. + * parse.c (decode_omp_directive): Match 'nothing' directive. + 2021-08-17 Tobias Burnus <tobias@codesourcery.com> * dump-parse-tree.c (show_omp_node, show_code_node): Handle diff --git a/gcc/hash-map-tests.c b/gcc/hash-map-tests.c index 257f2be..6acc0d4 100644 --- a/gcc/hash-map-tests.c +++ b/gcc/hash-map-tests.c @@ -328,11 +328,22 @@ test_map_of_type_with_ctor_and_dtor_expand (bool remove_some_inline) size_t expand_c_expected = 4; size_t expand_c = 0; - void *a[N_elem]; + /* For stability of this testing, we need all Key values 'k' to produce + unique hash values 'Traits::hash (k)', as otherwise the dynamic + insert/remove behavior may diverge across different architectures. This + is, for example, a problem when using the standard 'pointer_hash::hash', + which is simply doing a 'k >> 3' operation, which is fine on 64-bit + architectures, but on 32-bit architectures produces the same hash value + for subsequent 'a[i] = &a[i]' array elements. Therefore, use an + 'int_hash'. */ + + int a[N_elem]; for (size_t i = 0; i < N_elem; ++i) - a[i] = &a[i]; + a[i] = i; - typedef hash_map <void *, val_t> Map; + const int EMPTY = -1; + const int DELETED = -2; + typedef hash_map<int_hash<int, EMPTY, DELETED>, val_t> Map; /* Note that we are starting with a fresh 'Map'. Even if an existing one has been cleared out completely, there remain 'deleted' elements, and these diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index 2a2675a..7557e17 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -1,3 +1,8 @@ +2021-08-18 Iain Sandoe <iain@sandoe.co.uk> + + PR jit/100613 + * Make-lang.in: Provide clauses for Darwin hosts. + 2021-07-18 Antoni Boucher <bouanto@zoho.com> PR target/95498 diff --git a/gcc/jit/Make-lang.in b/gcc/jit/Make-lang.in index 663772a..2a774d7 100644 --- a/gcc/jit/Make-lang.in +++ b/gcc/jit/Make-lang.in @@ -53,8 +53,40 @@ jit: $(LIBGCCJIT_FILENAME) \ else -LIBGCCJIT_LINKER_NAME = libgccjit.so +ifneq (,$(findstring darwin,$(host))) + +LIBGCCJIT_AGE = 1 +LIBGCCJIT_BASENAME = libgccjit + +LIBGCCJIT_SONAME = \ + ${libdir}/$(LIBGCCJIT_BASENAME).$(LIBGCCJIT_VERSION_NUM).dylib +LIBGCCJIT_FILENAME = $(LIBGCCJIT_BASENAME).$(LIBGCCJIT_VERSION_NUM).dylib +LIBGCCJIT_LINKER_NAME = $(LIBGCCJIT_BASENAME).dylib + +# Conditionalize the use of the LD_VERSION_SCRIPT_OPTION and +# LD_SONAME_OPTION depending if configure found them, using $(if) +# We have to define a COMMA here, otherwise the commas in the "true" +# result are treated as separators by the $(if). +COMMA := , +LIBGCCJIT_VERSION_SCRIPT_OPTION = \ + $(if $(LD_VERSION_SCRIPT_OPTION),\ + -Wl$(COMMA)$(LD_VERSION_SCRIPT_OPTION)$(COMMA)$(srcdir)/jit/libgccjit.map) + +LIBGCCJIT_SONAME_OPTION = \ + $(if $(LD_SONAME_OPTION), \ + -Wl$(COMMA)$(LD_SONAME_OPTION)$(COMMA)$(LIBGCCJIT_SONAME)) + +LIBGCCJIT_SONAME_SYMLINK = $(LIBGCCJIT_FILENAME) +LIBGCCJIT_LINKER_NAME_SYMLINK = $(LIBGCCJIT_LINKER_NAME) + +jit: $(LIBGCCJIT_FILENAME) \ + $(LIBGCCJIT_SYMLINK) \ + $(LIBGCCJIT_LINKER_NAME_SYMLINK) \ + $(FULL_DRIVER_NAME) +else + +LIBGCCJIT_LINKER_NAME = libgccjit.so LIBGCCJIT_SONAME = $(LIBGCCJIT_LINKER_NAME).$(LIBGCCJIT_VERSION_NUM) LIBGCCJIT_FILENAME = \ $(LIBGCCJIT_SONAME).$(LIBGCCJIT_MINOR_NUM).$(LIBGCCJIT_RELEASE_NUM) @@ -79,6 +111,8 @@ jit: $(LIBGCCJIT_FILENAME) \ $(LIBGCCJIT_SYMLINK) \ $(LIBGCCJIT_LINKER_NAME_SYMLINK) \ $(FULL_DRIVER_NAME) + +endif endif jit.serial = $(LIBGCCJIT_FILENAME) @@ -109,9 +143,19 @@ ifneq (,$(findstring mingw,$(target))) # Create import library LIBGCCJIT_EXTRA_OPTS = -Wl,--out-implib,$(LIBGCCJIT_IMPORT_LIB) else + +ifneq (,$(findstring darwin,$(host))) +# TODO : Construct a Darwin-style symbol export file. +LIBGCCJIT_EXTRA_OPTS = -Wl,-compatibility_version,$(LIBGCCJIT_VERSION_NUM) \ + -Wl,-current_version,$(LIBGCCJIT_VERSION_NUM).$(LIBGCCJIT_MINOR_NUM).$(LIBGCCJIT_AGE) \ + $(LIBGCCJIT_VERSION_SCRIPT_OPTION) \ + $(LIBGCCJIT_SONAME_OPTION) +else + LIBGCCJIT_EXTRA_OPTS = $(LIBGCCJIT_VERSION_SCRIPT_OPTION) \ $(LIBGCCJIT_SONAME_OPTION) endif +endif # We avoid using $(BACKEND) from Makefile.in in order to avoid pulling # in main.o @@ -130,8 +174,12 @@ $(LIBGCCJIT_FILENAME): $(jit_OBJS) \ # Create symlinks when not building for Windows ifeq (,$(findstring mingw,$(target))) + +ifeq (,$(findstring darwin,$(host))) +# but only one level for Darwin, version info is embedded. $(LIBGCCJIT_SONAME_SYMLINK): $(LIBGCCJIT_FILENAME) ln -sf $(LIBGCCJIT_FILENAME) $(LIBGCCJIT_SONAME_SYMLINK) +endif $(LIBGCCJIT_LINKER_NAME_SYMLINK): $(LIBGCCJIT_SONAME_SYMLINK) ln -sf $(LIBGCCJIT_SONAME_SYMLINK) $(LIBGCCJIT_LINKER_NAME_SYMLINK) @@ -319,6 +367,18 @@ jit.install-common: installdirs jit.install-headers # Install DLL file $(INSTALL_PROGRAM) $(LIBGCCJIT_FILENAME) \ $(DESTDIR)$(bindir)/$(LIBGCCJIT_FILENAME) + +else +ifneq (,$(findstring darwin,$(host))) +# but only one level for Darwin + +jit.install-common: installdirs jit.install-headers + $(INSTALL_PROGRAM) $(LIBGCCJIT_FILENAME) \ + $(DESTDIR)$(libdir)/$(LIBGCCJIT_FILENAME) + ln -sf \ + $(LIBGCCJIT_SONAME_SYMLINK)\ + $(DESTDIR)$(libdir)/$(LIBGCCJIT_LINKER_NAME_SYMLINK) + else jit.install-common: installdirs jit.install-headers $(INSTALL_PROGRAM) $(LIBGCCJIT_FILENAME) \ @@ -330,6 +390,7 @@ jit.install-common: installdirs jit.install-headers $(LIBGCCJIT_SONAME_SYMLINK)\ $(DESTDIR)$(libdir)/$(LIBGCCJIT_LINKER_NAME_SYMLINK) endif +endif jit.install-man: diff --git a/gcc/jit/docs/examples/tut04-toyvm/toyvm.c b/gcc/jit/docs/examples/tut04-toyvm/toyvm.c index e742f34..8ea716e 100644 --- a/gcc/jit/docs/examples/tut04-toyvm/toyvm.c +++ b/gcc/jit/docs/examples/tut04-toyvm/toyvm.c @@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. If not see #include <stdlib.h> #include <string.h> -#include <dejagnu.h> +#include "jit-dejagnu.h" #include <libgccjit.h> diff --git a/gcc/jit/docs/examples/tut04-toyvm/toyvm.cc b/gcc/jit/docs/examples/tut04-toyvm/toyvm.cc index 4b9c765..7e95501 100644 --- a/gcc/jit/docs/examples/tut04-toyvm/toyvm.cc +++ b/gcc/jit/docs/examples/tut04-toyvm/toyvm.cc @@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. If not see #include <stdlib.h> #include <string.h> -#include <dejagnu.h> +#include "jit-dejagnu.h" #include <libgccjit++.h> diff --git a/gcc/jit/jit-dejagnu.h b/gcc/jit/jit-dejagnu.h new file mode 100644 index 0000000..eb53cc9 --- /dev/null +++ b/gcc/jit/jit-dejagnu.h @@ -0,0 +1,338 @@ +/* DejaGnu unit testing header. + Copyright (C) 2000-2016 Free Software Foundation, Inc. + +This file is part of DejaGnu. + +DejaGnu is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +DejaGnu is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with DejaGnu; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Imported from 1.6.2 with modifications + * to avoid and unused symbol in C compilations + * avoid wait () clashing with system-provided routines + * provide a deterministic last line of output after the totals. */ + +#ifndef __DEJAGNU_H__ +#define __DEJAGNU_H__ + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +/* If you have problems with DejaGnu dropping failed, untested, or + * unresolved messages generated by a unit testcase, then: */ + +/* #define _DEJAGNU_WAIT_ */ + +#ifdef _DEJAGNU_WAIT_ +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#endif + +static int passed; +static int failed; +static int untest; +static int unresolve; +static int xfailed; +#ifdef __cplusplus +static int xpassed; +#endif + +static char buffer[512]; + +#ifdef _DEJAGNU_WAIT_ +void +dg_wait (void) +{ + fd_set rfds; + struct timeval tv; + + FD_ZERO (&rfds); + tv.tv_sec = 0; + tv.tv_usec = 1; + + select (0, &rfds, NULL, NULL, &tv); +} +#endif + +static inline void +pass (const char* fmt, ...) +{ + va_list ap; + + passed++; + va_start (ap, fmt); + vsnprintf (buffer, sizeof (buffer), fmt, ap); + va_end (ap); + printf ("\tPASSED: %s\n", buffer); +#ifdef _DEJAGNU_WAIT_ + dg_wait (); +#endif +} + +static inline void +xpass (const char* fmt, ...) +{ + va_list ap; + + passed++; + va_start (ap, fmt); + vsnprintf (buffer, sizeof (buffer), fmt, ap); + va_end (ap); + printf ("\tXPASSED: %s\n", buffer); +#ifdef _DEJAGNU_WAIT_ + dg_wait (); +#endif +} + +static inline void +fail (const char* fmt, ...) +{ + va_list ap; + + failed++; + va_start (ap, fmt); + vsnprintf (buffer, sizeof (buffer), fmt, ap); + va_end (ap); + printf ("\tFAILED: %s\n", buffer); +#ifdef _DEJAGNU_WAIT_ + dg_wait (); +#endif +} + +static inline void +xfail (const char* fmt, ...) +{ + va_list ap; + + failed++; + va_start (ap, fmt); + vsnprintf (buffer, sizeof (buffer), fmt, ap); + va_end (ap); + printf ("\tXFAILED: %s\n", buffer); +#ifdef _DEJAGNU_WAIT_ + dg_wait (); +#endif +} + +static inline void +untested (const char* fmt, ...) +{ + va_list ap; + + untest++; + va_start (ap, fmt); + vsnprintf (buffer, sizeof (buffer), fmt, ap); + va_end (ap); + printf ("\tUNTESTED: %s\n", buffer); +#ifdef _DEJAGNU_WAIT_ + dg_wait (); +#endif +} + +static inline void +unresolved (const char* fmt, ...) +{ + va_list ap; + + unresolve++; + va_start (ap, fmt); + vsnprintf (buffer, sizeof (buffer), fmt, ap); + va_end (ap); + printf ("\tUNRESOLVED: %s\n", buffer); +#ifdef _DEJAGNU_WAIT_ + dg_wait (); +#endif +} + +static inline void +note (const char* fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + vsnprintf (buffer, sizeof (buffer), fmt, ap); + va_end (ap); + printf ("\tNOTE: %s\n", buffer); +#ifdef _DEJAGNU_WAIT_ + dg_wait (); +#endif +} + +static inline void +totals (void) +{ + printf ("\nTotals:\n"); + printf ("\t#passed:\t\t%d\n", passed); + printf ("\t#real failed:\t\t%d\n", failed); + if (xfailed) + printf ("\t#expected failures:\t\t%d\n", xfailed); + if (untest) + printf ("\t#untested:\t\t%d\n", untest); + if (unresolve) + printf ("\t#unresolved:\t\t%d\n", unresolve); + printf ("\njit-dg-harness-complete\n"); +} + +#ifdef __cplusplus + +#include <iostream> +#include <iomanip> +#include <fstream> +#include <string> + +const char *outstate_list[] = { + "FAILED: ", "PASSED: ", "UNTESTED: ", "UNRESOLVED: ", "XFAILED: ", "XPASSED: " +}; + +const char ** outstate = outstate_list; + +enum teststate { FAILED, PASSED, UNTESTED, UNRESOLVED, XFAILED, XPASSED} laststate; + +class TestState { + private: + teststate laststate; + std::string lastmsg; + public: + TestState (void) + { + passed = 0; + failed = 0; + untest = 0; + xpassed = 0; + xfailed = 0; + unresolve = 0; + } + + ~TestState (void) { totals(); } + + void testrun (bool b, std::string s) + { + if (b) + pass (s); + else + fail (s); + } + + void pass (std::string s) + { + passed++; + laststate = PASSED; + lastmsg = s; + std::cout << "\t" << outstate[PASSED] << s << std::endl; + } + + void pass (const char *c) + { + std::string s = c; + pass (s); + } + + void xpass (std::string s) + { + xpassed++; + laststate = PASSED; + lastmsg = s; + std::cout << "\t" << outstate[XPASSED] << s << std::endl; + } + + void xpass (const char *c) + { + std::string s = c; + xpass (s); + } + + void fail (std::string s) + { + failed++; + laststate = FAILED; + lastmsg = s; + std::cout << "\t" << outstate[FAILED] << s << std::endl; + } + + void fail (const char *c) + { + std::string s = c; + fail (s); + } + + void xfail (std::string s) + { + xfailed++; + laststate = XFAILED; + lastmsg = s; + std::cout << "\t" << outstate[XFAILED] << s << std::endl; + } + + void xfail (const char *c) + { + std::string s = c; + xfail (s); + } + + void untested (std::string s) + { + untest++; + laststate = UNTESTED; + lastmsg = s; + std::cout << "\t" << outstate[UNTESTED] << s << std::endl; + } + + void untested (const char *c) + { + std::string s = c; + untested (s); + } + + void unresolved (std::string s) + { + unresolve++; + laststate = UNRESOLVED; + lastmsg = s; + std::cout << "\t" << outstate[UNRESOLVED] << s << std::endl; + } + + void unresolved (const char *c) + { + std::string s = c; + unresolved (s); + } + + void totals (void) + { + std::cout << "\t#passed:\t\t" << passed << std::endl; + std::cout << "\t#real failed:\t\t" << failed << std::endl; + if (xfailed) + std::cout << "\t#expected failures:\t\t" << xfailed << std::endl; + if (xpassed) + std::cout << "\t#unexpected passes:\t\t" << xpassed << std::endl; + if (untest) + std::cout << "\t#untested:\t\t" << untest << std::endl; + if (unresolve) + std::cout << "\t#unresolved:\t\t" << unresolve << std::endl; + std::cout << "\njit-dg-harness-complete" << std::endl; + } + + // This is so this class can be printed in an ostream. + friend std::ostream & operator << (std::ostream &os, TestState& t) + { + return os << "\t" << outstate[t.laststate] << t.lastmsg ; + } + + int GetState (void) { return laststate; } + std::string GetMsg (void) { return lastmsg; } +}; + +#endif /* __cplusplus */ +#endif /* _DEJAGNU_H_ */ diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 8adde0d..ea8c88b 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,13 @@ +2021-08-18 Iain Sandoe <iain@sandoe.co.uk> + Matt Jacobson <mhjacobson@me.com> + + PR objc/101666 + * objc-act.c (objc_build_constructor): Handle empty constructor + lists. + * objc-next-runtime-abi-02.c (build_v2_objc_method_fixup_call): + Handle nil receivers. + (build_v2_build_objc_method_call): Likewise. + 2021-08-17 Matt Jacobson <mhjacobson@me.com> * objc-next-runtime-abi-02.c diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index ec20891..6e4fb62 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -3377,8 +3377,10 @@ objc_build_string_object (tree string) return addr; } -/* Build a static constant CONSTRUCTOR - with type TYPE and elements ELTS. */ +/* Build a static constant CONSTRUCTOR with type TYPE and elements ELTS. + We might be presented with a NULL for ELTS, which means 'empty ctor' + which will subsequently be converted into a zero initializer in the + middle end. */ tree objc_build_constructor (tree type, vec<constructor_elt, va_gc> *elts) @@ -3390,12 +3392,10 @@ objc_build_constructor (tree type, vec<constructor_elt, va_gc> *elts) TREE_READONLY (constructor) = 1; #ifdef OBJCPLUS - /* Adjust for impedance mismatch. We should figure out how to build - CONSTRUCTORs that consistently please both the C and C++ gods. */ - if (!(*elts)[0].index) + /* If we know the initializer, then set the type to what C++ expects. */ + if (elts && !(*elts)[0].index) TREE_TYPE (constructor) = init_list_type_node; #endif - return constructor; } @@ -9664,7 +9664,9 @@ objc_gimplify_property_ref (tree *expr_p) call_exp = TREE_OPERAND (getter, 1); } #endif - gcc_assert (TREE_CODE (call_exp) == CALL_EXPR); + gcc_checking_assert ((flag_objc_nilcheck + && TREE_CODE (call_exp) == COND_EXPR) + || TREE_CODE (call_exp) == CALL_EXPR); *expr_p = call_exp; } diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c index c552013..0d963e3 100644 --- a/gcc/objc/objc-next-runtime-abi-02.c +++ b/gcc/objc/objc-next-runtime-abi-02.c @@ -1675,13 +1675,8 @@ build_v2_objc_method_fixup_call (int super_flag, tree method_prototype, if (TREE_CODE (ret_type) == RECORD_TYPE || TREE_CODE (ret_type) == UNION_TYPE) - { - vec<constructor_elt, va_gc> *rtt = NULL; - /* ??? CHECKME. hmmm..... think we need something more - here. */ - CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE); - ftree = objc_build_constructor (ret_type, rtt); - } + /* An empty constructor is zero-filled by the middle end. */ + ftree = objc_build_constructor (ret_type, NULL); else ftree = fold_convert (ret_type, integer_zero_node); @@ -1694,11 +1689,11 @@ build_v2_objc_method_fixup_call (int super_flag, tree method_prototype, ifexp, ret_val, ftree, tf_warning_or_error); #else - /* ??? CHECKME. */ ret_val = build_conditional_expr (input_location, - ifexp, 1, + ifexp, 0, ret_val, NULL_TREE, input_location, ftree, NULL_TREE, input_location); + ret_val = fold_convert (ret_type, ret_val); #endif } return ret_val; @@ -1790,11 +1785,8 @@ build_v2_build_objc_method_call (int super, tree method_prototype, if (TREE_CODE (ret_type) == RECORD_TYPE || TREE_CODE (ret_type) == UNION_TYPE) { - vec<constructor_elt, va_gc> *rtt = NULL; - /* ??? CHECKME. hmmm..... think we need something more - here. */ - CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE); - ftree = objc_build_constructor (ret_type, rtt); + /* An empty constructor is zero-filled by the middle end. */ + ftree = objc_build_constructor (ret_type, NULL); } else ftree = fold_convert (ret_type, integer_zero_node); @@ -1807,10 +1799,10 @@ build_v2_build_objc_method_call (int super, tree method_prototype, ret_val = build_conditional_expr (loc, ifexp, ret_val, ftree, tf_warning_or_error); #else - /* ??? CHECKME. */ ret_val = build_conditional_expr (loc, ifexp, 1, ret_val, NULL_TREE, loc, ftree, NULL_TREE, loc); + ret_val = fold_convert (ret_type, ret_val); #endif } return ret_val; diff --git a/gcc/optabs.c b/gcc/optabs.c index 14d8ad2..ebed78f 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -2600,6 +2600,82 @@ widen_leading (scalar_int_mode mode, rtx op0, rtx target, optab unoptab) return 0; } +/* Attempt to emit (clrsb:mode op0) as + (plus:mode (clz:mode (xor:mode op0 (ashr:mode op0 (const_int prec-1)))) + (const_int -1)) + if CLZ_DEFINED_VALUE_AT_ZERO (mode, val) is 2 and val is prec, + or as + (clz:mode (ior:mode (xor:mode (ashl:mode op0 (const_int 1)) + (ashr:mode op0 (const_int prec-1))) + (const_int 1))) + otherwise. */ + +static rtx +expand_clrsb_using_clz (scalar_int_mode mode, rtx op0, rtx target) +{ + if (optimize_insn_for_size_p () + || optab_handler (clz_optab, mode) == CODE_FOR_nothing) + return NULL_RTX; + + start_sequence (); + HOST_WIDE_INT val = 0; + if (CLZ_DEFINED_VALUE_AT_ZERO (mode, val) != 2 + || val != GET_MODE_PRECISION (mode)) + val = 0; + else + val = 1; + + rtx temp2 = op0; + if (!val) + { + temp2 = expand_binop (mode, ashl_optab, op0, const1_rtx, + NULL_RTX, 0, OPTAB_DIRECT); + if (!temp2) + { + fail: + end_sequence (); + return NULL_RTX; + } + } + + rtx temp = expand_binop (mode, ashr_optab, op0, + GEN_INT (GET_MODE_PRECISION (mode) - 1), + NULL_RTX, 0, OPTAB_DIRECT); + if (!temp) + goto fail; + + temp = expand_binop (mode, xor_optab, temp2, temp, NULL_RTX, 0, + OPTAB_DIRECT); + if (!temp) + goto fail; + + if (!val) + { + temp = expand_binop (mode, ior_optab, temp, const1_rtx, + NULL_RTX, 0, OPTAB_DIRECT); + if (!temp) + goto fail; + } + temp = expand_unop_direct (mode, clz_optab, temp, val ? NULL_RTX : target, + true); + if (!temp) + goto fail; + if (val) + { + temp = expand_binop (mode, add_optab, temp, constm1_rtx, + target, 0, OPTAB_DIRECT); + if (!temp) + goto fail; + } + + rtx_insn *seq = get_insns (); + end_sequence (); + + add_equal_note (seq, temp, CLRSB, op0, NULL_RTX, mode); + emit_insn (seq); + return temp; +} + /* Try calculating clz of a double-word quantity as two clz's of word-sized quantities, choosing which based on whether the high word is nonzero. */ static rtx @@ -3171,6 +3247,9 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target, temp = widen_leading (int_mode, op0, target, unoptab); if (temp) return temp; + temp = expand_clrsb_using_clz (int_mode, op0, target); + if (temp) + return temp; } goto try_libcall; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e5dcd4a..57b714a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,77 @@ +2021-08-18 Tobias Burnus <tobias@codesourcery.com> + + PR testsuite/101963 + * gfortran.dg/nothing-1.f90: Moved to ... + * gfortran.dg/gomp/nothing-1.f90: ... here. + * gfortran.dg/nothing-2.f90: Moved to ... + * gfortran.dg/gomp/nothing-2.f90: ... here; + avoid $ issue in $OMP in dg-error. + +2021-08-18 Iain Sandoe <iain@sandoe.co.uk> + Matt Jacobson <mhjacobson@me.com> + + PR objc/101666 + * obj-c++.dg/pr101666-0.mm: New test. + * obj-c++.dg/pr101666-1.mm: New test. + * obj-c++.dg/pr101666.inc: New. + * objc.dg/pr101666-0.m: New test. + * objc.dg/pr101666-1.m: New test. + * objc.dg/pr101666.inc: New. + +2021-08-18 Ankur Saini <arsenic@sourceware.org> + + PR analyzer/97114 + * g++.dg/analyzer/vfunc-2.C: New test. + * g++.dg/analyzer/vfunc-3.C: New test. + * g++.dg/analyzer/vfunc-4.C: New test. + * g++.dg/analyzer/vfunc-5.C: New test. + +2021-08-18 Ankur Saini <arsenic@sourceware.org> + + PR analyzer/100546 + * gcc.dg/analyzer/function-ptr-4.c: New test. + * gcc.dg/analyzer/pr100546.c: New test. + +2021-08-18 Tobias Burnus <tobias@codesourcery.com> + + * gfortran.dg/nothing-1.f90: New test. + * gfortran.dg/nothing-2.f90: New test. + +2021-08-18 Patrick Palka <ppalka@redhat.com> + + PR c++/101344 + PR c++/101820 + * g++.dg/cpp2a/class-deduction-aggr11.C: New test. + * g++.dg/cpp2a/class-deduction-aggr12.C: New test. + +2021-08-18 Patrick Palka <ppalka@redhat.com> + + PR c++/101883 + * g++.dg/cpp2a/nontype-class49.C: New test. + +2021-08-18 Jakub Jelinek <jakub@redhat.com> + + * c-c++-common/gomp/nothing-1.c: New test. + * g++.dg/gomp/attrs-1.C (bar): Add nothing directive test. + * g++.dg/gomp/attrs-2.C (bar): Likewise. + * g++.dg/gomp/attrs-9.C: Likewise. + +2021-08-18 Jakub Jelinek <jakub@redhat.com> + + * c-c++-common/gomp/pr63326.c: Don't expect extra "before" errors + in C++. + * g++.dg/gomp/attrs-7.C: Don't expect one extra error. + * g++.dg/gomp/barrier-2.C: Likewise. + * gcc.dg/gomp/declare-simd-5.c: Likewise. + * gcc.dg/gomp/barrier-2.c: Likewise. + * gcc.dg/gomp/declare-variant-2.c: Likewise. + +2021-08-18 liuhongt <hongtao.liu@intel.com> + + PR target/97147 + * gcc.target/i386/pr54400.c: Adjust testcase. + * gcc.target/i386/pr94147.c: New test. + 2021-08-17 Martin Sebor <msebor@redhat.com> PR middle-end/101854 diff --git a/gcc/testsuite/c-c++-common/gomp/nothing-2.c b/gcc/testsuite/c-c++-common/gomp/nothing-2.c new file mode 100644 index 0000000..a152035 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/nothing-2.c @@ -0,0 +1,2 @@ +#pragma omp nothing , /* { dg-error "expected end of line before" } */ +#pragma omp nothing asdf /* { dg-error "expected end of line before" } */ diff --git a/gcc/testsuite/c-c++-common/gomp/requires-3.c b/gcc/testsuite/c-c++-common/gomp/requires-3.c index e5a6cbb..0e55b66 100644 --- a/gcc/testsuite/c-c++-common/gomp/requires-3.c +++ b/gcc/testsuite/c-c++-common/gomp/requires-3.c @@ -1,3 +1,5 @@ #pragma omp requires atomic_default_mem_order(acquire) /* { dg-error "expected 'seq_cst', 'relaxed' or 'acq_rel'" } */ #pragma omp requires atomic_default_mem_order(release) /* { dg-error "expected 'seq_cst', 'relaxed' or 'acq_rel'" } */ #pragma omp requires atomic_default_mem_order(foobar) /* { dg-error "expected 'seq_cst', 'relaxed' or 'acq_rel'" } */ +#pragma omp requires atomic_default_mem_order ( /* { dg-error "expected 'seq_cst', 'relaxed' or 'acq_rel'" } */ +/* { dg-error "expected '\\\)' before end of line" "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/g++.dg/analyzer/vfunc-2.C b/gcc/testsuite/g++.dg/analyzer/vfunc-2.C new file mode 100644 index 0000000..46b68e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/analyzer/vfunc-2.C @@ -0,0 +1,44 @@ +#include <cstdio> +#include <cstdlib> + +struct A +{ + int m_data; + A() {m_data = 0;} + virtual int deallocate (void) + { + return 42; + } +}; + +struct B: public A +{ + int *ptr; + int m_data_b; + B() {m_data_b = 0;} + void allocate () + { + ptr = (int*)malloc(sizeof(int)); + } + int deallocate (void) + { + free(ptr); + return 0; + } +}; + +void foo(A *a_ptr) +{ + printf("%d\n",a_ptr->deallocate()); +} + +void test() +{ + B b; + A a, *aptr; + aptr = &b; + b.allocate(); + foo(aptr); + aptr = &a; + foo(aptr); +} diff --git a/gcc/testsuite/g++.dg/analyzer/vfunc-3.C b/gcc/testsuite/g++.dg/analyzer/vfunc-3.C new file mode 100644 index 0000000..03d3cdc --- /dev/null +++ b/gcc/testsuite/g++.dg/analyzer/vfunc-3.C @@ -0,0 +1,32 @@ +#include <cstdlib> + +struct A +{ + virtual int foo (void) + { + return 42; + } +}; + +struct B: public A +{ + int *ptr; + void alloc () + { + ptr = (int*)malloc(sizeof(int)); + } + int foo (void) + { + free(ptr); /* { dg-warning "double-'free' of 'b.B::ptr'" } */ + return 0; + } +}; + +int test () +{ + struct B b, *bptr=&b; + b.alloc (); + bptr->foo (); /* { dg-message "\\(6\\) calling 'B::foo' from 'test'" "event 6" } */ + /* { dg-message "\\(9\\) returning to 'test' from 'B::foo'" "event 9" { target *-*-* } .-1 } */ + return bptr->foo (); +} diff --git a/gcc/testsuite/g++.dg/analyzer/vfunc-4.C b/gcc/testsuite/g++.dg/analyzer/vfunc-4.C new file mode 100644 index 0000000..9751084 --- /dev/null +++ b/gcc/testsuite/g++.dg/analyzer/vfunc-4.C @@ -0,0 +1,28 @@ +#include "../../gcc.dg/analyzer/analyzer-decls.h" + +struct A +{ + int m_data; + virtual char foo () + { + return 'A'; + } +}; + +struct B: public A +{ + int m_data_b; + char foo () + { + return 'B'; + } +}; + +void test() +{ + A a, *a_ptr = &a; + B b; + __analyzer_eval (a_ptr->foo () == 'A'); /* { dg-warning "TRUE" } */ + a_ptr = &b; + __analyzer_eval (a_ptr->foo () == 'B'); /* { dg-warning "TRUE" } */ +} diff --git a/gcc/testsuite/g++.dg/analyzer/vfunc-5.C b/gcc/testsuite/g++.dg/analyzer/vfunc-5.C new file mode 100644 index 0000000..2af8465 --- /dev/null +++ b/gcc/testsuite/g++.dg/analyzer/vfunc-5.C @@ -0,0 +1,103 @@ +/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-checker=malloc -fdiagnostics-show-caret" } */ +/* { dg-enable-nn-line-numbers "" } */ + +#include <cstdlib> + +struct Base +{ + virtual void allocate (); + virtual void deallocate (); +}; + +struct Derived: public Base +{ + int *ptr; + void allocate () + { + ptr = (int*)malloc(sizeof(int)); + } + void deallocate () + { + free(ptr); + } +}; + +void test() +{ + Derived D; + Base B, *base_ptr; + base_ptr = &D; + + D.allocate(); + base_ptr->deallocate(); + int n = *D.ptr; /* { dg-warning "use after 'free' of 'D.Derived::ptr'" } */ +} + +/* use after 'free' */ +/* { dg-begin-multiline-output "" } + NN | int n = *D.ptr; + | ^ + 'void test()': events 1-2 + | + | NN | void test() + | | ^~~~ + | | | + | | (1) entry to 'test' + |...... + | NN | D.allocate(); + | | ~~~~~~~~~~~~ + | | | + | | (2) calling 'Derived::allocate' from 'test' + | + +--> 'virtual void Derived::allocate()': events 3-4 + | + | NN | void allocate () + | | ^~~~~~~~ + | | | + | | (3) entry to 'Derived::allocate' + | NN | { + | NN | ptr = (int*)malloc(sizeof(int)); + | | ~~~~~~~~~~~~~~~~~~~ + | | | + | | (4) allocated here + | + <------+ + | + 'void test()': events 5-6 + | + | NN | D.allocate(); + | | ~~~~~~~~~~^~ + | | | + | | (5) returning to 'test' from 'Derived::allocate' + | NN | base_ptr->deallocate(); + | | ~~~~~~~~~~~~~~~~~~~~~~ + | | | + | | (6) calling 'Derived::deallocate' from 'test' + | + +--> 'virtual void Derived::deallocate()': events 7-8 + | + | NN | void deallocate () + | | ^~~~~~~~~~ + | | | + | | (7) entry to 'Derived::deallocate' + | NN | { + | NN | free(ptr); + | | ~~~~~~~~~ + | | | + | | (8) freed here + | + <------+ + | + 'void test()': events 9-10 + | + | NN | base_ptr->deallocate(); + | | ~~~~~~~~~~~~~~~~~~~~^~ + | | | + | | (9) returning to 'test' from 'Derived::deallocate' + | NN | int n = *D.ptr; + | | ~ + | | | + | | (10) use after 'free' of 'D.Derived::ptr'; freed at (8) + | + { dg-end-multiline-output "" } */ + diff --git a/gcc/testsuite/gcc.dg/analyzer/function-ptr-4.c b/gcc/testsuite/gcc.dg/analyzer/function-ptr-4.c new file mode 100644 index 0000000..016351a --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/function-ptr-4.c @@ -0,0 +1,24 @@ +/* Test to see if the analyzer detect and analyze calls via + function pointers or not. */ + +#include <stdlib.h> + +void fun(int *int_ptr) +{ + free(int_ptr); /* { dg-warning "double-'free' of 'int_ptr'" } */ +} + +void single_call() +{ + int *int_ptr = (int*)malloc(sizeof(int)); + void (*fun_ptr)(int *) = &fun; + (*fun_ptr)(int_ptr); +} + +void double_call() +{ + int *int_ptr = (int*)malloc(sizeof(int)); + void (*fun_ptr)(int *) = &fun; + (*fun_ptr)(int_ptr); /* { dg-message "calling 'fun' from 'double_call'" } */ + (*fun_ptr)(int_ptr); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr100546.c b/gcc/testsuite/gcc.dg/analyzer/pr100546.c new file mode 100644 index 0000000..3349d40 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr100546.c @@ -0,0 +1,17 @@ +#include <stdio.h> +#include <stdlib.h> + +static void noReturn(const char *str) __attribute__((noreturn)); +static void noReturn(const char *str) { + printf("%s\n", str); + exit(1); +} + +void (*noReturnPtr)(const char *str) = &noReturn; + +int main(int argc, char **argv) { + char *str = 0; + if (!str) + noReturnPtr(__FILE__); + return printf("%c\n", *str); +} diff --git a/gcc/testsuite/gcc.dg/pr78213.c b/gcc/testsuite/gcc.dg/pr78213.c index 40dd3c8..04bf038 100644 --- a/gcc/testsuite/gcc.dg/pr78213.c +++ b/gcc/testsuite/gcc.dg/pr78213.c @@ -8,4 +8,5 @@ int i; while (i--) bar(); } -/* { dg-message "fself\-test: " "-fself-test" { target *-*-* } 0 } */ + +/* { dg-regexp {^-fself-test: [0-9]+ pass\(es\) in [.0-9]+ seconds$|.*: note: self-tests are not enabled in this build$} } */ diff --git a/gcc/testsuite/gcc.target/i386/pr101950-1.c b/gcc/testsuite/gcc.target/i386/pr101950-1.c new file mode 100644 index 0000000..cc98064 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr101950-1.c @@ -0,0 +1,20 @@ +/* PR middle-end/101950 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-lzcnt" } */ +/* { dg-final { scan-assembler-not "call\[^\n\r]*__clrsb.i2" } } */ +/* { dg-final { scan-assembler-times "\tbsr\[ql]\t" 2 } } */ +/* { dg-final { scan-assembler-times "\txor\[ql]\t" 4 } } */ +/* { dg-final { scan-assembler-times "\tor\[ql]\t" 2 } } */ +/* { dg-final { scan-assembler-times "\tsar\[ql]\t|\tcltd" 2 } } */ + +int +foo (long x) +{ + return __builtin_clrsbl (x); +} + +int +bar (int x) +{ + return __builtin_clrsb (x); +} diff --git a/gcc/testsuite/gcc.target/i386/pr101950-2.c b/gcc/testsuite/gcc.target/i386/pr101950-2.c new file mode 100644 index 0000000..896f1b4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr101950-2.c @@ -0,0 +1,19 @@ +/* PR middle-end/101950 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mlzcnt" } */ +/* { dg-final { scan-assembler-not "call\[^\n\r]*__clrsb.i2" } } */ +/* { dg-final { scan-assembler-times "\tlzcnt\[ql]\t" 2 } } */ +/* { dg-final { scan-assembler-times "\txor\[ql]\t" 2 } } */ +/* { dg-final { scan-assembler-times "\tsar\[ql]\t|\tcltd" 2 } } */ + +int +foo (long x) +{ + return __builtin_clrsbl (x); +} + +int +bar (int x) +{ + return __builtin_clrsb (x); +} diff --git a/gcc/testsuite/gcc.target/i386/pr99881.c b/gcc/testsuite/gcc.target/i386/pr99881.c index a1ec1d1b..3e087eb 100644 --- a/gcc/testsuite/gcc.target/i386/pr99881.c +++ b/gcc/testsuite/gcc.target/i386/pr99881.c @@ -1,7 +1,7 @@ /* PR target/99881. */ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-Ofast -march=skylake" } */ -/* { dg-final { scan-assembler-not "xmm\[0-9\]" } } */ +/* { dg-final { scan-assembler-not "xmm\[0-9\]" { xfail *-*-* } } } */ void foo (int* __restrict a, int n, int c) diff --git a/gcc/testsuite/gfortran.dg/nothing-1.f90 b/gcc/testsuite/gfortran.dg/gomp/nothing-1.f90 index 9fc24d4..9fc24d4 100644 --- a/gcc/testsuite/gfortran.dg/nothing-1.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/nothing-1.f90 diff --git a/gcc/testsuite/gfortran.dg/nothing-2.f90 b/gcc/testsuite/gfortran.dg/gomp/nothing-2.f90 index 74a4a5a..554d4ef 100644 --- a/gcc/testsuite/gfortran.dg/nothing-2.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/nothing-2.f90 @@ -3,5 +3,5 @@ pure subroutine foo end subroutine subroutine bar - !$omp nothing foo ! { dg-error "Unexpected junk after $OMP NOTHING statement" } + !$omp nothing foo ! { dg-error "Unexpected junk after .OMP NOTHING statement" } end diff --git a/gcc/testsuite/jit.dg/harness.h b/gcc/testsuite/jit.dg/harness.h index 6b59fb5..0dc5ed1 100644 --- a/gcc/testsuite/jit.dg/harness.h +++ b/gcc/testsuite/jit.dg/harness.h @@ -27,7 +27,7 @@ #define note dejagnu_note #endif -#include <dejagnu.h> +#include "jit-dejagnu.h" #ifdef MAKE_DEJAGNU_H_THREADSAFE #undef pass diff --git a/gcc/testsuite/jit.dg/jit.exp b/gcc/testsuite/jit.dg/jit.exp index 9af87f9..005ba01 100644 --- a/gcc/testsuite/jit.dg/jit.exp +++ b/gcc/testsuite/jit.dg/jit.exp @@ -914,9 +914,14 @@ proc jit-verify-executable { args } { jit-run-executable $output_filename ${dg-output-text} } +set DEFAULT_CFLAGS "-I$srcdir/../jit -lgccjit -g -Wall -Werror" + # We need to link with --export-dynamic for test-calling-external-function.c # so that the JIT-built code can call into functions from the main program. -set DEFAULT_CFLAGS "-I$srcdir/../jit -lgccjit -g -Wall -Werror -Wl,--export-dynamic" + +if { [check_effective_target_rdynamic] } { + set DEFAULT_CFLAGS "$DEFAULT_CFLAGS -rdynamic" +} # Main loop. This will invoke jig-dg-test on each test-*.c file. dg-runtest $tests "" $DEFAULT_CFLAGS diff --git a/gcc/testsuite/jit.dg/test-asm.c b/gcc/testsuite/jit.dg/test-asm.c index 35a9f9d..43255dc 100644 --- a/gcc/testsuite/jit.dg/test-asm.c +++ b/gcc/testsuite/jit.dg/test-asm.c @@ -438,6 +438,18 @@ verify_code_4 (gcc_jit_context *ctxt, gcc_jit_result *result) static void create_test_i386_basic_asm_5 (gcc_jit_context *ctxt) { +#if __APPLE__ + /* Darwin's assemblers do not support push/pop section, do not use .type + and external symbols should use __USER_LABEL_PREFIX__. */ + gcc_jit_context_add_top_level_asm (ctxt, NULL, + "\t.text\n" + "\t.globl _add_asm\n" + "_add_asm:\n" + "\tmovq %rdi, %rax\n" + "\tadd %rsi, %rax\n" + "\tret\n" + "\t# some asm here\n"); +#else /* Quote from here in docs/topics/asm.rst: example 5: jit. */ gcc_jit_context_add_top_level_asm (ctxt, NULL, "\t.pushsection .text\n" @@ -450,6 +462,7 @@ create_test_i386_basic_asm_5 (gcc_jit_context *ctxt) "\t# some asm here\n" "\t.popsection\n"); /* Quote up to here in docs/topics/asm.rst: example 5: jit. */ +#endif } static void diff --git a/gcc/testsuite/jit.dg/test-asm.cc b/gcc/testsuite/jit.dg/test-asm.cc index be487e3..a3b45da 100644 --- a/gcc/testsuite/jit.dg/test-asm.cc +++ b/gcc/testsuite/jit.dg/test-asm.cc @@ -400,6 +400,17 @@ static void create_test_i386_basic_asm_5 (gcc_jit_context *c_ctxt) { gccjit::context ctxt (c_ctxt); +#if __APPLE__ + /* Darwin's assemblers do not support push/pop section, do not use .type + and external symbols should use __USER_LABEL_PREFIX__. */ + ctxt.add_top_level_asm ("\t.text\n" + "\t.globl _add_asm\n" + "_add_asm:\n" + "\tmovq %rdi, %rax\n" + "\tadd %rsi, %rax\n" + "\tret\n" + "\t# some asm here\n"); +#else /* Quote from here in docs/cp/topics/asm.rst: example 5: jit. */ ctxt.add_top_level_asm ("\t.pushsection .text\n" "\t.globl add_asm\n" @@ -411,6 +422,7 @@ create_test_i386_basic_asm_5 (gcc_jit_context *c_ctxt) "\t# some asm here\n" "\t.popsection\n"); /* Quote up to here in docs/cp/topics/asm.rst: example 5: jit. */ +#endif } static void diff --git a/gcc/testsuite/obj-c++.dg/pr101666-0.mm b/gcc/testsuite/obj-c++.dg/pr101666-0.mm new file mode 100644 index 0000000..5f87f60 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/pr101666-0.mm @@ -0,0 +1,7 @@ +/* { dg-do run } */ +/* { dg-skip-if "NeXT only" { *-*-* } { "-fgnu-runtime" } { "" } } */ +/* { dg-skip-if "ABI 2 only" { *-*-* && { ! objc2 } } { "*" } { "" } } */ +/* { dg-additional-options "-fobjc-nilcheck -Wno-objc-root-class" } */ + +#include "pr101666.inc" + diff --git a/gcc/testsuite/obj-c++.dg/pr101666-1.mm b/gcc/testsuite/obj-c++.dg/pr101666-1.mm new file mode 100644 index 0000000..41ef370 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/pr101666-1.mm @@ -0,0 +1,10 @@ +/* Later versions of Darwin can compile for 10.5, but cannot link it so we + can only run this test up to 10.13. */ +/* { dg-do compile { target *-*-darwin* } } */ +/* { dg-do run { target *-*-darwin[89]* *-*-darwin1[0-7]* } } */ +/* { dg-skip-if "NeXT only" { *-*-* } { "-fgnu-runtime" } { "" } } */ +/* { dg-skip-if "ABI 2 only" { *-*-* && { ! objc2 } } { "*" } { "" } } */ +/* { dg-additional-options "-fobjc-nilcheck -mmacosx-version-min=10.5 " } */ +/* { dg-additional-options "-Wno-objc-root-class" } */ + +#include "pr101666.inc" diff --git a/gcc/testsuite/obj-c++.dg/pr101666.inc b/gcc/testsuite/obj-c++.dg/pr101666.inc new file mode 100644 index 0000000..e81e1be --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/pr101666.inc @@ -0,0 +1,29 @@ +#include <cstdlib> +struct point { double x, y, z; }; + +@interface Foo +- (struct point)bar; +- (struct point)baz; +@end + +@implementation Foo +- (struct point)bar { struct point q = { 1.0, 2.0, 3.0 }; return q; }; +- (struct point)baz { struct point q = { 4.0, 5.0, 6.0 }; return q; }; +@end + +/* Cases where a check for nil should be inserted by the compiler, when + -fobjc-nilcheck is in force. We should not attempt the calls, and the + result should be 0-filled. */ + +Foo *f; + +int main(void) { + struct point p = [f bar]; + if (p.x != 0.0 || p.y != 0.0 || p.z != 0.0) + abort (); + id nilobj = (id)0; + p = [nilobj baz]; + if (p.x != 0.0 || p.y != 0.0 || p.z != 0.0) + abort (); + return 0; +} diff --git a/gcc/testsuite/objc.dg/pr101666-0.m b/gcc/testsuite/objc.dg/pr101666-0.m new file mode 100644 index 0000000..5f87f60 --- /dev/null +++ b/gcc/testsuite/objc.dg/pr101666-0.m @@ -0,0 +1,7 @@ +/* { dg-do run } */ +/* { dg-skip-if "NeXT only" { *-*-* } { "-fgnu-runtime" } { "" } } */ +/* { dg-skip-if "ABI 2 only" { *-*-* && { ! objc2 } } { "*" } { "" } } */ +/* { dg-additional-options "-fobjc-nilcheck -Wno-objc-root-class" } */ + +#include "pr101666.inc" + diff --git a/gcc/testsuite/objc.dg/pr101666-1.m b/gcc/testsuite/objc.dg/pr101666-1.m new file mode 100644 index 0000000..41ef370 --- /dev/null +++ b/gcc/testsuite/objc.dg/pr101666-1.m @@ -0,0 +1,10 @@ +/* Later versions of Darwin can compile for 10.5, but cannot link it so we + can only run this test up to 10.13. */ +/* { dg-do compile { target *-*-darwin* } } */ +/* { dg-do run { target *-*-darwin[89]* *-*-darwin1[0-7]* } } */ +/* { dg-skip-if "NeXT only" { *-*-* } { "-fgnu-runtime" } { "" } } */ +/* { dg-skip-if "ABI 2 only" { *-*-* && { ! objc2 } } { "*" } { "" } } */ +/* { dg-additional-options "-fobjc-nilcheck -mmacosx-version-min=10.5 " } */ +/* { dg-additional-options "-Wno-objc-root-class" } */ + +#include "pr101666.inc" diff --git a/gcc/testsuite/objc.dg/pr101666.inc b/gcc/testsuite/objc.dg/pr101666.inc new file mode 100644 index 0000000..f1dddca --- /dev/null +++ b/gcc/testsuite/objc.dg/pr101666.inc @@ -0,0 +1,29 @@ +#include <stdlib.h> +struct point { double x, y, z; }; + +@interface Foo +- (struct point)bar; +- (struct point)baz; +@end + +@implementation Foo +- (struct point)bar { struct point q = { 1.0, 2.0, 3.0 }; return q; }; +- (struct point)baz { struct point q = { 4.0, 5.0, 6.0 }; return q; }; +@end + +/* Cases where a check for nil should be inserted by the compiler, when + -fobjc-nilcheck is in force. We should not attempt the calls, and the + result should be 0-filled. */ + +Foo *f; + +int main(void) { + struct point p = [f bar]; + if (p.x != 0.0 || p.y != 0.0 || p.z != 0.0) + abort (); + id nilobj = (id)0; + p = [nilobj baz]; + if (p.x != 0.0 || p.y != 0.0 || p.z != 0.0) + abort (); + return 0; +} |