diff options
301 files changed, 7023 insertions, 3110 deletions
@@ -71,6 +71,3 @@ stamp-* /gmp* /isl* /gettext* - -# ADDITIONS from GCCRS front-end -libgrust/*/target/ diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d73ba82..4b6bc90 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,311 @@ +2025-08-04 Hans-Peter Nilsson <hp@bitrange.com> + + * defaults.h (MAX_FIXED_MODE_SIZE): Default to 2 * BITS_PER_WORD + for larger-than-32-bitters. + * doc/tm.texi.in (MAX_FIXED_MODE_SIZE): Adjust accordingly. Tweak + wording. + * doc/tm.texi: Regenerate. + +2025-08-04 David Malcolm <dmalcolm@redhat.com> + + * dump-context.h: Convert "enum optinfo_item_kind" into + "enum class kind" within class optinfo_item. + * dumpfile.cc: Likewise. Use "auto" in a few places. + Convert "enum optinfo_kind" to "enum class kind" within + class optinfo. + * opt-problem.cc: Likewise. + * optinfo-emit-json.cc: Likewise. + * optinfo.cc: Likewise. + * optinfo.h: Likewise. + +2025-08-04 David Malcolm <dmalcolm@redhat.com> + + PR diagnostics/116253 + * diagnostics/context.cc (context::set_nesting_level): New. + * diagnostics/context.h (context::set_nesting_level): New decl. + * doc/libgdiagnostics/topics/compatibility.rst + (LIBGDIAGNOSTICS_ABI_5): New. + * doc/libgdiagnostics/topics/physical-locations.rst + (diagnostic_manager_set_debug_physical_locations): New. + * libgdiagnostics++.h (manager::set_debug_physical_locations): + New. + * libgdiagnostics-private.h + (private_diagnostic_set_nesting_level): New decl. + * libgdiagnostics.cc (diagnostic_manager::diagnostic_manager): + Initialize m_debug_physical_locations. + (diagnostic_manager::new_location_from_file_and_line): Add debug + printing. + (diagnostic_manager::new_location_from_file_line_column): + Likewise. + (diagnostic_manager::new_location_from_range): Likewise. + (diagnostic_manager::set_debug_physical_locations): New. + (diagnostic_manager::ensure_linemap_for_file_and_line): Avoid + redundant calls to linemap_add. + (diagnostic_manager::new_location): Add debug printing. + (diagnostic_manager::m_debug_physical_locations): New field. + (diagnostic::diagnostic): Initialize m_nesting_level. + (diagnostic::get_nesting_level): New accessor. + (diagnostic::set_nesting_level): New. + (diagnostic::m_nesting_level): New field. + (diagnostic_manager::emit_va): Set and reset the nesting level + of the context from that of the diagnostic. + (diagnostic_manager_set_debug_physical_locations): New. + (private_diagnostic_set_nesting_level): New. + * libgdiagnostics.h + (diagnostic_manager_set_debug_physical_locations): New decl. + * libgdiagnostics.map (LIBGDIAGNOSTICS_ABI_5): New. + * libsarifreplay.cc (sarif_replayer::handle_result_obj): Support + the "nestingLevel" property. + * libsarifreplay.h (replay_options::m_debug_physical_locations): + New field. + * sarif-replay.cc: Add -fdebug-physical-locations. + +2025-08-04 David Malcolm <dmalcolm@redhat.com> + + PR diagnostics/116792 + * diagnostics/html-sink.cc + (html_builder::make_element_for_diagnostic): Don't add the + metadata element if it's empty. + (html_builder::make_element_for_metadata): Return null rather than + an empty element. + +2025-08-04 David Malcolm <dmalcolm@redhat.com> + + * diagnostics/context.h: Move struct counters to its own header + and include it. + * diagnostics/counters.h: New file, from the above. + +2025-08-04 David Malcolm <dmalcolm@redhat.com> + + * diagnostics/context.h: Split struct source_printing_options out + into "diagnostics/source-printing-options.h" and include it. + * diagnostics/source-printing-options.h: New file, from the above. + +2025-08-04 David Malcolm <dmalcolm@redhat.com> + + * diagnostics/context.cc: Update for renaming of option_manager to + option_id_manager and of context::m_option_mgr to + context::m_option_id_mgr. + * diagnostics/context.h: Likewise, moving class declaration to a + new diagnostics/option-id-manager.h. + * diagnostics/lazy-paths.cc: Likewise. + * diagnostics/option-id-manager.h: New file, from material in + diagnostics/context.h. + * lto-wrapper.cc: Update for renaming of option_manager to + option_id_manager. + * opts-common.cc: Likewise. + * opts-diagnostic.h: Likewise. + * opts.cc: Likewise. + * toplev.cc: Likewise. + +2025-08-04 David Malcolm <dmalcolm@redhat.com> + + * diagnostics/buffering.h: Update comment to refer to output sinks + rather than output formats. + +2025-08-04 David Malcolm <dmalcolm@redhat.com> + + * gimple-warn-recursion.cc (pass_warn_recursion::execute): Add + missing auto_diagnostic_group. + +2025-08-04 Konstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu> + + PR rtl-optimization/121303 + * avoid-store-forwarding.cc (is_store_forwarding): Add check + for `off_val` in `is_store_forwarding`. + +2025-08-04 Richard Biener <rguenther@suse.de> + + * tree-vect-slp.cc (vect_analyze_slp): When analyzing a loop + and slp instance discovery fails, immediately fail the whole + process. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64-sve-builtins.cc + (function_expander::expand): Assert that the return value + has an appropriate mode. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64-protos.h + (aarch64_convert_sve_data_to_pred): Remove the mode argument. + * config/aarch64/aarch64.cc + (aarch64_sve_emit_int_cmp): Allow PRED_MODE to be VNx16BI or + the natural predicate mode for the data mode. + (aarch64_convert_sve_data_to_pred): Remove the mode argument + and instead always create a VNx16BI result. + (aarch64_expand_sve_const_pred): Update call accordingly. + * config/aarch64/aarch64-sve-builtins-base.cc + (svdupq_impl::expand): Likewise, ensuring that the result + has mode VNx16BI. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64-protos.h + (aarch64_emit_sve_pred_vec_duplicate): Declare. + * config/aarch64/aarch64.cc + (aarch64_emit_sve_pred_vec_duplicate): New function. + * config/aarch64/aarch64-sve.md (vec_duplicate<PRED_ALL:mode>): Use it. + * config/aarch64/aarch64-sve-builtins-base.cc + (svdup_impl::expand): Handle boolean values specially. Check for + constants and fall back on aarch64_emit_sve_pred_vec_duplicate + for the variable case, ensuring that the result has mode VNx16BI. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/iterators.md (PNEXT_ONLY): New int iterator. + * config/aarch64/aarch64-sve.md + (@aarch64_sve_<sve_pred_op><mode>): Restrict SVE_PITER pattern + to VNx16BI_ONLY. + (@aarch64_sve_<sve_pred_op><mode>): New PNEXT_ONLY pattern for + PRED_HSD. + (*aarch64_sve_<sve_pred_op><mode>): Likewise. + (*aarch64_sve_<sve_pred_op><mode>_cc): Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64-sve2.md (@aarch64_pred_<sve_int_op><mode>): + Split SVE2_MATCH pattern into a VNx16QI_ONLY define_ins and a + VNx8HI_ONLY define_expand. Use a VNx16BI destination for the latter. + (*aarch64_pred_<sve_int_op><mode>): New SVE2_MATCH pattern for + VNx8HI_ONLY. + (*aarch64_pred_<sve_int_op><mode>_cc): Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64-sve.md (@aarch64_pred_fac<cmp_op><mode>): + Replace with... + (@aarch64_pred_fac<cmp_op><mode>_acle): ...this new expander. + (*aarch64_pred_fac<cmp_op><mode>_strict_acle): New pattern. + * config/aarch64/aarch64-sve-builtins-base.cc + (svac_impl::expand): Update accordingly. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64-sve.md (@aarch64_pred_fcm<cmp_op><mode>_acle) + (*aarch64_pred_fcm<cmp_op><mode>_acle, @aarch64_pred_fcmuo<mode>_acle) + (*aarch64_pred_fcmuo<mode>_acle): New patterns. + * config/aarch64/aarch64-sve-builtins-base.cc + (svcmp_impl::expand, svcmpuo_impl::expand): Use them. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64-sve.md (@aarch64_pred_cmp<cmp_op><mode>_wide): + Split into VNx16QI_ONLY and SVE_FULL_HSI patterns. Use VNx16BI + results for both. + (*aarch64_pred_cmp<cmp_op><mode>_wide): New pattern. + (*aarch64_pred_cmp<cmp_op><mode>_wide_cc): Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64-sve.md + (*aarch64_pred_cmp<cmp_op><mode>_wide_cc): Turn into a + define_insn_and_rewrite and rewrite the governing predicate + of the comparison so that it is identical to the PTEST's. + (*aarch64_pred_cmp<cmp_op><mode>_wide_ptest): Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64-sve.md (@aarch64_pred_cmp<cmp_op><mode>_wide) + (*aarch64_pred_cmp<cmp_op><mode>_wide_cc): Use <VPRED> instead of + VNx16BI for the governing predicate. + (*aarch64_pred_cmp<cmp_op><mode>_wide_ptest): Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64-sve.md (@aarch64_pred_cmp<cmp_op><mode>_acle) + (*aarch64_pred_cmp<cmp_op><mode>_acle, *cmp<cmp_op><mode>_acle_cc) + (*cmp<cmp_op><mode>_acle_and): New patterns that yield VNx16BI + results for all element types. + * config/aarch64/aarch64-sve-builtins-base.cc + (svcmp_impl::expand): Use them. + (svcmp_wide_impl::expand): Likewise when implementing an svcmp_wide + against an in-range constant. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * config/aarch64/aarch64-sve.md (@aarch64_sve_punpk<perm_hilo>_acle) + (*aarch64_sve_punpk<perm_hilo>_acle): New patterns. + * config/aarch64/aarch64-sve-builtins-base.cc + (svunpk_impl::expand): Use them for boolean svunpk*. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + PR target/121294 + * config/aarch64/aarch64.md (UNSPEC_REV_PRED): New unspec. + * config/aarch64/aarch64-sve.md (@aarch64_sve_rev<mode>_acle) + (*aarch64_sve_rev<mode>_acle): New patterns. + * config/aarch64/aarch64-sve-builtins-base.cc + (svrev_impl::expand): Use the new patterns for boolean svrev. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + PR target/121294 + * config/aarch64/iterators.md (UNSPEC_TRN1_CONV): Delete. + (UNSPEC_PERMUTE_PRED): New unspec. + * config/aarch64/aarch64-sve.md (@aarch64_sve_trn1_conv<mode>): + Replace with... + (@aarch64_sve_<perm_insn><mode>_acle) + (*aarch64_sve_<perm_insn><mode>_acle): ...these new patterns. + * config/aarch64/aarch64.cc (aarch64_expand_sve_const_pred_trn): + Update accordingly. + * config/aarch64/aarch64-sve-builtins-functions.h + (binary_permute::expand): Use the new _acle patterns for + predicate operations. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + PR testsuite/121118 + * config/aarch64/iterators.md (VNx16BI_ONLY): New mode iterator. + * config/aarch64/predicates.md (aarch64_ptrue_all_operand): New + predicate. + * config/aarch64/aarch64-sve.md + (@aarch64_sve_while_<while_optab_cmp><GPI:mode><VNx16BI_ONLY:mode>_acle) + (@aarch64_sve_while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle) + (*aarch64_sve_while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle) + (*while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle_cc): New + patterns. + * config/aarch64/aarch64-sve-builtins-functions.h + (while_comparison::expand): Use the new _acle patterns that + always return a VNx16BI. + * config/aarch64/aarch64-sve-builtins-sve2.cc + (svwhilerw_svwhilewr_impl::expand): Likewise. + * config/aarch64/aarch64.cc + (aarch64_sve_move_pred_via_while): Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + PR target/121293 + * config/aarch64/aarch64-sve-builtins-base.cc (svdupq_lane::expand): + Use aarch64_sve_reinterpret instead of subregs. Explicitly + reinterpret the result back to the required mode, rather than + leaving the caller to take a subreg. + +2025-08-04 Richard Biener <rguenther@suse.de> + + PR tree-optimization/121362 + * tree-ssa-sccvn.cc (vn_reference_lookup_3): Generalize + aggregate copy handling. + +2025-08-04 Filip Kastl <fkastl@suse.cz> + + * doc/invoke.texi: Add remark about -options being documented + under -fdump-tree. Remove remark about -graph working only for + RTL. + +2025-08-04 H.J. Lu <hjl.tools@gmail.com> + + PR target/120941 + * config/i386/i386-features.cc (x86_cse_kind): Moved before + ix86_place_single_vector_set. + (redundant_load): Likewise. + (ix86_place_single_vector_set): Replace the last argument to the + pointer to redundant_load. For X86_CSE_VEC_DUP, don't place the + vector set outside of the loop to avoid extra spills. + (remove_redundant_vector_load): Pass load to + ix86_place_single_vector_set. + 2025-08-03 Georg-Johann Lay <avr@gjlay.de> * config/avr/avr.md (define_insn_and_split) [reload_completed]: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 85faa76..3724f15 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20250804 +20250805 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 85464e3..063d6a7 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,118 @@ +2025-08-04 Viljar Indus <indus@adacore.com> + + * contracts.adb: Use Is_Ignored_In_Codegen instead of just + using Is_Ignored. + * exp_ch6.adb: Likewise. + * exp_prag.adb: Likewise. + * exp_util.adb: Likewise. + * frontend.adb: Avoid removal of ignored nodes in GNATProve_Mode. + * gnat1drv.adb: Avoid forcing Assertions_Enabled in GNATProve_Mode. + * lib-writ.adb (Write_With_File_Names): Avoid early exit + with ignored entities in GNATProve_Mode. + * lib-xref.adb: Likewise. + * opt.adb: Remove check for Assertions_Enabled. + * sem_attr.adb: Use Is_Ignored_In_Codegen instead of Is_Ignored. + * sem_ch13.adb: Likewise. Additionally always add predicates in + GNATProve_Mode. + * sem_prag.adb: Likewise. Additionally remove modifications + to applied policies in GNATProve_Mode. + * sem_util.adb (Is_Ignored_In_Codegen): New function that overrides + Is_Ignored in GNATProve_Mode and Codepeer_Mode. + (Is_Ignored_Ghost_Pragma_In_Codegen): Likewise for + Is_Ignored_Ghost_Pragma. + (Is_Ignored_Ghost_Entity_In_Codegen): Likewise for + Is_Ignored_Ghost_Entity. + (Policy_In_List): Remove overriding of policies in GNATProve_Mode. + * sem_util.ads: Add specs for new functions. + * (Predicates_Enabled): Always generate predicates in + GNATProve_Mode. + +2025-08-04 Bob Duff <duff@adacore.com> + + * treepr.adb (Print_Node_Ref): Protect against + Entity (N) being empty before calling + Compile_Time_Known_Value. + +2025-08-04 Viljar Indus <indus@adacore.com> + + * sem_prag.adb (Validate_Compile_Time_Warning_Errors): + Check if the original compile time pragma was replaced and + validate the original node instead. + +2025-08-04 Viljar Indus <indus@adacore.com> + + * sem_prag.adb (Validate_Compile_Time_Warning_Or_Error): + simplify the implementation. + +2025-08-04 Steve Baird <baird@adacore.com> + + * exp_ch6.adb (Apply_Access_Discrims_Accessibility_Check): If the + accessibility level being checked is known statically, then + statically check it against the level of the function being + returned from. + +2025-08-04 Viljar Indus <indus@adacore.com> + + * atree.adb: update references to Ghost_Mode. + * exp_ch3.adb: use a structure type to store all of the existing + ghost mode related state variables. + * exp_disp.adb: Likewise. + * exp_spark.adb: Likewise. + * exp_util.adb: Likewise. + * expander.adb: Likewise. + * freeze.adb: Likewise and replace references to existing ghost + mode variables. + * ghost.adb (Install_Ghost_Region): install the changes of + the region in to the new Ghost_Config structure. + (Restore_Ghost_Region): Use the new Ghost_Config instead. + In general replace all references to the existing ghost mode + variables with the new structure equivalent. + * ghost.ads (Restore_Ghost_Region): update the spec. + * opt.ads (Ghost_Config_Type): A new type that has two of the + previous ghost code related global variables as memembers - + Ghost_Mode and Ignored_Ghost_Region. + (Ghost_Config) New variable to store the previous Ghost_Mode and + Ignored_Ghost_Region info. + * rtsfind.adb: Replace references to existing ghost mode variables. + * sem.adb: Likewise. + * sem_ch12.adb: Likewise. + * sem_ch13.adb: Likewise. + * sem_ch3.adb: Likewise. + * sem_ch5.adb: Likewise. + * sem_ch6.adb: Likewise. + * sem_ch7.adb: Likewise. + * sem_prag.adb: Likewise. + * sem_util.adb: Likewise. + +2025-08-04 Steve Baird <baird@adacore.com> + + * freeze.adb (Freeze_Profile): Do not emit a warning stating that + a formal parameter's size is 8 if the parameter's size is not 8. + +2025-08-04 Viljar Indus <indus@adacore.com> + + * table.adb (Max): Move variable to the body and initialize + it with the same value as in the Init function. + * table.ads (Max): Likewise. + +2025-08-04 Bob Duff <duff@adacore.com> + + * par.adb: Move and rewrite some comments. + (Util): Shared code and comments for dealing with + defining_identifier_lists. + * par-util.adb (Append): Shared code for appending + one identifier onto Defining_Identifiers. + (P_Def_Ids): Shared code for parsing a defining_identifier_list. + Unfortunately, this is not used in all cases, because some of + them mix in sophisticated error recovery, which we do not + modify here. + * par-ch12.adb (P_Formal_Object_Declarations): + Use Defining_Identifiers and related code. + * par-ch3.adb (P_Identifier_Declarations): Likewise. + (P_Known_Discriminant_Part_Opt): Likewise. + (P_Component_Items): Likewise. + * par-ch6.adb (P_Formal_Part): Likewise. + 2025-07-31 Eric Botcazou <ebotcazou@gcc.gnu.org> Revert: diff --git a/gcc/config/avr/avr-log.cc b/gcc/config/avr/avr-log.cc index fadb3ca..972ba6b 100644 --- a/gcc/config/avr/avr-log.cc +++ b/gcc/config/avr/avr-log.cc @@ -373,7 +373,6 @@ avr_log_set_avr_log (void) SET_DUMP_DETAIL (insn_addresses); SET_DUMP_DETAIL (legitimate_address_p); SET_DUMP_DETAIL (legitimize_address); - SET_DUMP_DETAIL (legitimize_reload_address); SET_DUMP_DETAIL (progmem); SET_DUMP_DETAIL (rtx_costs); diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index 9aa00d3..8ba1945 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -146,7 +146,6 @@ extern void out_shift_with_cnt (const char *templ, rtx_insn *insn, extern enum reg_class avr_mode_code_base_reg_class (machine_mode, addr_space_t, rtx_code, rtx_code); extern bool avr_regno_mode_code_ok_for_base_p (int, machine_mode, addr_space_t, rtx_code, rtx_code); extern rtx avr_incoming_return_addr_rtx (void); -extern rtx avr_legitimize_reload_address (rtx*, machine_mode, int, int, int, int, rtx (*)(rtx,int)); extern bool avr_adiw_reg_p (rtx); extern bool avr_mem_flash_p (rtx); extern bool avr_mem_flashx_p (rtx); @@ -241,7 +240,6 @@ typedef struct unsigned insn_addresses :1; unsigned legitimate_address_p :1; unsigned legitimize_address :1; - unsigned legitimize_reload_address :1; unsigned progmem :1; unsigned rtx_costs :1; } avr_log_t; diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 2afea95..1bfa3f5 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -453,13 +453,6 @@ avr_ld_regno_p (int regno) } -static bool -ra_in_progress () -{ - return avropt_lra_p ? lra_in_progress : reload_in_progress; -} - - /* Set `avr_arch' as specified by `-mmcu='. Return true on success. */ @@ -2347,8 +2340,8 @@ avr_legitimate_address_p (machine_mode mode, rtx x, bool strict) if (avr_log.legitimate_address_p) { avr_edump ("\n%?: ret=%d, mode=%m strict=%d " - "reload_completed=%d ra_in_progress=%d %s:", - ok, mode, strict, reload_completed, ra_in_progress (), + "reload_completed=%d lra_in_progress=%d %s:", + ok, mode, strict, reload_completed, lra_in_progress, reg_renumber ? "(reg_renumber)" : ""); if (GET_CODE (x) == PLUS @@ -2418,88 +2411,6 @@ avr_legitimize_address (rtx x, rtx oldx, machine_mode mode) } -/* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */ -/* This will allow register R26/27 to be used where it is no worse than normal - base pointers R28/29 or R30/31. For example, if base offset is greater - than 63 bytes or for R++ or --R addressing. */ - -rtx -avr_legitimize_reload_address (rtx *px, machine_mode mode, int opnum, - int type, int addr_type, int /*ind_levels*/, - rtx (*mk_memloc)(rtx,int)) -{ - rtx x = *px; - - if (avr_log.legitimize_reload_address) - avr_edump ("\n%?:%m %r\n", mode, x); - - if (1 && (GET_CODE (x) == POST_INC - || GET_CODE (x) == PRE_DEC)) - { - push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0), - POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0, - opnum, RELOAD_OTHER); - - if (avr_log.legitimize_reload_address) - avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n", - POINTER_REGS, XEXP (x, 0), XEXP (x, 0)); - - return x; - } - - if (GET_CODE (x) == PLUS - && REG_P (XEXP (x, 0)) - && reg_equiv_constant (REGNO (XEXP (x, 0))) == 0 - && CONST_INT_P (XEXP (x, 1)) - && INTVAL (XEXP (x, 1)) >= 1) - { - bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode); - - if (fit) - { - if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0) - { - int regno = REGNO (XEXP (x, 0)); - rtx mem = mk_memloc (x, regno); - - push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL, - POINTER_REGS, Pmode, VOIDmode, 0, 0, - 1, (enum reload_type) addr_type); - - if (avr_log.legitimize_reload_address) - avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n", - POINTER_REGS, XEXP (mem, 0), NULL_RTX); - - push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL, - BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0, - opnum, (enum reload_type) type); - - if (avr_log.legitimize_reload_address) - avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n", - BASE_POINTER_REGS, mem, NULL_RTX); - - return x; - } - } - else if (! (frame_pointer_needed - && XEXP (x, 0) == frame_pointer_rtx)) - { - push_reload (x, NULL_RTX, px, NULL, - POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0, - opnum, (enum reload_type) type); - - if (avr_log.legitimize_reload_address) - avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n", - POINTER_REGS, x, NULL_RTX); - - return x; - } - } - - return NULL_RTX; -} - - /* Helper function to print assembler resp. track instruction sequence lengths. Always return "". @@ -13959,8 +13870,8 @@ extra_constraint_Q (rtx x) || xx == arg_pointer_rtx); if (avr_log.constraints) - avr_edump ("\n%?=%d reload_completed=%d ra_in_progress=%d\n %r\n", - ok, reload_completed, ra_in_progress (), x); + avr_edump ("\n%?=%d reload_completed=%d lra_in_progress=%d\n %r\n", + ok, reload_completed, lra_in_progress, x); } return ok; @@ -14165,17 +14076,6 @@ avr_hard_regno_mode_ok (unsigned int regno, machine_mode mode) if (GET_MODE_SIZE (mode) == 1) return true; - /* FIXME: Ideally, the following test is not needed. - However, it turned out that it can reduce the number - of spill fails. AVR and it's poor endowment with - address registers is extreme stress test for reload. */ - - if (GET_MODE_SIZE (mode) >= 4 - && regno + GET_MODE_SIZE (mode) >= REG_30 - // This problem only concerned the old reload. - && ! avropt_lra_p) - return false; - /* All modes larger than 8 bits should start in an even register. */ return !(regno & 1); @@ -14937,8 +14837,8 @@ avr_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict, if (avr_log.legitimate_address_p) { avr_edump ("\n%?: ret=%b, mode=%m strict=%d " - "reload_completed=%d ra_in_progress=%d %s:", - ok, mode, strict, reload_completed, ra_in_progress (), + "reload_completed=%d lra_in_progress=%d %s:", + ok, mode, strict, reload_completed, lra_in_progress, reg_renumber ? "(reg_renumber)" : ""); if (GET_CODE (x) == PLUS @@ -16716,15 +16616,6 @@ avr_unwind_word_mode () return Pmode; } - -/* Implement `TARGET_LRA_P'. */ - -static bool -avr_use_lra_p () -{ - return avropt_lra_p; -} - /* Initialize the GCC target structure. */ @@ -16866,9 +16757,6 @@ avr_use_lra_p () #undef TARGET_CONVERT_TO_TYPE #define TARGET_CONVERT_TO_TYPE avr_convert_to_type -#undef TARGET_LRA_P -#define TARGET_LRA_P avr_use_lra_p - #undef TARGET_ADDR_SPACE_SUBSET_P #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index cb818c3..335f9fa5 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -309,12 +309,6 @@ enum reg_class { #define STATIC_CHAIN_REGNUM ((AVR_TINY) ? 18 :2) -#define RELOAD_ELIMINABLE_REGS { \ - { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ - { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }, \ - { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ - { FRAME_POINTER_REGNUM + 1, STACK_POINTER_REGNUM + 1 } } - #define ELIMINABLE_REGS \ { \ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ @@ -358,18 +352,6 @@ typedef struct avr_args #define MAX_REGS_PER_ADDRESS 1 -#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN) \ - do { \ - rtx new_x = avr_legitimize_reload_address (&(X), MODE, OPNUM, TYPE, \ - ADDR_TYPE (TYPE), \ - IND_L, make_memloc); \ - if (new_x) \ - { \ - X = new_x; \ - goto WIN; \ - } \ - } while (0) - /* We increase branch costs after reload in order to keep basic-block reordering from introducing out-of-line jumps and to prefer fall-through edges instead. The default branch costs are 0, mainly because otherwise diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 67e88c1..d4bf4da 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -5009,41 +5009,6 @@ ;;<< << << << << << << << << << << << << << << << << << << << << << << << << << ;; arithmetic shift left -;; Work around PR120423: Transform left shift of a paradoxical subreg -;; into left shift of the zero-extended entity. -(define_split ; PR120423 - [(set (match_operand:HISI 0 "register_operand") - (ashift:HISI (subreg:HISI (match_operand:QIPSI 1 "nonimmediate_operand") - 0) - (match_operand:QI 2 "const_int_operand")))] - "!reload_completed - && !avropt_lra_p - && <HISI:SIZE> > <QIPSI:SIZE>" - [(set (match_dup 4) - (zero_extend:HISI (match_dup 5))) - (set (match_dup 0) - (ashift:HISI (match_dup 4) - (match_dup 2)))] - { - operands[4] = gen_reg_rtx (<HISI:MODE>mode); - operands[5] = force_reg (<QIPSI:MODE>mode, operands[1]); - }) - -;; Similar happens for PR116389. -(define_split ; PR116389 - [(set (match_operand:HISI 0 "register_operand") - (subreg:HISI (match_operand:QIPSI 1 "nonimmediate_operand") - 0))] - "!reload_completed - && !avropt_lra_p - && <HISI:SIZE> > <QIPSI:SIZE>" - [(set (match_dup 0) - (zero_extend:HISI (match_dup 2)))] - { - operands[2] = force_reg (<QIPSI:MODE>mode, operands[1]); - }) - - ;; "ashlqi3" ;; "ashlqq3" "ashluqq3" (define_expand "ashl<mode>3" diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt index 7f6f18c..2bed8ea 100644 --- a/gcc/config/avr/avr.opt +++ b/gcc/config/avr/avr.opt @@ -18,10 +18,6 @@ ; along with GCC; see the file COPYING3. If not see ; <http://www.gnu.org/licenses/>. -mlra -Target Var(avropt_lra_p) UInteger Init(1) Optimization Undocumented -Usa LRA for reload instead of the old reload framework. This option is experimental, on per default, and it may be removed in future versions of the compiler. - mcall-prologues Target Mask(CALL_PROLOGUES) Optimization Optimization. Use subroutines for function prologues and epilogues. diff --git a/gcc/config/avr/avr.opt.urls b/gcc/config/avr/avr.opt.urls index 87c26b2..fa560bc 100644 --- a/gcc/config/avr/avr.opt.urls +++ b/gcc/config/avr/avr.opt.urls @@ -1,7 +1,5 @@ ; Autogenerated by regenerate-opt-urls.py from gcc/config/avr/avr.opt and generated HTML -; skipping UrlSuffix for 'mlra' due to finding no URLs - mcall-prologues UrlSuffix(gcc/AVR-Options.html#index-mcall-prologues) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index a50475b..2b0dd66 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1618,10 +1618,8 @@ (compare (match_operand:QI 0 "nonimmediate_operand" "QBn") (subreg:QI - (match_operator:SWI248 2 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0)))] + (match_operator:SWI248 2 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q")]) 0)))] "ix86_match_ccmode (insn, CCmode)" "cmp{b}\t{%h1, %0|%0, %h1}" [(set_attr "addr" "gpr8") @@ -1632,10 +1630,8 @@ [(set (reg FLAGS_REG) (compare (subreg:QI - (match_operator:SWI248 2 "extract_operator" - [(match_operand 0 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 2 "extract_high_operator" + [(match_operand 0 "int248_register_operand" "Q")]) 0) (match_operand:QI 1 "const0_operand")))] "ix86_match_ccmode (insn, CCNOmode)" "test{b}\t%h0, %h0" @@ -1657,10 +1653,8 @@ [(set (reg FLAGS_REG) (compare (subreg:QI - (match_operator:SWI248 2 "extract_operator" - [(match_operand 0 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 2 "extract_high_operator" + [(match_operand 0 "int248_register_operand" "Q")]) 0) (match_operand:QI 1 "general_operand" "QnBn")))] "ix86_match_ccmode (insn, CCmode)" "cmp{b}\t{%1, %h0|%h0, %1}" @@ -1672,15 +1666,11 @@ [(set (reg FLAGS_REG) (compare (subreg:QI - (match_operator:SWI248 2 "extract_operator" - [(match_operand 0 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 2 "extract_high_operator" + [(match_operand 0 "int248_register_operand" "Q")]) 0) (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0)))] + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q")]) 0)))] "ix86_match_ccmode (insn, CCmode)" "cmp{b}\t{%h1, %h0|%h0, %h1}" [(set_attr "type" "icmp") @@ -3480,10 +3470,8 @@ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+Q")) (subreg:QI - (match_operator:SWI248 2 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0))] + (match_operator:SWI248 2 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q")]) 0))] "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)" "mov{b}\t{%h1, %0|%0, %h1}" [(set_attr "type" "imov") @@ -3566,10 +3554,8 @@ (define_insn "*extzvqi" [(set (match_operand:QI 0 "nonimmediate_operand" "=QBn,?R") (subreg:QI - (match_operator:SWI248 2 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q,Q") - (const_int 8) - (const_int 8)]) 0))] + (match_operator:SWI248 2 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q,Q")]) 0))] "" { switch (get_attr_type (insn)) @@ -3690,10 +3676,8 @@ (match_operand 0 "int248_register_operand" "+Q") (const_int 8) (const_int 8)) - (match_operator:SWI248 2 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]))] + (match_operator:SWI248 2 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q")]))] "" "mov{b}\t{%h1, %h0|%h0, %h1}" [(set_attr "type" "imov") @@ -5260,10 +5244,8 @@ [(set (match_operand:SWI24 0 "register_operand" "=R") (sign_extend:SWI24 (subreg:QI - (match_operator:SWI248 2 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0)))] + (match_operator:SWI248 2 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q")]) 0)))] "" "movs{b<SWI24:imodesuffix>|x}\t{%h1, %0|%0, %h1}" [(set_attr "type" "imovx") @@ -7009,10 +6991,8 @@ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+Q,&Q")) (plus:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q,Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q,Q")]) 0) (match_operand:QI 1 "nonimmediate_operand" "0,!qm"))) (clobber (reg:CC FLAGS_REG))] "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)" @@ -7026,8 +7006,8 @@ [(set (strict_low_part (match_dup 0)) (plus:QI (subreg:QI - (match_op_dup 3 - [(match_dup 2) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 2) (const_int 8) (const_int 8)) 0) (match_dup 0))) (clobber (reg:CC FLAGS_REG))])] "" @@ -7038,29 +7018,25 @@ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+&Q")) (plus:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q")]) 0) (subreg:QI - (match_operator:SWI248 4 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0))) + (match_operator:SWI248 4 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q")]) 0))) (clobber (reg:CC FLAGS_REG))] "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)" "#" "&& reload_completed" [(set (strict_low_part (match_dup 0)) (subreg:QI - (match_op_dup 4 - [(match_dup 2) (const_int 8) (const_int 8)]) 0)) + (zero_extract:SWI248 + (match_dup 2) (const_int 8) (const_int 8)) 0)) (parallel [(set (strict_low_part (match_dup 0)) (plus:QI (subreg:QI - (match_op_dup 3 - [(match_dup 1) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 1) (const_int 8) (const_int 8)) 0) (match_dup 0))) (clobber (reg:CC FLAGS_REG))])] "" @@ -7475,10 +7451,8 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=QBn") (plus:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q")]) 0) (match_operand:QI 1 "nonimmediate_operand" "0"))) (clobber (reg:CC FLAGS_REG))] "" @@ -7491,29 +7465,25 @@ [(set (match_operand:QI 0 "register_operand" "=&Q") (plus:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q")]) 0) (subreg:QI - (match_operator:SWI248 4 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0))) + (match_operator:SWI248 4 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q")]) 0))) (clobber (reg:CC FLAGS_REG))] "" "#" "&& reload_completed" [(set (match_dup 0) (subreg:QI - (match_op_dup 4 - [(match_dup 2) (const_int 8) (const_int 8)]) 0)) + (zero_extract:SWI248 + (match_dup 2) (const_int 8) (const_int 8)) 0)) (parallel [(set (match_dup 0) (plus:QI (subreg:QI - (match_op_dup 3 - [(match_dup 1) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 1) (const_int 8) (const_int 8)) 0) (match_dup 0))) (clobber (reg:CC FLAGS_REG))])] "" @@ -7543,10 +7513,8 @@ (subreg:SWI248 (plus:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "0,!Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "0,!Q")]) 0) (match_operand:QI 2 "general_operand" "QnBn,QnBn")) 0)) (clobber (reg:CC FLAGS_REG))] "" @@ -7581,8 +7549,8 @@ (subreg:SWI248 (plus:QI (subreg:QI - (match_op_dup 3 - [(match_dup 0) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 0) (const_int 8) (const_int 8)) 0) (match_dup 2)) 0)) (clobber (reg:CC FLAGS_REG))])] "" @@ -7602,15 +7570,11 @@ (subreg:SWI248 (plusminus:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "<comm>0,!Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "<comm>0,!Q")]) 0) (subreg:QI - (match_operator:SWI248 4 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q,Q") - (const_int 8) - (const_int 8)]) 0)) 0)) + (match_operator:SWI248 4 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q,Q")]) 0)) 0)) (clobber (reg:CC FLAGS_REG))] "" "@ @@ -7629,11 +7593,11 @@ (subreg:SWI248 (plusminus:QI (subreg:QI - (match_op_dup 3 - [(match_dup 0) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 0) (const_int 8) (const_int 8)) 0) (subreg:QI - (match_op_dup 4 - [(match_dup 2) (const_int 8) (const_int 8)]) 0)) 0)) + (zero_extract:SWI248 + (match_dup 2) (const_int 8) (const_int 8)) 0)) 0)) (clobber (reg:CC FLAGS_REG))])] "" [(set_attr "type" "alu") @@ -8230,10 +8194,8 @@ (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,!qm") (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q,Q") - (const_int 8) - (const_int 8)]) 0))) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q,Q")]) 0))) (clobber (reg:CC FLAGS_REG))] "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)" "@ @@ -8247,8 +8209,8 @@ (minus:QI (match_dup 0) (subreg:QI - (match_op_dup 3 - [(match_dup 2) (const_int 8) (const_int 8)]) 0))) + (zero_extract:SWI248 + (match_dup 2) (const_int 8) (const_int 8)) 0))) (clobber (reg:CC FLAGS_REG))])] "" [(set_attr "type" "alu") @@ -8258,30 +8220,26 @@ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+&Q")) (minus:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q")]) 0) (subreg:QI - (match_operator:SWI248 4 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0))) + (match_operator:SWI248 4 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q")]) 0))) (clobber (reg:CC FLAGS_REG))] "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)" "#" "&& reload_completed" [(set (strict_low_part (match_dup 0)) (subreg:QI - (match_op_dup 3 - [(match_dup 1) (const_int 8) (const_int 8)]) 0)) + (zero_extract:SWI248 + (match_dup 1) (const_int 8) (const_int 8)) 0)) (parallel [(set (strict_low_part (match_dup 0)) (minus:QI (match_dup 0) (subreg:QI - (match_op_dup 4 - [(match_dup 2) (const_int 8) (const_int 8)]) 0))) + (zero_extract:SWI248 + (match_dup 2) (const_int 8) (const_int 8)) 0))) (clobber (reg:CC FLAGS_REG))])] "" [(set_attr "type" "alu") @@ -8332,10 +8290,8 @@ (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0") (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0))) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q")]) 0))) (clobber (reg:CC FLAGS_REG))] "" "sub{b}\t{%h2, %0|%0, %h2}" @@ -8347,30 +8303,26 @@ [(set (match_operand:QI 0 "register_operand" "=&Q") (minus:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q")]) 0) (subreg:QI - (match_operator:SWI248 4 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0))) + (match_operator:SWI248 4 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q")]) 0))) (clobber (reg:CC FLAGS_REG))] "" "#" "&& reload_completed" [(set (match_dup 0) (subreg:QI - (match_op_dup 3 - [(match_dup 1) (const_int 8) (const_int 8)]) 0)) + (zero_extract:SWI248 + (match_dup 1) (const_int 8) (const_int 8)) 0)) (parallel [(set (match_dup 0) (minus:QI (match_dup 0) (subreg:QI - (match_op_dup 4 - [(match_dup 2) (const_int 8) (const_int 8)]) 0))) + (zero_extract:SWI248 + (match_dup 2) (const_int 8) (const_int 8)) 0))) (clobber (reg:CC FLAGS_REG))])] "" [(set_attr "type" "alu") @@ -8385,10 +8337,8 @@ (subreg:SWI248 (minus:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "0,!Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "0,!Q")]) 0) (match_operand:QI 2 "general_operand" "QnBn,QnBn")) 0)) (clobber (reg:CC FLAGS_REG))] "" @@ -8407,8 +8357,8 @@ (subreg:SWI248 (minus:QI (subreg:QI - (match_op_dup 3 - [(match_dup 0) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 0) (const_int 8) (const_int 8)) 0) (match_dup 2)) 0)) (clobber (reg:CC FLAGS_REG))])] "" @@ -12356,10 +12306,8 @@ (compare (and:QI (subreg:QI - (match_operator:SWI248 2 "extract_operator" - [(match_operand 0 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 2 "extract_high_operator" + [(match_operand 0 "int248_register_operand" "Q")]) 0) (match_operand:QI 1 "general_operand" "QnBn")) (const_int 0)))] "ix86_match_ccmode (insn, CCNOmode)" @@ -12373,15 +12321,11 @@ (compare (and:QI (subreg:QI - (match_operator:SWI248 2 "extract_operator" - [(match_operand 0 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 2 "extract_high_operator" + [(match_operand 0 "int248_register_operand" "Q")]) 0) (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0)) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q")]) 0)) (const_int 0)))] "ix86_match_ccmode (insn, CCNOmode)" "test{b}\t{%h1, %h0|%h0, %h1}" @@ -12970,10 +12914,8 @@ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+Q,&Q")) (any_logic:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q,Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q,Q")]) 0) (match_operand:QI 1 "nonimmediate_operand" "0,!qm"))) (clobber (reg:CC FLAGS_REG))] "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)" @@ -12987,8 +12929,8 @@ [(set (strict_low_part (match_dup 0)) (any_logic:QI (subreg:QI - (match_op_dup 3 - [(match_dup 2) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 2) (const_int 8) (const_int 8)) 0) (match_dup 0))) (clobber (reg:CC FLAGS_REG))])] "" @@ -12999,29 +12941,25 @@ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+&Q")) (any_logic:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q")]) 0) (subreg:QI - (match_operator:SWI248 4 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0))) + (match_operator:SWI248 4 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q")]) 0))) (clobber (reg:CC FLAGS_REG))] "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)" "#" "&& reload_completed" [(set (strict_low_part (match_dup 0)) (subreg:QI - (match_op_dup 4 - [(match_dup 2) (const_int 8) (const_int 8)]) 0)) + (zero_extract:SWI248 + (match_dup 2) (const_int 8) (const_int 8)) 0)) (parallel [(set (strict_low_part (match_dup 0)) (any_logic:QI (subreg:QI - (match_op_dup 3 - [(match_dup 1) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 1) (const_int 8) (const_int 8)) 0) (match_dup 0))) (clobber (reg:CC FLAGS_REG))])] "" @@ -13224,10 +13162,8 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=QBn") (any_logic:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q")]) 0) (match_operand:QI 1 "nonimmediate_operand" "0"))) (clobber (reg:CC FLAGS_REG))] "" @@ -13240,29 +13176,25 @@ [(set (match_operand:QI 0 "register_operand" "=&Q") (any_logic:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "Q")]) 0) (subreg:QI - (match_operator:SWI248 4 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q") - (const_int 8) - (const_int 8)]) 0))) + (match_operator:SWI248 4 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q")]) 0))) (clobber (reg:CC FLAGS_REG))] "" "#" "&& reload_completed" [(set (match_dup 0) (subreg:QI - (match_op_dup 4 - [(match_dup 2) (const_int 8) (const_int 8)]) 0)) + (zero_extract:SWI248 + (match_dup 2) (const_int 8) (const_int 8)) 0)) (parallel [(set (match_dup 0) (any_logic:QI (subreg:QI - (match_op_dup 3 - [(match_dup 1) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 1) (const_int 8) (const_int 8)) 0) (match_dup 0))) (clobber (reg:CC FLAGS_REG))])] "" @@ -13292,10 +13224,8 @@ (subreg:SWI248 (any_logic:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "0,!Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "0,!Q")]) 0) (match_operand:QI 2 "general_operand" "QnBn,QnBn")) 0)) (clobber (reg:CC FLAGS_REG))] "" @@ -13314,8 +13244,8 @@ (subreg:SWI248 (any_logic:QI (subreg:QI - (match_op_dup 3 - [(match_dup 0) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 0) (const_int 8) (const_int 8)) 0) (match_dup 2)) 0)) (clobber (reg:CC FLAGS_REG))])] "" @@ -13329,10 +13259,8 @@ (match_operator 5 "compare_operator" [(any_logic:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "0,!Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "0,!Q")]) 0) (match_operand:QI 2 "general_operand" "QnBn,QnBn")) (const_int 0)])) (set (zero_extract:SWI248 @@ -13342,8 +13270,8 @@ (subreg:SWI248 (any_logic:QI (subreg:QI - (match_op_dup 3 - [(match_dup 0) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 0) (const_int 8) (const_int 8)) 0) (match_dup 2)) 0))] "ix86_match_ccmode (insn, CCNOmode)" "@ @@ -13359,9 +13287,9 @@ [(set (match_dup 4) (match_op_dup 5 [(any_logic:QI - (subreg:QI - (match_op_dup 3 - [(match_dup 0) (const_int 8) (const_int 8)]) 0) + (subreg:QI + (zero_extract:SWI248 + (match_dup 0) (const_int 8) (const_int 8)) 0) (match_dup 2)) (const_int 0)])) (set (zero_extract:SWI248 @@ -13369,8 +13297,8 @@ (subreg:SWI248 (any_logic:QI (subreg:QI - (match_op_dup 3 - [(match_dup 1) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 1) (const_int 8) (const_int 8)) 0) (match_dup 2)) 0))])] "" [(set_attr "addr" "gpr8") @@ -13386,15 +13314,11 @@ (subreg:SWI248 (any_logic:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "%0,!Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "%0,!Q")]) 0) (subreg:QI - (match_operator:SWI248 4 "extract_operator" - [(match_operand 2 "int248_register_operand" "Q,Q") - (const_int 8) - (const_int 8)]) 0)) 0)) + (match_operator:SWI248 4 "extract_high_operator" + [(match_operand 2 "int248_register_operand" "Q,Q")]) 0)) 0)) (clobber (reg:CC FLAGS_REG))] "" "@ @@ -13413,11 +13337,11 @@ (subreg:SWI248 (any_logic:QI (subreg:QI - (match_op_dup 3 - [(match_dup 0) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 0) (const_int 8) (const_int 8)) 0) (subreg:QI - (match_op_dup 4 - [(match_dup 2) (const_int 8) (const_int 8)]) 0)) 0)) + (zero_extract:SWI248 + (match_dup 2) (const_int 8) (const_int 8)) 0)) 0)) (clobber (reg:CC FLAGS_REG))])] "" [(set_attr "type" "alu") @@ -13429,12 +13353,10 @@ (match_operand 0 "int248_register_operand" "+Q,&Q") (const_int 8) (const_int 8)) - (match_operator:SWI248 3 "extract_operator" + (match_operator:SWI248 3 "extract_high_operator" [(any_logic (match_operand 1 "int248_register_operand" "%0,!Q") - (match_operand 2 "int248_register_operand" "Q,Q")) - (const_int 8) - (const_int 8)])) + (match_operand 2 "int248_register_operand" "Q,Q"))])) (clobber (reg:CC FLAGS_REG))] "GET_MODE (operands[1]) == GET_MODE (operands[2])" "@ @@ -13450,9 +13372,9 @@ (parallel [(set (zero_extract:SWI248 (match_dup 0) (const_int 8) (const_int 8)) - (match_op_dup 3 - [(any_logic (match_dup 4) (match_dup 2)) - (const_int 8) (const_int 8)])) + (zero_extract:SWI248 + (any_logic (match_dup 4) (match_dup 2)) + (const_int 8) (const_int 8))) (clobber (reg:CC FLAGS_REG))])] "operands[4] = gen_lowpart (GET_MODE (operands[1]), operands[0]);" [(set_attr "type" "alu") @@ -14697,10 +14619,8 @@ (subreg:SWI248 (neg:QI (subreg:QI - (match_operator:SWI248 2 "extract_operator" - [(match_operand 1 "int248_register_operand" "0,!Q") - (const_int 8) - (const_int 8)]) 0)) 0)) + (match_operator:SWI248 2 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "0,!Q")]) 0)) 0)) (clobber (reg:CC FLAGS_REG))] "" "@ @@ -14718,8 +14638,8 @@ (subreg:SWI248 (neg:QI (subreg:QI - (match_op_dup 2 - [(match_dup 0) (const_int 8) (const_int 8)]) 0)) 0)) + (zero_extract:SWI248 + (match_dup 0) (const_int 8) (const_int 8)) 0)) 0)) (clobber (reg:CC FLAGS_REG))])] "" [(set_attr "type" "negnot") @@ -15351,13 +15271,9 @@ (match_operand 0 "int248_register_operand" "+Q,&Q") (const_int 8) (const_int 8)) - (subreg:SWI248 - (not:QI - (subreg:QI - (match_operator:SWI248 2 "extract_operator" - [(match_operand 1 "int248_register_operand" "0,!Q") - (const_int 8) - (const_int 8)]) 0)) 0))] + (not:SWI248 + (match_operator:SWI248 2 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "0,!Q")])))] "" "@ not{b}\t%h0 @@ -15370,11 +15286,8 @@ (match_dup 1) (const_int 8) (const_int 8))) (set (zero_extract:SWI248 (match_dup 0) (const_int 8) (const_int 8)) - (subreg:SWI248 - (not:QI - (subreg:QI - (match_op_dup 2 - [(match_dup 0) (const_int 8) (const_int 8)]) 0)) 0))] + (not:SWI248 + (zero_extract:SWI248 (match_dup 0) (const_int 8) (const_int 8))))] "" [(set_attr "type" "negnot") (set_attr "mode" "QI")]) @@ -16721,10 +16634,8 @@ (subreg:SWI248 (ashift:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "0,!Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "0,!Q")]) 0) (match_operand:QI 2 "nonmemory_operand" "cI,cI")) 0)) (clobber (reg:CC FLAGS_REG))] "" @@ -16758,8 +16669,8 @@ (subreg:SWI248 (ashift:QI (subreg:QI - (match_op_dup 3 - [(match_dup 0) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 0) (const_int 8) (const_int 8)) 0) (match_dup 2)) 0)) (clobber (reg:CC FLAGS_REG))])] "" @@ -18005,10 +17916,8 @@ (subreg:SWI248 (any_shiftrt:QI (subreg:QI - (match_operator:SWI248 3 "extract_operator" - [(match_operand 1 "int248_register_operand" "0,!Q") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 3 "extract_high_operator" + [(match_operand 1 "int248_register_operand" "0,!Q")]) 0) (match_operand:QI 2 "nonmemory_operand" "cI,cI")) 0)) (clobber (reg:CC FLAGS_REG))] "" @@ -18034,8 +17943,8 @@ (subreg:SWI248 (any_shiftrt:QI (subreg:QI - (match_op_dup 3 - [(match_dup 0) (const_int 8) (const_int 8)]) 0) + (zero_extract:SWI248 + (match_dup 0) (const_int 8) (const_int 8)) 0) (match_dup 2)) 0)) (clobber (reg:CC FLAGS_REG))])] "" @@ -28252,10 +28161,8 @@ (match_operator 1 "compare_operator" [(and:QI (subreg:QI - (match_operator:SWI248 4 "extract_operator" - [(match_operand 2 "int248_register_operand") - (const_int 8) - (const_int 8)]) 0) + (match_operator:SWI248 4 "extract_high_operator" + [(match_operand 2 "int248_register_operand")]) 0) (match_operand 3 "const_int_operand")) (const_int 0)]))] "! TARGET_PARTIAL_REG_STALL @@ -28267,9 +28174,9 @@ (match_op_dup 1 [(and:QI (subreg:QI - (match_op_dup 4 [(match_dup 2) - (const_int 8) - (const_int 8)]) 0) + (zero_extract:SWI248 (match_dup 2) + (const_int 8) + (const_int 8)) 0) (match_dup 3)) (const_int 0)])) (set (zero_extract:SWI248 (match_dup 2) @@ -28278,9 +28185,9 @@ (subreg:SWI248 (and:QI (subreg:QI - (match_op_dup 4 [(match_dup 2) - (const_int 8) - (const_int 8)]) 0) + (zero_extract:SWI248 (match_dup 2) + (const_int 8) + (const_int 8)) 0) (match_dup 3)) 0))])]) ;; Don't do logical operations with memory inputs. diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index b2d2eec..0f31090 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -1740,8 +1740,12 @@ (define_predicate "compare_operator" (match_code "compare")) -(define_predicate "extract_operator" - (match_code "zero_extract,sign_extract")) +(define_predicate "extract_high_operator" + (match_code "zero_extract,sign_extract,ashiftrt,lshiftrt") +{ + return (const8_operand (XEXP (op, 1), VOIDmode) + && (BINARY_P (op) || const8_operand (XEXP (op, 2), VOIDmode))); +}) ;; Return true if OP is a memory operand, aligned to ;; less than its natural alignment. diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 0a9fcef..e0d8904 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -13867,9 +13867,9 @@ riscv_expand_xmode_usmul (rtx dest, rtx x, rtx y) riscv_emit_binary (MULT, mul, x, y); if (TARGET_64BIT) - emit_insn (gen_usmuldi3_highpart (mulhu, x, y)); + emit_insn (gen_umuldi3_highpart (mulhu, x, y)); else - emit_insn (gen_usmulsi3_highpart (mulhu, x, y)); + emit_insn (gen_umulsi3_highpart (mulhu, x, y)); riscv_emit_binary (NE, overflow_p, mulhu, CONST0_RTX (Xmode)); riscv_emit_unary (NEG, overflow_p, overflow_p); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3f76afd..3ab14f0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2025-08-04 Patrick Palka <ppalka@redhat.com> + + PR c++/121351 + PR c++/119859 + * class.cc (add_method): Substitute outer template arguments + into constraints before comparing them if the declarations are + from different classes. + +2025-08-04 Patrick Palka <ppalka@redhat.com> + + PR c++/120620 + * constexpr.cc (cxx_dynamic_cast_fn_p): Return true only + for synthesized __dynamic_cast. + 2025-08-01 Nathaniel Shead <nathanieloshead@gmail.com> PR c++/108080 diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index f3f1445..64c1217 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -1887,8 +1887,8 @@ Produce code conforming to version 20191213. In the absence of this configuration option the default version is 20191213. @item --enable-__cxa_atexit -Define if you want to use @code{__cxa_atexit}, rather than atexit, to -register C++ destructors for local statics and global objects. +Define if you want to use @code{__cxa_atexit}, rather than @code{atexit}, +to register C++ destructors for local statics and global objects. This is essential for fully standards-compliant handling of destructors, but requires @code{__cxa_atexit} in libc. This option is currently only available on systems with GNU libc. When enabled, this diff --git a/gcc/explow.cc b/gcc/explow.cc index 7799a98..8f8ca7f 100644 --- a/gcc/explow.cc +++ b/gcc/explow.cc @@ -854,6 +854,18 @@ promote_function_mode (const_tree type, machine_mode mode, int *punsignedp, switch (TREE_CODE (type)) { + case BITINT_TYPE: + if (TYPE_MODE (type) == BLKmode) + return mode; + + struct bitint_info info; + bool ok; + ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); + gcc_assert (ok); + + if (!info.extended) + return mode; + /* FALLTHRU */ case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: case REAL_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE: case POINTER_TYPE: case REFERENCE_TYPE: @@ -893,6 +905,18 @@ promote_mode (const_tree type ATTRIBUTE_UNUSED, machine_mode mode, switch (code) { + case BITINT_TYPE: + if (TYPE_MODE (type) == BLKmode) + return mode; + + struct bitint_info info; + bool ok; + ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); + gcc_assert (ok); + + if (!info.extended) + return mode; + /* FALLTHRU */ case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: case REAL_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE: /* Values of these types always have scalar mode. */ diff --git a/gcc/expr.cc b/gcc/expr.cc index 3f2b121..3d2b253 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -76,6 +76,10 @@ along with GCC; see the file COPYING3. If not see the same indirect address eventually. */ int cse_not_expected; +/* Cache of the "extended" flag in the target's _BitInt description + for use during expand. */ +int bitint_extended = -1; + static bool block_move_libcall_safe_for_call_parm (void); static bool emit_block_move_via_pattern (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT, unsigned HOST_WIDE_INT, @@ -11280,6 +11284,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, when reading from SSA_NAMEs of vars. */ #define EXTEND_BITINT(expr) \ ((TREE_CODE (type) == BITINT_TYPE \ + && !bitint_extended \ && reduce_bit_field \ && mode != BLKmode \ && modifier != EXPAND_MEMORY \ @@ -11291,6 +11296,13 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, type = TREE_TYPE (exp); mode = TYPE_MODE (type); unsignedp = TYPE_UNSIGNED (type); + if (TREE_CODE (type) == BITINT_TYPE && bitint_extended == -1) + { + struct bitint_info info; + bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); + gcc_assert (ok); + bitint_extended = info.extended; + } treeop0 = treeop1 = treeop2 = NULL_TREE; if (!VL_EXP_CLASS_P (exp)) @@ -388,4 +388,8 @@ extern void expand_crc_table_based (rtx, rtx, rtx, rtx, machine_mode); extern void expand_reversed_crc_table_based (rtx, rtx, rtx, rtx, machine_mode, void (*) (rtx *)); +/* Cache of the "extended" flag in the target's _BitInt description + for use during expand. */ +extern int bitint_extended; + #endif /* GCC_EXPR_H */ diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 990aaaf..45980d6 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -284,16 +284,6 @@ gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value) } -/* This provides address access to the data field. This should only be - used by array allocation, passing this on to the runtime. */ - -tree -gfc_conv_descriptor_data_addr (tree desc) -{ - tree field = gfc_get_descriptor_field (desc, DATA_FIELD); - return gfc_build_addr_expr (NULL_TREE, field); -} - static tree gfc_conv_descriptor_offset (tree desc) { @@ -9588,9 +9578,8 @@ gfc_conv_array_parameter (gfc_se *se, gfc_expr *expr, bool g77, new_field = gfc_conv_descriptor_dtype (new_desc); gfc_add_modify (&se->pre, new_field, old_field); - old_field = gfc_conv_descriptor_offset (old_desc); - new_field = gfc_conv_descriptor_offset (new_desc); - gfc_add_modify (&se->pre, new_field, old_field); + old_field = gfc_conv_descriptor_offset_get (old_desc); + gfc_conv_descriptor_offset_set (&se->pre, new_desc, old_field); for (int i = 0; i < expr->rank; i++) { @@ -11760,8 +11749,8 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, gfc_index_zero_node); } - tmp = gfc_conv_descriptor_offset (desc); - gfc_add_modify (&loop_pre_block, tmp, gfc_index_zero_node); + gfc_conv_descriptor_offset_set (&loop_pre_block, desc, + gfc_index_zero_node); tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, array1, diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h index 29098fd..345a975 100644 --- a/gcc/fortran/trans-array.h +++ b/gcc/fortran/trans-array.h @@ -173,7 +173,6 @@ void gfc_get_descriptor_offsets_for_info (const_tree, tree *, tree *, tree *, tr tree *, tree *, tree *, tree *); tree gfc_conv_descriptor_data_get (tree); -tree gfc_conv_descriptor_data_addr (tree); tree gfc_conv_descriptor_offset_get (tree); tree gfc_conv_descriptor_span_get (tree); tree gfc_conv_descriptor_dtype (tree); diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index 3b49b18..b495f43 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -5148,18 +5148,31 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block) se.descriptor_only = 1; gfc_conv_expr (&se, e); descriptor = se.expr; - se.expr = gfc_conv_descriptor_data_addr (se.expr); - se.expr = build_fold_indirect_ref_loc (input_location, se.expr); + se.expr = gfc_conv_descriptor_data_get (se.expr); } gfc_free_expr (e); if (!sym->attr.dummy || sym->attr.intent == INTENT_OUT) { /* Nullify when entering the scope. */ - tmp = fold_build2_loc (input_location, MODIFY_EXPR, - TREE_TYPE (se.expr), se.expr, - fold_convert (TREE_TYPE (se.expr), - null_pointer_node)); + if (sym->ts.type == BT_CLASS + && (CLASS_DATA (sym)->attr.dimension + || CLASS_DATA (sym)->attr.codimension)) + { + stmtblock_t nullify; + gfc_init_block (&nullify); + gfc_conv_descriptor_data_set (&nullify, descriptor, + null_pointer_node); + tmp = gfc_finish_block (&nullify); + } + else + { + tree typed_null = fold_convert (TREE_TYPE (se.expr), + null_pointer_node); + tmp = fold_build2_loc (input_location, MODIFY_EXPR, + TREE_TYPE (se.expr), se.expr, + typed_null); + } if (sym->attr.optional) { tree present = gfc_conv_expr_present (sym); diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index ec24084..e6c3218 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -9583,8 +9583,8 @@ gfc_trans_alloc_subarray_assign (tree dest, gfc_component * cm, /* Shift the lbound and ubound of temporaries to being unity, rather than zero, based. Always calculate the offset. */ + gfc_conv_descriptor_offset_set (&block, dest, gfc_index_zero_node); offset = gfc_conv_descriptor_offset_get (dest); - gfc_add_modify (&block, offset, gfc_index_zero_node); tmp2 =gfc_create_var (gfc_array_index_type, NULL); for (n = 0; n < expr->rank; n++) diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc index b4ddf75..4f2f4da 100644 --- a/gcc/fortran/trans-stmt.cc +++ b/gcc/fortran/trans-stmt.cc @@ -2494,9 +2494,10 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block) { tmp = sym->backend_decl; if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp))) - tmp = gfc_conv_descriptor_data_get (tmp); - gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp), - null_pointer_node)); + gfc_conv_descriptor_data_set (&se.pre, tmp, null_pointer_node); + else + gfc_add_modify (&se.pre, tmp, + fold_convert (TREE_TYPE (tmp), null_pointer_node)); } lhs = gfc_lval_expr_from_sym (sym); diff --git a/gcc/fortran/trans.cc b/gcc/fortran/trans.cc index 13fd5ad..47396c3 100644 --- a/gcc/fortran/trans.cc +++ b/gcc/fortran/trans.cc @@ -1740,7 +1740,7 @@ gfc_finalize_tree_expr (gfc_se *se, gfc_symbol *derived, gfc_call_free (data_ptr), build_empty_stmt (input_location)); gfc_add_expr_to_block (&se->loop->post, tmp); - gfc_add_modify (&se->loop->post, data_ptr, data_null); + gfc_conv_descriptor_data_set (&se->loop->post, desc, data_null); } else { @@ -1754,7 +1754,7 @@ gfc_finalize_tree_expr (gfc_se *se, gfc_symbol *derived, gfc_call_free (data_ptr), build_empty_stmt (input_location)); gfc_add_expr_to_block (&se->finalblock, tmp); - gfc_add_modify (&se->finalblock, data_ptr, data_null); + gfc_conv_descriptor_data_set (&se->finalblock, desc, data_null); } } } diff --git a/gcc/function.cc b/gcc/function.cc index 2b77bbd..5a054a9 100644 --- a/gcc/function.cc +++ b/gcc/function.cc @@ -4965,6 +4965,10 @@ prepare_function_start (void) /* Indicate we have no need of a frame pointer yet. */ frame_pointer_needed = 0; + + /* Reset the cache of the "extended" flag in the target's + _BitInt info struct. */ + bitint_extended = -1; } void diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 835e113..c919b3d 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -100,6 +100,7 @@ GRS_OBJS = \ rust/rust-derive-default.o \ rust/rust-derive-partial-eq.o \ rust/rust-derive-eq.o \ + rust/rust-derive-ord.o \ rust/rust-derive-hash.o \ rust/rust-proc-macro.o \ rust/rust-macro-invoc-lexer.o \ @@ -123,7 +124,6 @@ GRS_OBJS = \ rust/rust-keyword-values.o \ rust/rust-abi.o \ rust/rust-token-converter.o \ - rust/rust-macro.o \ rust/rust-ast-lower.o \ rust/rust-ast-lower-base.o \ rust/rust-ast-lower-pattern.o \ @@ -242,6 +242,7 @@ GRS_OBJS = \ rust/rust-collect-lang-items.o \ rust/rust-desugar-for-loops.o \ rust/rust-desugar-question-mark.o \ + rust/rust-desugar-apit.o \ $(END) # removed object files from here diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc index 13126b4..7f8571a 100644 --- a/gcc/rust/ast/rust-ast-builder-type.cc +++ b/gcc/rust/ast/rust-ast-builder-type.cc @@ -62,7 +62,8 @@ ASTTypeBuilder::visit (TypePath &path) { switch (seg->get_type ()) { - case TypePathSegment::REG: { + case TypePathSegment::REG: + { const TypePathSegment &segment = (const TypePathSegment &) (*seg.get ()); TypePathSegment *s @@ -74,7 +75,8 @@ ASTTypeBuilder::visit (TypePath &path) } break; - case TypePathSegment::GENERIC: { + case TypePathSegment::GENERIC: + { TypePathSegmentGeneric &generic = (TypePathSegmentGeneric &) (*seg.get ()); @@ -89,7 +91,8 @@ ASTTypeBuilder::visit (TypePath &path) } break; - case TypePathSegment::FUNCTION: { + case TypePathSegment::FUNCTION: + { rust_unreachable (); // TODO // const TypePathSegmentFunction &fn diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 08c52b1..fbc8f27 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -442,6 +442,14 @@ Builder::field_access (std::unique_ptr<Expr> &&instance, new FieldAccessExpr (std::move (instance), field, {}, loc)); } +std::unique_ptr<StructPatternField> +Builder::struct_pattern_ident_pattern (std::string field_name, + std::unique_ptr<Pattern> &&pattern) +{ + return std::make_unique<StructPatternFieldIdentPat> ( + field_name, std::move (pattern), std::vector<Attribute> (), loc); +} + std::unique_ptr<Pattern> Builder::wildcard () const { @@ -566,7 +574,8 @@ Builder::new_type_param ( { switch (b->get_bound_type ()) { - case TypeParamBound::TypeParamBoundType::TRAIT: { + case TypeParamBound::TypeParamBoundType::TRAIT: + { const TraitBound &tb = (const TraitBound &) *b.get (); const TypePath &path = tb.get_type_path (); @@ -591,7 +600,8 @@ Builder::new_type_param ( { switch (seg->get_type ()) { - case TypePathSegment::REG: { + case TypePathSegment::REG: + { const TypePathSegment &segment = (const TypePathSegment &) (*seg.get ()); TypePathSegment *s = new TypePathSegment ( @@ -603,7 +613,8 @@ Builder::new_type_param ( } break; - case TypePathSegment::GENERIC: { + case TypePathSegment::GENERIC: + { TypePathSegmentGeneric &generic = (TypePathSegmentGeneric &) (*seg.get ()); @@ -617,7 +628,8 @@ Builder::new_type_param ( } break; - case TypePathSegment::FUNCTION: { + case TypePathSegment::FUNCTION: + { rust_unreachable (); // TODO // const TypePathSegmentFunction &fn @@ -639,7 +651,8 @@ Builder::new_type_param ( } break; - case TypeParamBound::TypeParamBoundType::LIFETIME: { + case TypeParamBound::TypeParamBoundType::LIFETIME: + { const Lifetime &l = (const Lifetime &) *b.get (); auto bl = new Lifetime (l.get_lifetime_type (), @@ -692,7 +705,8 @@ Builder::new_generic_args (GenericArgs &args) { switch (arg.get_kind ()) { - case GenericArg::Kind::Type: { + case GenericArg::Kind::Type: + { std::unique_ptr<Type> ty = new_type (arg.get_type ()); GenericArg arg = GenericArg::create_type (std::move (ty)); } diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index 41ce118..a5115b68 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -254,6 +254,10 @@ public: std::unique_ptr<Expr> field_access (std::unique_ptr<Expr> &&instance, std::string field) const; + std::unique_ptr<StructPatternField> + struct_pattern_ident_pattern (std::string field_name, + std::unique_ptr<Pattern> &&pattern); + /* Create a wildcard pattern (`_`) */ std::unique_ptr<Pattern> wildcard () const; /* Create a reference pattern (`&pattern`) */ diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index c850e96..b0e06ab 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -154,20 +154,24 @@ TokenCollector::visit (Attribute &attrib) { switch (attrib.get_attr_input ().get_attr_input_type ()) { - case AST::AttrInput::AttrInputType::LITERAL: { + case AST::AttrInput::AttrInputType::LITERAL: + { visit (static_cast<AttrInputLiteral &> (attrib.get_attr_input ())); break; } - case AST::AttrInput::AttrInputType::MACRO: { + case AST::AttrInput::AttrInputType::MACRO: + { visit (static_cast<AttrInputMacro &> (attrib.get_attr_input ())); break; } - case AST::AttrInput::AttrInputType::META_ITEM: { + case AST::AttrInput::AttrInputType::META_ITEM: + { visit (static_cast<AttrInputMetaItemContainer &> ( attrib.get_attr_input ())); break; } - case AST::AttrInput::AttrInputType::TOKEN_TREE: { + case AST::AttrInput::AttrInputType::TOKEN_TREE: + { visit (static_cast<DelimTokenTree &> (attrib.get_attr_input ())); break; } @@ -634,7 +638,8 @@ TokenCollector::visit (GenericArg &arg) case GenericArg::Kind::Type: visit (arg.get_type ()); break; - case GenericArg::Kind::Either: { + case GenericArg::Kind::Either: + { auto path = arg.get_path (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path))); } @@ -789,7 +794,8 @@ TokenCollector::visit (Literal &lit, location_t locus) push (Rust::Token::make_float (locus, std::move (value), lit.get_type_hint ())); break; - case Literal::LitType::BOOL: { + case Literal::LitType::BOOL: + { if (value == Values::Keywords::FALSE_LITERAL) push (Rust::Token::make (FALSE_LITERAL, locus)); else if (value == Values::Keywords::TRUE_LITERAL) @@ -1264,12 +1270,28 @@ TokenCollector::visit (BlockExpr &expr) } void +TokenCollector::visit (AnonConst &expr) +{ + visit (expr.get_inner_expr ()); +} + +void +TokenCollector::visit (ConstBlock &expr) +{ + push (Rust::Token::make (CONST, expr.get_locus ())); + + // The inner expression is already a block expr, so we don't need to add + // curlies + visit (expr.get_const_expr ()); +} + +void TokenCollector::visit (ClosureExprInnerTyped &expr) { visit_closure_common (expr); push (Rust::Token::make (RETURN_TYPE, expr.get_locus ())); visit (expr.get_return_type ()); - visit (expr.get_definition_block ()); + visit (expr.get_definition_expr ()); } void @@ -1518,7 +1540,95 @@ TokenCollector::visit (AsyncBlockExpr &expr) void TokenCollector::visit (InlineAsm &expr) -{} +{ + push (Rust::Token::make_identifier (expr.get_locus (), "asm")); + push (Rust::Token::make (EXCLAM, expr.get_locus ())); + push (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); + + for (auto &template_str : expr.get_template_strs ()) + push (Rust::Token::make_string (template_str.get_locus (), + std::move (template_str.symbol))); + + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &operand : expr.get_operands ()) + { + using RegisterType = AST::InlineAsmOperand::RegisterType; + switch (operand.get_register_type ()) + { + case RegisterType::In: + { + visit (operand.get_in ().expr); + break; + } + case RegisterType::Out: + { + visit (operand.get_out ().expr); + break; + } + case RegisterType::InOut: + { + visit (operand.get_in_out ().expr); + break; + } + case RegisterType::SplitInOut: + { + auto split = operand.get_split_in_out (); + visit (split.in_expr); + visit (split.out_expr); + break; + } + case RegisterType::Const: + { + visit (operand.get_const ().anon_const.get_inner_expr ()); + break; + } + case RegisterType::Sym: + { + visit (operand.get_sym ().expr); + break; + } + case RegisterType::Label: + { + visit (operand.get_label ().expr); + break; + } + } + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &clobber : expr.get_clobber_abi ()) + { + push (Rust::Token::make_string (expr.get_locus (), + std::move (clobber.symbol))); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto it = expr.named_args.begin (); it != expr.named_args.end (); ++it) + { + auto &arg = *it; + push ( + Rust::Token::make_identifier (expr.get_locus (), arg.first.c_str ())); + push (Rust::Token::make (EQUAL, expr.get_locus ())); + push (Rust::Token::make_identifier (expr.get_locus (), + std::to_string (arg.second))); + + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &option : expr.get_options ()) + { + push (Rust::Token::make_identifier ( + expr.get_locus (), InlineAsm::option_to_string (option).c_str ())); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ())); +} void TokenCollector::visit (LlvmInlineAsm &expr) @@ -1695,7 +1805,8 @@ TokenCollector::visit (UseTreeGlob &use_tree) { switch (use_tree.get_glob_type ()) { - case UseTreeGlob::PathType::PATH_PREFIXED: { + case UseTreeGlob::PathType::PATH_PREFIXED: + { auto path = use_tree.get_path (); visit (path); push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); @@ -1715,7 +1826,8 @@ TokenCollector::visit (UseTreeList &use_tree) { switch (use_tree.get_path_type ()) { - case UseTreeList::PathType::PATH_PREFIXED: { + case UseTreeList::PathType::PATH_PREFIXED: + { auto path = use_tree.get_path (); visit (path); push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); @@ -1743,7 +1855,8 @@ TokenCollector::visit (UseTreeRebind &use_tree) visit (path); switch (use_tree.get_new_bind_type ()) { - case UseTreeRebind::NewBindType::IDENTIFIER: { + case UseTreeRebind::NewBindType::IDENTIFIER: + { push (Rust::Token::make (AS, UNDEF_LOCATION)); auto id = use_tree.get_identifier ().as_string (); push ( @@ -1964,8 +2077,7 @@ TokenCollector::visit (ConstantItem &item) } else { - auto id = item.get_identifier (); - push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); + push (Rust::Token::make_identifier (item.get_identifier ())); } push (Rust::Token::make (COLON, UNDEF_LOCATION)); visit (item.get_type ()); @@ -2370,7 +2482,7 @@ TokenCollector::visit (IdentifierPattern &pattern) auto id = pattern.get_ident ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); - if (pattern.has_pattern_to_bind ()) + if (pattern.has_subpattern ()) { push (Rust::Token::make (PATTERN_BIND, UNDEF_LOCATION)); visit (pattern.get_pattern_to_bind ()); diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index f45e3cc..cec2365 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -277,6 +277,8 @@ public: void visit (ClosureParam ¶m); void visit (ClosureExprInner &expr); void visit (BlockExpr &expr); + void visit (AnonConst &expr); + void visit (ConstBlock &expr); void visit (ClosureExprInnerTyped &expr); void visit (ContinueExpr &expr); void visit (BreakExpr &expr); diff --git a/gcc/rust/ast/rust-ast-dump.h b/gcc/rust/ast/rust-ast-dump.h index 02c99b7..0c3875e 100644 --- a/gcc/rust/ast/rust-ast-dump.h +++ b/gcc/rust/ast/rust-ast-dump.h @@ -49,7 +49,8 @@ public: { switch (item.get_kind ()) { - case AST::CollectItem::Kind::Token: { + case AST::CollectItem::Kind::Token: + { TokenPtr current = item.get_token (); if (require_spacing (previous, current)) stream << " "; @@ -90,7 +91,6 @@ private: } // namespace Rust // In the global namespace to make it easier to call from debugger -void -debug (Rust::AST::Visitable &v); +void debug (Rust::AST::Visitable &v); #endif // !RUST_AST_DUMP_H diff --git a/gcc/rust/ast/rust-ast-formatting.h b/gcc/rust/ast/rust-ast-formatting.h index 3dfabbc..aace93f 100644 --- a/gcc/rust/ast/rust-ast-formatting.h +++ b/gcc/rust/ast/rust-ast-formatting.h @@ -35,23 +35,18 @@ enum AttrMode INNER }; -std::string -indent_spaces (enum indent_mode mode); +std::string indent_spaces (enum indent_mode mode); // Gets a string in a certain delim type. -std::string -get_string_in_delims (std::string str_input, DelimType delim_type); +std::string get_string_in_delims (std::string str_input, DelimType delim_type); -std::string -get_mode_dump_desc (AttrMode mode); +std::string get_mode_dump_desc (AttrMode mode); // Adds lines below adding attributes -std::string -append_attributes (std::vector<Attribute> attrs, AttrMode mode); +std::string append_attributes (std::vector<Attribute> attrs, AttrMode mode); // Removes the beginning and end quotes of a quoted string. -std::string -unquote_string (std::string input); +std::string unquote_string (std::string input); } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 9359248..b410f3a 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -115,6 +115,8 @@ struct ClosureParam; class ClosureExpr; class ClosureExprInner; class BlockExpr; +class AnonConst; +class ConstBlock; class ClosureExprInnerTyped; class ContinueExpr; class BreakExpr; @@ -146,7 +148,6 @@ class MatchExpr; class AwaitExpr; class AsyncBlockExpr; enum class InlineAsmOption; -struct AnonConst; struct InlineAsmRegOrRegClass; class InlineAsmOperand; struct InlineAsmPlaceHolder; diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index b6833f6..02f4f16 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -456,13 +456,25 @@ DefaultASTVisitor::visit (AST::BlockExpr &expr) } void +DefaultASTVisitor::visit (AST::ConstBlock &expr) +{ + visit (expr.get_const_expr ()); +} + +void +DefaultASTVisitor::visit (AST::AnonConst &expr) +{ + visit (expr.get_inner_expr ()); +} + +void DefaultASTVisitor::visit (AST::ClosureExprInnerTyped &expr) { visit_outer_attrs (expr); for (auto ¶m : expr.get_params ()) visit (param); visit (expr.get_return_type ()); - visit (expr.get_definition_block ()); + visit (expr.get_definition_expr ()); } void @@ -680,33 +692,40 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr) { switch (operand.get_register_type ()) { - case RegisterType::In: { + case RegisterType::In: + { visit (operand.get_in ().expr); break; } - case RegisterType::Out: { + case RegisterType::Out: + { visit (operand.get_out ().expr); break; } - case RegisterType::InOut: { + case RegisterType::InOut: + { visit (operand.get_in_out ().expr); break; } - case RegisterType::SplitInOut: { + case RegisterType::SplitInOut: + { auto split = operand.get_split_in_out (); visit (split.in_expr); visit (split.out_expr); break; } - case RegisterType::Const: { - visit (operand.get_const ().anon_const.expr); + case RegisterType::Const: + { + visit (operand.get_const ().anon_const.get_inner_expr ()); break; } - case RegisterType::Sym: { + case RegisterType::Sym: + { visit (operand.get_sym ().expr); break; } - case RegisterType::Label: { + case RegisterType::Label: + { visit (operand.get_label ().expr); break; } @@ -755,7 +774,8 @@ DefaultASTVisitor::visit (AST::TypeBoundWhereClauseItem &item) void DefaultASTVisitor::visit (AST::Visibility &vis) { - visit (vis.get_path ()); + if (vis.has_path ()) + visit (vis.get_path ()); } void @@ -922,7 +942,7 @@ DefaultASTVisitor::visit (AST::EnumItem &item) void DefaultASTVisitor::visit (AST::EnumItemTuple &item) { - visit (reinterpret_cast<EnumItem &> (item)); + DefaultASTVisitor::visit (reinterpret_cast<EnumItem &> (item)); for (auto &field : item.get_tuple_fields ()) visit (field); } @@ -930,7 +950,7 @@ DefaultASTVisitor::visit (AST::EnumItemTuple &item) void DefaultASTVisitor::visit (AST::EnumItemStruct &item) { - visit (reinterpret_cast<EnumItem &> (item)); + DefaultASTVisitor::visit (reinterpret_cast<EnumItem &> (item)); for (auto &field : item.get_struct_fields ()) visit (field); } @@ -938,7 +958,7 @@ DefaultASTVisitor::visit (AST::EnumItemStruct &item) void DefaultASTVisitor::visit (AST::EnumItemDiscriminant &item) { - visit (reinterpret_cast<EnumItem &> (item)); + DefaultASTVisitor::visit (reinterpret_cast<EnumItem &> (item)); visit (item.get_expr ()); } @@ -1179,7 +1199,7 @@ DefaultASTVisitor::visit (AST::LiteralPattern &pattern) void DefaultASTVisitor::visit (AST::IdentifierPattern &pattern) { - if (pattern.has_pattern_to_bind ()) + if (pattern.has_subpattern ()) visit (pattern.get_pattern_to_bind ()); } diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index b1fc504..22fd98b 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -104,6 +104,8 @@ public: virtual void visit (FieldAccessExpr &expr) = 0; virtual void visit (ClosureExprInner &expr) = 0; virtual void visit (BlockExpr &expr) = 0; + virtual void visit (AnonConst &expr) = 0; + virtual void visit (ConstBlock &expr) = 0; virtual void visit (ClosureExprInnerTyped &expr) = 0; virtual void visit (ContinueExpr &expr) = 0; virtual void visit (BreakExpr &expr) = 0; @@ -293,6 +295,8 @@ public: virtual void visit (AST::FieldAccessExpr &expr) override; virtual void visit (AST::ClosureExprInner &expr) override; virtual void visit (AST::BlockExpr &expr) override; + virtual void visit (AST::AnonConst &expr) override; + virtual void visit (AST::ConstBlock &expr) override; virtual void visit (AST::ClosureExprInnerTyped &expr) override; virtual void visit (AST::ContinueExpr &expr) override; virtual void visit (AST::BreakExpr &expr) override; diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 4e82be4..916829f 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -249,27 +249,31 @@ Attribute::get_traits_to_derive () auto &input = get_attr_input (); switch (input.get_attr_input_type ()) { - case AST::AttrInput::META_ITEM: { + case AST::AttrInput::META_ITEM: + { auto &meta = static_cast<AST::AttrInputMetaItemContainer &> (input); for (auto ¤t : meta.get_items ()) { // HACK: Find a better way to achieve the downcast. switch (current->get_kind ()) { - case AST::MetaItemInner::Kind::MetaItem: { + case AST::MetaItemInner::Kind::MetaItem: + { // Let raw pointer go out of scope without freeing, it doesn't // own the data anyway auto meta_item = static_cast<AST::MetaItem *> (current.get ()); switch (meta_item->get_item_kind ()) { - case AST::MetaItem::ItemKind::Path: { + case AST::MetaItem::ItemKind::Path: + { auto path = static_cast<AST::MetaItemPath *> (meta_item); result.push_back (path->get_path ()); } break; - case AST::MetaItem::ItemKind::Word: { + case AST::MetaItem::ItemKind::Word: + { auto word = static_cast<AST::MetaWord *> (meta_item); // Convert current word to path current = std::make_unique<AST::MetaItemPath> ( @@ -620,7 +624,7 @@ ConstantItem::as_string () const { std::string str = VisItem::as_string (); - str += "const " + identifier; + str += "const " + identifier.as_string (); // DEBUG: null pointer check if (type == nullptr) @@ -782,7 +786,8 @@ UseTreeGlob::as_string () const return "*"; case GLOBAL: return "::*"; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { std::string path_str = path.as_string (); return path_str + "::*"; } @@ -805,7 +810,8 @@ UseTreeList::as_string () const case GLOBAL: path_str = "::{"; break; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { path_str = path.as_string () + "::{"; break; } @@ -1272,6 +1278,18 @@ BlockExpr::as_string () const } std::string +AnonConst::as_string () const +{ + return "AnonConst: " + expr->as_string (); +} + +std::string +ConstBlock::as_string () const +{ + return "ConstBlock: " + expr.as_string (); +} + +std::string TraitImpl::as_string () const { std::string str = VisItem::as_string (); @@ -2714,7 +2732,7 @@ ImplTraitTypeOneBound::as_string () const { std::string str ("ImplTraitTypeOneBound: \n TraitBound: "); - return str + trait_bound.as_string (); + return str + trait_bound->as_string (); } std::string @@ -3653,14 +3671,16 @@ AttributeParser::parse_path_meta_item () switch (peek_token ()->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { std::vector<std::unique_ptr<MetaItemInner>> meta_items = parse_meta_item_seq (); return std::unique_ptr<MetaItemSeq> ( new MetaItemSeq (std::move (path), std::move (meta_items))); } - case EQUAL: { + case EQUAL: + { skip_token (); location_t locus = peek_token ()->get_locus (); @@ -4513,6 +4533,18 @@ BlockExpr::accept_vis (ASTVisitor &vis) } void +AnonConst::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstBlock::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void ClosureExprInnerTyped::accept_vis (ASTVisitor &vis) { vis.visit (*this); @@ -5047,7 +5079,8 @@ FormatArgs::get_outer_attrs () rust_unreachable (); } -void FormatArgs::set_outer_attrs (std::vector<Attribute>) +void +FormatArgs::set_outer_attrs (std::vector<Attribute>) { rust_unreachable (); } diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index aa6ad50..cd586c6 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -62,13 +62,14 @@ public: return ident == other.ident; } + operator const std::string & () const { return ident; } + private: std::string ident; location_t loc; }; -std::ostream & -operator<< (std::ostream &os, Identifier const &i); +std::ostream &operator<< (std::ostream &os, Identifier const &i); namespace AST { // foward decl: ast visitor @@ -403,15 +404,15 @@ class SimplePath public: // Constructor - SimplePath (std::vector<SimplePathSegment> path_segments, - bool has_opening_scope_resolution = false, - location_t locus = UNDEF_LOCATION) + explicit SimplePath (std::vector<SimplePathSegment> path_segments, + bool has_opening_scope_resolution = false, + location_t locus = UNDEF_LOCATION) : opening_scope_resolution (has_opening_scope_resolution), segments (std::move (path_segments)), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} - SimplePath (Identifier ident) + explicit SimplePath (Identifier ident) : opening_scope_resolution (false), segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}), locus (ident.get_locus ()), @@ -1256,6 +1257,8 @@ public: FieldAccess, Closure, Block, + ConstExpr, + ConstBlock, Continue, Break, Range, diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc index cd6be7f..306c6f7 100644 --- a/gcc/rust/ast/rust-collect-lang-items.cc +++ b/gcc/rust/ast/rust-collect-lang-items.cc @@ -109,5 +109,29 @@ CollectLangItems::visit (AST::EnumItem &item) DefaultASTVisitor::visit (item); } +void +CollectLangItems::visit (AST::EnumItemTuple &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::EnumItemStruct &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::EnumItemDiscriminant &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-collect-lang-items.h b/gcc/rust/ast/rust-collect-lang-items.h index ddb34a9..ddc7b51 100644 --- a/gcc/rust/ast/rust-collect-lang-items.h +++ b/gcc/rust/ast/rust-collect-lang-items.h @@ -50,6 +50,9 @@ public: void visit (AST::Function &item) override; void visit (AST::StructStruct &item) override; void visit (AST::EnumItem &item) override; + void visit (AST::EnumItemTuple &item) override; + void visit (AST::EnumItemStruct &item) override; + void visit (AST::EnumItemDiscriminant &item) override; private: template <typename T> void maybe_add_lang_item (const T &item); diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h index 610b904..56a5646 100644 --- a/gcc/rust/ast/rust-cond-compilation.h +++ b/gcc/rust/ast/rust-cond-compilation.h @@ -42,8 +42,8 @@ public: protected: // Clone function impl to be overriden in base classes - virtual ConfigurationPredicate * - clone_configuration_predicate_impl () const = 0; + virtual ConfigurationPredicate *clone_configuration_predicate_impl () const + = 0; }; // A configuration option - true if option is set, false if option is not set. diff --git a/gcc/rust/ast/rust-desugar-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc new file mode 100644 index 0000000..bca14ee --- /dev/null +++ b/gcc/rust/ast/rust-desugar-apit.cc @@ -0,0 +1,522 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-desugar-apit.h" +#include "rust-ast.h" +#include "rust-type.h" + +namespace Rust { +namespace AST { + +class DesugarApitType : public DefaultASTVisitor +{ + using DefaultASTVisitor::visit; + +public: + static std::pair<AST::Type *, std::vector<std::unique_ptr<GenericParam>>> + Desugar (AST::Type &type) + { + DesugarApitType visitor (&type); + type.accept_vis (visitor); + rust_assert (visitor.translated != nullptr); + return std::make_pair (visitor.translated, + std::move (visitor.implicit_generic_params)); + } + + // Generate a unique impl trait parameter name + static Identifier get_impl_name () + { + static size_t counter = 0; + return Identifier ("Impl_" + std::to_string (counter++)); + } + + // these can hold other types + void visit (AST::TupleType &tuple) override + { + for (auto &elem : tuple.get_elems ()) + { + auto &type = *elem.get (); + auto desugar = Desugar (type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + continue; + + if (tt != elem.get ()) + elem = std::unique_ptr<Type> (tt); + + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + } + + void visit (AST::ArrayType &type) override + { + auto &element_type = type.get_element_type (); + auto desugar = Desugar (*element_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (tt != element_type.get ()) + element_type = std::unique_ptr<AST::Type> (tt); + + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::ReferenceType &type) override + { + // Get a reference to the current type for in-place modification + auto &referenced_type = type.get_type_referenced (); + auto desugar = Desugar (referenced_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + // Update the reference type's contents rather than creating a new one + if (&referenced_type != tt) + { + std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds ( + static_cast<AST::TypeNoBounds *> (tt)); + type.get_type_ptr () = std::move (new_type_no_bounds); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::RawPointerType &type) override + { + auto &pointed_type = type.get_type_pointed_to (); + auto desugar = Desugar (pointed_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + // Update the pointer's inner type directly using the new accessor + if (&pointed_type != tt) + { + std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds ( + static_cast<AST::TypeNoBounds *> (tt)); + type.get_type_ptr () = std::move (new_type_no_bounds); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::SliceType &type) override + { + auto &element_type = type.get_elem_type (); + auto desugar = Desugar (element_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (&element_type != tt) + { + std::unique_ptr<AST::Type> new_elem_type (tt); + type.get_elem_type_ptr () = std::move (new_elem_type); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::ParenthesisedType &type) override + { + auto &inner_type_ptr = type.get_type_in_parens (); + auto desugar = Desugar (*inner_type_ptr); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (inner_type_ptr.get () != tt) + { + std::unique_ptr<AST::Type> new_inner_type (tt); + inner_type_ptr = std::move (new_inner_type); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + // this is where the desugar happens + void visit (AST::ImplTraitType &type) override + { + // Generate a unique name using the static method + auto ident = get_impl_name (); + + // Create a type path for the new generic parameter + // Create a SimplePathSegment with the identifier string + auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ()); + // Create a vector of SimplePathSegments for SimplePath constructor + std::vector<SimplePathSegment> simple_segs = {simple_seg}; + // Create a SimplePath + auto simple_path = SimplePath (simple_segs, false, type.get_locus ()); + + // Convert to TypePath by creating path segments + std::vector<std::unique_ptr<TypePathSegment>> segments; + segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment ( + PathIdentSegment (ident.as_string (), type.get_locus ()), false, + type.get_locus ()))); + + // Create TypePath from segments + auto type_path + = new TypePath (std::move (segments), type.get_locus (), false); + + // Convert bounds from impl trait to generic parameter bounds + std::vector<std::unique_ptr<TypeParamBound>> bounds; + for (auto &bound : type.get_type_param_bounds ()) + bounds.push_back (bound->clone_type_param_bound ()); + + // Create the new generic parameter + auto generic_param = std::unique_ptr<TypeParam> ( + new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {}, + true /*from impl trait*/)); + + // Store the generic parameter to be added to the function signature + implicit_generic_params.push_back (std::move (generic_param)); + + // Replace impl trait with the new type parameter + translated = type_path; + } + + void visit (AST::ImplTraitTypeOneBound &type) override + { + // Generate a unique name using the static method + auto ident = get_impl_name (); + + // Create a type path for the new generic parameter + // Create a SimplePathSegment with the identifier string + auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ()); + // Create a vector of SimplePathSegments for SimplePath constructor + std::vector<SimplePathSegment> simple_segs = {simple_seg}; + // Create a SimplePath + auto simple_path = SimplePath (simple_segs, false, type.get_locus ()); + + // Convert to TypePath by creating path segments + std::vector<std::unique_ptr<TypePathSegment>> segments; + segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment ( + PathIdentSegment (ident.as_string (), type.get_locus ()), false, + type.get_locus ()))); + + // Create TypePath from segments + auto type_path + = new TypePath (std::move (segments), type.get_locus (), false); + + // Convert the bound to a generic parameter bound + std::vector<std::unique_ptr<TypeParamBound>> bounds; + bounds.push_back (std::move (type.get_trait_bound ())); + + // Create the new generic parameter + auto generic_param = std::unique_ptr<TypeParam> ( + new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {}, + true /*from impl trait*/)); + + // Store the generic parameter to be added to the function signature + implicit_generic_params.push_back (std::move (generic_param)); + + // Replace impl trait with the new type parameter + translated = type_path; + } + +private: + DesugarApitType (AST::Type *base) + : translated (base), implicit_generic_params () + {} + + AST::Type *translated; + std::vector<std::unique_ptr<GenericParam>> implicit_generic_params; +}; + +// --------- + +class ApitBoundProcessor +{ +public: + ApitBoundProcessor ( + WhereClause &where_clause, + std::vector<std::unique_ptr<GenericParam>> &generic_params) + : where_clause (where_clause), generic_params (generic_params) + {} + + void go (std::vector<std::unique_ptr<GenericParam>> &implicit_generics) + { + // some desugars are more complex so imagine this case + // + // pub fn foo(_value: impl Bar<Baz = impl Foo>) -> i32 { + // 15 + // } + // + // this needs to become: + // + // pub fn foo<T, U>(_value: T) -> i32 + // where + // T: Bar<Baz = U>, + // U: Foo, + // { + // 15 + // } + // + // so we need to walk all the implicit generics and the trait bounds paths + // for more generics + + for (auto &implicit_generic : implicit_generics) + { + switch (implicit_generic->get_kind ()) + { + case GenericParam::Kind::Type: + { + TypeParam &p + = *static_cast<TypeParam *> (implicit_generic.get ()); + + process_type_param (p); + generic_params.push_back (std::move (implicit_generic)); + for (auto &synth : synthetic_params) + generic_params.push_back (std::move (synth)); + synthetic_params.clear (); + } + break; + + default: + generic_params.push_back (std::move (implicit_generic)); + break; + } + } + } + +private: + void process_type_param (TypeParam &p) + { + auto &bounds = p.get_type_param_bounds (); + std::vector<size_t> bounds_to_remove; + for (size_t i = 0; i < bounds.size (); i++) + { + auto &tb = bounds[i]; + switch (tb->get_bound_type ()) + { + case TypeParamBound::TypeParamBoundType::TRAIT: + { + TraitBound &ttb = *static_cast<TraitBound *> (tb.get ()); + TypePath &path = ttb.get_type_path (); + bool deusgared = process_type_path (p, ttb, path); + if (deusgared) + bounds_to_remove.push_back (i); + } + + default: + break; + } + } + for (auto it = bounds_to_remove.rbegin (); it != bounds_to_remove.rend (); + ++it) + bounds.erase (bounds.begin () + *it); + } + + bool process_type_path (TypeParam &p, TraitBound &parent, TypePath &path) + { + bool desugared = false; + for (auto &segment : path.get_segments ()) + { + switch (segment->get_type ()) + { + case TypePathSegment::SegmentType::GENERIC: + { + TypePathSegmentGeneric &seg + = *static_cast<TypePathSegmentGeneric *> (segment.get ()); + desugared |= process_generic_segment (p, parent, path, seg); + } + + default: + break; + } + } + return desugared; + } + + bool process_generic_segment (TypeParam &p, TraitBound &parent, + TypePath &path, TypePathSegmentGeneric &seg) + { + // we need to look for any impl types as default arguments in any generics + // and remove this index from the generic arguments by using a where + // constraint instead + + std::vector<std::unique_ptr<WhereClauseItem>> new_clauses; + GenericArgs &generic_args = seg.get_generic_args (); + std::vector<std::reference_wrapper<const GenericArgsBinding>> + bindings_desugared; + std::vector<GenericArgsBinding> &bindings + = generic_args.get_binding_args (); + + for (auto &generic : bindings) + { + auto &t = generic.get_type (); + auto translated = DesugarApitType::Desugar (t); + auto tt = translated.first; + + auto &implicit_generics = translated.second; + if (implicit_generics.empty ()) + continue; + + if (tt != &t) + { + bindings_desugared.push_back (generic); + generic.get_type_ptr () = std::unique_ptr<Type> (tt); + } + + for (auto &implicit_generic : implicit_generics) + { + switch (implicit_generic->get_kind ()) + { + case GenericParam::Kind::Type: + { + TypeParam &tp + = *static_cast<TypeParam *> (implicit_generic.get ()); + + std::vector<std::unique_ptr<TypeParamBound>> + type_param_bounds; + for (auto &b : tp.get_type_param_bounds ()) + type_param_bounds.push_back (std::move (b)); + tp.get_type_param_bounds ().clear (); + + // add synthetic parameter for this + synthetic_params.push_back (std::move (implicit_generic)); + + auto bound_type_path + = get_type_for_identifier (tp.get_type_representation ()); + + auto clause = new TypeBoundWhereClauseItem ( + {}, std::move (bound_type_path), + std::move (type_param_bounds), tp.get_locus ()); + std::unique_ptr<WhereClauseItem> clause_item + = std::unique_ptr<WhereClauseItem> (clause); + new_clauses.push_back (std::move (clause_item)); + } + break; + + default: + synthetic_params.push_back (std::move (implicit_generic)); + break; + } + } + } + + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; + auto bound = std::unique_ptr<TypeParamBound> (new TraitBound (parent)); + type_param_bounds.push_back (std::move (bound)); + auto parent_type_path + = get_type_for_identifier (p.get_type_representation ()); + auto clause + = new TypeBoundWhereClauseItem ({}, std::move (parent_type_path), + std::move (type_param_bounds), + parent.get_locus ()); + std::unique_ptr<WhereClauseItem> clause_item + = std::unique_ptr<WhereClauseItem> (clause); + where_clause.get_items ().push_back (std::move (clause_item)); + + for (auto &where_item : new_clauses) + where_clause.get_items ().push_back (std::move (where_item)); + + return !bindings_desugared.empty (); + } + + static std::unique_ptr<Type> get_type_for_identifier (const Identifier &ident) + { + auto simple_seg + = SimplePathSegment (ident.as_string (), ident.get_locus ()); + std::vector<SimplePathSegment> simple_segs = {simple_seg}; + auto simple_path = SimplePath (simple_segs, false, ident.get_locus ()); + std::vector<std::unique_ptr<TypePathSegment>> segments; + segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment ( + PathIdentSegment (ident.as_string (), ident.get_locus ()), false, + ident.get_locus ()))); + auto type_path = new TypePath (std::move (segments), ident.get_locus ()); + return std::unique_ptr<Type> (type_path); + } + +private: + WhereClause &where_clause; + std::vector<std::unique_ptr<GenericParam>> &generic_params; + + // mutates + std::vector<std::unique_ptr<GenericParam>> synthetic_params; +}; + +// --------- + +DesugarApit::DesugarApit () {} + +void +DesugarApit::go (AST::Crate &crate) +{ + DefaultASTVisitor::visit (crate); +} + +void +DesugarApit::visit (AST::Function &function) +{ + if (!function.has_function_params ()) + return; + + auto &fn_params = function.get_function_params (); + for (auto ¶m : fn_params) + { + if (param->is_variadic () || param->is_self ()) + continue; + + auto *p = param.get (); + auto &fp = *static_cast<AST::FunctionParam *> (p); + auto &type = fp.get_type (); + + auto translated = DesugarApitType::Desugar (type); + auto tt = translated.first; + + auto &implicit_generics = translated.second; + if (implicit_generics.empty ()) + continue; + + if (fp.get_type_ptr ().get () != tt) + { + fp.get_type_ptr () = std::unique_ptr<AST::Type> (tt); + } + + ApitBoundProcessor processor (function.get_where_clause (), + function.get_generic_params ()); + processor.go (implicit_generics); + } +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/ast/rust-desugar-apit.h index 2703438..07c25e2 100644 --- a/gcc/rust/ast/rust-macro.cc +++ b/gcc/rust/ast/rust-desugar-apit.h @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. +// Copyright (C) 2025 Free Software Foundation, Inc. // This file is part of GCC. @@ -16,10 +16,27 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -#include "rust-macro.h" +#ifndef RUST_DESUGAR_APIT_H +#define RUST_DESUGAR_APIT_H + +#include "rust-ast-visitor.h" namespace Rust { namespace AST { +class DesugarApit : public DefaultASTVisitor +{ + using DefaultASTVisitor::visit; + +public: + DesugarApit (); + void go (AST::Crate &); + +private: + void visit (AST::Function &) override; +}; + } // namespace AST } // namespace Rust + +#endif // ! RUST_DESUGAR_APIT_H diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index fdb6360..8f44d58 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1214,6 +1214,8 @@ protected: class ArrayElemsCopied : public ArrayElems { std::unique_ptr<Expr> elem_to_copy; + + // TODO: This should be replaced by a ConstExpr std::unique_ptr<Expr> num_copies; location_t locus; @@ -2504,6 +2506,8 @@ public: bool get_has_move () const { return has_move; } Expr::Kind get_expr_kind () const override { return Expr::Kind::Closure; } + + virtual Expr &get_definition_expr () = 0; }; // Represents a non-type-specified closure expression AST node @@ -2563,7 +2567,7 @@ public: return closure_inner == nullptr; } - Expr &get_definition_expr () + Expr &get_definition_expr () override { rust_assert (closure_inner != nullptr); return *closure_inner; @@ -2744,6 +2748,124 @@ protected: } }; +class AnonConst : public ExprWithBlock +{ +public: + AnonConst (std::unique_ptr<Expr> &&expr, location_t locus = UNKNOWN_LOCATION) + : ExprWithBlock (), locus (locus), expr (std::move (expr)) + { + rust_assert (this->expr); + } + + AnonConst (const AnonConst &other) + { + node_id = other.node_id; + locus = other.locus; + expr = other.expr->clone_expr (); + } + + AnonConst operator= (const AnonConst &other) + { + node_id = other.node_id; + locus = other.locus; + expr = other.expr->clone_expr (); + + return *this; + } + + std::string as_string () const override; + + Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstExpr; } + + location_t get_locus () const override { return locus; } + Expr &get_inner_expr () { return *expr; } + NodeId get_node_id () const override { return node_id; } + + /* FIXME: AnonConst are always "internal" and should not have outer attributes + * - is that true? Or should we instead call + * expr->get_outer_attrs()/expr->set_outer_attrs() */ + + std::vector<Attribute> &get_outer_attrs () override + { + static auto attrs = std::vector<Attribute> (); + return attrs; + } + + void set_outer_attrs (std::vector<Attribute>) override {} + + /* FIXME: Likewise for mark_for_strip() ? */ + void mark_for_strip () override {} + bool is_marked_for_strip () const override { return false; } + + void accept_vis (ASTVisitor &vis) override; + +private: + location_t locus; + std::unique_ptr<Expr> expr; + + AnonConst *clone_expr_with_block_impl () const override + { + return new AnonConst (*this); + } +}; + +class ConstBlock : public ExprWithBlock +{ +public: + ConstBlock (AnonConst &&expr, location_t locus = UNKNOWN_LOCATION, + std::vector<Attribute> &&outer_attrs = {}) + : ExprWithBlock (), expr (std::move (expr)), + outer_attrs (std::move (outer_attrs)), locus (locus) + {} + + ConstBlock (const ConstBlock &other) + : ExprWithBlock (other), expr (other.expr), outer_attrs (other.outer_attrs), + locus (other.locus) + {} + + ConstBlock operator= (const ConstBlock &other) + { + expr = other.expr; + node_id = other.node_id; + outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + std::string as_string () const override; + + Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstBlock; } + + AnonConst &get_const_expr () { return expr; } + + void accept_vis (ASTVisitor &vis) override; + + std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } + + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } + + location_t get_locus () const override { return locus; } + + bool is_marked_for_strip () const override { return marked_for_strip; } + void mark_for_strip () override { marked_for_strip = true; } + +private: + AnonConst expr; + + std::vector<Attribute> outer_attrs; + location_t locus; + bool marked_for_strip = false; + + ConstBlock *clone_expr_with_block_impl () const override + { + return new ConstBlock (*this); + } +}; + // Represents a type-specified closure expression AST node class ClosureExprInnerTyped : public ClosureExpr { @@ -2812,7 +2934,7 @@ public: bool is_marked_for_strip () const override { return expr == nullptr; } // TODO: is this better? Or is a "vis_block" better? - BlockExpr &get_definition_block () + BlockExpr &get_definition_expr () override { rust_assert (expr != nullptr); return *expr; @@ -4836,29 +4958,6 @@ enum class InlineAsmOption MAY_UNWIND = 1 << 8, }; -struct AnonConst -{ - NodeId id; - std::unique_ptr<Expr> expr; - AnonConst (NodeId id, std::unique_ptr<Expr> expr) - : id (id), expr (std::move (expr)) - { - rust_assert (this->expr != nullptr); - } - AnonConst (const AnonConst &other) - { - id = other.id; - expr = other.expr->clone_expr (); - } - - AnonConst operator= (const AnonConst &other) - { - id = other.id; - expr = other.expr->clone_expr (); - return *this; - } -}; - struct InlineAsmRegOrRegClass { enum Type @@ -5288,6 +5387,20 @@ struct TupleTemplateStr // Inline Assembly Node class InlineAsm : public ExprWithoutBlock { +public: + enum class Option + { + PURE = 1 << 0, + NOMEM = 1 << 1, + READONLY = 1 << 2, + PRESERVES_FLAGS = 1 << 3, + NORETURN = 1 << 4, + NOSTACK = 1 << 5, + ATT_SYNTAX = 1 << 6, + RAW = 1 << 7, + MAY_UNWIND = 1 << 8, + }; + private: location_t locus; // TODO: Not sure how outer_attrs plays with InlineAsm, I put it here in order @@ -5311,7 +5424,7 @@ public: std::map<std::string, int> named_args; std::set<int> reg_args; std::vector<TupleClobber> clobber_abi; - std::set<InlineAsmOption> options; + std::set<InlineAsm::Option> options; std::vector<location_t> line_spans; @@ -5342,7 +5455,7 @@ public: std::vector<TupleClobber> get_clobber_abi () { return clobber_abi; } - std::set<InlineAsmOption> get_options () { return options; } + std::set<InlineAsm::Option> get_options () { return options; } InlineAsm *clone_expr_without_block_impl () const override { @@ -5350,6 +5463,33 @@ public: } Expr::Kind get_expr_kind () const override { return Expr::Kind::InlineAsm; } + + static std::string option_to_string (Option option) + { + switch (option) + { + case Option::PURE: + return "pure"; + case Option::NOMEM: + return "nomem"; + case Option::READONLY: + return "readonly"; + case Option::PRESERVES_FLAGS: + return "preserves_flags"; + case Option::NORETURN: + return "noreturn"; + case Option::NOSTACK: + return "nostack"; + case Option::ATT_SYNTAX: + return "att_syntax"; + case Option::RAW: + return "raw"; + case Option::MAY_UNWIND: + return "may_unwind"; + default: + rust_unreachable (); + } + } }; class LlvmInlineAsm : public ExprWithoutBlock diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h index a54faec..3722db2 100644 --- a/gcc/rust/ast/rust-fmt.h +++ b/gcc/rust/ast/rust-fmt.h @@ -266,11 +266,10 @@ enum ParseMode extern "C" { -FormatArgsHandle -collect_pieces (const char *input, bool append_newline, ParseMode parse_mode); +FormatArgsHandle collect_pieces (const char *input, bool append_newline, + ParseMode parse_mode); -FormatArgsHandle -clone_pieces (const FormatArgsHandle &); +FormatArgsHandle clone_pieces (const FormatArgsHandle &); void destroy_pieces (FormatArgsHandle); diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 062f85d..d11eed7 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -51,21 +51,12 @@ class TypePath; // A type generic parameter (as opposed to a lifetime generic parameter) class TypeParam : public GenericParam { - // bool has_outer_attribute; - // std::unique_ptr<Attribute> outer_attr; AST::AttrVec outer_attrs; - Identifier type_representation; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - std::vector<std::unique_ptr<TypeParamBound>> - type_param_bounds; // inlined form - - // bool has_type; + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; std::unique_ptr<Type> type; - location_t locus; + bool was_impl_trait; public: Identifier get_type_representation () const { return type_representation; } @@ -85,18 +76,19 @@ public: std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds = std::vector<std::unique_ptr<TypeParamBound>> (), std::unique_ptr<Type> type = nullptr, - AST::AttrVec outer_attrs = {}) + AST::AttrVec outer_attrs = {}, bool was_impl_trait = false) : GenericParam (Analysis::Mappings::get ().get_next_node_id ()), outer_attrs (std::move (outer_attrs)), type_representation (std::move (type_representation)), type_param_bounds (std::move (type_param_bounds)), - type (std::move (type)), locus (locus) + type (std::move (type)), locus (locus), was_impl_trait (was_impl_trait) {} // Copy constructor uses clone TypeParam (TypeParam const &other) : GenericParam (other.node_id), outer_attrs (other.outer_attrs), - type_representation (other.type_representation), locus (other.locus) + type_representation (other.type_representation), locus (other.locus), + was_impl_trait (other.was_impl_trait) { // guard to prevent null pointer dereference if (other.type != nullptr) @@ -114,6 +106,7 @@ public: outer_attrs = other.outer_attrs; locus = other.locus; node_id = other.node_id; + was_impl_trait = other.was_impl_trait; // guard to prevent null pointer dereference if (other.type != nullptr) @@ -153,17 +146,19 @@ public: return type; } - // TODO: mutable getter seems kinda dodgy std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds () { return type_param_bounds; } + const std::vector<std::unique_ptr<TypeParamBound>> & get_type_param_bounds () const { return type_param_bounds; } + bool from_impl_trait () const { return was_impl_trait; } + protected: // Clone function implementation as virtual method TypeParam *clone_generic_param_impl () const override @@ -2455,7 +2450,7 @@ class ConstantItem : public VisItem, public AssociatedItem // either has an identifier or "_" - maybe handle in identifier? // bool identifier_is_underscore; // if no identifier declared, identifier will be "_" - std::string identifier; + Identifier identifier; std::unique_ptr<Type> type; std::unique_ptr<Expr> const_expr; @@ -2465,7 +2460,7 @@ class ConstantItem : public VisItem, public AssociatedItem public: std::string as_string () const override; - ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type, + ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type, std::unique_ptr<Expr> const_expr, std::vector<Attribute> outer_attrs, location_t locus) : VisItem (std::move (vis), std::move (outer_attrs)), @@ -2473,7 +2468,7 @@ public: const_expr (std::move (const_expr)), locus (locus) {} - ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type, + ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type, std::vector<Attribute> outer_attrs, location_t locus) : VisItem (std::move (vis), std::move (outer_attrs)), identifier (std::move (ident)), type (std::move (type)), @@ -2516,7 +2511,7 @@ public: /* Returns whether constant item is an "unnamed" (wildcard underscore used * as identifier) constant. */ - bool is_unnamed () const { return identifier == "_"; } + bool is_unnamed () const { return identifier.as_string () == "_"; } location_t get_locus () const override final { return locus; } @@ -2561,7 +2556,7 @@ public: return type; } - std::string get_identifier () const { return identifier; } + const Identifier &get_identifier () const { return identifier; } Item::Kind get_item_kind () const override { diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc index 8e43ddf..793423a 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -266,6 +266,27 @@ TypePath::as_simple_path () const locus); } +std::string +TypePath::make_debug_string () const +{ + rust_assert (!segments.empty ()); + + std::string output; + + for (const auto &segment : segments) + { + if (segment != nullptr && !segment->is_lang_item () + && !segment->is_error ()) + { + if (!output.empty () || has_opening_scope_resolution_op ()) + output.append ("::"); + output.append (segment->get_ident_segment ().as_string ()); + } + } + + return output; +} + // hopefully definition here will prevent circular dependency issue TraitBound * TypePath::to_trait_bound (bool in_parens) const diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index a4ba93b..11f7248 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -968,11 +968,7 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_pattern" better? - GenericArgs &get_generic_args () - { - rust_assert (has_generic_args ()); - return generic_args; - } + GenericArgs &get_generic_args () { return generic_args; } // Use covariance to override base class method TypePathSegmentGeneric *clone_type_path_segment_impl () const override @@ -1215,6 +1211,8 @@ public: std::string as_string () const override; + std::string make_debug_string () const; + /* Converts TypePath to SimplePath if possible (i.e. no generic or function * arguments). Otherwise returns an empty SimplePath. */ SimplePath as_simple_path () const; diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc index fc7b610..62bf6f2 100644 --- a/gcc/rust/ast/rust-pattern.cc +++ b/gcc/rust/ast/rust-pattern.cc @@ -65,8 +65,8 @@ IdentifierPattern::as_string () const str += variable_ident.as_string (); - if (has_pattern_to_bind ()) - str += " @ " + to_bind->as_string (); + if (has_subpattern ()) + str += " @ " + subpattern->as_string (); return str; } diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 69dbd98..195a08f 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -74,7 +74,7 @@ class IdentifierPattern : public Pattern bool is_mut; // bool has_pattern; - std::unique_ptr<Pattern> to_bind; + std::unique_ptr<Pattern> subpattern; location_t locus; NodeId node_id; @@ -82,22 +82,22 @@ public: std::string as_string () const override; // Returns whether the IdentifierPattern has a pattern to bind. - bool has_pattern_to_bind () const { return to_bind != nullptr; } + bool has_subpattern () const { return subpattern != nullptr; } // Constructor IdentifierPattern (Identifier ident, location_t locus, bool is_ref = false, bool is_mut = false, - std::unique_ptr<Pattern> to_bind = nullptr) + std::unique_ptr<Pattern> subpattern = nullptr) : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), - is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), + is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} IdentifierPattern (NodeId node_id, Identifier ident, location_t locus, bool is_ref = false, bool is_mut = false, - std::unique_ptr<Pattern> to_bind = nullptr) + std::unique_ptr<Pattern> subpattern = nullptr) : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), - is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), + is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus), node_id (node_id) {} @@ -107,8 +107,8 @@ public: is_mut (other.is_mut), locus (other.locus), node_id (other.node_id) { // fix to get prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); } // Overload assignment operator to use clone @@ -121,10 +121,10 @@ public: node_id = other.node_id; // fix to prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); else - to_bind = nullptr; + subpattern = nullptr; return *this; } @@ -140,8 +140,8 @@ public: // TODO: is this better? Or is a "vis_pattern" better? Pattern &get_pattern_to_bind () { - rust_assert (has_pattern_to_bind ()); - return *to_bind; + rust_assert (has_subpattern ()); + return *subpattern; } Identifier get_ident () const { return variable_ident; } @@ -375,8 +375,7 @@ enum class RangeKind EXCLUDED, }; -RangeKind -tokenid_to_rangekind (TokenId id); +RangeKind tokenid_to_rangekind (TokenId id); // AST node for matching within a certain range (range pattern) class RangePattern : public Pattern { diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 1bb521d..6c0652a 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -73,6 +73,13 @@ public: type_path (std::move (type_path)), locus (locus) {} + TraitBound (TraitBound const &other) + : TypeParamBound (other.get_node_id ()), in_parens (other.in_parens), + opening_question_mark (other.opening_question_mark), + for_lifetimes (other.for_lifetimes), type_path (other.type_path), + locus (other.locus) + {} + std::string as_string () const override; location_t get_locus () const override final { return locus; } @@ -305,33 +312,31 @@ public: // Impl trait with a single bound? Poor reference material here. class ImplTraitTypeOneBound : public TypeNoBounds { - TraitBound trait_bound; + std::unique_ptr<TypeParamBound> trait_bound; location_t locus; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override - { - return new ImplTraitTypeOneBound (*this); - } - public: - ImplTraitTypeOneBound (TraitBound trait_bound, location_t locus) + ImplTraitTypeOneBound (std::unique_ptr<TypeParamBound> trait_bound, + location_t locus) : trait_bound (std::move (trait_bound)), locus (locus) {} + ImplTraitTypeOneBound (ImplTraitTypeOneBound const &other) + : trait_bound (other.trait_bound->clone_type_param_bound ()), + locus (other.locus) + {} + std::string as_string () const override; location_t get_locus () const override final { return locus; } void accept_vis (ASTVisitor &vis) override; - // TODO: would a "vis_type" be better? - TraitBound &get_trait_bound () + std::unique_ptr<TypeParamBound> &get_trait_bound () { return trait_bound; } + + TypeNoBounds *clone_type_no_bounds_impl () const override { - // TODO: check to ensure invariants are met? - return trait_bound; + return new ImplTraitTypeOneBound (*this); } }; @@ -529,6 +534,9 @@ public: return *type; } + // Getter for direct access to the type unique_ptr + std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -604,6 +612,9 @@ public: TypeNoBounds &get_base_type () { return *type; } + // Getter for direct access to the type unique_ptr + std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -666,6 +677,11 @@ public: return *size; } + std::unique_ptr<Type> &get_element_type () { return elem_type; } + + // Additional getter for direct access to the size expr unique_ptr + std::unique_ptr<Expr> &get_size_ptr () { return size; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -719,6 +735,9 @@ public: return *elem_type; } + // Getter for direct access to the elem_type unique_ptr + std::unique_ptr<Type> &get_elem_type_ptr () { return elem_type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index 12b9561..84c4bcd 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -687,11 +687,6 @@ HIRCompileBase::compile_function ( } std::string asm_name = fn_name; - auto &mappings = Analysis::Mappings::get (); - - if (flag_name_resolution_2_0) - ir_symbol_name = mappings.get_current_crate_name () + "::" + ir_symbol_name; - unsigned int flags = 0; tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, "" /* asm_name */, flags, locus); diff --git a/gcc/rust/backend/rust-compile-block.cc b/gcc/rust/backend/rust-compile-block.cc index f844a27..03c36d2 100644 --- a/gcc/rust/backend/rust-compile-block.cc +++ b/gcc/rust/backend/rust-compile-block.cc @@ -19,6 +19,7 @@ #include "rust-compile-block.h" #include "rust-compile-stmt.h" #include "rust-compile-expr.h" +#include "rust-hir-expr.h" namespace Rust { namespace Compile { diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h index 3f38d08..90515f6 100644 --- a/gcc/rust/backend/rust-compile-block.h +++ b/gcc/rust/backend/rust-compile-block.h @@ -83,6 +83,8 @@ public: void visit (HIR::MethodCallExpr &) override {} void visit (HIR::FieldAccessExpr &) override {} void visit (HIR::BlockExpr &) override {} + void visit (HIR::AnonConst &) override {} + void visit (HIR::ConstBlock &) override {} void visit (HIR::ContinueExpr &) override {} void visit (HIR::BreakExpr &) override {} void visit (HIR::RangeFromToExpr &) override {} @@ -138,6 +140,12 @@ public: translated = CompileBlock::compile (expr, ctx, result); } + void visit (HIR::ConstBlock &expr) override + { + rust_unreachable (); + // translated = CompileExpr::compile (expr, ctx, result); + } + // Empty visit for unused Expression HIR nodes. void visit (HIR::PathInExpression &) override {} void visit (HIR::QualifiedPathInExpression &) override {} @@ -184,6 +192,7 @@ public: void visit (HIR::AsyncBlockExpr &) override {} void visit (HIR::InlineAsm &) override {} void visit (HIR::LlvmInlineAsm &) override {} + void visit (HIR::AnonConst &) override {} private: CompileExprWithBlock (Context *ctx, Bvariable *result) diff --git a/gcc/rust/backend/rust-compile-context.cc b/gcc/rust/backend/rust-compile-context.cc index 86f0894..284a5aa 100644 --- a/gcc/rust/backend/rust-compile-context.cc +++ b/gcc/rust/backend/rust-compile-context.cc @@ -70,7 +70,8 @@ Context::type_hasher (tree type) hstate.add_object (TYPE_HASH (TYPE_OFFSET_BASETYPE (type))); break; - case ARRAY_TYPE: { + case ARRAY_TYPE: + { if (TYPE_DOMAIN (type)) hstate.add_object (TYPE_HASH (TYPE_DOMAIN (type))); if (!AGGREGATE_TYPE_P (TREE_TYPE (type))) @@ -81,7 +82,8 @@ Context::type_hasher (tree type) } break; - case INTEGER_TYPE: { + case INTEGER_TYPE: + { tree t = TYPE_MAX_VALUE (type); if (!t) t = TYPE_MIN_VALUE (type); @@ -91,7 +93,8 @@ Context::type_hasher (tree type) } case REAL_TYPE: - case FIXED_POINT_TYPE: { + case FIXED_POINT_TYPE: + { unsigned prec = TYPE_PRECISION (type); hstate.add_object (prec); break; @@ -103,7 +106,8 @@ Context::type_hasher (tree type) case RECORD_TYPE: case UNION_TYPE: - case QUAL_UNION_TYPE: { + case QUAL_UNION_TYPE: + { for (tree t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t)) { hashval_t name_hash = IDENTIFIER_HASH_VALUE (DECL_NAME (t)); @@ -118,7 +122,8 @@ Context::type_hasher (tree type) break; case REFERENCE_TYPE: - case POINTER_TYPE: { + case POINTER_TYPE: + { hashval_t type_hash = type_hasher (TREE_TYPE (type)); hstate.add_object (type_hash); } diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index dd3420f..d8ddab5 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -30,6 +30,7 @@ #include "realmpfr.h" #include "convert.h" #include "print-tree.h" +#include "rust-hir-expr.h" #include "rust-system.h" #include "rust-tyty.h" @@ -441,6 +442,18 @@ CompileExpr::visit (HIR::BlockExpr &expr) } void +CompileExpr::visit (HIR::AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +CompileExpr::visit (HIR::ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + +void CompileExpr::visit (HIR::UnsafeBlockExpr &expr) { expr.get_block_expr ().accept_vis (*this); @@ -1883,7 +1896,8 @@ CompileExpr::visit (HIR::ArrayExpr &expr) HIR::ArrayElems &elements = expr.get_internal_elements (); switch (elements.get_array_expr_type ()) { - case HIR::ArrayElems::ArrayExprType::VALUES: { + case HIR::ArrayElems::ArrayExprType::VALUES: + { HIR::ArrayElemsValues &elems = static_cast<HIR::ArrayElemsValues &> (elements); translated @@ -2032,7 +2046,8 @@ HIRCompileBase::resolve_adjustements ( return error_mark_node; case Resolver::Adjustment::AdjustmentType::IMM_REF: - case Resolver::Adjustment::AdjustmentType::MUT_REF: { + case Resolver::Adjustment::AdjustmentType::MUT_REF: + { if (!RS_DST_FLAG (TREE_TYPE (e))) { e = address_expression (e, locus); diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 65ed4b3..bc347bf 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -48,6 +48,8 @@ public: void visit (HIR::IfExpr &expr) override; void visit (HIR::IfExprConseqElse &expr) override; void visit (HIR::BlockExpr &expr) override; + void visit (HIR::AnonConst &expr) override; + void visit (HIR::ConstBlock &expr) override; void visit (HIR::UnsafeBlockExpr &expr) override; void visit (HIR::StructExprStruct &struct_expr) override; void visit (HIR::StructExprStructFields &struct_expr) override; diff --git a/gcc/rust/backend/rust-compile-implitem.cc b/gcc/rust/backend/rust-compile-implitem.cc index 1230c85..f9172c5 100644 --- a/gcc/rust/backend/rust-compile-implitem.cc +++ b/gcc/rust/backend/rust-compile-implitem.cc @@ -33,8 +33,8 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - canonical_path = nr_ctx.values.to_canonical_path ( - constant.get_mappings ().get_nodeid ()); + canonical_path + = nr_ctx.to_canonical_path (constant.get_mappings ().get_nodeid ()); } else { @@ -103,7 +103,7 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func) = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.values.to_canonical_path (func.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (func.get_mappings ().get_nodeid ()); } else { diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index 4888e23..7627620 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -32,8 +32,7 @@ // declaration taken from "stringpool.h" // the get_identifier macro causes compilation issues -extern tree -get_identifier (const char *); +extern tree get_identifier (const char *); namespace Rust { namespace Compile { @@ -70,28 +69,19 @@ check_for_basic_integer_type (const std::string &intrinsic_str, return is_basic_integer; } -static tree -offset_handler (Context *ctx, TyTy::FnType *fntype); -static tree -sizeof_handler (Context *ctx, TyTy::FnType *fntype); -static tree -transmute_handler (Context *ctx, TyTy::FnType *fntype); -static tree -rotate_handler (Context *ctx, TyTy::FnType *fntype, tree_code op); -static tree -wrapping_op_handler_inner (Context *ctx, TyTy::FnType *fntype, tree_code op); -static tree -op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, tree_code op); -static tree -uninit_handler (Context *ctx, TyTy::FnType *fntype); -static tree -move_val_init_handler (Context *ctx, TyTy::FnType *fntype); -static tree -assume_handler (Context *ctx, TyTy::FnType *fntype); -static tree -discriminant_value_handler (Context *ctx, TyTy::FnType *fntype); -static tree -variant_count_handler (Context *ctx, TyTy::FnType *fntype); +static tree offset_handler (Context *ctx, TyTy::FnType *fntype); +static tree sizeof_handler (Context *ctx, TyTy::FnType *fntype); +static tree transmute_handler (Context *ctx, TyTy::FnType *fntype); +static tree rotate_handler (Context *ctx, TyTy::FnType *fntype, tree_code op); +static tree wrapping_op_handler_inner (Context *ctx, TyTy::FnType *fntype, + tree_code op); +static tree op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, + tree_code op); +static tree uninit_handler (Context *ctx, TyTy::FnType *fntype); +static tree move_val_init_handler (Context *ctx, TyTy::FnType *fntype); +static tree assume_handler (Context *ctx, TyTy::FnType *fntype); +static tree discriminant_value_handler (Context *ctx, TyTy::FnType *fntype); +static tree variant_count_handler (Context *ctx, TyTy::FnType *fntype); enum class Prefetch { @@ -99,8 +89,8 @@ enum class Prefetch Write }; -static tree -prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind); +static tree prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, + Prefetch kind); static inline tree rotate_left_handler (Context *ctx, TyTy::FnType *fntype) @@ -140,10 +130,10 @@ prefetch_write_data (Context *ctx, TyTy::FnType *fntype) return prefetch_data_handler (ctx, fntype, Prefetch::Write); } -static tree -atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering); -static tree -atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering); +static tree atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, + int ordering); +static tree atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, + int ordering); static inline std::function<tree (Context *, TyTy::FnType *)> atomic_store_handler (int ordering) @@ -161,8 +151,8 @@ atomic_load_handler (int ordering) }; } -static inline tree -unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, tree_code op); +static inline tree unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, + tree_code op); const static std::function<tree (Context *, TyTy::FnType *)> unchecked_op_handler (tree_code op) @@ -172,8 +162,8 @@ unchecked_op_handler (tree_code op) }; } -static inline tree -copy_handler_inner (Context *ctx, TyTy::FnType *fntype, bool overlaps); +static inline tree copy_handler_inner (Context *ctx, TyTy::FnType *fntype, + bool overlaps); const static std::function<tree (Context *, TyTy::FnType *)> copy_handler (bool overlaps) @@ -183,8 +173,8 @@ copy_handler (bool overlaps) }; } -static inline tree -expect_handler_inner (Context *ctx, TyTy::FnType *fntype, bool likely); +static inline tree expect_handler_inner (Context *ctx, TyTy::FnType *fntype, + bool likely); const static std::function<tree (Context *, TyTy::FnType *)> expect_handler (bool likely) @@ -194,8 +184,8 @@ expect_handler (bool likely) }; } -static tree -try_handler_inner (Context *ctx, TyTy::FnType *fntype, bool is_new_api); +static tree try_handler_inner (Context *ctx, TyTy::FnType *fntype, + bool is_new_api); const static std::function<tree (Context *, TyTy::FnType *)> try_handler (bool is_new_api) diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc index 9666990..3e7ea9a 100644 --- a/gcc/rust/backend/rust-compile-item.cc +++ b/gcc/rust/backend/rust-compile-item.cc @@ -58,7 +58,7 @@ CompileItem::visit (HIR::StaticItem &var) = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.values.to_canonical_path (var.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (var.get_mappings ().get_nodeid ()); } else { @@ -124,8 +124,7 @@ CompileItem::visit (HIR::ConstantItem &constant) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - canonical_path - = nr_ctx.values.to_canonical_path (mappings.get_nodeid ()).value (); + canonical_path = nr_ctx.to_canonical_path (mappings.get_nodeid ()); } else { @@ -218,10 +217,8 @@ CompileItem::visit (HIR::Function &function) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto path = nr_ctx.values.to_canonical_path ( - function.get_mappings ().get_nodeid ()); - - canonical_path = path.value (); + canonical_path + = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ()); } else { diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index e83717b..e19aa67 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -22,6 +22,11 @@ #include "rust-constexpr.h" #include "rust-compile-type.h" #include "print-tree.h" +#include "rust-diagnostics.h" +#include "rust-hir-pattern-abstract.h" +#include "rust-hir-pattern.h" +#include "rust-system.h" +#include "rust-tyty.h" namespace Rust { namespace Compile { @@ -107,7 +112,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound, tree result = NULL_TREE; switch (bound.get_bound_type ()) { - case HIR::RangePatternBound::RangePatternBoundType::LITERAL: { + case HIR::RangePatternBound::RangePatternBoundType::LITERAL: + { auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound); HIR::LiteralExpr litexpr (mappings, ref.get_literal (), locus, @@ -117,7 +123,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound, } break; - case HIR::RangePatternBound::RangePatternBoundType::PATH: { + case HIR::RangePatternBound::RangePatternBoundType::PATH: + { auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound); result = ResolvePathRef::Compile (ref.get_path (), ctx); @@ -127,7 +134,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound, } break; - case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: { + case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: + { auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound); result = ResolvePathRef::Compile (ref.get_qualified_path (), ctx); @@ -204,6 +212,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) rust_assert (adt->number_of_variants () > 0); TyTy::VariantDef *variant = nullptr; + tree variant_accesser_expr = nullptr; if (adt->is_enum ()) { // lookup the variant @@ -218,9 +227,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) // find expected discriminant // // need to access qualifier the field, if we use QUAL_UNION_TYPE this - // // would be DECL_QUALIFIER i think. For now this will just access the - // // first record field and its respective qualifier because it will - // // always be set because this is all a big special union + // // would be DECL_QUALIFIER i think. HIR::Expr &discrim_expr = variant->get_discriminant (); tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); @@ -229,6 +236,14 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) = Backend::struct_field_expression (match_scrutinee_expr, 0, pattern.get_path ().get_locus ()); + // access variant data + tree scrutinee_union_expr + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern.get_path ().get_locus ()); + variant_accesser_expr + = Backend::struct_field_expression (scrutinee_union_expr, variant_index, + pattern.get_path ().get_locus ()); + check_expr = Backend::comparison_expression (ComparisonOperator::EQUAL, scrutinee_expr_qualifier_expr, @@ -240,6 +255,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) else { variant = adt->get_variants ().at (0); + variant_accesser_expr = match_scrutinee_expr; check_expr = boolean_true_node; } @@ -248,13 +264,15 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) { switch (field->get_item_type ()) { - case HIR::StructPatternField::ItemType::TUPLE_PAT: { + case HIR::StructPatternField::ItemType::TUPLE_PAT: + { // TODO rust_unreachable (); } break; - case HIR::StructPatternField::ItemType::IDENT_PAT: { + case HIR::StructPatternField::ItemType::IDENT_PAT: + { HIR::StructPatternFieldIdentPat &ident = static_cast<HIR::StructPatternFieldIdentPat &> (*field.get ()); @@ -263,11 +281,8 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) nullptr, &offs); rust_assert (ok); - // we may be offsetting by + 1 here since the first field in the - // record is always the discriminator - offs += adt->is_enum (); tree field_expr - = Backend::struct_field_expression (match_scrutinee_expr, offs, + = Backend::struct_field_expression (variant_accesser_expr, offs, ident.get_locus ()); tree check_expr_sub @@ -279,7 +294,8 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) } break; - case HIR::StructPatternField::ItemType::IDENT: { + case HIR::StructPatternField::ItemType::IDENT: + { // ident pattern always matches - do nothing } break; @@ -338,13 +354,15 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern) HIR::TupleStructItems &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: { + case HIR::TupleStructItems::RANGED: + { // TODO rust_unreachable (); } break; - case HIR::TupleStructItems::MULTIPLE: { + case HIR::TupleStructItems::MULTIPLE: + { HIR::TupleStructItemsNoRange &items_no_range = static_cast<HIR::TupleStructItemsNoRange &> (items); @@ -386,13 +404,15 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::RANGED: { + case HIR::TuplePatternItems::RANGED: + { // TODO gcc_unreachable (); } break; - case HIR::TuplePatternItems::MULTIPLE: { + case HIR::TuplePatternItems::MULTIPLE: + { auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( pattern.get_items ()); size_t tuple_field_index = 0; @@ -414,6 +434,20 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) } } +void +CompilePatternCheckExpr::visit (HIR::IdentifierPattern &pattern) +{ + if (pattern.has_subpattern ()) + { + check_expr = CompilePatternCheckExpr::Compile (pattern.get_subpattern (), + match_scrutinee_expr, ctx); + } + else + { + check_expr = boolean_true_node; + } +} + // setup the bindings void @@ -449,13 +483,15 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) HIR::TupleStructItems &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: { + case HIR::TupleStructItems::RANGED: + { // TODO rust_unreachable (); } break; - case HIR::TupleStructItems::MULTIPLE: { + case HIR::TupleStructItems::MULTIPLE: + { HIR::TupleStructItemsNoRange &items_no_range = static_cast<HIR::TupleStructItemsNoRange &> (items); @@ -504,6 +540,71 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) } } +tree +CompilePatternBindings::make_struct_access (TyTy::ADTType *adt, + TyTy::VariantDef *variant, + const Identifier &ident, + int variant_index) +{ + size_t offs = 0; + auto ok = variant->lookup_field (ident.as_string (), nullptr, &offs); + rust_assert (ok); + + if (adt->is_enum ()) + { + tree payload_accessor_union + = Backend::struct_field_expression (match_scrutinee_expr, 1, + ident.get_locus ()); + + tree variant_accessor + = Backend::struct_field_expression (payload_accessor_union, + variant_index, ident.get_locus ()); + + return Backend::struct_field_expression (variant_accessor, offs, + ident.get_locus ()); + } + else + { + tree variant_accessor = match_scrutinee_expr; + + return Backend::struct_field_expression (variant_accessor, offs, + ident.get_locus ()); + } +} + +void +CompilePatternBindings::handle_struct_pattern_ident ( + HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant, + int variant_index) +{ + HIR::StructPatternFieldIdent &ident + = static_cast<HIR::StructPatternFieldIdent &> (pat); + + auto identifier = ident.get_identifier (); + tree binding = make_struct_access (adt, variant, identifier, variant_index); + + ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (), binding); +} + +void +CompilePatternBindings::handle_struct_pattern_ident_pat ( + HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant, + int variant_index) +{ + auto &pattern = static_cast<HIR::StructPatternFieldIdentPat &> (pat); + + tree binding = make_struct_access (adt, variant, pattern.get_identifier (), + variant_index); + CompilePatternBindings::Compile (pattern.get_pattern (), binding, ctx); +} + +void +CompilePatternBindings::handle_struct_pattern_tuple_pat ( + HIR::StructPatternField &pat) +{ + rust_unreachable (); +} + void CompilePatternBindings::visit (HIR::StructPattern &pattern) { @@ -539,54 +640,14 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern) { switch (field->get_item_type ()) { - case HIR::StructPatternField::ItemType::TUPLE_PAT: { - // TODO - rust_unreachable (); - } + case HIR::StructPatternField::ItemType::TUPLE_PAT: + handle_struct_pattern_tuple_pat (*field); break; - - case HIR::StructPatternField::ItemType::IDENT_PAT: { - // TODO - rust_unreachable (); - } + case HIR::StructPatternField::ItemType::IDENT_PAT: + handle_struct_pattern_ident_pat (*field, adt, variant, variant_index); break; - - case HIR::StructPatternField::ItemType::IDENT: { - HIR::StructPatternFieldIdent &ident - = static_cast<HIR::StructPatternFieldIdent &> (*field.get ()); - - size_t offs = 0; - ok = variant->lookup_field (ident.get_identifier ().as_string (), - nullptr, &offs); - rust_assert (ok); - - tree binding = error_mark_node; - if (adt->is_enum ()) - { - tree payload_accessor_union - = Backend::struct_field_expression (match_scrutinee_expr, 1, - ident.get_locus ()); - - tree variant_accessor - = Backend::struct_field_expression (payload_accessor_union, - variant_index, - ident.get_locus ()); - - binding - = Backend::struct_field_expression (variant_accessor, offs, - ident.get_locus ()); - } - else - { - tree variant_accessor = match_scrutinee_expr; - binding - = Backend::struct_field_expression (variant_accessor, offs, - ident.get_locus ()); - } - - ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (), - binding); - } + case HIR::StructPatternField::ItemType::IDENT: + handle_struct_pattern_ident (*field, adt, variant, variant_index); break; } } @@ -631,7 +692,8 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::RANGED: { + case HIR::TuplePatternItems::ItemType::RANGED: + { size_t tuple_idx = 0; auto &items = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); @@ -674,7 +736,8 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) return; } - case HIR::TuplePatternItems::ItemType::MULTIPLE: { + case HIR::TuplePatternItems::ItemType::MULTIPLE: + { size_t tuple_idx = 0; auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( pattern.get_items ()); @@ -695,7 +758,8 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) return; } - default: { + default: + { rust_unreachable (); } } @@ -755,7 +819,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::RANGED: { + case HIR::TuplePatternItems::ItemType::RANGED: + { size_t tuple_idx = 0; auto &items = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); @@ -799,7 +864,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) return; } - case HIR::TuplePatternItems::ItemType::MULTIPLE: { + case HIR::TuplePatternItems::ItemType::MULTIPLE: + { size_t tuple_idx = 0; auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( pattern.get_items ()); @@ -821,7 +887,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) return; } - default: { + default: + { rust_unreachable (); } } diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h index c7a62fc..4dd7d55 100644 --- a/gcc/rust/backend/rust-compile-pattern.h +++ b/gcc/rust/backend/rust-compile-pattern.h @@ -17,7 +17,9 @@ // <http://www.gnu.org/licenses/>. #include "rust-compile-base.h" +#include "rust-hir-pattern.h" #include "rust-hir-visitor.h" +#include "rust-tyty.h" namespace Rust { namespace Compile { @@ -43,12 +45,9 @@ public: void visit (HIR::StructPattern &) override; void visit (HIR::TupleStructPattern &) override; void visit (HIR::TuplePattern &) override; + void visit (HIR::IdentifierPattern &) override; // Always succeeds - void visit (HIR::IdentifierPattern &) override - { - check_expr = boolean_true_node; - } void visit (HIR::WildcardPattern &) override { check_expr = boolean_true_node; @@ -78,6 +77,19 @@ public: pattern.accept_vis (compiler); } + tree make_struct_access (TyTy::ADTType *adt, TyTy::VariantDef *variant, + const Identifier &ident, int variant_index); + + void handle_struct_pattern_ident (HIR::StructPatternField &pat, + TyTy::ADTType *adt, + TyTy::VariantDef *variant, + int variant_index); + void handle_struct_pattern_ident_pat (HIR::StructPatternField &pat, + TyTy::ADTType *adt, + TyTy::VariantDef *variant, + int variant_index); + void handle_struct_pattern_tuple_pat (HIR::StructPatternField &pat); + void visit (HIR::StructPattern &pattern) override; void visit (HIR::TupleStructPattern &pattern) override; void visit (HIR::ReferencePattern &pattern) override; diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index 83e5756..7e56a0f 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -17,11 +17,11 @@ // <http://www.gnu.org/licenses/>. #include "rust-compile-type.h" -#include "rust-compile-expr.h" #include "rust-constexpr.h" -#include "rust-gcc.h" +#include "rust-compile-base.h" #include "tree.h" +#include "fold-const.h" #include "stor-layout.h" namespace Rust { @@ -454,7 +454,7 @@ TyTyResolveCompile::visit (const TyTy::TupleType &type) } tree struct_type_record = Backend::struct_type (fields); - translated = Backend::named_type (type.as_string (), struct_type_record, + translated = Backend::named_type (type.get_name (), struct_type_record, type.get_ident ().locus); } @@ -480,9 +480,12 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type) tree folded_capacity_expr = fold_expr (capacity_expr); - translated = Backend::array_type (element_type, folded_capacity_expr); - if (translated != error_mark_node) - translated = ctx->insert_compiled_type (translated); + // build_index_type takes the maximum index, which is one less than + // the length. + tree index_type_tree = build_index_type ( + fold_build2 (MINUS_EXPR, sizetype, folded_capacity_expr, size_one_node)); + + translated = build_array_type (element_type, index_type_tree, false); } void @@ -755,7 +758,9 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type) void TyTyResolveCompile::visit (const TyTy::OpaqueType &type) { - translated = error_mark_node; + rust_assert (type.can_resolve ()); + auto underlying = type.resolve (); + translated = TyTyResolveCompile::compile (ctx, underlying, trait_object_mode); } tree diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index 4c46a7b..5c6d145 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -70,7 +70,8 @@ public: { switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::MULTIPLE: { + case HIR::TuplePatternItems::ItemType::MULTIPLE: + { rust_assert (TREE_CODE (translated_type) == RECORD_TYPE); auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( pattern.get_items ()); diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index dc2d6b1..d524d09 100644 --- a/gcc/rust/backend/rust-constexpr.cc +++ b/gcc/rust/backend/rust-constexpr.cc @@ -68,32 +68,24 @@ literal_type_p (tree t) return false; } -static bool -verify_constant (tree, bool, bool *, bool *); - -static HOST_WIDE_INT -find_array_ctor_elt (tree ary, tree dindex, bool insert = false); -static int -array_index_cmp (tree key, tree index); -static bool -potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, - tsubst_flags_t flags, tree *jump_target); -bool -potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, - tsubst_flags_t flags); -tree -unshare_constructor (tree t MEM_STAT_DECL); -void -maybe_save_constexpr_fundef (tree fun); - -static bool -returns (tree *jump_target); -static bool -breaks (tree *jump_target); -static bool -continues (tree *jump_target); -static bool -switches (tree *jump_target); +static bool verify_constant (tree, bool, bool *, bool *); + +static HOST_WIDE_INT find_array_ctor_elt (tree ary, tree dindex, + bool insert = false); +static int array_index_cmp (tree key, tree index); +static bool potential_constant_expression_1 (tree t, bool want_rval, + bool strict, bool now, + tsubst_flags_t flags, + tree *jump_target); +bool potential_constant_expression_1 (tree t, bool want_rval, bool strict, + bool now, tsubst_flags_t flags); +tree unshare_constructor (tree t MEM_STAT_DECL); +void maybe_save_constexpr_fundef (tree fun); + +static bool returns (tree *jump_target); +static bool breaks (tree *jump_target); +static bool continues (tree *jump_target); +static bool switches (tree *jump_target); struct constexpr_global_ctx { @@ -463,60 +455,52 @@ save_fundef_copy (tree fun, tree copy) *slot = copy; } -static tree -constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p, - bool unshare_p); -tree -decl_constant_value (tree decl, bool unshare_p); +static tree constant_value_1 (tree decl, bool strict_p, + bool return_aggregate_cst_ok_p, bool unshare_p); +tree decl_constant_value (tree decl, bool unshare_p); -static void -non_const_var_error (location_t loc, tree r); +static void non_const_var_error (location_t loc, tree r); -static tree -eval_constant_expression (const constexpr_ctx *ctx, tree, bool, bool *, bool *, - tree * = NULL); +static tree eval_constant_expression (const constexpr_ctx *ctx, tree, bool, + bool *, bool *, tree * = NULL); -static tree -constexpr_fn_retval (const constexpr_ctx *ctx, tree r); +static tree constexpr_fn_retval (const constexpr_ctx *ctx, tree r); -static tree -eval_store_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *); +static tree eval_store_expression (const constexpr_ctx *ctx, tree r, bool, + bool *, bool *); -static tree -eval_call_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *); +static tree eval_call_expression (const constexpr_ctx *ctx, tree r, bool, + bool *, bool *); -static tree -eval_binary_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *); +static tree eval_binary_expression (const constexpr_ctx *ctx, tree r, bool, + bool *, bool *); -static tree -get_function_named_in_call (tree t); +static tree get_function_named_in_call (tree t); -static tree -eval_statement_list (const constexpr_ctx *ctx, tree t, bool *non_constant_p, - bool *overflow_p, tree *jump_target); -static tree -extract_string_elt (tree string, unsigned chars_per_elt, unsigned index); +static tree eval_statement_list (const constexpr_ctx *ctx, tree t, + bool *non_constant_p, bool *overflow_p, + tree *jump_target); +static tree extract_string_elt (tree string, unsigned chars_per_elt, + unsigned index); -static tree -eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p, - tree *jump_target); +static tree eval_conditional_expression (const constexpr_ctx *ctx, tree t, + bool lval, bool *non_constant_p, + bool *overflow_p, tree *jump_target); -static tree -eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p); +static tree eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval, + bool *non_constant_p, bool *overflow_p); -static tree -eval_loop_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, - bool *overflow_p, tree *jump_target); +static tree eval_loop_expr (const constexpr_ctx *ctx, tree t, + bool *non_constant_p, bool *overflow_p, + tree *jump_target); -static tree -eval_switch_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, - bool *overflow_p, tree *jump_target); +static tree eval_switch_expr (const constexpr_ctx *ctx, tree t, + bool *non_constant_p, bool *overflow_p, + tree *jump_target); -static tree -eval_unary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/, - bool *non_constant_p, bool *overflow_p); +static tree eval_unary_expression (const constexpr_ctx *ctx, tree t, + bool /*lval*/, bool *non_constant_p, + bool *overflow_p); /* Variables and functions to manage constexpr call expansion context. These do not need to be marked for PCH or GC. */ @@ -1235,7 +1219,8 @@ get_or_insert_ctor_field (tree ctor, tree index, int pos_hint = -1) /* We fell off the end of the CONSTRUCTOR, so insert a new entry at the end. */ - insert : { + insert: + { constructor_elt ce = {index, NULL_TREE}; vec_safe_insert (CONSTRUCTOR_ELTS (ctor), idx, ce); @@ -1568,10 +1553,9 @@ free_constructor (tree t) } } -static tree -eval_and_check_array_index (const constexpr_ctx *ctx, tree t, - bool allow_one_past, bool *non_constant_p, - bool *overflow_p); +static tree eval_and_check_array_index (const constexpr_ctx *ctx, tree t, + bool allow_one_past, + bool *non_constant_p, bool *overflow_p); // forked from gcc/cp/constexpr.cc cxx_eval_array_reference @@ -1901,6 +1885,9 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, location_t loc = EXPR_LOCATION (t); + if (t == NULL_TREE) + return NULL_TREE; + if (CONSTANT_CLASS_P (t)) { if (TREE_OVERFLOW (t)) @@ -1936,8 +1923,9 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, return eval_constant_expression (ctx, r, lval, non_constant_p, overflow_p); } - /* fall through */ - case CONST_DECL: { + /* fall through */ + case CONST_DECL: + { /* We used to not check lval for CONST_DECL, but darwin.cc uses CONST_DECL for aggregate constants. */ if (lval) @@ -2045,7 +2033,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, overflow_p); break; - case TARGET_EXPR: { + case TARGET_EXPR: + { tree type = TREE_TYPE (t); if (!literal_type_p (type)) @@ -2129,7 +2118,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, } break; - case DECL_EXPR: { + case DECL_EXPR: + { r = DECL_EXPR_DECL (t); if (AGGREGATE_TYPE_P (TREE_TYPE (r)) || VECTOR_TYPE_P (TREE_TYPE (r))) @@ -2201,7 +2191,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, return eval_constant_expression (ctx, OBJ_TYPE_REF_EXPR (t), lval, non_constant_p, overflow_p); - case EXIT_EXPR: { + case EXIT_EXPR: + { tree cond = TREE_OPERAND (t, 0); cond = eval_constant_expression (ctx, cond, /*lval*/ false, non_constant_p, overflow_p); @@ -2243,7 +2234,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, } break; - case ADDR_EXPR: { + case ADDR_EXPR: + { tree oldop = TREE_OPERAND (t, 0); tree op = eval_constant_expression (ctx, oldop, /*lval*/ true, non_constant_p, @@ -2261,7 +2253,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, break; } - case COMPOUND_EXPR: { + case COMPOUND_EXPR: + { /* check_return_expr sometimes wraps a TARGET_EXPR in a COMPOUND_EXPR; don't get confused. Also handle EMPTY_CLASS_EXPR introduced by build_call_a. */ @@ -2401,7 +2394,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, non_constant_p, overflow_p, jump_target); break; - case CLEANUP_POINT_EXPR: { + case CLEANUP_POINT_EXPR: + { auto_vec<tree, 2> cleanups; vec<tree> *prev_cleanups = ctx->global->cleanups; ctx->global->cleanups = &cleanups; @@ -2441,7 +2435,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, /* FALLTHROUGH. */ case NOP_EXPR: case CONVERT_EXPR: - case VIEW_CONVERT_EXPR: { + case VIEW_CONVERT_EXPR: + { tree oldop = TREE_OPERAND (t, 0); tree op = eval_constant_expression (ctx, oldop, lval, non_constant_p, @@ -2688,7 +2683,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, { case BIT_FIELD_REF: case COMPONENT_REF: - case ARRAY_REF: { + case ARRAY_REF: + { tree ob = TREE_OPERAND (probe, 0); tree elt = TREE_OPERAND (probe, 1); if (TREE_CODE (elt) == FIELD_DECL /*&& DECL_MUTABLE_P (elt)*/) @@ -3940,7 +3936,8 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body) { switch (TREE_CODE (body)) { - case STATEMENT_LIST: { + case STATEMENT_LIST: + { tree expr = NULL_TREE; for (tree stmt : tsi_range (body)) { @@ -3958,13 +3955,15 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body) return expr; } - case RETURN_EXPR: { + case RETURN_EXPR: + { bool non_constant_p = false; bool overflow_p = false; return eval_constant_expression (ctx, body, false, &non_constant_p, &overflow_p); } - case DECL_EXPR: { + case DECL_EXPR: + { tree decl = DECL_EXPR_DECL (body); if (TREE_CODE (decl) == USING_DECL /* Accept __func__, __FUNCTION__, and __PRETTY_FUNCTION__. */ @@ -3976,7 +3975,8 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body) case CLEANUP_POINT_EXPR: return constexpr_fn_retval (ctx, TREE_OPERAND (body, 0)); - case BIND_EXPR: { + case BIND_EXPR: + { tree b = BIND_EXPR_BODY (body); return constexpr_fn_retval (ctx, b); } @@ -4136,7 +4136,8 @@ array_index_cmp (tree key, tree index) { case INTEGER_CST: return tree_int_cst_compare (key, index); - case RANGE_EXPR: { + case RANGE_EXPR: + { tree lo = TREE_OPERAND (index, 0); tree hi = TREE_OPERAND (index, 1); if (tree_int_cst_lt (key, lo)) @@ -5943,7 +5944,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case BIT_FIELD_REF: return RECUR (TREE_OPERAND (t, 0), want_rval); - case INDIRECT_REF: { + case INDIRECT_REF: + { tree x = TREE_OPERAND (t, 0); STRIP_NOPS (x); return RECUR (x, rval); @@ -6214,7 +6216,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case INIT_EXPR: return RECUR (TREE_OPERAND (t, 1), rval); - case CONSTRUCTOR: { + case CONSTRUCTOR: + { vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t); constructor_elt *ce; for (i = 0; vec_safe_iterate (v, i, &ce); ++i) @@ -6223,7 +6226,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, return true; } - case TREE_LIST: { + case TREE_LIST: + { gcc_assert (TREE_PURPOSE (t) == NULL_TREE || DECL_P (TREE_PURPOSE (t))); if (!RECUR (TREE_VALUE (t), want_rval)) return false; @@ -6238,7 +6242,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case ROUND_DIV_EXPR: case TRUNC_MOD_EXPR: case CEIL_MOD_EXPR: - case ROUND_MOD_EXPR: { + case ROUND_MOD_EXPR: + { tree denom = TREE_OPERAND (t, 1); if (!RECUR (denom, rval)) return false; @@ -6258,7 +6263,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, } } - case COMPOUND_EXPR: { + case COMPOUND_EXPR: + { /* check_return_expr sometimes wraps a TARGET_EXPR in a COMPOUND_EXPR; don't get confused. */ tree op0 = TREE_OPERAND (t, 0); @@ -6280,7 +6286,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, case TRUTH_OR_EXPR: case TRUTH_ORIF_EXPR: tmp = boolean_false_node; - truth : { + truth: + { tree op0 = TREE_OPERAND (t, 0); tree op1 = TREE_OPERAND (t, 1); if (!RECUR (op0, rval)) diff --git a/gcc/rust/backend/rust-constexpr.h b/gcc/rust/backend/rust-constexpr.h index 77a0797..27f0a2e 100644 --- a/gcc/rust/backend/rust-constexpr.h +++ b/gcc/rust/backend/rust-constexpr.h @@ -24,8 +24,7 @@ namespace Rust { namespace Compile { extern tree fold_expr (tree); -extern void -maybe_save_constexpr_fundef (tree fun); +extern void maybe_save_constexpr_fundef (tree fun); } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-mangle-v0.cc b/gcc/rust/backend/rust-mangle-v0.cc index d0df4ab..f6b1a4c 100644 --- a/gcc/rust/backend/rust-mangle-v0.cc +++ b/gcc/rust/backend/rust-mangle-v0.cc @@ -62,9 +62,9 @@ struct V0Path } }; -static std::string -v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path); +static std::string v0_path (Rust::Compile::Context *ctx, + const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); static std::string v0_tuple_prefix (const TyTy::BaseType *ty) @@ -148,7 +148,8 @@ v0_complex_type_prefix (Context *ctx, const TyTy::BaseType *ty) // TODO: generics switch (ty->get_kind ()) { - case TyTy::TypeKind::ADT: { + case TyTy::TypeKind::ADT: + { const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (ty); return v0_path (ctx, ty, adt->get_ident ().path); } @@ -387,7 +388,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, { switch (impl_item->first->get_impl_item_type ()) { - case HIR::ImplItem::FUNCTION: { + case HIR::ImplItem::FUNCTION: + { HIR::Function *fn = static_cast<HIR::Function *> (impl_item->first); v0path @@ -408,7 +410,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, { switch (trait_item.value ()->get_item_kind ()) { - case HIR::TraitItem::FUNC: { + case HIR::TraitItem::FUNC: + { auto fn = static_cast<HIR::TraitItemFunc *> (*trait_item); rust_unreachable (); v0path = v0_function_path (v0path, ctx, ty, @@ -428,7 +431,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, else if (auto item = mappings.lookup_hir_item (hir_id)) switch (item.value ()->get_item_kind ()) { - case HIR::Item::ItemKind::Function: { + case HIR::Item::ItemKind::Function: + { HIR::Function *fn = static_cast<HIR::Function *> (*item); v0path = v0_function_path (v0path, ctx, ty, fn->get_generic_params (), diff --git a/gcc/rust/backend/rust-mangle.h b/gcc/rust/backend/rust-mangle.h index 2a84b6b..418f2bd 100644 --- a/gcc/rust/backend/rust-mangle.h +++ b/gcc/rust/backend/rust-mangle.h @@ -49,13 +49,12 @@ private: static enum MangleVersion version; }; -std::string -legacy_mangle_item (const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path); +std::string legacy_mangle_item (const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); -std::string -v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path); +std::string v0_mangle_item (Rust::Compile::Context *ctx, + const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc index 2302ffb..b86c3c8 100644 --- a/gcc/rust/backend/rust-tree.cc +++ b/gcc/rust/backend/rust-tree.cc @@ -268,7 +268,8 @@ convert_to_void (tree expr, impl_conv_void implicit) return expr; switch (TREE_CODE (expr)) { - case COND_EXPR: { + case COND_EXPR: + { /* The two parts of a cond expr might be separate lvalues. */ tree op1 = TREE_OPERAND (expr, 1); tree op2 = TREE_OPERAND (expr, 2); @@ -294,7 +295,8 @@ convert_to_void (tree expr, impl_conv_void implicit) break; } - case COMPOUND_EXPR: { + case COMPOUND_EXPR: + { /* The second part of a compound expr contains the value. */ tree op1 = TREE_OPERAND (expr, 1); tree new_op1; @@ -323,7 +325,8 @@ convert_to_void (tree expr, impl_conv_void implicit) maybe_warn_nodiscard (expr, implicit); break; - case INDIRECT_REF: { + case INDIRECT_REF: + { tree type = TREE_TYPE (expr); int is_reference = TYPE_REF_P (TREE_TYPE (TREE_OPERAND (expr, 0))); int is_volatile = TYPE_VOLATILE (type); @@ -518,7 +521,8 @@ convert_to_void (tree expr, impl_conv_void implicit) break; } - case VAR_DECL: { + case VAR_DECL: + { /* External variables might be incomplete. */ tree type = TREE_TYPE (expr); int is_complete = COMPLETE_TYPE_P (type); @@ -1485,7 +1489,8 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void *data) parameter pack. ??? Should some of these be in cp_walk_subtrees? */ switch (TREE_CODE (t)) { - case DECL_EXPR: { + case DECL_EXPR: + { tree decl = DECL_EXPR_DECL (t); if (is_typedef_decl (decl)) /* Since we stop at typedefs above, we need to look through them at @@ -1506,7 +1511,8 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void *data) *walk_subtrees = 0; return NULL_TREE; - case DECLTYPE_TYPE: { + case DECLTYPE_TYPE: + { /* When traversing a DECLTYPE_TYPE_EXPR, we need to set type_pack_expansion_p to false so that any placeholders within the expression don't get marked as parameter packs. */ @@ -1970,7 +1976,8 @@ rs_tree_equal (tree t1, tree t2) case SAVE_EXPR: return rs_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); - case CALL_EXPR: { + case CALL_EXPR: + { if (KOENIG_LOOKUP_P (t1) != KOENIG_LOOKUP_P (t2)) return false; @@ -1996,7 +2003,8 @@ rs_tree_equal (tree t1, tree t2) return true; } - case TARGET_EXPR: { + case TARGET_EXPR: + { tree o1 = TREE_OPERAND (t1, 0); tree o2 = TREE_OPERAND (t2, 0); @@ -2067,7 +2075,8 @@ rs_tree_equal (tree t1, tree t2) case tcc_expression: case tcc_vl_exp: case tcc_reference: - case tcc_statement: { + case tcc_statement: + { int n = rs_tree_operand_length (t1); if (TREE_CODE_CLASS (code1) == tcc_vl_exp && n != TREE_OPERAND_LENGTH (t2)) @@ -2095,7 +2104,11 @@ rs_tree_equal (tree t1, tree t2) /* TRUE iff TYPE is publicly & uniquely derived from PARENT. */ -bool publicly_uniquely_derived_p (tree, tree) { return false; } +bool +publicly_uniquely_derived_p (tree, tree) +{ + return false; +} // forked from gcc/cp/typeck.cc comp_except_types @@ -3375,7 +3388,11 @@ release_tree_vector (vec<tree, va_gc> *vec) /* As above, but also check value-dependence of the expression as a whole. */ -bool instantiation_dependent_expression_p (tree) { return false; } +bool +instantiation_dependent_expression_p (tree) +{ + return false; +} // forked from gcc/cp/cvt.cc cp_get_callee @@ -3425,7 +3442,11 @@ scalarish_type_p (const_tree t) constructors are deleted. This function implements the ABI notion of non-trivial copy, which has diverged from the one in the standard. */ -bool type_has_nontrivial_copy_init (const_tree) { return false; } +bool +type_has_nontrivial_copy_init (const_tree) +{ + return false; +} // forked from gcc/cp/tree.cc build_local_temp @@ -3448,7 +3469,11 @@ build_local_temp (tree type) /* Returns true iff DECL is a capture proxy for a normal capture (i.e. without explicit initializer). */ -bool is_normal_capture_proxy (tree) { return false; } +bool +is_normal_capture_proxy (tree) +{ + return false; +} // forked from gcc/cp/c-common.cc reject_gcc_builtin @@ -3522,7 +3547,8 @@ is_bitfield_expr_with_lowered_type (const_tree exp) case BIT_NOT_EXPR: return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0)); - case COMPONENT_REF: { + case COMPONENT_REF: + { tree field; field = TREE_OPERAND (exp, 1); @@ -3909,7 +3935,8 @@ retry: break; case OFFSET_TYPE: - bad_member : { + bad_member: + { tree member = TREE_OPERAND (value, 1); if (is_overloaded_fn (member)) member = get_first_fn (member); @@ -3994,13 +4021,21 @@ decl_constant_var_p (tree decl) /* Returns true iff DECL is a variable or function declared with an auto type that has not yet been deduced to a real type. */ -bool undeduced_auto_decl (tree) { return false; } +bool +undeduced_auto_decl (tree) +{ + return false; +} // forked from gcc/cp/decl.cc require_deduced_type /* Complain if DECL has an undeduced return type. */ -bool require_deduced_type (tree, tsubst_flags_t) { return true; } +bool +require_deduced_type (tree, tsubst_flags_t) +{ + return true; +} /* Return the location of a tree passed to %+ formats. */ @@ -4290,10 +4325,9 @@ struct GTY ((for_user)) source_location_table_entry } // namespace Rust -extern void -gt_pch_nx (Rust::source_location_table_entry &); -extern void -gt_pch_nx (Rust::source_location_table_entry *, gt_pointer_operator, void *); +extern void gt_pch_nx (Rust::source_location_table_entry &); +extern void gt_pch_nx (Rust::source_location_table_entry *, gt_pointer_operator, + void *); namespace Rust { @@ -4421,7 +4455,8 @@ lvalue_kind (const_tree ref) case VIEW_CONVERT_EXPR: return lvalue_kind (TREE_OPERAND (ref, 0)); - case ARRAY_REF: { + case ARRAY_REF: + { tree op1 = TREE_OPERAND (ref, 0); if (TREE_CODE (TREE_TYPE (op1)) == ARRAY_TYPE) { @@ -4518,7 +4553,8 @@ lvalue_kind (const_tree ref) op2_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 1)); break; - case COND_EXPR: { + case COND_EXPR: + { tree op1 = TREE_OPERAND (ref, 1); if (!op1) op1 = TREE_OPERAND (ref, 0); diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h index 3630b0e..9e859d4 100644 --- a/gcc/rust/backend/rust-tree.h +++ b/gcc/rust/backend/rust-tree.h @@ -1543,7 +1543,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; #if defined ENABLE_TREE_CHECKING #define LANG_DECL_MIN_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (!LANG_DECL_HAS_MIN (NODE)) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -1554,7 +1554,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; template, not just on a FUNCTION_DECL. So when looking for things in lang_decl_fn, look down through a TEMPLATE_DECL into its result. */ #define LANG_DECL_FN_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (!DECL_DECLARES_FUNCTION_P (NODE) || lt->u.base.selector != lds_fn) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -1562,7 +1562,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; }) #define LANG_DECL_NS_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (TREE_CODE (NODE) != NAMESPACE_DECL || lt->u.base.selector != lds_ns) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -1570,7 +1570,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; }) #define LANG_DECL_PARM_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (TREE_CODE (NODE) != PARM_DECL || lt->u.base.selector != lds_parm) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -1578,7 +1578,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX]; }) #define LANG_DECL_DECOMP_CHECK(NODE) \ - __extension__({ \ + __extension__ ({ \ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \ if (!VAR_P (NODE) || lt->u.base.selector != lds_decomp) \ lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \ @@ -2060,8 +2060,8 @@ struct GTY (()) rust_cxx_saved_binding // forked from gcc/cp/name-lookup.h resort_type_member_vec /* needed for GTY annotation */ -extern void -resort_type_member_vec (void *, void *, gt_pointer_operator, void *); +extern void resort_type_member_vec (void *, void *, gt_pointer_operator, + void *); // forked from gcc/cp/cp-tree.h saved_scope @@ -2895,8 +2895,7 @@ enum compare_bounds_t bounds_first }; -extern tree -convert_to_void (tree expr, impl_conv_void implicit); +extern tree convert_to_void (tree expr, impl_conv_void implicit); // The lvalue-to-rvalue conversion (7.1) is applied if and only if the // expression is a glvalue of volatile-qualified type and it is one of the @@ -2911,63 +2910,52 @@ convert_to_void (tree expr, impl_conv_void implicit); // operands are one of these expressions, or // * comma expression (8.19) where the right operand is one of these // expressions. -extern tree -mark_discarded_use (tree expr); +extern tree mark_discarded_use (tree expr); // Mark EXP as read, not just set, for set but not used -Wunused warning // purposes. -extern void -mark_exp_read (tree exp); +extern void mark_exp_read (tree exp); // We've seen an actual use of EXPR. Possibly replace an outer variable // reference inside with its constant value or a lambda capture. -extern tree -mark_use (tree expr, bool rvalue_p, bool read_p, location_t loc, - bool reject_builtin); +extern tree mark_use (tree expr, bool rvalue_p, bool read_p, location_t loc, + bool reject_builtin); // Called whenever the expression EXPR is used in an rvalue context. // When REJECT_BUILTIN is true the expression is checked to make sure // it doesn't make it possible to obtain the address of a GCC built-in // function with no library fallback (or any of its bits, such as in // a conversion to bool). -extern tree -mark_rvalue_use (tree, location_t = UNKNOWN_LOCATION, - bool reject_builtin = true); +extern tree mark_rvalue_use (tree, location_t = UNKNOWN_LOCATION, + bool reject_builtin = true); // Called whenever an expression is used in an lvalue context. -extern tree -mark_lvalue_use (tree expr); +extern tree mark_lvalue_use (tree expr); // As above, but don't consider this use a read. -extern tree -mark_lvalue_use_nonread (tree expr); +extern tree mark_lvalue_use_nonread (tree expr); // We are using a reference VAL for its value. Bash that reference all the way // down to its lowest form. -extern tree -convert_from_reference (tree val); +extern tree convert_from_reference (tree val); // Subroutine of convert_to_void. Warn if we're discarding something with // attribute [[nodiscard]]. -extern void -maybe_warn_nodiscard (tree expr, impl_conv_void implicit); +extern void maybe_warn_nodiscard (tree expr, impl_conv_void implicit); -extern location_t -expr_loc_or_loc (const_tree t, location_t or_loc); +extern location_t expr_loc_or_loc (const_tree t, location_t or_loc); -extern location_t -expr_loc_or_input_loc (const_tree t); +extern location_t expr_loc_or_input_loc (const_tree t); // FN is the callee of a CALL_EXPR or AGGR_INIT_EXPR; return the FUNCTION_DECL // if we can. -extern tree -get_fndecl_from_callee (tree fn); +extern tree get_fndecl_from_callee (tree fn); // FIXME some helpers from HIRCompileBase could probably be moved here over time // Return an expression for the address of BASE[INDEX], used in offset intrinsic -extern tree -pointer_offset_expression (tree base_tree, tree index_tree, location_t locus); +extern tree pointer_offset_expression (tree base_tree, tree index_tree, + location_t locus); /* A tree node, together with a location, so that we can track locations (and ranges) during parsing. @@ -2978,11 +2966,9 @@ pointer_offset_expression (tree base_tree, tree index_tree, location_t locus); extern location_t rs_expr_location (const_tree); -extern int -is_empty_class (tree type); +extern int is_empty_class (tree type); -extern bool -is_really_empty_class (tree, bool); +extern bool is_really_empty_class (tree, bool); extern bool builtin_valid_in_constant_expr_p (const_tree); @@ -2990,15 +2976,13 @@ extern bool maybe_constexpr_fn (tree); extern bool var_in_maybe_constexpr_fn (tree); -extern int -rs_type_quals (const_tree type); +extern int rs_type_quals (const_tree type); inline bool type_unknown_p (const_tree); extern bool decl_maybe_constant_var_p (tree); -extern void -init_modules (); +extern void init_modules (); extern bool var_in_constexpr_fn (tree); @@ -3006,11 +2990,9 @@ inline tree ovl_first (tree) ATTRIBUTE_PURE; inline bool type_unknown_p (const_tree); -extern tree -lookup_add (tree fns, tree lookup); +extern tree lookup_add (tree fns, tree lookup); -extern tree -ovl_make (tree fn, tree next = NULL_TREE); +extern tree ovl_make (tree fn, tree next = NULL_TREE); extern int is_overloaded_fn (tree) ATTRIBUTE_PURE; @@ -3024,19 +3006,15 @@ extern tree make_conv_op_name (tree); extern int type_memfn_quals (const_tree); -struct c_fileinfo * -get_fileinfo (const char *); +struct c_fileinfo *get_fileinfo (const char *); -extern tree -cxx_make_type (enum tree_code CXX_MEM_STAT_INFO); +extern tree cxx_make_type (enum tree_code CXX_MEM_STAT_INFO); -extern tree -build_cplus_array_type (tree, tree, int is_dep = -1); +extern tree build_cplus_array_type (tree, tree, int is_dep = -1); extern bool is_byte_access_type (tree); -extern bool -comptypes (tree, tree, int); +extern bool comptypes (tree, tree, int); extern tree canonical_eh_spec (tree); @@ -3046,8 +3024,7 @@ extern bool rs_tree_equal (tree, tree); extern bool compparms (const_tree, const_tree); -extern tree -rs_build_qualified_type_real (tree, int, tsubst_flags_t); +extern tree rs_build_qualified_type_real (tree, int, tsubst_flags_t); #define rs_build_qualified_type(TYPE, QUALS) \ rs_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error) extern bool cv_qualified_p (const_tree); @@ -3056,21 +3033,18 @@ extern bool similar_type_p (tree, tree); extern bool rs_tree_equal (tree, tree); -extern bool -vector_targets_convertible_p (const_tree t1, const_tree t2); +extern bool vector_targets_convertible_p (const_tree t1, const_tree t2); extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree); extern bool comp_ptr_ttypes_const (tree, tree, compare_bounds_t); -extern tree -get_class_binding_direct (tree, tree, bool want_type = false); +extern tree get_class_binding_direct (tree, tree, bool want_type = false); extern tree skip_artificial_parms_for (const_tree, tree); -extern void -lang_check_failed (const char *, int, - const char *) ATTRIBUTE_NORETURN ATTRIBUTE_COLD; +extern void lang_check_failed (const char *, int, + const char *) ATTRIBUTE_NORETURN ATTRIBUTE_COLD; extern tree default_init_uninitialized_part (tree); @@ -3088,8 +3062,7 @@ extern tree in_class_defaulted_default_constructor (tree); extern bool is_instantiation_of_constexpr (tree); -extern bool -check_for_uninitialized_const_var (tree, bool, tsubst_flags_t); +extern bool check_for_uninitialized_const_var (tree, bool, tsubst_flags_t); extern bool reduced_constant_expression_p (tree); @@ -3108,19 +3081,17 @@ extern tree is_bitfield_expr_with_lowered_type (const_tree); extern tree convert_bitfield_to_declared_type (tree); -extern tree -cp_fold_maybe_rvalue (tree, bool); +extern tree cp_fold_maybe_rvalue (tree, bool); extern tree maybe_undo_parenthesized_ref (tree); -extern tree -fold_offsetof (tree, tree = size_type_node, tree_code ctx = ERROR_MARK); +extern tree fold_offsetof (tree, tree = size_type_node, + tree_code ctx = ERROR_MARK); extern tree cp_truthvalue_conversion (tree, tsubst_flags_t); -extern tree -fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error, - bool = false, tree = NULL_TREE); +extern tree fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error, + bool = false, tree = NULL_TREE); extern int char_type_p (tree); @@ -3163,13 +3134,11 @@ extern tree build_new_constexpr_heap_type (tree, tree, tree); extern bool is_empty_field (tree); -extern bool -in_immediate_context (); +extern bool in_immediate_context (); extern tree cp_get_callee_fndecl_nofold (tree); -extern bool -cxx_mark_addressable (tree, bool = false); +extern bool cxx_mark_addressable (tree, bool = false); extern tree fold_builtin_source_location (location_t); @@ -3183,25 +3152,22 @@ extern bool glvalue_p (const_tree); extern cp_lvalue_kind lvalue_kind (const_tree); -extern tree -decl_constant_value (tree, bool); +extern tree decl_constant_value (tree, bool); extern tree lookup_enumerator (tree, tree); -extern int -is_class_type (tree, int); +extern int is_class_type (tree, int); extern tree braced_lists_to_strings (tree, tree); -extern tree -fold_builtin_is_pointer_inverconvertible_with_class (location_t, int, tree *); +extern tree fold_builtin_is_pointer_inverconvertible_with_class (location_t, + int, tree *); extern bool layout_compatible_type_p (tree, tree); extern tree finish_underlying_type (tree); -extern tree -c_common_type_for_mode (machine_mode, int); +extern tree c_common_type_for_mode (machine_mode, int); extern bool std_layout_type_p (const_tree); @@ -3213,25 +3179,21 @@ extern void note_failed_type_completion_for_satisfaction (tree); extern tree complete_type_or_maybe_complain (tree, tree, tsubst_flags_t); -extern bool -next_common_initial_seqence (tree &, tree &); +extern bool next_common_initial_seqence (tree &, tree &); extern bool null_member_pointer_value_p (tree); -extern tree -fold_builtin_is_corresponding_member (location_t, int, tree *); +extern tree fold_builtin_is_corresponding_member (location_t, int, tree *); extern tree cp_fold_rvalue (tree); -extern tree -maybe_constant_value (tree, tree = NULL_TREE, bool = false); +extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false); extern tree lvalue_type (tree); extern void lvalue_error (location_t, enum lvalue_use); -extern tree -cp_fold_maybe_rvalue (tree, bool); +extern tree cp_fold_maybe_rvalue (tree, bool); extern tree get_first_fn (tree) ATTRIBUTE_PURE; @@ -3253,13 +3215,12 @@ enum ce_exact }; -extern tree -rs_build_qualified_type_real (tree, int, tsubst_flags_t); +extern tree rs_build_qualified_type_real (tree, int, tsubst_flags_t); #define rs_build_qualified_type(TYPE, QUALS) \ rs_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error) -extern tree -rs_walk_subtrees (tree *, int *, walk_tree_fn, void *, hash_set<tree> *); +extern tree rs_walk_subtrees (tree *, int *, walk_tree_fn, void *, + hash_set<tree> *); #define rs_walk_tree(tp, func, data, pset) \ walk_tree_1 (tp, func, data, pset, rs_walk_subtrees) #define rs_walk_tree_without_duplicates(tp, func, data) \ @@ -3351,11 +3312,9 @@ gnu_vector_type_p (const_tree type) return TREE_CODE (type) == VECTOR_TYPE && !TYPE_INDIVISIBLE_P (type); } -extern vec<tree, va_gc> * -make_tree_vector (void); +extern vec<tree, va_gc> *make_tree_vector (void); -extern void -release_tree_vector (vec<tree, va_gc> *); +extern void release_tree_vector (vec<tree, va_gc> *); /* Simplified unique_ptr clone to release a tree vec on exit. */ @@ -3373,7 +3332,7 @@ public: releasing_vec &operator= (const releasing_vec &); vec_t &operator* () const { return *v; } - vec_t *operator-> () const { return v; } + vec_t *operator->() const { return v; } vec_t *get () const { return v; } operator vec_t * () const { return v; } vec_t **operator& () { return &v; } @@ -3442,8 +3401,7 @@ cxx_incomplete_type_error (const_tree value, const_tree type) cxx_incomplete_type_diagnostic (value, type, diagnostics::kind::error); } -extern location_t -location_of (tree t); +extern location_t location_of (tree t); /* Helpers for IMPLICIT_RVALUE_P to look through automatic dereference. */ @@ -3465,23 +3423,18 @@ set_implicit_rvalue_p (tree ot) } namespace Compile { -extern tree -maybe_constant_init (tree, tree = NULL_TREE, bool = false); +extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false); -extern void -explain_invalid_constexpr_fn (tree fun); +extern void explain_invalid_constexpr_fn (tree fun); extern bool potential_constant_expression (tree); -extern bool -literal_type_p (tree t); +extern bool literal_type_p (tree t); -extern bool -maybe_constexpr_fn (tree t); +extern bool maybe_constexpr_fn (tree t); -extern tree -fold_non_dependent_init (tree, tsubst_flags_t = tf_warning_or_error, - bool = false, tree = NULL_TREE); +extern tree fold_non_dependent_init (tree, tsubst_flags_t = tf_warning_or_error, + bool = false, tree = NULL_TREE); } // namespace Compile } // namespace Rust diff --git a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h index 0ce2142..0434bcf 100644 --- a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h +++ b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h @@ -239,31 +239,25 @@ struct Facts * * Output is not yet implemented and is only dumped to stdout. */ -extern "C" FFI::Output -polonius_run (FFI::FactsView input, bool dump_enabled); +extern "C" FFI::Output polonius_run (FFI::FactsView input, bool dump_enabled); // Helper functions for FFIVector to be used on Rust side extern "C" { -FFI::FFIVector<size_t> * -FFIVector__new (); +FFI::FFIVector<size_t> *FFIVector__new (); -FFI::FFIVectorPair * -FFIVector__new_vec_pair (); +FFI::FFIVectorPair *FFIVector__new_vec_pair (); -FFI::FFIVectorTriple * -FFIVector__new_vec_triple (); +FFI::FFIVectorTriple *FFIVector__new_vec_triple (); -void -FFIVector__push (FFI::FFIVector<size_t> *vector, size_t element); +void FFIVector__push (FFI::FFIVector<size_t> *vector, size_t element); void FFIVector__push_vec_pair (FFI::FFIVectorPair *vector, FFI::Pair<size_t, FFI::FFIVector<size_t> *> element); -void -FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector, - FFI::Triple<size_t, size_t, size_t> element); +void FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector, + FFI::Triple<size_t, size_t, size_t> element); } } // namespace Polonius diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc index 6b8b2e9..0799a4e 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc @@ -240,7 +240,8 @@ ExprStmtBuilder::visit (HIR::ArrayExpr &expr) auto &elems = expr.get_internal_elements (); switch (elems.get_array_expr_type ()) { - case HIR::ArrayElems::VALUES: { + case HIR::ArrayElems::VALUES: + { auto &elem_vals = (static_cast<HIR::ArrayElemsValues &> (elems)); auto init_values = visit_list (elem_vals.get_values ()); // collect locations @@ -254,7 +255,8 @@ ExprStmtBuilder::visit (HIR::ArrayExpr &expr) lookup_type (expr), expr.get_locus ()); break; } - case HIR::ArrayElems::COPIED: { + case HIR::ArrayElems::COPIED: + { auto &elem_copied = (static_cast<HIR::ArrayElemsCopied &> (elems)); auto init = visit_expr (elem_copied.get_elem_to_copy ()); return_expr (new InitializerExpr ({init}), lookup_type (expr), @@ -415,6 +417,18 @@ ExprStmtBuilder::visit (HIR::BlockExpr &block) } void +ExprStmtBuilder::visit (HIR::AnonConst &block) +{ + rust_unreachable (); +} + +void +ExprStmtBuilder::visit (HIR::ConstBlock &block) +{ + rust_unreachable (); +} + +void ExprStmtBuilder::visit (HIR::ContinueExpr &cont) { LoopAndLabelCtx info = cont.has_label () ? get_label_ctx (cont.get_label ()) diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h index 5cab3c4..45d3d58 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h @@ -84,6 +84,8 @@ protected: // Expr void visit (HIR::MethodCallExpr &expr) override; void visit (HIR::FieldAccessExpr &expr) override; void visit (HIR::BlockExpr &block) override; + void visit (HIR::AnonConst &block) override; + void visit (HIR::ConstBlock &block) override; void visit (HIR::ContinueExpr &cont) override; void visit (HIR::BreakExpr &brk) override; void visit (HIR::RangeFromToExpr &range) override; diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h index 4df0e14..e2cc2dd 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h @@ -27,6 +27,8 @@ #include "rust-name-resolver.h" #include "rust-bir.h" #include "rust-bir-free-region.h" +#include "rust-immutable-name-resolution-context.h" +#include "options.h" namespace Rust { @@ -402,19 +404,40 @@ protected: // HIR resolution helpers template <typename T> NodeId resolve_label (T &expr) { NodeId resolved_label; - bool ok - = ctx.resolver.lookup_resolved_label (expr.get_mappings ().get_nodeid (), - &resolved_label); - rust_assert (ok); + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto res = nr_ctx.lookup (expr.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + resolved_label = res.value (); + } + else + { + bool ok = ctx.resolver.lookup_resolved_label ( + expr.get_mappings ().get_nodeid (), &resolved_label); + rust_assert (ok); + } return resolved_label; } template <typename T> PlaceId resolve_variable (T &variable) { NodeId variable_id; - bool ok = ctx.resolver.lookup_resolved_name ( - variable.get_mappings ().get_nodeid (), &variable_id); - rust_assert (ok); + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + variable_id = res.value (); + } + else + { + bool ok = ctx.resolver.lookup_resolved_name ( + variable.get_mappings ().get_nodeid (), &variable_id); + rust_assert (ok); + } return ctx.place_db.lookup_variable (variable_id); } @@ -425,9 +448,20 @@ protected: // HIR resolution helpers // Unlike variables, // functions do not have to be declared in PlaceDB before use. NodeId variable_id; - bool ok = ctx.resolver.lookup_resolved_name ( - variable.get_mappings ().get_nodeid (), &variable_id); - rust_assert (ok); + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + variable_id = res.value (); + } + else + { + bool ok = ctx.resolver.lookup_resolved_name ( + variable.get_mappings ().get_nodeid (), &variable_id); + rust_assert (ok); + } if (ty->is<TyTy::FnType> ()) return ctx.place_db.get_constant (ty); else diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h index b7a1555..a5ec569 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h @@ -169,6 +169,14 @@ public: { return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ()); } + void visit (HIR::AnonConst &expr) override + { + return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ()); + } + void visit (HIR::ConstBlock &expr) override + { + return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ()); + } void visit (HIR::UnsafeBlockExpr &expr) override { return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ()); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc index ee37bb0..2d655f9 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc @@ -101,7 +101,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern) { switch (field->get_item_type ()) { - case HIR::StructPatternField::TUPLE_PAT: { + case HIR::StructPatternField::TUPLE_PAT: + { auto tuple = static_cast<HIR::StructPatternFieldTuplePat *> (field.get ()); @@ -123,7 +124,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern) tuple->get_tuple_pattern ().accept_vis (*this); break; } - case HIR::StructPatternField::IDENT_PAT: { + case HIR::StructPatternField::IDENT_PAT: + { auto ident_field = static_cast<HIR::StructPatternFieldIdentPat *> (field.get ()); TyTy::StructFieldType *field_ty = nullptr; @@ -139,7 +141,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern) ident_field->get_pattern ().accept_vis (*this); break; } - case HIR::StructPatternField::IDENT: { + case HIR::StructPatternField::IDENT: + { auto ident_field = static_cast<HIR::StructPatternFieldIdent *> (field.get ()); TyTy::StructFieldType *field_ty = nullptr; @@ -199,13 +202,15 @@ PatternBindingBuilder::visit (HIR::TuplePattern &pattern) size_t index = 0; switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::MULTIPLE: { + case HIR::TuplePatternItems::MULTIPLE: + { auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( pattern.get_items ()); visit_tuple_fields (items.get_patterns (), saved, index); break; } - case HIR::TuplePatternItems::RANGED: { + case HIR::TuplePatternItems::RANGED: + { auto &items = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); @@ -244,7 +249,8 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern) size_t index = 0; switch (pattern.get_items ().get_item_type ()) { - case HIR::TupleStructItems::RANGED: { + case HIR::TupleStructItems::RANGED: + { auto &items = static_cast<HIR::TupleStructItemsRange &> (pattern.get_items ()); @@ -261,7 +267,8 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern) visit_tuple_fields (items.get_upper_patterns (), saved, index); break; } - case HIR::TupleStructItems::MULTIPLE: { + case HIR::TupleStructItems::MULTIPLE: + { auto &items = static_cast<HIR::TupleStructItemsNoRange &> (pattern.get_items ()); visit_tuple_fields (items.get_patterns (), saved, index); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h index 84311cc..2e11f63 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h @@ -133,6 +133,8 @@ protected: void visit (HIR::MethodCallExpr &expr) override { rust_unreachable (); } void visit (HIR::FieldAccessExpr &expr) override { rust_unreachable (); } void visit (HIR::BlockExpr &expr) override { rust_unreachable (); } + void visit (HIR::AnonConst &expr) override { rust_unreachable (); } + void visit (HIR::ConstBlock &expr) override { rust_unreachable (); } void visit (HIR::ClosureExpr &expr) override { rust_unreachable (); } void visit (HIR::ContinueExpr &expr) override { rust_unreachable (); } void visit (HIR::BreakExpr &expr) override { rust_unreachable (); } diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc index 3864b81..9a7bb20 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc @@ -182,7 +182,8 @@ Dump::visit (const Statement &stmt) statement_place = stmt.get_place (); switch (stmt.get_kind ()) { - case Statement::Kind::ASSIGNMENT: { + case Statement::Kind::ASSIGNMENT: + { visit_place (stmt.get_place ()); stream << " = "; stmt.get_expr ().accept_vis (*this); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h index 32a4cd7..e3a1247 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h @@ -232,42 +232,50 @@ protected: // Main collection entry points (for different categories). { switch (stmt.get_kind ()) { - case Statement::Kind::ASSIGNMENT: { + case Statement::Kind::ASSIGNMENT: + { // TODO: for unwind, must had hadning for non-panic-only assignements issue_write_deep (stmt.get_place ()); visit_assignment_expr (stmt.get_place (), stmt.get_expr ()); break; } - case Statement::Kind::SWITCH: { + case Statement::Kind::SWITCH: + { issue_read_move (stmt.get_place ()); issue_jumps (); } break; - case Statement::Kind::GOTO: { + case Statement::Kind::GOTO: + { issue_jumps (); } break; - case Statement::Kind::RETURN: { + case Statement::Kind::RETURN: + { issue_place_access (RETURN_VALUE_PLACE); issue_locals_dealloc (); break; } - case Statement::Kind::STORAGE_DEAD: { + case Statement::Kind::STORAGE_DEAD: + { facts.path_moved_at_base.emplace_back (stmt.get_place ().value, get_current_point_mid ()); facts.var_defined_at.emplace_back (stmt.get_place ().value, get_current_point_mid ()); break; } - case Statement::Kind::STORAGE_LIVE: { + case Statement::Kind::STORAGE_LIVE: + { issue_write_deep (stmt.get_place (), true); break; } - case Statement::Kind::USER_TYPE_ASCRIPTION: { + case Statement::Kind::USER_TYPE_ASCRIPTION: + { issue_user_type_constraints (stmt.get_place (), stmt.get_type ()); break; } - case Statement::Kind::FAKE_READ: { + case Statement::Kind::FAKE_READ: + { issue_place_access (stmt.get_place ()); break; } @@ -791,7 +799,8 @@ protected: // Subset helpers. type->as<const TyTy::SliceType> ()->get_element_type (), region_start, regions); case TyTy::FNDEF: - case TyTy::TUPLE: { + case TyTy::TUPLE: + { for (auto &field : type->as<const TyTy::TupleType> ()->get_fields ()) sanitize_constraints (field.get_tyty (), region_start, regions); } diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h index dd9e672..14f1dd6 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h @@ -217,7 +217,7 @@ public: const T &operator[] (I pid) const { return internal_vector[pid.value]; } void push_back (T &¶m) { internal_vector.push_back (std::move (param)); } - template <typename... Args> void emplace_back (Args &&... args) + template <typename... Args> void emplace_back (Args &&...args) { internal_vector.emplace_back (std::forward<Args> (args)...); } @@ -471,14 +471,16 @@ private: case TyTy::FNDEF: case TyTy::NEVER: return true; - case TyTy::TUPLE: { + case TyTy::TUPLE: + { auto &fields = ty->as<TyTy::TupleType> ()->get_fields (); return std::all_of (fields.begin (), fields.end (), [] (const TyTy::TyVar &field) { return is_type_copy (field.get_tyty ()); }); } - case TyTy::ARRAY: { + case TyTy::ARRAY: + { return is_type_copy (ty->as<TyTy::ArrayType> ()->get_element_type ()); } case TyTy::INFER: diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h index 5dac89e..d405569 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h @@ -51,7 +51,7 @@ template <typename BASE, typename T> class VisitableImpl : public BASE { public: template <typename... Args> - explicit VisitableImpl (Args &&... args) : BASE (std::forward<Args> (args)...) + explicit VisitableImpl (Args &&...args) : BASE (std::forward<Args> (args)...) {} void accept_vis (Visitor &visitor) override diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h b/gcc/rust/checks/errors/borrowck/rust-function-collector.h index 7cf0952..860915e 100644 --- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h +++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h @@ -104,6 +104,8 @@ public: void visit (HIR::MethodCallExpr &expr) override {} void visit (HIR::FieldAccessExpr &expr) override {} void visit (HIR::BlockExpr &expr) override {} + void visit (HIR::AnonConst &expr) override {} + void visit (HIR::ConstBlock &expr) override {} void visit (HIR::ContinueExpr &expr) override {} void visit (HIR::BreakExpr &expr) override {} void visit (HIR::RangeFromToExpr &expr) override {} diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc index 3d25459..5291276 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc @@ -25,8 +25,7 @@ #include "rust-pub-restricted-visitor.h" #include "rust-privacy-reporter.h" -extern bool -saw_errors (void); +extern bool saw_errors (void); namespace Rust { namespace Privacy { diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h b/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h index a506613f..9699ac4 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h +++ b/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h @@ -71,8 +71,7 @@ private: #if CHECKING_P namespace selftest { -void -rust_privacy_ctx_test (void); +void rust_privacy_ctx_test (void); } #endif // !CHECKING_P diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc index 2a10053..e8a6792 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc @@ -157,7 +157,8 @@ PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, { case ModuleVisibility::Public: break; - case ModuleVisibility::Restricted: { + case ModuleVisibility::Restricted: + { // If we are in the crate, everything is restricted correctly, but we // can't get a module for it if (!current_module.has_value ()) @@ -215,12 +216,14 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings, case TyTy::USIZE: case TyTy::ISIZE: case TyTy::ADT: - case TyTy::STR: { + case TyTy::STR: + { auto ref_id = ty->get_ref (); if (auto lookup_id = mappings.lookup_hir_to_node (ref_id)) return check_for_privacy_violation (*lookup_id, locus); - rust_unreachable (); } + break; + case TyTy::REF: return recursive_check ( static_cast<const TyTy::ReferenceType *> (ty)->get_base ()); @@ -243,7 +246,8 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings, static_cast<const TyTy::TupleType *> (ty)->get_fields ()) recursive_check (param.get_tyty ()); return; - case TyTy::PLACEHOLDER: { + case TyTy::PLACEHOLDER: + { const auto p = static_cast<const TyTy::PlaceholderType *> (ty); if (!p->can_resolve ()) return; @@ -413,7 +417,8 @@ PrivacyReporter::visit (HIR::ArrayExpr &expr) HIR::ArrayElems &elements = expr.get_internal_elements (); switch (elements.get_array_expr_type ()) { - case HIR::ArrayElems::ArrayExprType::VALUES: { + case HIR::ArrayElems::ArrayExprType::VALUES: + { auto &elems = static_cast<HIR::ArrayElemsValues &> (elements); for (auto &value : elems.get_values ()) value->accept_vis (*this); @@ -518,6 +523,18 @@ PrivacyReporter::visit (HIR::BlockExpr &expr) } void +PrivacyReporter::visit (HIR::AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +PrivacyReporter::visit (HIR::ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + +void PrivacyReporter::visit (HIR::ContinueExpr &) {} diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h index 7df2cf4..07eebf6 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h @@ -106,6 +106,8 @@ types virtual void visit (HIR::MethodCallExpr &expr); virtual void visit (HIR::FieldAccessExpr &expr); virtual void visit (HIR::BlockExpr &expr); + virtual void visit (HIR::AnonConst &expr); + virtual void visit (HIR::ConstBlock &expr); virtual void visit (HIR::ContinueExpr &expr); virtual void visit (HIR::BreakExpr &expr); virtual void visit (HIR::RangeFromToExpr &expr); diff --git a/gcc/rust/checks/errors/privacy/rust-reachability.cc b/gcc/rust/checks/errors/privacy/rust-reachability.cc index 1e57674..223c77b 100644 --- a/gcc/rust/checks/errors/privacy/rust-reachability.cc +++ b/gcc/rust/checks/errors/privacy/rust-reachability.cc @@ -158,7 +158,8 @@ ReachabilityVisitor::visit (HIR::Enum &enum_item) switch (variant->get_enum_item_kind ()) { - case HIR::EnumItem::Tuple: { + case HIR::EnumItem::Tuple: + { // Should we update the fields only if they are public? Similarly to // what we do in the ReachabilityVisitor for HIR::TupleStruct? auto tuple_variant @@ -167,7 +168,8 @@ ReachabilityVisitor::visit (HIR::Enum &enum_item) ctx.update_reachability (field.get_mappings (), variant_reach); break; } - case HIR::EnumItem::Struct: { + case HIR::EnumItem::Struct: + { // Should we update the fields only if they are public? Similarly to // what we do in the ReachabilityVisitor for HIR::StructStruct? auto struct_variant diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc index f0da745..c59763d 100644 --- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc +++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc @@ -127,7 +127,8 @@ VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility, case HIR::Visibility::PUBLIC: to_resolve = ModuleVisibility::create_public (); return true; - case HIR::Visibility::RESTRICTED: { + case HIR::Visibility::RESTRICTED: + { // FIXME: We also need to handle 2015 vs 2018 edition conflicts auto id = UNKNOWN_DEFID; auto result = resolve_module_path (visibility.get_path (), id); diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc index 3716ea5..5cbab3d 100644 --- a/gcc/rust/checks/errors/rust-const-checker.cc +++ b/gcc/rust/checks/errors/rust-const-checker.cc @@ -417,6 +417,26 @@ ConstChecker::visit (BlockExpr &expr) } void +ConstChecker::visit (AnonConst &expr) +{ + const_context.enter (expr.get_mappings ().get_hirid ()); + + expr.get_inner_expr ().accept_vis (*this); + + const_context.exit (); +} + +void +ConstChecker::visit (ConstBlock &expr) +{ + const_context.enter (expr.get_mappings ().get_hirid ()); + + expr.get_const_expr ().accept_vis (*this); + + const_context.exit (); +} + +void ConstChecker::visit (ContinueExpr &) {} diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h index b954330..2239874 100644 --- a/gcc/rust/checks/errors/rust-const-checker.h +++ b/gcc/rust/checks/errors/rust-const-checker.h @@ -113,6 +113,8 @@ private: virtual void visit (FieldAccessExpr &expr) override; virtual void visit (ClosureExpr &expr) override; virtual void visit (BlockExpr &expr) override; + virtual void visit (AnonConst &expr) override; + virtual void visit (ConstBlock &expr) override; virtual void visit (ContinueExpr &expr) override; virtual void visit (BreakExpr &expr) override; virtual void visit (RangeFromToExpr &expr) override; diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc index 648bc07..ec22a0e 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc @@ -295,6 +295,18 @@ PatternChecker::visit (BlockExpr &expr) } void +PatternChecker::visit (AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +PatternChecker::visit (ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + +void PatternChecker::visit (ContinueExpr &) {} @@ -728,23 +740,27 @@ Constructor::is_covered_by (const Constructor &o) const switch (kind) { - case ConstructorKind::VARIANT: { + case ConstructorKind::VARIANT: + { rust_assert (kind == ConstructorKind::VARIANT); return variant_idx == o.variant_idx; } break; - case ConstructorKind::INT_RANGE: { + case ConstructorKind::INT_RANGE: + { rust_assert (kind == ConstructorKind::INT_RANGE); return int_range.lo >= o.int_range.lo && int_range.hi <= o.int_range.hi; } break; - case ConstructorKind::WILDCARD: { + case ConstructorKind::WILDCARD: + { // TODO: wildcard is covered by a variant of enum with a single // variant return false; } break; - case ConstructorKind::STRUCT: { + case ConstructorKind::STRUCT: + { // Struct pattern is always covered by a other struct constructor. return true; } @@ -900,19 +916,22 @@ PlaceInfo::specialize (const Constructor &c) const switch (c.get_kind ()) { case Constructor::ConstructorKind::WILDCARD: - case Constructor::ConstructorKind::INT_RANGE: { + case Constructor::ConstructorKind::INT_RANGE: + { return {}; } break; case Constructor::ConstructorKind::STRUCT: - case Constructor::ConstructorKind::VARIANT: { + case Constructor::ConstructorKind::VARIANT: + { rust_assert (ty->get_kind () == TyTy::TypeKind::ADT); TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty); switch (adt->get_adt_kind ()) { case TyTy::ADTType::ADTKind::ENUM: case TyTy::ADTType::ADTKind::STRUCT_STRUCT: - case TyTy::ADTType::ADTKind::TUPLE_STRUCT: { + case TyTy::ADTType::ADTKind::TUPLE_STRUCT: + { TyTy::VariantDef *variant = adt->get_variants ().at (c.get_variant_index ()); if (variant->get_variant_type () @@ -926,14 +945,16 @@ PlaceInfo::specialize (const Constructor &c) const return new_place_infos; } break; - case TyTy::ADTType::ADTKind::UNION: { + case TyTy::ADTType::ADTKind::UNION: + { // TODO: support unions rust_unreachable (); } } } break; - default: { + default: + { rust_unreachable (); } break; @@ -991,7 +1012,8 @@ WitnessPat::to_string () const { switch (ctor.get_kind ()) { - case Constructor::ConstructorKind::STRUCT: { + case Constructor::ConstructorKind::STRUCT: + { TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty); TyTy::VariantDef *variant = adt->get_variants ().at (ctor.get_variant_index ()); @@ -1016,7 +1038,8 @@ WitnessPat::to_string () const return buf; } break; - case Constructor::ConstructorKind::VARIANT: { + case Constructor::ConstructorKind::VARIANT: + { std::string buf; TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty); buf += adt->get_identifier (); @@ -1026,11 +1049,13 @@ WitnessPat::to_string () const switch (variant->get_variant_type ()) { - case TyTy::VariantDef::VariantType::NUM: { + case TyTy::VariantDef::VariantType::NUM: + { return buf; } break; - case TyTy::VariantDef::VariantType::TUPLE: { + case TyTy::VariantDef::VariantType::TUPLE: + { buf += "("; for (size_t i = 0; i < fields.size (); i++) { @@ -1042,7 +1067,8 @@ WitnessPat::to_string () const return buf; } break; - case TyTy::VariantDef::VariantType::STRUCT: { + case TyTy::VariantDef::VariantType::STRUCT: + { buf += " {"; if (!fields.empty ()) buf += " "; @@ -1061,7 +1087,8 @@ WitnessPat::to_string () const buf += "}"; } break; - default: { + default: + { rust_unreachable (); } break; @@ -1069,21 +1096,25 @@ WitnessPat::to_string () const return buf; } break; - case Constructor::ConstructorKind::INT_RANGE: { + case Constructor::ConstructorKind::INT_RANGE: + { // TODO: implement rust_unreachable (); } break; - case Constructor::ConstructorKind::WILDCARD: { + case Constructor::ConstructorKind::WILDCARD: + { return "_"; } break; - case Constructor::ConstructorKind::REFERENCE: { + case Constructor::ConstructorKind::REFERENCE: + { // TODO: implement rust_unreachable (); } break; - default: { + default: + { rust_unreachable (); } break; @@ -1100,12 +1131,14 @@ WitnessMatrix::apply_constructor (const Constructor &ctor, // TODO: only support struct and variant ctor for now. switch (ctor.get_kind ()) { - case Constructor::ConstructorKind::WILDCARD: { + case Constructor::ConstructorKind::WILDCARD: + { arity = 0; } break; case Constructor::ConstructorKind::STRUCT: - case Constructor::ConstructorKind::VARIANT: { + case Constructor::ConstructorKind::VARIANT: + { if (ty->get_kind () == TyTy::TypeKind::ADT) { TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty); @@ -1118,7 +1151,8 @@ WitnessMatrix::apply_constructor (const Constructor &ctor, } } break; - default: { + default: + { rust_unreachable (); } } @@ -1160,9 +1194,9 @@ WitnessMatrix::extend (const WitnessMatrix &other) } // forward declarations -static DeconstructedPat -lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern, - TyTy::BaseType *scrutinee_ty); +static DeconstructedPat lower_pattern (Resolver::TypeCheckContext *ctx, + HIR::Pattern &pattern, + TyTy::BaseType *scrutinee_ty); static DeconstructedPat lower_tuple_pattern (Resolver::TypeCheckContext *ctx, @@ -1175,7 +1209,8 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx, std::vector<DeconstructedPat> fields; switch (elems.get_item_type ()) { - case HIR::TupleStructItems::ItemType::MULTIPLE: { + case HIR::TupleStructItems::ItemType::MULTIPLE: + { HIR::TupleStructItemsNoRange &multiple = static_cast<HIR::TupleStructItemsNoRange &> (elems); @@ -1191,12 +1226,14 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx, return DeconstructedPat (ctor, arity, fields, pattern.get_locus ()); } break; - case HIR::TupleStructItems::ItemType::RANGED: { + case HIR::TupleStructItems::ItemType::RANGED: + { // TODO: ranged tuple struct items rust_unreachable (); } break; - default: { + default: + { rust_unreachable (); } } @@ -1227,7 +1264,8 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx, { switch (elem->get_item_type ()) { - case HIR::StructPatternField::ItemType::IDENT: { + case HIR::StructPatternField::ItemType::IDENT: + { HIR::StructPatternFieldIdent *ident = static_cast<HIR::StructPatternFieldIdent *> (elem.get ()); int field_idx @@ -1236,7 +1274,8 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx, = DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::StructPatternField::ItemType::IDENT_PAT: { + case HIR::StructPatternField::ItemType::IDENT_PAT: + { HIR::StructPatternFieldIdentPat *ident_pat = static_cast<HIR::StructPatternFieldIdentPat *> (elem.get ()); int field_idx @@ -1246,12 +1285,14 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx, variant->get_fields ().at (field_idx)->get_field_type ()); } break; - case HIR::StructPatternField::ItemType::TUPLE_PAT: { + case HIR::StructPatternField::ItemType::TUPLE_PAT: + { // TODO: tuple: pat rust_unreachable (); } break; - default: { + default: + { rust_unreachable (); } } @@ -1268,11 +1309,13 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern, switch (pat_type) { case HIR::Pattern::PatternType::WILDCARD: - case HIR::Pattern::PatternType::IDENTIFIER: { + case HIR::Pattern::PatternType::IDENTIFIER: + { return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::PATH: { + case HIR::Pattern::PatternType::PATH: + { // TODO: support constants, associated constants, enum variants and // structs // https://doc.rust-lang.org/reference/patterns.html#path-patterns @@ -1280,13 +1323,15 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern, return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::REFERENCE: { + case HIR::Pattern::PatternType::REFERENCE: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; case HIR::Pattern::PatternType::STRUCT: - case HIR::Pattern::PatternType::TUPLE_STRUCT: { + case HIR::Pattern::PatternType::TUPLE_STRUCT: + { HirId path_id = UNKNOWN_HIRID; if (pat_type == HIR::Pattern::PatternType::STRUCT) { @@ -1343,37 +1388,44 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern, } } break; - case HIR::Pattern::PatternType::TUPLE: { + case HIR::Pattern::PatternType::TUPLE: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::SLICE: { + case HIR::Pattern::PatternType::SLICE: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::ALT: { + case HIR::Pattern::PatternType::ALT: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::LITERAL: { + case HIR::Pattern::PatternType::LITERAL: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::RANGE: { + case HIR::Pattern::PatternType::RANGE: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - case HIR::Pattern::PatternType::GROUPED: { + case HIR::Pattern::PatternType::GROUPED: + { // TODO: unimplemented. Treat this pattern as wildcard for now. return DeconstructedPat::make_wildcard (pattern.get_locus ()); } break; - default: { + default: + { rust_unreachable (); } } diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h index 6d60ced..5766180 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h @@ -33,9 +33,9 @@ namespace Analysis { using namespace HIR; -void -check_match_usefulness (Resolver::TypeCheckContext *ctx, - TyTy::BaseType *scrutinee_ty, HIR::MatchExpr &expr); +void check_match_usefulness (Resolver::TypeCheckContext *ctx, + TyTy::BaseType *scrutinee_ty, + HIR::MatchExpr &expr); class PatternChecker : public HIR::HIRFullVisitor { @@ -86,6 +86,8 @@ private: virtual void visit (MethodCallExpr &expr) override; virtual void visit (FieldAccessExpr &expr) override; virtual void visit (BlockExpr &expr) override; + virtual void visit (AnonConst &expr) override; + virtual void visit (ConstBlock &expr) override; virtual void visit (ClosureExpr &expr) override; virtual void visit (ContinueExpr &expr) override; virtual void visit (BreakExpr &expr) override; diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc index 46eef11..d90088f 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.cc +++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc @@ -540,6 +540,18 @@ UnsafeChecker::visit (BlockExpr &expr) } void +UnsafeChecker::visit (AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +UnsafeChecker::visit (ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + +void UnsafeChecker::visit (ContinueExpr &) {} diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h index 9a8fb7c..8a9830f 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.h +++ b/gcc/rust/checks/errors/rust-unsafe-checker.h @@ -95,6 +95,8 @@ private: virtual void visit (FieldAccessExpr &expr) override; virtual void visit (ClosureExpr &expr) override; virtual void visit (BlockExpr &expr) override; + virtual void visit (AnonConst &expr) override; + virtual void visit (ConstBlock &expr) override; virtual void visit (ContinueExpr &expr) override; virtual void visit (BreakExpr &expr) override; virtual void visit (RangeFromToExpr &expr) override; diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index a8c3ca5..0db6122 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -289,7 +289,8 @@ CfgStrip::maybe_strip_generic_args (AST::GenericArgs &args) { switch (arg.get_kind ()) { - case AST::GenericArg::Kind::Type: { + case AST::GenericArg::Kind::Type: + { auto &type = arg.get_type (); type.accept_vis (*this); @@ -298,7 +299,8 @@ CfgStrip::maybe_strip_generic_args (AST::GenericArgs &args) "cannot strip type in this position"); break; } - case AST::GenericArg::Kind::Const: { + case AST::GenericArg::Kind::Const: + { auto &expr = arg.get_expression (); expr.accept_vis (*this); @@ -1190,7 +1192,7 @@ CfgStrip::visit (AST::ClosureExprInnerTyped &expr) rust_error_at (type.get_locus (), "cannot strip type in this position"); // can't strip expression itself, but can strip sub-expressions - auto &definition_block = expr.get_definition_block (); + auto &definition_block = expr.get_definition_expr (); definition_block.accept_vis (*this); if (definition_block.is_marked_for_strip ()) rust_error_at (definition_block.get_locus (), @@ -2260,7 +2262,7 @@ void CfgStrip::visit (AST::IdentifierPattern &pattern) { // can only strip sub-patterns of the inner pattern to bind - if (!pattern.has_pattern_to_bind ()) + if (!pattern.has_subpattern ()) return; AST::DefaultASTVisitor::visit (pattern); diff --git a/gcc/rust/expand/rust-derive-clone.h b/gcc/rust/expand/rust-derive-clone.h index 61224ba..a3320c7 100644 --- a/gcc/rust/expand/rust-derive-clone.h +++ b/gcc/rust/expand/rust-derive-clone.h @@ -29,7 +29,7 @@ class DeriveClone : DeriveVisitor public: DeriveClone (location_t loc); - std::unique_ptr<AST::Item> go (Item &item); + std::unique_ptr<Item> go (Item &item); private: std::unique_ptr<Item> expanded; @@ -80,10 +80,10 @@ private: MatchCase clone_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive-copy.h b/gcc/rust/expand/rust-derive-copy.h index 71972eb..664a8e0 100644 --- a/gcc/rust/expand/rust-derive-copy.h +++ b/gcc/rust/expand/rust-derive-copy.h @@ -44,10 +44,10 @@ private: copy_impl (std::string name, const std::vector<std::unique_ptr<GenericParam>> &type_generics); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive-default.cc b/gcc/rust/expand/rust-derive-default.cc index 2e8b456..1b497b5 100644 --- a/gcc/rust/expand/rust-derive-default.cc +++ b/gcc/rust/expand/rust-derive-default.cc @@ -98,7 +98,8 @@ DeriveDefault::visit_struct (StructStruct &item) for (auto &field : item.get_fields ()) { auto name = field.get_field_name ().as_string (); - auto expr = default_call (field.get_field_type ().clone_type ()); + auto type = Builder::new_type (field.get_field_type ()); + auto expr = default_call (std::move (type)); cloned_fields.emplace_back ( builder.struct_expr_field (std::move (name), std::move (expr))); @@ -119,7 +120,7 @@ DeriveDefault::visit_tuple (TupleStruct &tuple_item) for (auto &field : tuple_item.get_fields ()) { - auto type = field.get_field_type ().clone_type (); + auto type = Builder::new_type (field.get_field_type ()); defaulted_fields.emplace_back (default_call (std::move (type))); } diff --git a/gcc/rust/expand/rust-derive-eq.cc b/gcc/rust/expand/rust-derive-eq.cc index 5e7a894..9765127 100644 --- a/gcc/rust/expand/rust-derive-eq.cc +++ b/gcc/rust/expand/rust-derive-eq.cc @@ -142,7 +142,10 @@ DeriveEq::visit_tuple (TupleStruct &item) auto types = std::vector<std::unique_ptr<Type>> (); for (auto &field : item.get_fields ()) - types.emplace_back (field.get_field_type ().clone_type ()); + { + auto type = Builder::new_type (field.get_field_type ()); + types.emplace_back (std::move (type)); + } expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)), item.get_identifier ().as_string (), @@ -155,7 +158,10 @@ DeriveEq::visit_struct (StructStruct &item) auto types = std::vector<std::unique_ptr<Type>> (); for (auto &field : item.get_fields ()) - types.emplace_back (field.get_field_type ().clone_type ()); + { + auto type = Builder::new_type (field.get_field_type ()); + types.emplace_back (std::move (type)); + } expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)), item.get_identifier ().as_string (), @@ -175,19 +181,26 @@ DeriveEq::visit_enum (Enum &item) case EnumItem::Kind::Discriminant: // nothing to do as they contain no inner types continue; - case EnumItem::Kind::Tuple: { + case EnumItem::Kind::Tuple: + { auto &tuple = static_cast<EnumItemTuple &> (*variant); for (auto &field : tuple.get_tuple_fields ()) - types.emplace_back (field.get_field_type ().clone_type ()); - + { + auto type = Builder::new_type (field.get_field_type ()); + types.emplace_back (std::move (type)); + } break; } - case EnumItem::Kind::Struct: { + case EnumItem::Kind::Struct: + { auto &tuple = static_cast<EnumItemStruct &> (*variant); for (auto &field : tuple.get_struct_fields ()) - types.emplace_back (field.get_field_type ().clone_type ()); + { + auto type = Builder::new_type (field.get_field_type ()); + types.emplace_back (std::move (type)); + } break; } @@ -205,7 +218,10 @@ DeriveEq::visit_union (Union &item) auto types = std::vector<std::unique_ptr<Type>> (); for (auto &field : item.get_variants ()) - types.emplace_back (field.get_field_type ().clone_type ()); + { + auto type = Builder::new_type (field.get_field_type ()); + types.emplace_back (std::move (type)); + } expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)), item.get_identifier ().as_string (), diff --git a/gcc/rust/expand/rust-derive-eq.h b/gcc/rust/expand/rust-derive-eq.h index 17af526..fb187cc 100644 --- a/gcc/rust/expand/rust-derive-eq.h +++ b/gcc/rust/expand/rust-derive-eq.h @@ -31,7 +31,7 @@ class DeriveEq : DeriveVisitor public: DeriveEq (location_t loc); - std::vector<std::unique_ptr<AST::Item>> go (Item &item); + std::vector<std::unique_ptr<Item>> go (Item &item); private: std::vector<std::unique_ptr<Item>> expanded; @@ -70,10 +70,10 @@ private: */ std::unique_ptr<Stmt> assert_type_is_eq (std::unique_ptr<Type> &&type); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive-hash.h b/gcc/rust/expand/rust-derive-hash.h index 02b0bee..67170d0 100644 --- a/gcc/rust/expand/rust-derive-hash.h +++ b/gcc/rust/expand/rust-derive-hash.h @@ -29,7 +29,7 @@ class DeriveHash : DeriveVisitor public: DeriveHash (location_t loc); - std::unique_ptr<AST::Item> go (Item &item); + std::unique_ptr<Item> go (Item &item); private: std::unique_ptr<Item> expanded; @@ -49,10 +49,10 @@ private: MatchCase match_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc new file mode 100644 index 0000000..7eaaa47 --- /dev/null +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -0,0 +1,172 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-derive-ord.h" +#include "rust-ast-dump.h" +#include "rust-ast.h" +#include "rust-derive.h" +#include "rust-item.h" + +namespace Rust { +namespace AST { + +DeriveOrd::DeriveOrd (Ordering ordering, location_t loc) + : DeriveVisitor (loc), ordering (ordering) +{} + +std::unique_ptr<Item> +DeriveOrd::go (Item &item) +{ + item.accept_vis (*this); + + AST::Dump::debug (*expanded); + + return std::move (expanded); +} + +std::unique_ptr<Item> +DeriveOrd::cmp_impl ( + std::unique_ptr<BlockExpr> &&fn_block, Identifier type_name, + const std::vector<std::unique_ptr<GenericParam>> &type_generics) +{ + auto fn = cmp_fn (std::move (fn_block), type_name); + + auto trait = ordering == Ordering::Partial ? "PartialOrd" : "Ord"; + auto trait_path = builder.type_path ({"core", "cmp", trait}, true); + + auto trait_bound + = builder.trait_bound (builder.type_path ({"core", "cmp", trait}, true)); + + auto trait_items = vec (std::move (fn)); + + auto cmp_generics + = setup_impl_generics (type_name.as_string (), type_generics, + std::move (trait_bound)); + + return builder.trait_impl (trait_path, std::move (cmp_generics.self_type), + std::move (trait_items), + std::move (cmp_generics.impl)); +} + +std::unique_ptr<AssociatedItem> +DeriveOrd::cmp_fn (std::unique_ptr<BlockExpr> &&block, Identifier type_name) +{ + // Ordering + auto return_type = builder.type_path ({"core", "cmp", "Ordering"}, true); + + // In the case of PartialOrd, we return an Option<Ordering> + if (ordering == Ordering::Partial) + { + auto generic = GenericArg::create_type (ptrify (return_type)); + + auto generic_seg = builder.type_path_segment_generic ( + "Option", GenericArgs ({}, {generic}, {}, loc)); + auto core = builder.type_path_segment ("core"); + auto option = builder.type_path_segment ("option"); + + return_type + = builder.type_path (vec (std::move (core), std::move (option), + std::move (generic_seg)), + true); + } + + // &self, other: &Self + auto params = vec ( + builder.self_ref_param (), + builder.function_param (builder.identifier_pattern ("other"), + builder.reference_type (ptrify ( + builder.type_path (type_name.as_string ()))))); + + auto function_name = ordering == Ordering::Partial ? "partial_cmp" : "cmp"; + + return builder.function (function_name, std::move (params), + ptrify (return_type), std::move (block)); +} +std::unique_ptr<Expr> +recursive_match () +{ + return nullptr; +} + +// we need to do a recursive match expression for all of the fields used in a +// struct so for something like struct Foo { a: i32, b: i32, c: i32 } we must +// first compare each `a` field, then `b`, then `c`, like this: +// +// match cmp_fn(self.<field>, other.<field>) { +// Ordering::Equal => <recurse>, +// cmp => cmp, +// } +// +// and the recurse will be the exact same expression, on the next field. so that +// our result looks like this: +// +// match cmp_fn(self.a, other.a) { +// Ordering::Equal => match cmp_fn(self.b, other.b) { +// Ordering::Equal =>cmp_fn(self.c, other.c), +// cmp => cmp, +// } +// cmp => cmp, +// } +// +// the last field comparison needs not to be a match but just the function call. +// this is going to be annoying lol +void +DeriveOrd::visit_struct (StructStruct &item) +{ + // FIXME: Put cmp_fn call inside cmp_impl, pass a block to cmp_impl instead - + // this avoids repeating the same parameter twice (the type name) + expanded = cmp_impl (builder.block (), item.get_identifier (), + item.get_generic_params ()); +} + +// same as structs, but for each field index instead of each field name - +// straightforward once we have `visit_struct` working +void +DeriveOrd::visit_tuple (TupleStruct &item) +{} + +// for enums, we need to generate a match for each of the enum's variant that +// contains data and then do the same thing as visit_struct or visit_enum. if +// the two aren't the same variant, then compare the two discriminant values for +// all the dataless enum variants and in the general case. +// +// so for enum Foo { A(i32, i32), B, C } we need to do the following +// +// match (self, other) { +// (A(self_0, self_1), A(other_0, other_1)) => { +// match cmp_fn(self_0, other_0) { +// Ordering::Equal => cmp_fn(self_1, other_1), +// cmp => cmp, +// }, +// _ => cmp_fn(discr_value(self), discr_value(other)) +// } +void +DeriveOrd::visit_enum (Enum &item) +{} + +void +DeriveOrd::visit_union (Union &item) +{ + auto trait_name = ordering == Ordering::Total ? "Ord" : "PartialOrd"; + + rust_error_at (item.get_locus (), "derive(%s) cannot be used on unions", + trait_name); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/expand/rust-derive-ord.h b/gcc/rust/expand/rust-derive-ord.h new file mode 100644 index 0000000..fae1326 --- /dev/null +++ b/gcc/rust/expand/rust-derive-ord.h @@ -0,0 +1,74 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_DERIVE_ORD_H +#define RUST_DERIVE_ORD_H + +#include "rust-ast.h" +#include "rust-derive.h" + +namespace Rust { +namespace AST { + +/** + * DeriveOrd is a bit special as the expansion of both `PartialOrd` and `Ord` + * is extremely similar. The only difference is that `PartialOrd` concerns + * partial-ordering, and thus its main method returns an `Option<Ordering>`, + * while `Ord` concerns total-ordering, and its main method returns an + * `Ordering`. Otherwise, the expansion logic is the same, so we factor both + * derives into one. + */ +class DeriveOrd : public DeriveVisitor +{ +public: + enum class Ordering + { + Total, + Partial + }; + + DeriveOrd (Ordering ordering, location_t loc); + + std::unique_ptr<Item> go (Item &item); + +private: + std::unique_ptr<Item> expanded; + + Ordering ordering; + + /** + * Create the recursive matching structure used when implementing the + * comparison function on multiple sub items (fields, tuple indexes...) */ + std::unique_ptr<Expr> recursive_match (); + + std::unique_ptr<Item> + cmp_impl (std::unique_ptr<BlockExpr> &&fn_block, Identifier type_name, + const std::vector<std::unique_ptr<GenericParam>> &type_generics); + std::unique_ptr<AssociatedItem> cmp_fn (std::unique_ptr<BlockExpr> &&block, + Identifier type_name); + + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DERIVE_ORD_H diff --git a/gcc/rust/expand/rust-derive-partial-eq.cc b/gcc/rust/expand/rust-derive-partial-eq.cc index ff66faa..22368bc 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.cc +++ b/gcc/rust/expand/rust-derive-partial-eq.cc @@ -199,8 +199,6 @@ DerivePartialEq::match_enum_tuple (PathInExpression variant_path, auto self_pattern_str = "__self_" + std::to_string (i); auto other_pattern_str = "__other_" + std::to_string (i); - rust_debug ("]ARTHUR[ %s", self_pattern_str.c_str ()); - self_patterns.emplace_back ( builder.identifier_pattern (self_pattern_str)); other_patterns.emplace_back ( @@ -240,15 +238,55 @@ MatchCase DerivePartialEq::match_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant) { - // NOTE: We currently do not support compiling struct patterns where an - // identifier is assigned a new pattern, e.g. Bloop { f0: x } - // This is what we should be using to compile PartialEq for enum struct - // variants, as we need to be comparing the field of each instance meaning we - // need to give two different names to two different instances of the same - // field. We cannot just use the field's name like we do when deriving - // `Clone`. - - rust_unreachable (); + auto self_fields = std::vector<std::unique_ptr<StructPatternField>> (); + auto other_fields = std::vector<std::unique_ptr<StructPatternField>> (); + + auto self_other_exprs = std::vector<SelfOther> (); + + for (auto &field : variant.get_struct_fields ()) + { + // The patterns we're creating for each field are `self_<field>` and + // `other_<field>` where `field` is the name of the field. It doesn't + // actually matter what we use, as long as it's ordered, unique, and that + // we can reuse it in the match case's return expression to check that + // they are equal. + + auto field_name = field.get_field_name ().as_string (); + + auto self_pattern_str = "__self_" + field_name; + auto other_pattern_str = "__other_" + field_name; + + self_fields.emplace_back (builder.struct_pattern_ident_pattern ( + field_name, builder.identifier_pattern (self_pattern_str))); + other_fields.emplace_back (builder.struct_pattern_ident_pattern ( + field_name, builder.identifier_pattern (other_pattern_str))); + + self_other_exprs.emplace_back (SelfOther{ + builder.identifier (self_pattern_str), + builder.identifier (other_pattern_str), + }); + } + + auto self_elts = StructPatternElements (std::move (self_fields)); + auto other_elts = StructPatternElements (std::move (other_fields)); + + auto self_pattern = std::unique_ptr<Pattern> ( + new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern ( + variant_path, loc, std::move (self_elts))), + false, false, loc)); + auto other_pattern = std::unique_ptr<Pattern> ( + new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern ( + variant_path, loc, std::move (other_elts))), + false, false, loc)); + + auto tuple_items = std::make_unique<TuplePatternItemsMultiple> ( + vec (std::move (self_pattern), std::move (other_pattern))); + + auto pattern = std::make_unique<TuplePattern> (std::move (tuple_items), loc); + + auto expr = build_eq_expression (std::move (self_other_exprs)); + + return builder.match_case (std::move (pattern), std::move (expr)); } void @@ -275,9 +313,9 @@ DerivePartialEq::visit_enum (Enum &item) static_cast<EnumItemTuple &> (*variant))); break; case EnumItem::Kind::Struct: - rust_sorry_at ( - item.get_locus (), - "cannot derive(PartialEq) for enum struct variants yet"); + cases.emplace_back ( + match_enum_struct (variant_path, + static_cast<EnumItemStruct &> (*variant))); break; } } diff --git a/gcc/rust/expand/rust-derive-partial-eq.h b/gcc/rust/expand/rust-derive-partial-eq.h index ac963a6..12d793d 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.h +++ b/gcc/rust/expand/rust-derive-partial-eq.h @@ -30,7 +30,7 @@ class DerivePartialEq : DeriveVisitor public: DerivePartialEq (location_t loc); - std::vector<std::unique_ptr<AST::Item>> go (Item &item); + std::vector<std::unique_ptr<Item>> go (Item &item); private: std::vector<std::unique_ptr<Item>> expanded; @@ -73,10 +73,10 @@ private: MatchCase match_enum_struct (PathInExpression variant_path, const EnumItemStruct &variant); - virtual void visit_struct (StructStruct &item); - virtual void visit_tuple (TupleStruct &item); - virtual void visit_enum (Enum &item); - virtual void visit_union (Union &item); + virtual void visit_struct (StructStruct &item) override; + virtual void visit_tuple (TupleStruct &item) override; + virtual void visit_enum (Enum &item) override; + virtual void visit_union (Union &item) override; }; } // namespace AST diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc index 015b81e..69081db 100644 --- a/gcc/rust/expand/rust-derive.cc +++ b/gcc/rust/expand/rust-derive.cc @@ -22,6 +22,7 @@ #include "rust-derive-debug.h" #include "rust-derive-default.h" #include "rust-derive-eq.h" +#include "rust-derive-ord.h" #include "rust-derive-partial-eq.h" #include "rust-derive-hash.h" @@ -59,10 +60,11 @@ DeriveVisitor::derive (Item &item, const Attribute &attr, case BuiltinMacro::Hash: return vec (DeriveHash (loc).go (item)); case BuiltinMacro::Ord: + return vec (DeriveOrd (DeriveOrd::Ordering::Total, loc).go (item)); case BuiltinMacro::PartialOrd: + return vec (DeriveOrd (DeriveOrd::Ordering::Partial, loc).go (item)); default: - rust_sorry_at (loc, "unimplemented builtin derive macro"); - return {}; + rust_unreachable (); }; } @@ -79,7 +81,8 @@ DeriveVisitor::setup_impl_generics ( { switch (generic->get_kind ()) { - case GenericParam::Kind::Lifetime: { + case GenericParam::Kind::Lifetime: + { LifetimeParam &lifetime_param = (LifetimeParam &) *generic.get (); Lifetime l = builder.new_lifetime (lifetime_param.get_lifetime ()); @@ -91,7 +94,8 @@ DeriveVisitor::setup_impl_generics ( } break; - case GenericParam::Kind::Type: { + case GenericParam::Kind::Type: + { TypeParam &type_param = (TypeParam &) *generic.get (); std::unique_ptr<Type> associated_type = builder.single_type_path ( @@ -113,7 +117,8 @@ DeriveVisitor::setup_impl_generics ( } break; - case GenericParam::Kind::Const: { + case GenericParam::Kind::Const: + { rust_unreachable (); // TODO diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index 5fca49c..ff4f427 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -147,6 +147,8 @@ private: virtual void visit (FieldAccessExpr &expr) override final{}; virtual void visit (ClosureExprInner &expr) override final{}; virtual void visit (BlockExpr &expr) override final{}; + virtual void visit (AnonConst &expr) override final{}; + virtual void visit (ConstBlock &expr) override final{}; virtual void visit (ClosureExprInnerTyped &expr) override final{}; virtual void visit (ContinueExpr &expr) override final{}; virtual void visit (BreakExpr &expr) override final{}; diff --git a/gcc/rust/expand/rust-expand-format-args.cc b/gcc/rust/expand/rust-expand-format-args.cc index af6182f..bda28dd 100644 --- a/gcc/rust/expand/rust-expand-format-args.cc +++ b/gcc/rust/expand/rust-expand-format-args.cc @@ -85,11 +85,13 @@ expand_format_args (AST::FormatArgs &fmt, static_pieces.emplace_back ( builder.literal_string (node.string._0.to_string ())); break; - case ffi::Piece::Tag::NextArgument: { + case ffi::Piece::Tag::NextArgument: + { auto next_argument = node.next_argument._0; switch (node.next_argument._0.position.tag) { - case ffi::Position::Tag::ArgumentImplicitlyIs: { + case ffi::Position::Tag::ArgumentImplicitlyIs: + { auto idx = next_argument.position.argument_implicitly_is._0; auto trait = next_argument.format; auto arg = arguments.at (idx); diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index 42df5e1..ba7bac1 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -641,7 +641,7 @@ ExpandVisitor::visit (AST::ClosureExprInnerTyped &expr) maybe_expand_type (expr.get_return_type_ptr ()); - visit (expr.get_definition_block ()); + visit (expr.get_definition_expr ()); } void diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h index ad237c0..b82040c 100644 --- a/gcc/rust/expand/rust-expand-visitor.h +++ b/gcc/rust/expand/rust-expand-visitor.h @@ -28,14 +28,12 @@ namespace Rust { /** * Whether or not an attribute is a derive attribute */ -bool -is_derive (AST::Attribute &attr); +bool is_derive (AST::Attribute &attr); /** * Whether or not an attribute is builtin */ -bool -is_builtin (AST::Attribute &attr); +bool is_builtin (AST::Attribute &attr); class ExpandVisitor : public AST::DefaultASTVisitor { diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc index e255729..850c8dd 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.cc +++ b/gcc/rust/expand/rust-macro-builtins-asm.cc @@ -25,18 +25,6 @@ #include "rust-parse.h" namespace Rust { -std::map<AST::InlineAsmOption, std::string> InlineAsmOptionMap{ - {AST::InlineAsmOption::PURE, "pure"}, - {AST::InlineAsmOption::NOMEM, "nomem"}, - {AST::InlineAsmOption::READONLY, "readonly"}, - {AST::InlineAsmOption::PRESERVES_FLAGS, "preserves_flags"}, - {AST::InlineAsmOption::NORETURN, "noreturn"}, - {AST::InlineAsmOption::NOSTACK, "nostack"}, - {AST::InlineAsmOption::MAY_UNWIND, "may_unwind"}, - {AST::InlineAsmOption::ATT_SYNTAX, "att_syntax"}, - {AST::InlineAsmOption::RAW, "raw"}, -}; - std::set<std::string> potentially_nonpromoted_keywords = {"in", "out", "lateout", "inout", "inlateout", "const", "sym", "label"}; @@ -500,7 +488,7 @@ parse_reg_operand_unexpected (InlineAsmContext inline_asm_ctx) } void -check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option) +check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsm::Option option) { auto &parser = inline_asm_ctx.parser; auto &inline_asm = inline_asm_ctx.inline_asm; @@ -509,7 +497,7 @@ check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option) // TODO: report an error of duplication rust_error_at (parser.peek_current_token ()->get_locus (), "the %qs option was already provided", - InlineAsmOptionMap[option].c_str ()); + AST::InlineAsm::option_to_string (option).c_str ()); return; } else @@ -536,39 +524,40 @@ parse_options (InlineAsmContext &inline_asm_ctx) { if (!is_global_asm && check_identifier (parser, "pure")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::PURE); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::PURE); } else if (!is_global_asm && check_identifier (parser, "nomem")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::NOMEM); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NOMEM); } else if (!is_global_asm && check_identifier (parser, "readonly")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::READONLY); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::READONLY); } else if (!is_global_asm && check_identifier (parser, "preserves_flags")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::PRESERVES_FLAGS); + check_and_set (inline_asm_ctx, + AST::InlineAsm::Option::PRESERVES_FLAGS); } else if (!is_global_asm && check_identifier (parser, "noreturn")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::NORETURN); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NORETURN); } else if (!is_global_asm && check_identifier (parser, "nostack")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::NOSTACK); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NOSTACK); } else if (!is_global_asm && check_identifier (parser, "may_unwind")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::MAY_UNWIND); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::MAY_UNWIND); } else if (check_identifier (parser, "att_syntax")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::ATT_SYNTAX); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::ATT_SYNTAX); } else if (check_identifier (parser, "raw")) { - check_and_set (inline_asm_ctx, AST::InlineAsmOption::RAW); + check_and_set (inline_asm_ctx, AST::InlineAsm::Option::RAW); } else { @@ -807,7 +796,8 @@ expand_inline_asm_strings (InlineAsmContext inline_asm_ctx) auto next_argument = piece.next_argument._0; switch (piece.next_argument._0.position.tag) { - case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs: { + case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs: + { auto idx = next_argument.position.argument_implicitly_is._0; /*auto trait = next_argument.format;*/ /*auto arg = arguments.at (idx);*/ diff --git a/gcc/rust/expand/rust-macro-builtins-asm.h b/gcc/rust/expand/rust-macro-builtins-asm.h index bd64a7f..3196a5a 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.h +++ b/gcc/rust/expand/rust-macro-builtins-asm.h @@ -142,16 +142,16 @@ tl::expected<InlineAsmContext, InlineAsmParseError> parse_reg_operand_unexpected (InlineAsmContext inline_asm_ctx); WARN_UNUSED_RESULT -tl::optional<AST::Fragment> -parse_asm (location_t invoc_locus, AST::MacroInvocData &invoc, - AST::InvocKind semicolon, AST::AsmKind is_global_asm); +tl::optional<AST::Fragment> parse_asm (location_t invoc_locus, + AST::MacroInvocData &invoc, + AST::InvocKind semicolon, + AST::AsmKind is_global_asm); WARN_UNUSED_RESULT -bool -check_identifier (Parser<MacroInvocLexer> &parser, std::string ident); +bool check_identifier (Parser<MacroInvocLexer> &parser, std::string ident); -void -check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option); +void check_and_set (InlineAsmContext &inline_asm_ctx, + AST::InlineAsm::Option option); // From rustc WARN_UNUSED_RESULT @@ -168,9 +168,9 @@ tl::optional<std::string> parse_format_string (InlineAsmContext &inline_asm_ctx); WARN_UNUSED_RESULT -tl::optional<std::string> -parse_label (Parser<MacroInvocLexer> &parser, TokenId last_token_id, - InlineAsmContext &inline_asm_ctx); +tl::optional<std::string> parse_label (Parser<MacroInvocLexer> &parser, + TokenId last_token_id, + InlineAsmContext &inline_asm_ctx); // LLVM ASM bits @@ -188,17 +188,13 @@ public: {} }; -void -parse_llvm_outputs (LlvmAsmContext &ctx); +void parse_llvm_outputs (LlvmAsmContext &ctx); -void -parse_llvm_inputs (LlvmAsmContext &ctx); +void parse_llvm_inputs (LlvmAsmContext &ctx); -void -parse_llvm_clobbers (LlvmAsmContext &ctx); +void parse_llvm_clobbers (LlvmAsmContext &ctx); -void -parse_llvm_options (LlvmAsmContext &ctx); +void parse_llvm_options (LlvmAsmContext &ctx); WARN_UNUSED_RESULT tl::optional<AST::Fragment> parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc, diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.h b/gcc/rust/expand/rust-macro-builtins-helpers.h index 429537e..32cf58f 100644 --- a/gcc/rust/expand/rust-macro-builtins-helpers.h +++ b/gcc/rust/expand/rust-macro-builtins-helpers.h @@ -33,29 +33,23 @@ #include "rust-token.h" namespace Rust { -std::string -make_macro_path_str (BuiltinMacro kind); +std::string make_macro_path_str (BuiltinMacro kind); -std::vector<std::unique_ptr<AST::MacroInvocation>> -check_for_eager_invocations ( +std::vector<std::unique_ptr<AST::MacroInvocation>> check_for_eager_invocations ( std::vector<std::unique_ptr<AST::Expr>> &expressions); // Shorthand function for creating unique_ptr tokens -std::unique_ptr<AST::Token> -make_token (const TokenPtr tok); +std::unique_ptr<AST::Token> make_token (const TokenPtr tok); -std::unique_ptr<AST::Expr> -make_string (location_t locus, std::string value); +std::unique_ptr<AST::Expr> make_string (location_t locus, std::string value); // TODO: Is this correct? -AST::Fragment -make_eager_builtin_invocation ( +AST::Fragment make_eager_builtin_invocation ( BuiltinMacro kind, location_t locus, AST::DelimTokenTree arguments, std::vector<std::unique_ptr<AST::MacroInvocation>> &&pending_invocations); // Match the end token of a macro given the start delimiter of the macro -TokenId -macro_end_token (AST::DelimTokenTree &invoc_token_tree, - Parser<MacroInvocLexer> &parser); +TokenId macro_end_token (AST::DelimTokenTree &invoc_token_tree, + Parser<MacroInvocLexer> &parser); // Expand and then extract a string literal from the macro std::unique_ptr<AST::LiteralExpr> try_extract_string_literal_from_fragment (const location_t &parent_locus, @@ -70,21 +64,18 @@ try_expand_many_expr (Parser<MacroInvocLexer> &parser, // and return the LiteralExpr for it. Allow for an optional trailing comma, // but otherwise enforce that these are the only tokens. -std::unique_ptr<AST::Expr> -parse_single_string_literal (BuiltinMacro kind, - AST::DelimTokenTree &invoc_token_tree, - location_t invoc_locus, MacroExpander *expander, - bool is_semicoloned = false); +std::unique_ptr<AST::Expr> parse_single_string_literal ( + BuiltinMacro kind, AST::DelimTokenTree &invoc_token_tree, + location_t invoc_locus, MacroExpander *expander, bool is_semicoloned = false); // Treat PATH as a path relative to the source file currently being // compiled, and return the absolute path for it. -std::string -source_relative_path (std::string path, location_t locus); +std::string source_relative_path (std::string path, location_t locus); // Read the full contents of the file FILENAME and return them in a vector. // FIXME: platform specific. -tl::optional<std::vector<uint8_t>> -load_file_bytes (location_t invoc_locus, const char *filename); +tl::optional<std::vector<uint8_t>> load_file_bytes (location_t invoc_locus, + const char *filename); } // namespace Rust #endif // GCCRS_RUST_MACRO_BUILTINS_HELPERS_H diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 673b8fb..475ad56 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -430,7 +430,8 @@ MacroExpander::match_fragment (Parser<MacroInvocLexer> &parser, parser.parse_visibility (); break; - case AST::MacroFragSpec::STMT: { + case AST::MacroFragSpec::STMT: + { auto restrictions = ParseRestrictions (); restrictions.consume_semi = false; parser.parse_stmt (restrictions); @@ -480,19 +481,22 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, // this is used so we can check that we delimit the stream correctly. switch (delimiter->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { if (!check_delim (AST::DelimType::PARENS)) return false; } break; - case LEFT_SQUARE: { + case LEFT_SQUARE: + { if (!check_delim (AST::DelimType::SQUARE)) return false; } break; - case LEFT_CURLY: { + case LEFT_CURLY: + { if (!check_delim (AST::DelimType::CURLY)) return false; } @@ -510,7 +514,8 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, switch (match->get_macro_match_type ()) { - case AST::MacroMatch::MacroMatchType::Fragment: { + case AST::MacroMatch::MacroMatchType::Fragment: + { AST::MacroMatchFragment *fragment = static_cast<AST::MacroMatchFragment *> (match.get ()); if (!match_fragment (parser, *fragment)) @@ -524,14 +529,16 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, } break; - case AST::MacroMatch::MacroMatchType::Tok: { + case AST::MacroMatch::MacroMatchType::Tok: + { AST::Token *tok = static_cast<AST::Token *> (match.get ()); if (!match_token (parser, *tok)) return false; } break; - case AST::MacroMatch::MacroMatchType::Repetition: { + case AST::MacroMatch::MacroMatchType::Repetition: + { AST::MacroMatchRepetition *rep = static_cast<AST::MacroMatchRepetition *> (match.get ()); if (!match_repetition (parser, *rep)) @@ -539,7 +546,8 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, } break; - case AST::MacroMatch::MacroMatchType::Matcher: { + case AST::MacroMatch::MacroMatchType::Matcher: + { AST::MacroMatcher *m = static_cast<AST::MacroMatcher *> (match.get ()); expansion_depth++; @@ -556,19 +564,22 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, switch (delimiter->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { if (!parser.skip_token (RIGHT_PAREN)) return false; } break; - case LEFT_SQUARE: { + case LEFT_SQUARE: + { if (!parser.skip_token (RIGHT_SQUARE)) return false; } break; - case LEFT_CURLY: { + case LEFT_CURLY: + { if (!parser.skip_token (RIGHT_CURLY)) return false; } @@ -617,7 +628,8 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser, size_t offs_begin = source.get_offs (); switch (match->get_macro_match_type ()) { - case AST::MacroMatch::MacroMatchType::Fragment: { + case AST::MacroMatch::MacroMatchType::Fragment: + { AST::MacroMatchFragment *fragment = static_cast<AST::MacroMatchFragment *> (match.get ()); valid_current_match = match_fragment (parser, *fragment); @@ -632,20 +644,23 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser, } break; - case AST::MacroMatch::MacroMatchType::Tok: { + case AST::MacroMatch::MacroMatchType::Tok: + { AST::Token *tok = static_cast<AST::Token *> (match.get ()); valid_current_match = match_token (parser, *tok); } break; - case AST::MacroMatch::MacroMatchType::Repetition: { + case AST::MacroMatch::MacroMatchType::Repetition: + { AST::MacroMatchRepetition *rep = static_cast<AST::MacroMatchRepetition *> (match.get ()); valid_current_match = match_repetition (parser, *rep); } break; - case AST::MacroMatch::MacroMatchType::Matcher: { + case AST::MacroMatch::MacroMatchType::Matcher: + { AST::MacroMatcher *m = static_cast<AST::MacroMatcher *> (match.get ()); valid_current_match = match_matcher (parser, *m, true); diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc index 02e4e3b..ac36ed8 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.cc +++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc @@ -273,7 +273,8 @@ SubstituteCtx::substitute_token (size_t token_idx) // don't substitute, dollar sign is alone/metavar is unknown return {std::vector<std::unique_ptr<AST::Token>> (), 0}; - case LEFT_PAREN: { + case LEFT_PAREN: + { // We need to parse up until the closing delimiter and expand this // fragment->n times. rust_debug ("expanding repetition"); diff --git a/gcc/rust/expand/rust-proc-macro.h b/gcc/rust/expand/rust-proc-macro.h index 6ffaaf6..058c93a 100644 --- a/gcc/rust/expand/rust-proc-macro.h +++ b/gcc/rust/expand/rust-proc-macro.h @@ -82,11 +82,9 @@ public: * * @param The path to the shared object file to load. */ -const std::vector<ProcMacro::Procmacro> -load_macros (std::string path); +const std::vector<ProcMacro::Procmacro> load_macros (std::string path); -std::string -generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id); +std::string generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id); } // namespace Rust diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index 2d9a445..5b35052 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -201,6 +201,12 @@ void ASTLoweringBase::visit (AST::BlockExpr &) {} void +ASTLoweringBase::visit (AST::AnonConst &) +{} +void +ASTLoweringBase::visit (AST::ConstBlock &) +{} +void ASTLoweringBase::visit (AST::ClosureExprInnerTyped &) {} void @@ -648,12 +654,14 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args) { switch (arg.get_kind ()) { - case AST::GenericArg::Kind::Type: { + case AST::GenericArg::Kind::Type: + { auto type = ASTLoweringType::translate (arg.get_type ()); type_args.emplace_back (std::unique_ptr<HIR::Type> (type)); break; } - case AST::GenericArg::Kind::Const: { + case AST::GenericArg::Kind::Const: + { auto expr = ASTLoweringExpr::translate (arg.get_expression ()); const_args.emplace_back ( HIR::ConstGenericArg (std::unique_ptr<HIR::Expr> (expr), @@ -887,7 +895,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound) std::unique_ptr<HIR::RangePatternBound> hir_bound = nullptr; switch (bound.get_bound_type ()) { - case AST::RangePatternBound::RangePatternBoundType::LITERAL: { + case AST::RangePatternBound::RangePatternBoundType::LITERAL: + { AST::RangePatternBoundLiteral &ref = static_cast<AST::RangePatternBoundLiteral &> (bound); @@ -898,7 +907,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound) ref.get_has_minus ())); } break; - case AST::RangePatternBound::RangePatternBoundType::PATH: { + case AST::RangePatternBound::RangePatternBoundType::PATH: + { auto &ref = static_cast<AST::RangePatternBoundPath &> (bound); HIR::PathInExpression *path @@ -908,7 +918,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound) new HIR::RangePatternBoundPath (*path)); } break; - case AST::RangePatternBound::RangePatternBoundType::QUALPATH: { + case AST::RangePatternBound::RangePatternBoundType::QUALPATH: + { auto &ref = static_cast<AST::RangePatternBoundQualPath &> (bound); HIR::QualifiedPathInExpression *qualpath diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index 3116181..51912be 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -131,6 +131,8 @@ public: virtual void visit (AST::FieldAccessExpr &expr) override; virtual void visit (AST::ClosureExprInner &expr) override; virtual void visit (AST::BlockExpr &expr) override; + virtual void visit (AST::AnonConst &expr) override; + virtual void visit (AST::ConstBlock &expr) override; virtual void visit (AST::ClosureExprInnerTyped &expr) override; virtual void visit (AST::ContinueExpr &expr) override; virtual void visit (AST::BreakExpr &expr) override; diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc index 07d0c835..3f3d600 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.cc +++ b/gcc/rust/hir/rust-ast-lower-expr.cc @@ -25,6 +25,7 @@ #include "rust-ast-lower-type.h" #include "rust-ast.h" #include "rust-diagnostics.h" +#include "rust-hir-map.h" #include "rust-system.h" #include "tree/rust-hir-expr.h" @@ -127,6 +128,43 @@ ASTLoweringExpr::visit (AST::BlockExpr &expr) } void +ASTLoweringExpr::visit (AST::AnonConst &expr) +{ + auto inner_expr = ASTLoweringExpr::translate (expr.get_inner_expr ()); + + auto &mappings = Analysis::Mappings::get (); + auto crate_num = mappings.get_current_crate (); + auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (), + mappings.get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::AnonConst (std::move (mapping), + std::unique_ptr<Expr> (inner_expr), + expr.get_locus ()); +} + +void +ASTLoweringExpr::visit (AST::ConstBlock &expr) +{ + auto inner_expr = ASTLoweringExpr::translate (expr.get_const_expr ()); + + // we know this will always be an `AnonConst`, or we have an issue. Let's + // assert just to be sure. + rust_assert (inner_expr->get_expression_type () == Expr::ExprType::AnonConst); + auto anon_const = static_cast<AnonConst *> (inner_expr); + + auto &mappings = Analysis::Mappings::get (); + auto crate_num = mappings.get_current_crate (); + auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (), + mappings.get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::ConstBlock (std::move (mapping), std::move (*anon_const), + expr.get_locus (), expr.get_outer_attrs ()); +} + +void ASTLoweringExpr::visit (AST::UnsafeBlockExpr &expr) { translated = ASTLoweringBlock::translate (expr, &terminated); @@ -798,7 +836,7 @@ ASTLoweringExpr::visit (AST::ClosureExprInnerTyped &expr) { HIR::Type *closure_return_type = nullptr; HIR::Expr *closure_expr - = ASTLoweringExpr::translate (expr.get_definition_block ()); + = ASTLoweringExpr::translate (expr.get_definition_expr ()); std::vector<HIR::ClosureParam> closure_params; for (auto ¶m : expr.get_params ()) @@ -841,6 +879,7 @@ translate_operand_out (const AST::InlineAsmOperand &operand) *out_value.expr.get ()))); return out; } + HIR::InlineAsmOperand translate_operand_inout (const AST::InlineAsmOperand &operand) { @@ -851,6 +890,7 @@ translate_operand_inout (const AST::InlineAsmOperand &operand) *inout_value.expr.get ()))); return inout; } + HIR::InlineAsmOperand translate_operand_split_in_out (const AST::InlineAsmOperand &operand) { @@ -863,19 +903,21 @@ translate_operand_split_in_out (const AST::InlineAsmOperand &operand) ASTLoweringExpr::translate (*split_in_out_value.out_expr.get ()))); return split_in_out; } + HIR::InlineAsmOperand translate_operand_const (const AST::InlineAsmOperand &operand) { auto const_value = operand.get_const (); - struct HIR::AnonConst anon_const (const_value.anon_const.id, - std::unique_ptr<Expr> ( - ASTLoweringExpr::translate ( - *const_value.anon_const.expr.get ()))); - struct HIR::InlineAsmOperand::Const cnst - { - anon_const - }; - return cnst; + + auto inner_expr = ASTLoweringExpr::translate (const_value.anon_const); + + // Like `ConstBlock`, we know this should only be an `AnonConst` - let's + // assert to make sure and static cast + rust_assert (inner_expr->get_expression_type () == Expr::ExprType::AnonConst); + + auto anon_const = static_cast<AnonConst *> (inner_expr); + + return HIR::InlineAsmOperand::Const{*anon_const}; } HIR::InlineAsmOperand diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index adedeb3..9d1bf68 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -82,6 +82,8 @@ public: void visit (AST::IfLetExpr &expr) override; void visit (AST::IfLetExprConseqElse &expr) override; void visit (AST::BlockExpr &expr) override; + void visit (AST::AnonConst &expr) override; + void visit (AST::ConstBlock &expr) override; void visit (AST::UnsafeBlockExpr &expr) override; void visit (AST::PathInExpression &expr) override; void visit (AST::QualifiedPathInExpression &expr) override; diff --git a/gcc/rust/hir/rust-ast-lower-extern.h b/gcc/rust/hir/rust-ast-lower-extern.h index 0105e38..3dca1b6 100644 --- a/gcc/rust/hir/rust-ast-lower-extern.h +++ b/gcc/rust/hir/rust-ast-lower-extern.h @@ -99,7 +99,7 @@ public: = static_cast<AST::IdentifierPattern &> (param.get_pattern ()); Identifier param_name = param_kind == AST::Pattern::Kind::Identifier ? param_ident.get_ident () - : std::string ("_"); + : Identifier ("_", param.get_locus ()); HIR::Type *param_type = ASTLoweringType::translate (param.get_type ()); diff --git a/gcc/rust/hir/rust-ast-lower-implitem.cc b/gcc/rust/hir/rust-ast-lower-implitem.cc index d815a71..fc9fe1a 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.cc +++ b/gcc/rust/hir/rust-ast-lower-implitem.cc @@ -138,7 +138,8 @@ ASTLowerImplItem::visit (AST::Function &function) std::unique_ptr<HIR::Type> return_type = function.has_return_type () ? std::unique_ptr<HIR::Type> ( - ASTLoweringType::translate (function.get_return_type ())) + ASTLoweringType::translate (function.get_return_type (), false, + true /* impl trait is allowed here*/)) : nullptr; Defaultness defaultness diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc index f4396b5..acec008 100644 --- a/gcc/rust/hir/rust-ast-lower-item.cc +++ b/gcc/rust/hir/rust-ast-lower-item.cc @@ -217,7 +217,7 @@ ASTLoweringItem::visit (AST::StructStruct &struct_decl) field.get_outer_attrs ()); if (struct_field_name_exists (fields, translated_field)) - break; + continue; fields.push_back (std::move (translated_field)); } @@ -411,7 +411,8 @@ ASTLoweringItem::visit (AST::Function &function) std::unique_ptr<HIR::Type> return_type = function.has_return_type () ? std::unique_ptr<HIR::Type> ( - ASTLoweringType::translate (function.get_return_type ())) + ASTLoweringType::translate (function.get_return_type (), false, + true /* impl trait is allowed here*/)) : nullptr; std::vector<HIR::FunctionParam> function_params; @@ -494,7 +495,8 @@ ASTLoweringItem::visit (AST::InherentImpl &impl_block) { switch (generic_param->get_kind ()) { - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { const HIR::TypeParam &t = static_cast<const HIR::TypeParam &> (*generic_param); @@ -651,7 +653,8 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block) { switch (generic_param->get_kind ()) { - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { const HIR::TypeParam &t = static_cast<const HIR::TypeParam &> (*generic_param); diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc index b7a4c56..9baf81d 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.cc +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -49,13 +49,18 @@ ASTLoweringPattern::visit (AST::IdentifierPattern &pattern) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - std::unique_ptr<Pattern> to_bind; + std::unique_ptr<Pattern> subpattern; + if (pattern.has_subpattern ()) + { + subpattern = std::unique_ptr<Pattern> ( + ASTLoweringPattern::translate (pattern.get_pattern_to_bind ())); + } translated = new HIR::IdentifierPattern (mapping, pattern.get_ident (), pattern.get_locus (), pattern.get_is_ref (), pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm, - std::move (to_bind)); + std::move (subpattern)); } void @@ -74,13 +79,15 @@ ASTLoweringPattern::visit (AST::TupleStructPattern &pattern) auto &items = pattern.get_items (); switch (items.get_item_type ()) { - case AST::TupleStructItems::RANGE: { + case AST::TupleStructItems::RANGE: + { // TODO rust_unreachable (); } break; - case AST::TupleStructItems::NO_RANGE: { + case AST::TupleStructItems::NO_RANGE: + { AST::TupleStructItemsNoRange &items_no_range = static_cast<AST::TupleStructItemsNoRange &> (items); @@ -120,7 +127,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) HIR::StructPatternField *f = nullptr; switch (field->get_item_type ()) { - case AST::StructPatternField::ItemType::TUPLE_PAT: { + case AST::StructPatternField::ItemType::TUPLE_PAT: + { auto &tuple = static_cast<AST::StructPatternFieldTuplePat &> (*field); @@ -140,7 +148,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) } break; - case AST::StructPatternField::ItemType::IDENT_PAT: { + case AST::StructPatternField::ItemType::IDENT_PAT: + { AST::StructPatternFieldIdentPat &ident = static_cast<AST::StructPatternFieldIdentPat &> (*field); @@ -160,7 +169,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) } break; - case AST::StructPatternField::ItemType::IDENT: { + case AST::StructPatternField::ItemType::IDENT: + { AST::StructPatternFieldIdent &ident = static_cast<AST::StructPatternFieldIdent &> (*field.get ()); @@ -213,7 +223,8 @@ ASTLoweringPattern::visit (AST::TuplePattern &pattern) std::unique_ptr<HIR::TuplePatternItems> items; switch (pattern.get_items ().get_pattern_type ()) { - case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: { + case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: + { AST::TuplePatternItemsMultiple &ref = static_cast<AST::TuplePatternItemsMultiple &> ( pattern.get_items ()); @@ -221,7 +232,8 @@ ASTLoweringPattern::visit (AST::TuplePattern &pattern) } break; - case AST::TuplePatternItems::TuplePatternItemType::RANGED: { + case AST::TuplePatternItems::TuplePatternItemType::RANGED: + { AST::TuplePatternItemsRanged &ref = static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ()); items = lower_tuple_pattern_ranged (ref); diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc index a678f18..1841576 100644 --- a/gcc/rust/hir/rust-ast-lower-type.cc +++ b/gcc/rust/hir/rust-ast-lower-type.cc @@ -209,10 +209,17 @@ ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path) path.get_locus ()); } +ASTLoweringType::ASTLoweringType (bool default_to_static_lifetime, + bool impl_trait_allowed) + : ASTLoweringBase (), default_to_static_lifetime (default_to_static_lifetime), + impl_trait_allowed (impl_trait_allowed), translated (nullptr) +{} + HIR::Type * -ASTLoweringType::translate (AST::Type &type, bool default_to_static_lifetime) +ASTLoweringType::translate (AST::Type &type, bool default_to_static_lifetime, + bool impl_trait_allowed) { - ASTLoweringType resolver (default_to_static_lifetime); + ASTLoweringType resolver (default_to_static_lifetime, impl_trait_allowed); type.accept_vis (resolver); rust_assert (resolver.translated != nullptr); @@ -260,7 +267,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype) HIR::Type *param_type = ASTLoweringType::translate (param.get_type (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); HIR::MaybeNamedParam p (param.get_name (), kind, std::unique_ptr<HIR::Type> (param_type), @@ -272,7 +280,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype) if (fntype.has_return_type ()) { return_type = ASTLoweringType::translate (fntype.get_return_type (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); } auto crate_num = mappings.get_current_crate (); @@ -292,8 +301,8 @@ ASTLoweringType::visit (AST::TupleType &tuple) std::vector<std::unique_ptr<HIR::Type>> elems; for (auto &e : tuple.get_elems ()) { - HIR::Type *t - = ASTLoweringType::translate (*e, default_to_static_lifetime); + HIR::Type *t = ASTLoweringType::translate (*e, default_to_static_lifetime, + impl_trait_allowed); elems.push_back (std::unique_ptr<HIR::Type> (t)); } @@ -323,7 +332,8 @@ ASTLoweringType::visit (AST::ArrayType &type) { HIR::Type *translated_type = ASTLoweringType::translate (type.get_elem_type (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); HIR::Expr *array_size = ASTLoweringExpr::translate (type.get_size_expr ()); auto crate_num = mappings.get_current_crate (); @@ -343,9 +353,9 @@ ASTLoweringType::visit (AST::ReferenceType &type) HIR::Lifetime lifetime = lower_lifetime (type.get_lifetime (), default_to_static_lifetime); - HIR::Type *base_type - = ASTLoweringType::translate (type.get_base_type (), - default_to_static_lifetime); + HIR::Type *base_type = ASTLoweringType::translate (type.get_base_type (), + default_to_static_lifetime, + impl_trait_allowed); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -364,7 +374,8 @@ ASTLoweringType::visit (AST::RawPointerType &type) { HIR::Type *base_type = ASTLoweringType::translate (type.get_type_pointed_to (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -384,9 +395,9 @@ ASTLoweringType::visit (AST::RawPointerType &type) void ASTLoweringType::visit (AST::SliceType &type) { - HIR::Type *base_type - = ASTLoweringType::translate (type.get_elem_type (), - default_to_static_lifetime); + HIR::Type *base_type = ASTLoweringType::translate (type.get_elem_type (), + default_to_static_lifetime, + impl_trait_allowed); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -463,7 +474,8 @@ void ASTLoweringType::visit (AST::ParenthesisedType &type) { auto *inner = ASTLoweringType::translate (*type.get_type_in_parens (), - default_to_static_lifetime); + default_to_static_lifetime, + impl_trait_allowed); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -480,6 +492,9 @@ ASTLoweringType::visit (AST::ParenthesisedType &type) void ASTLoweringType::visit (AST::ImplTraitType &type) { + if (!impl_trait_allowed) + emit_impl_trait_error (type.get_locus ()); + std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds; for (auto &bound : type.get_type_param_bounds ()) { @@ -499,9 +514,12 @@ ASTLoweringType::visit (AST::ImplTraitType &type) void ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type) { + if (!impl_trait_allowed) + emit_impl_trait_error (type.get_locus ()); + std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds; - auto b = ASTLoweringTypeBounds::translate (type.get_trait_bound ()); + auto b = ASTLoweringTypeBounds::translate (*type.get_trait_bound ().get ()); bounds.push_back (std::unique_ptr<HIR::TypeParamBound> (b)); auto crate_num = mappings.get_current_crate (); @@ -513,6 +531,15 @@ ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type) = new HIR::ImplTraitType (mapping, std::move (bounds), type.get_locus ()); } +void +ASTLoweringType::emit_impl_trait_error (location_t locus) +{ + rich_location r (line_table, locus); + rust_error_at (r, ErrorCode::E0562, + "%<impl Trait%> not allowed outside of function and inherent " + "method return types"); +} + HIR::GenericParam * ASTLowerGenericParam::translate (AST::GenericParam ¶m) { @@ -593,7 +620,8 @@ ASTLowerGenericParam::visit (AST::TypeParam ¶m) translated = new HIR::TypeParam (mapping, param.get_type_representation (), param.get_locus (), std::move (type_param_bounds), - std::move (type), param.get_outer_attrs ()); + std::move (type), param.get_outer_attrs (), + param.from_impl_trait ()); } HIR::TypeParamBound * diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 4efaeee..50f543a 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -66,7 +66,8 @@ class ASTLoweringType : public ASTLoweringBase public: static HIR::Type *translate (AST::Type &type, - bool default_to_static_lifetime = false); + bool default_to_static_lifetime = false, + bool impl_trait_allowed = false); void visit (AST::BareFunctionType &fntype) override; void visit (AST::TupleType &tuple) override; @@ -81,19 +82,17 @@ public: void visit (AST::TraitObjectTypeOneBound &type) override; void visit (AST::TraitObjectType &type) override; void visit (AST::ParenthesisedType &type) override; - void visit (AST::ImplTraitType &type) override; void visit (AST::ImplTraitTypeOneBound &type) override; + void emit_impl_trait_error (location_t locus); + private: - ASTLoweringType (bool default_to_static_lifetime) - : ASTLoweringBase (), - default_to_static_lifetime (default_to_static_lifetime), - translated (nullptr) - {} + ASTLoweringType (bool default_to_static_lifetime, bool impl_trait_allowed); /** Used when compiling const and static items. */ bool default_to_static_lifetime; + bool impl_trait_allowed; HIR::Type *translated; }; diff --git a/gcc/rust/hir/rust-ast-lower.h b/gcc/rust/hir/rust-ast-lower.h index cc74082..0787ddf 100644 --- a/gcc/rust/hir/rust-ast-lower.h +++ b/gcc/rust/hir/rust-ast-lower.h @@ -28,16 +28,14 @@ namespace HIR { /* Checks whether the name of a field already exists. Returns true and produces an error if so. */ -bool -struct_field_name_exists (std::vector<HIR::StructField> &fields, - HIR::StructField &new_field); +bool struct_field_name_exists (std::vector<HIR::StructField> &fields, + HIR::StructField &new_field); /** * Lowers a Visibility from the AST into an HIR Visibility, desugaring it in * the process */ -Visibility -translate_visibility (const AST::Visibility &vis); +Visibility translate_visibility (const AST::Visibility &vis); /** * Main base class used for lowering AST to HIR. diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index cb32f68..38079c7 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -1297,6 +1297,28 @@ Dump::visit (BlockExpr &e) } void +Dump::visit (AnonConst &e) +{ + begin ("AnonConst"); + do_expr (e); + + visit_field ("inner", e.get_inner_expr ()); + + end ("AnonConst"); +} + +void +Dump::visit (ConstBlock &e) +{ + begin ("ConstBlock"); + do_expr (e); + + visit_field ("inner", e.get_const_expr ()); + + end ("ConstBlock"); +} + +void Dump::visit (ContinueExpr &e) { begin ("ContinueExpr"); @@ -1602,7 +1624,8 @@ Dump::visit (UseTreeGlob &e) case UseTreeGlob::PathType::GLOBAL: glob = "::*"; break; - case UseTreeGlob::PathType::PATH_PREFIXED: { + case UseTreeGlob::PathType::PATH_PREFIXED: + { path = e.get_path ().as_string (); glob = "::*"; break; @@ -1630,7 +1653,8 @@ Dump::visit (UseTreeList &e) case UseTreeList::PathType::GLOBAL: path_type = "::*"; break; - case UseTreeList::PathType::PATH_PREFIXED: { + case UseTreeList::PathType::PATH_PREFIXED: + { path = e.get_path ().as_string (); path_type = "::*"; break; @@ -2091,10 +2115,10 @@ Dump::visit (IdentifierPattern &e) put_field ("is_ref", std::to_string (e.get_is_ref ())); put_field ("mut", std::to_string (e.is_mut ())); - if (e.has_pattern_to_bind ()) - put_field ("to_bind", e.get_to_bind ().as_string ()); + if (e.has_subpattern ()) + visit_field ("subpattern", e.get_subpattern ()); else - put_field ("to_bind", "none"); + put_field ("subpattern", "none"); end ("IdentifierPattern"); } diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h index 45b1708..8c39f48 100644 --- a/gcc/rust/hir/rust-hir-dump.h +++ b/gcc/rust/hir/rust-hir-dump.h @@ -146,6 +146,8 @@ private: virtual void visit (FieldAccessExpr &) override; virtual void visit (ClosureExpr &) override; virtual void visit (BlockExpr &) override; + virtual void visit (AnonConst &) override; + virtual void visit (ConstBlock &) override; virtual void visit (ContinueExpr &) override; virtual void visit (BreakExpr &) override; virtual void visit (RangeFromToExpr &) override; @@ -252,7 +254,6 @@ private: } // namespace Rust // In the global namespace to make it easier to call from debugger -void -debug (Rust::HIR::FullVisitable &v); +void debug (Rust::HIR::FullVisitable &v); #endif // !RUST_HIR_DUMP_H diff --git a/gcc/rust/hir/tree/rust-hir-expr-abstract.h b/gcc/rust/hir/tree/rust-hir-expr-abstract.h index 5bc5d89..8272a828 100644 --- a/gcc/rust/hir/tree/rust-hir-expr-abstract.h +++ b/gcc/rust/hir/tree/rust-hir-expr-abstract.h @@ -43,7 +43,7 @@ public: WITHOUT_BLOCK, }; - enum ExprType + enum class ExprType { Lit, Operator, @@ -58,6 +58,8 @@ public: FieldAccess, Closure, Block, + AnonConst, + ConstBlock, Continue, Break, Range, diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc b/gcc/rust/hir/tree/rust-hir-expr.cc index 266c79c..93dcec2 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.cc +++ b/gcc/rust/hir/tree/rust-hir-expr.cc @@ -790,6 +790,50 @@ BlockExpr::operator= (BlockExpr const &other) return *this; } +AnonConst::AnonConst (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> &&expr, location_t locus) + : ExprWithBlock (std::move (mappings), {}), locus (locus), + expr (std::move (expr)) +{ + rust_assert (this->expr); +} + +AnonConst::AnonConst (const AnonConst &other) + : ExprWithBlock (other), locus (other.locus), expr (other.expr->clone_expr ()) +{} + +AnonConst +AnonConst::operator= (const AnonConst &other) +{ + ExprWithBlock::operator= (other); + + locus = other.locus; + expr = other.expr->clone_expr (); + + return *this; +} + +ConstBlock::ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr, + location_t locus, AST::AttrVec outer_attrs) + : ExprWithBlock (std::move (mappings), std::move (outer_attrs)), + expr (std::move (expr)), locus (locus) +{} + +ConstBlock::ConstBlock (const ConstBlock &other) + : ExprWithBlock (other), expr (other.expr), locus (other.locus) +{} + +ConstBlock +ConstBlock::operator= (const ConstBlock &other) +{ + ExprWithBlock::operator= (other); + + expr = other.expr; + locus = other.locus; + + return *this; +} + ContinueExpr::ContinueExpr (Analysis::NodeMapping mappings, location_t locus, tl::optional<Lifetime> label, AST::AttrVec outer_attribs) @@ -1310,26 +1354,6 @@ OperatorExprMeta::OperatorExprMeta (HIR::ComparisonExpr &expr) locus (expr.get_locus ()) {} -AnonConst::AnonConst (NodeId id, std::unique_ptr<Expr> expr) - : id (id), expr (std::move (expr)) -{ - rust_assert (this->expr != nullptr); -} - -AnonConst::AnonConst (const AnonConst &other) -{ - id = other.id; - expr = other.expr->clone_expr (); -} - -AnonConst -AnonConst::operator= (const AnonConst &other) -{ - id = other.id; - expr = other.expr->clone_expr (); - return *this; -} - InlineAsmOperand::In::In ( const tl::optional<struct AST::InlineAsmRegOrRegClass> ®, std::unique_ptr<Expr> expr) @@ -1476,7 +1500,7 @@ InlineAsm::InlineAsm (location_t locus, bool is_global_asm, std::vector<AST::TupleTemplateStr> template_strs, std::vector<HIR::InlineAsmOperand> operands, std::vector<AST::TupleClobber> clobber_abi, - std::set<AST::InlineAsmOption> options, + std::set<AST::InlineAsm::Option> options, Analysis::NodeMapping mappings, AST::AttrVec outer_attribs) : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 375f474..bf278d6 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -19,12 +19,14 @@ #ifndef RUST_HIR_EXPR_H #define RUST_HIR_EXPR_H +#include "rust-ast.h" #include "rust-hir-expr-abstract.h" #include "rust-hir-literal.h" #include "rust-common.h" #include "rust-hir-bound.h" #include "rust-hir-attrs.h" #include "rust-expr.h" +#include "rust-hir-map.h" namespace Rust { namespace HIR { @@ -1800,6 +1802,71 @@ protected: } }; +class AnonConst : public ExprWithBlock +{ +public: + AnonConst (Analysis::NodeMapping mappings, std::unique_ptr<Expr> &&expr, + location_t locus = UNKNOWN_LOCATION); + AnonConst (const AnonConst &other); + AnonConst operator= (const AnonConst &other); + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + ExprType get_expression_type () const final override + { + return ExprType::AnonConst; + } + + location_t get_locus () const override { return locus; } + Expr &get_inner_expr () { return *expr; } + const Expr &get_inner_expr () const { return *expr; } + +private: + location_t locus; + std::unique_ptr<Expr> expr; + + AnonConst *clone_expr_with_block_impl () const override + { + return new AnonConst (*this); + } +}; + +class ConstBlock : public ExprWithBlock +{ +public: + ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr, + location_t locus = UNKNOWN_LOCATION, + AST::AttrVec outer_attrs = {}); + ConstBlock (const ConstBlock &other); + ConstBlock operator= (const ConstBlock &other); + + void accept_vis (HIRFullVisitor &vis) override; + void accept_vis (HIRExpressionVisitor &vis) override; + + std::string as_string () const override; + + ExprType get_expression_type () const final override + { + return ExprType::ConstBlock; + } + + location_t get_locus () const override { return locus; } + AnonConst &get_const_expr () { return expr; } + const AnonConst &get_const_expr () const { return expr; } + +private: + AnonConst expr; + location_t locus; + + ConstBlock *clone_expr_with_block_impl () const override + { + return new ConstBlock (*this); + } +}; + // HIR node representing continue expression within loops class ContinueExpr : public ExprWithoutBlock { @@ -2892,18 +2959,6 @@ class InlineAsmRegClass std::string placeholder; }; -struct AnonConst -{ - NodeId id; - std::unique_ptr<Expr> expr; - - AnonConst (NodeId id, std::unique_ptr<Expr> expr); - - AnonConst (const AnonConst &other); - - AnonConst operator= (const AnonConst &other); -}; - class InlineAsmOperand { public: @@ -3059,7 +3114,7 @@ public: std::vector<AST::TupleTemplateStr> template_strs; std::vector<HIR::InlineAsmOperand> operands; std::vector<AST::TupleClobber> clobber_abi; - std::set<AST::InlineAsmOption> options; + std::set<AST::InlineAsm::Option> options; std::vector<location_t> line_spans; @@ -3094,7 +3149,7 @@ public: std::vector<AST::TupleClobber> get_clobber_abi () { return clobber_abi; } - std::set<AST::InlineAsmOption> get_options () { return options; } + std::set<AST::InlineAsm::Option> get_options () { return options; } bool is_simple_asm () { @@ -3113,7 +3168,7 @@ public: std::vector<AST::TupleTemplateStr> template_strs, std::vector<HIR::InlineAsmOperand> operands, std::vector<AST::TupleClobber> clobber_abi, - std::set<AST::InlineAsmOption> options, + std::set<AST::InlineAsm::Option> options, Analysis::NodeMapping mappings, AST::AttrVec outer_attribs = AST::AttrVec ()); }; diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h index 1e313ec..2905117 100644 --- a/gcc/rust/hir/tree/rust-hir-full-decls.h +++ b/gcc/rust/hir/tree/rust-hir-full-decls.h @@ -95,6 +95,8 @@ class FieldAccessExpr; struct ClosureParam; class ClosureExpr; class BlockExpr; +class AnonConst; +class ConstBlock; class ContinueExpr; class BreakExpr; class RangeExpr; @@ -123,7 +125,6 @@ class AwaitExpr; class AsyncBlockExpr; class InlineAsmReg; class InlineAsmRegClass; -struct AnonConst; class InlineAsmOperand; class InlineAsm; class LlvmInlineAsm; diff --git a/gcc/rust/hir/tree/rust-hir-item.cc b/gcc/rust/hir/tree/rust-hir-item.cc index 160f710..1406e7a 100644 --- a/gcc/rust/hir/tree/rust-hir-item.cc +++ b/gcc/rust/hir/tree/rust-hir-item.cc @@ -26,16 +26,18 @@ TypeParam::TypeParam ( Analysis::NodeMapping mappings, Identifier type_representation, location_t locus, std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds, - tl::optional<std::unique_ptr<Type>> type, AST::AttrVec outer_attrs) + tl::optional<std::unique_ptr<Type>> type, AST::AttrVec outer_attrs, + bool was_impl_trait) : GenericParam (mappings), outer_attrs (std::move (outer_attrs)), type_representation (std::move (type_representation)), type_param_bounds (std::move (type_param_bounds)), type (std::move (type)), - locus (locus) + locus (locus), was_impl_trait (was_impl_trait) {} TypeParam::TypeParam (TypeParam const &other) : GenericParam (other.mappings), outer_attrs (other.outer_attrs), - type_representation (other.type_representation), locus (other.locus) + type_representation (other.type_representation), locus (other.locus), + was_impl_trait (other.was_impl_trait) { // guard to prevent null pointer dereference if (other.has_type ()) @@ -55,6 +57,7 @@ TypeParam::operator= (TypeParam const &other) outer_attrs = other.outer_attrs; locus = other.locus; mappings = other.mappings; + was_impl_trait = other.was_impl_trait; // guard to prevent null pointer dereference if (other.has_type ()) diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 37f599c..d610277 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -95,17 +95,11 @@ protected: class TypeParam : public GenericParam { AST::AttrVec outer_attrs; - Identifier type_representation; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - std::vector<std::unique_ptr<TypeParamBound>> - type_param_bounds; // inlined form - + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; tl::optional<std::unique_ptr<Type>> type; - location_t locus; + bool was_impl_trait; public: // Returns whether the type of the type param has been specified. @@ -121,9 +115,9 @@ public: TypeParam (Analysis::NodeMapping mappings, Identifier type_representation, location_t locus = UNDEF_LOCATION, std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds - = std::vector<std::unique_ptr<TypeParamBound>> (), + = {}, tl::optional<std::unique_ptr<Type>> type = tl::nullopt, - AST::AttrVec outer_attrs = std::vector<AST::Attribute> ()); + AST::AttrVec outer_attrs = {}, bool was_impl_trait = false); // Copy constructor uses clone TypeParam (TypeParam const &other); @@ -154,6 +148,8 @@ public: std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds (); + bool from_impl_trait () const { return was_impl_trait; } + protected: // Clone function implementation as (not pure) virtual method TypeParam *clone_generic_param_impl () const override diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h index 5cc5c95..9c636ca 100644 --- a/gcc/rust/hir/tree/rust-hir-pattern.h +++ b/gcc/rust/hir/tree/rust-hir-pattern.h @@ -80,7 +80,7 @@ class IdentifierPattern : public Pattern Identifier variable_ident; bool is_ref; Mutability mut; - std::unique_ptr<Pattern> to_bind; + std::unique_ptr<Pattern> subpattern; location_t locus; Analysis::NodeMapping mappings; @@ -88,15 +88,15 @@ public: std::string as_string () const override; // Returns whether the IdentifierPattern has a pattern to bind. - bool has_pattern_to_bind () const { return to_bind != nullptr; } + bool has_subpattern () const { return subpattern != nullptr; } // Constructor IdentifierPattern (Analysis::NodeMapping mappings, Identifier ident, location_t locus, bool is_ref = false, Mutability mut = Mutability::Imm, - std::unique_ptr<Pattern> to_bind = nullptr) + std::unique_ptr<Pattern> subpattern = nullptr) : variable_ident (std::move (ident)), is_ref (is_ref), mut (mut), - to_bind (std::move (to_bind)), locus (locus), mappings (mappings) + subpattern (std::move (subpattern)), locus (locus), mappings (mappings) {} // Copy constructor with clone @@ -105,8 +105,8 @@ public: mut (other.mut), locus (other.locus), mappings (other.mappings) { // fix to get prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); } // Overload assignment operator to use clone @@ -119,8 +119,8 @@ public: mappings = other.mappings; // fix to get prevent null pointer dereference - if (other.to_bind != nullptr) - to_bind = other.to_bind->clone_pattern (); + if (other.subpattern != nullptr) + subpattern = other.subpattern->clone_pattern (); return *this; } @@ -133,7 +133,7 @@ public: bool is_mut () const { return mut == Mutability::Mut; } bool get_is_ref () const { return is_ref; } - Pattern &get_to_bind () { return *to_bind; } + Pattern &get_subpattern () { return *subpattern; } void accept_vis (HIRFullVisitor &vis) override; void accept_vis (HIRPatternVisitor &vis) override; diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h index 283cc34..43f00dd 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.h +++ b/gcc/rust/hir/tree/rust-hir-visitor.h @@ -64,6 +64,8 @@ public: virtual void visit (MethodCallExpr &expr) = 0; virtual void visit (FieldAccessExpr &expr) = 0; virtual void visit (BlockExpr &expr) = 0; + virtual void visit (AnonConst &expr) = 0; + virtual void visit (ConstBlock &expr) = 0; virtual void visit (ClosureExpr &expr) = 0; virtual void visit (ContinueExpr &expr) = 0; virtual void visit (BreakExpr &expr) = 0; @@ -201,6 +203,8 @@ public: virtual void visit (FieldAccessExpr &) override {} virtual void visit (ClosureExpr &) override {} virtual void visit (BlockExpr &) override {} + virtual void visit (AnonConst &) override {} + virtual void visit (ConstBlock &) override {} virtual void visit (ContinueExpr &) override {} virtual void visit (BreakExpr &) override {} virtual void visit (RangeFromToExpr &) override {} @@ -427,6 +431,8 @@ public: virtual void visit (MethodCallExpr &expr) = 0; virtual void visit (FieldAccessExpr &expr) = 0; virtual void visit (BlockExpr &expr) = 0; + virtual void visit (AnonConst &expr) = 0; + virtual void visit (ConstBlock &expr) = 0; virtual void visit (ContinueExpr &expr) = 0; virtual void visit (BreakExpr &expr) = 0; virtual void visit (RangeFromToExpr &expr) = 0; diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index 093d8d5..dc94fb5 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -577,7 +577,8 @@ UseTreeGlob::as_string () const return "*"; case GLOBAL: return "::*"; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { std::string path_str = path.as_string (); return path_str + "::*"; } @@ -600,7 +601,8 @@ UseTreeList::as_string () const case GLOBAL: path_str = "::{"; break; - case PATH_PREFIXED: { + case PATH_PREFIXED: + { path_str = path.as_string () + "::{"; break; } @@ -1048,6 +1050,33 @@ BlockExpr::as_string () const } std::string +AnonConst::as_string () const +{ + std::string istr = indent_spaces (enter); + std::string str = istr + "AnonConst:\n" + istr; + + str += get_inner_expr ().as_string (); + + str += "\n" + indent_spaces (out); + + return str; +} + +std::string +ConstBlock::as_string () const +{ + std::string istr = indent_spaces (enter); + + std::string str = istr + "ConstBlock:\n" + istr; + + str += get_const_expr ().as_string (); + + str += "\n" + indent_spaces (out); + + return str; +} + +std::string TypeAlias::as_string () const { std::string str = VisItem::as_string (); @@ -2579,9 +2608,9 @@ IdentifierPattern::as_string () const str += variable_ident.as_string (); - if (has_pattern_to_bind ()) + if (has_subpattern ()) { - str += " @ " + to_bind->as_string (); + str += " @ " + subpattern->as_string (); } return str; @@ -4055,6 +4084,18 @@ BlockExpr::accept_vis (HIRFullVisitor &vis) } void +AnonConst::accept_vis (HIRFullVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstBlock::accept_vis (HIRFullVisitor &vis) +{ + vis.visit (*this); +} + +void ContinueExpr::accept_vis (HIRFullVisitor &vis) { vis.visit (*this); @@ -5027,6 +5068,18 @@ BlockExpr::accept_vis (HIRExpressionVisitor &vis) } void +AnonConst::accept_vis (HIRExpressionVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstBlock::accept_vis (HIRExpressionVisitor &vis) +{ + vis.visit (*this); +} + +void Function::accept_vis (HIRStmtVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index b143e70..76ff15c 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -1317,7 +1317,8 @@ Lexer::parse_escape (char opening_char) switch (current_char.value) { - case 'x': { + case 'x': + { auto hex_escape_pair = parse_partial_hex_escape (); long hexLong = hex_escape_pair.first; additional_length_offset += hex_escape_pair.second; @@ -1400,7 +1401,8 @@ Lexer::parse_utf8_escape () switch (current_char.value) { - case 'x': { + case 'x': + { auto hex_escape_pair = parse_partial_hex_escape (); long hexLong = hex_escape_pair.first; additional_length_offset += hex_escape_pair.second; @@ -1438,7 +1440,8 @@ Lexer::parse_utf8_escape () case '"': output_char = '"'; break; - case 'u': { + case 'u': + { auto unicode_escape_pair = parse_partial_unicode_escape (); output_char = unicode_escape_pair.first; additional_length_offset += unicode_escape_pair.second; @@ -1894,6 +1897,11 @@ Lexer::parse_raw_byte_string (location_t loc) break; } } + else if (current_char.is_eof ()) + { + rust_error_at (string_begin_locus, "unended raw byte string literal"); + return Token::make (END_OF_FILE, get_current_location ()); + } else if (current_char.value > 127) { rust_error_at (get_current_location (), @@ -1901,11 +1909,6 @@ Lexer::parse_raw_byte_string (location_t loc) current_char.as_string ().c_str ()); current_char = 0; } - else if (current_char.is_eof ()) - { - rust_error_at (string_begin_locus, "unended raw byte string literal"); - return Token::make (END_OF_FILE, get_current_location ()); - } length++; current_column++; diff --git a/gcc/rust/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h index 10293e0..383ffac 100644 --- a/gcc/rust/lex/rust-lex.h +++ b/gcc/rust/lex/rust-lex.h @@ -263,8 +263,7 @@ private: #if CHECKING_P namespace selftest { -void -rust_input_source_test (); +void rust_input_source_test (); } // namespace selftest diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc index 8493889..c396e10 100644 --- a/gcc/rust/lex/rust-token.cc +++ b/gcc/rust/lex/rust-token.cc @@ -20,6 +20,7 @@ #include "rust-token.h" #include "rust-diagnostics.h" #include "rust-unicode.h" +#include "rust-ast.h" namespace Rust { // Hackily defined way to get token description for enum value using x-macros @@ -88,7 +89,8 @@ token_id_keyword_string (TokenId id) switch (id) { #define RS_TOKEN_KEYWORD_2015(id, str_ptr) \ - case id: { \ + case id: \ + { \ static const std::string str (str_ptr); \ return str; \ } \ @@ -234,6 +236,13 @@ escape_special_chars (const std::string &source, Context ctx) } // namespace +TokenPtr +Token::make_identifier (const Identifier &ident) +{ + std::string str = ident; + return make_identifier (ident.get_locus (), std::move (str)); +} + std::string Token::as_string () const { diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index c683ecd..2021aec 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -24,6 +24,10 @@ #include "rust-unicode.h" namespace Rust { + +// used by Rust::Token::make_identifier +class Identifier; + // "Primitive core types" in Rust - the different int and float types, as well // as some others enum PrimitiveCoreType @@ -221,25 +225,20 @@ typedef std::shared_ptr<Token> TokenPtr; typedef std::shared_ptr<const Token> const_TokenPtr; // Hackily defined way to get token description for enum value using x-macros -const char * -get_token_description (TokenId id); +const char *get_token_description (TokenId id); /* Hackily defined way to get token description as a string for enum value using * x-macros */ -const char * -token_id_to_str (TokenId id); +const char *token_id_to_str (TokenId id); /* checks if a token is a keyword */ -bool -token_id_is_keyword (TokenId id); +bool token_id_is_keyword (TokenId id); /* gets the string associated with a keyword */ -const std::string & -token_id_keyword_string (TokenId id); +const std::string &token_id_keyword_string (TokenId id); // Get type hint description as a string. -const char * -get_type_hint_string (PrimitiveCoreType type); +const char *get_type_hint_string (PrimitiveCoreType type); /* Normalize string if a token is a identifier */ -std::string -nfc_normalize_token_string (location_t loc, TokenId id, const std::string &str); +std::string nfc_normalize_token_string (location_t loc, TokenId id, + const std::string &str); // Represents a single token. Create using factory static methods. class Token @@ -329,6 +328,8 @@ public: return TokenPtr (new Token (IDENTIFIER, locus, std::move (str))); } + static TokenPtr make_identifier (const Identifier &ident); + // Makes and returns a new TokenPtr of type INT_LITERAL. static TokenPtr make_int (location_t locus, std::string &&str, PrimitiveCoreType type_hint = CORETYPE_UNKNOWN) diff --git a/gcc/rust/metadata/rust-export-metadata.cc b/gcc/rust/metadata/rust-export-metadata.cc index 771bec6..1829a85 100644 --- a/gcc/rust/metadata/rust-export-metadata.cc +++ b/gcc/rust/metadata/rust-export-metadata.cc @@ -263,8 +263,7 @@ PublicInterface::write_to_path (const std::string &path) const FILE *nfd = fopen (path.c_str (), "wb"); if (nfd == NULL) { - rust_error_at (UNDEF_LOCATION, - "failed to open file %qs for writing: %s", + rust_error_at (UNDEF_LOCATION, "failed to open file %qs for writing: %s", path.c_str (), xstrerror (errno)); return; } diff --git a/gcc/rust/metadata/rust-import-archive.cc b/gcc/rust/metadata/rust-import-archive.cc index cf24607..f64de4e 100644 --- a/gcc/rust/metadata/rust-import-archive.cc +++ b/gcc/rust/metadata/rust-import-archive.cc @@ -683,7 +683,7 @@ public: const Header &operator* () const { return this->header_; } - const Header *operator-> () const { return &this->header_; } + const Header *operator->() const { return &this->header_; } Archive_iterator &operator++ () { diff --git a/gcc/rust/metadata/rust-imports.h b/gcc/rust/metadata/rust-imports.h index a497c67..65a2af1 100644 --- a/gcc/rust/metadata/rust-imports.h +++ b/gcc/rust/metadata/rust-imports.h @@ -11,8 +11,7 @@ namespace Rust { -extern void -add_search_path (const std::string &path); +extern void add_search_path (const std::string &path); class Import { diff --git a/gcc/rust/parse/rust-cfg-parser.h b/gcc/rust/parse/rust-cfg-parser.h index 0d64016..61db240 100644 --- a/gcc/rust/parse/rust-cfg-parser.h +++ b/gcc/rust/parse/rust-cfg-parser.h @@ -36,15 +36,14 @@ namespace Rust { * * @return false if the given input was invalid, true otherwise */ -bool -parse_cfg_option (std::string &input, std::string &key, std::string &value); +bool parse_cfg_option (std::string &input, std::string &key, + std::string &value); } // namespace Rust #if CHECKING_P namespace selftest { -extern void -rust_cfg_parser_test (void); +extern void rust_cfg_parser_test (void); } // namespace selftest #endif // CHECKING_P diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 9dda231..9c9208f 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -227,19 +227,22 @@ Parser<ManagedTokenSource>::skip_generics_right_angle () // this is good - skip token lexer.skip_token (); return true; - case RIGHT_SHIFT: { + case RIGHT_SHIFT: + { // new implementation that should be better lexer.split_current_token (RIGHT_ANGLE, RIGHT_ANGLE); lexer.skip_token (); return true; } - case GREATER_OR_EQUAL: { + case GREATER_OR_EQUAL: + { // new implementation that should be better lexer.split_current_token (RIGHT_ANGLE, EQUAL); lexer.skip_token (); return true; } - case RIGHT_SHIFT_EQ: { + case RIGHT_SHIFT_EQ: + { // new implementation that should be better lexer.split_current_token (RIGHT_ANGLE, GREATER_OR_EQUAL); lexer.skip_token (); @@ -790,7 +793,8 @@ Parser<ManagedTokenSource>::parse_attr_input () { case LEFT_PAREN: case LEFT_SQUARE: - case LEFT_CURLY: { + case LEFT_CURLY: + { // must be a delimited token tree, so parse that std::unique_ptr<AST::AttrInput> input_tree ( new AST::DelimTokenTree (parse_delim_token_tree ())); @@ -799,7 +803,8 @@ Parser<ManagedTokenSource>::parse_attr_input () return input_tree; } - case EQUAL: { + case EQUAL: + { // = LiteralExpr lexer.skip_token (); @@ -877,7 +882,10 @@ Parser<ManagedTokenSource>::parse_attr_input () return attr_input_lit; } break; + case RIGHT_PAREN: case RIGHT_SQUARE: + case RIGHT_CURLY: + case END_OF_FILE: // means AttrInput is missing, which is allowed return nullptr; default: @@ -2117,7 +2125,8 @@ Parser<ManagedTokenSource>::parse_macro_match () { case LEFT_PAREN: case LEFT_SQUARE: - case LEFT_CURLY: { + case LEFT_CURLY: + { // must be macro matcher as delimited AST::MacroMatcher matcher = parse_macro_matcher (); if (matcher.is_error ()) @@ -2131,7 +2140,8 @@ Parser<ManagedTokenSource>::parse_macro_match () return std::unique_ptr<AST::MacroMatcher> ( new AST::MacroMatcher (std::move (matcher))); } - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { // have to do more lookahead to determine if fragment or repetition const_TokenPtr t2 = lexer.peek_token (1); switch (t2->get_id ()) @@ -2402,7 +2412,8 @@ Parser<ManagedTokenSource>::parse_visibility () skip_token (RIGHT_PAREN); return AST::Visibility::create_super (path_loc, vis_loc); - case IN: { + case IN: + { lexer.skip_token (); // parse the "in" path as well @@ -2466,7 +2477,8 @@ Parser<ManagedTokenSource>::parse_module (AST::Visibility vis, new AST::Module (std::move (name), std::move (vis), std::move (outer_attrs), locus, safety, lexer.get_filename (), inline_module_stack)); - case LEFT_CURLY: { + case LEFT_CURLY: + { lexer.skip_token (); // parse inner attributes @@ -2730,7 +2742,8 @@ Parser<ManagedTokenSource>::parse_use_tree () return std::unique_ptr<AST::UseTreeGlob> ( new AST::UseTreeGlob (AST::UseTreeGlob::NO_PATH, AST::SimplePath::create_empty (), locus)); - case LEFT_CURLY: { + case LEFT_CURLY: + { // nested tree UseTree type lexer.skip_token (); @@ -2808,7 +2821,8 @@ Parser<ManagedTokenSource>::parse_use_tree () return std::unique_ptr<AST::UseTreeGlob> ( new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED, std::move (path), locus)); - case LEFT_CURLY: { + case LEFT_CURLY: + { // nested tree UseTree type lexer.skip_token (); @@ -2845,7 +2859,8 @@ Parser<ManagedTokenSource>::parse_use_tree () std::move (path), std::move (use_trees), locus)); } - case AS: { + case AS: + { // rebind UseTree type lexer.skip_token (); @@ -3100,7 +3115,8 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token) switch (token->get_id ()) { - case LIFETIME: { + case LIFETIME: + { auto lifetime = parse_lifetime (false); if (!lifetime) { @@ -3126,7 +3142,8 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token) std::move (outer_attrs), token->get_locus ())); break; } - case IDENTIFIER: { + case IDENTIFIER: + { auto type_ident = token->get_str (); lexer.skip_token (); @@ -3161,7 +3178,8 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token) std::move (outer_attrs))); break; } - case CONST: { + case CONST: + { lexer.skip_token (); auto name_token = expect_token (IDENTIFIER); @@ -4356,7 +4374,8 @@ Parser<ManagedTokenSource>::parse_struct (AST::Visibility vis, const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case LEFT_CURLY: { + case LEFT_CURLY: + { // struct with body // skip curly bracket @@ -4759,7 +4778,8 @@ Parser<ManagedTokenSource>::parse_enum_item () const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case LEFT_PAREN: { + case LEFT_PAREN: + { // tuple enum item lexer.skip_token (); @@ -4780,7 +4800,8 @@ Parser<ManagedTokenSource>::parse_enum_item () std::move (item_name), std::move (vis), std::move (tuple_fields), std::move (outer_attrs), item_name_tok->get_locus ())); } - case LEFT_CURLY: { + case LEFT_CURLY: + { // struct enum item lexer.skip_token (); @@ -4797,7 +4818,8 @@ Parser<ManagedTokenSource>::parse_enum_item () std::move (item_name), std::move (vis), std::move (struct_fields), std::move (outer_attrs), item_name_tok->get_locus ())); } - case EQUAL: { + case EQUAL: + { // discriminant enum item lexer.skip_token (); @@ -5450,7 +5472,8 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item () case SUPER: case SELF: case CRATE: - case PUB: { + case PUB: + { // visibility, so not a macro invocation semi - must be constant, // function, or method AST::Visibility vis = parse_visibility (); @@ -5964,7 +5987,8 @@ Parser<ManagedTokenSource>::parse_external_item () { case IDENTIFIER: return parse_macro_invocation_semi (outer_attrs); - case STATIC_KW: { + case STATIC_KW: + { // parse extern static item lexer.skip_token (); @@ -6261,7 +6285,8 @@ Parser<ManagedTokenSource>::parse_generic_arg () switch (tok->get_id ()) { - case IDENTIFIER: { + case IDENTIFIER: + { // This is a bit of a weird situation: With an identifier token, we // could either have a valid type or a macro (FIXME: anything else?). So // we need one bit of lookahead to differentiate if this is really @@ -6309,9 +6334,10 @@ Parser<ManagedTokenSource>::parse_generic_arg () case FALSE_LITERAL: expr = parse_literal_expr (); break; - // FIXME: Because of this, error reporting is garbage for const generic - // parameter's default values - default: { + // FIXME: Because of this, error reporting is garbage for const generic + // parameter's default values + default: + { auto type = parse_type (); // FIXME: Find a better way to do this? if (type) @@ -6510,7 +6536,8 @@ Parser<ManagedTokenSource>::parse_type_path_segment () switch (t->get_id ()) { case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // parse generic args AST::GenericArgs generic_args = parse_path_generic_args (); @@ -6519,7 +6546,8 @@ Parser<ManagedTokenSource>::parse_type_path_segment () has_separating_scope_resolution, std::move (generic_args), locus)); } - case LEFT_PAREN: { + case LEFT_PAREN: + { // parse type path function AST::TypePathFunction type_path_function = parse_type_path_function (locus); @@ -7068,16 +7096,14 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs, case SELF: case SELF_ALIAS: case DOLLAR_SIGN: - case SCOPE_RESOLUTION: { + case SCOPE_RESOLUTION: + { AST::PathInExpression path = parse_path_in_expression (); std::unique_ptr<AST::Expr> null_denotation; if (lexer.peek_token ()->get_id () == EXCLAM) { - // Bind a reference to avoid -Wredundant-move on post-P1825R0 - // compilers. Change to non-reference type and remove the moves - // below once C++20 is required to build gcc. - std::unique_ptr<AST::MacroInvocation> &&invoc + std::unique_ptr<AST::MacroInvocation> invoc = parse_macro_invocation_partial (std::move (path), std::move (outer_attrs)); @@ -7085,7 +7111,7 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs, { invoc->add_semicolon (); // Macro invocation with semicolon. - return std::move (invoc); + return invoc; } TokenId after_macro = lexer.peek_token ()->get_id (); @@ -7093,14 +7119,14 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs, if (restrictions.allow_close_after_expr_stmt && (after_macro == RIGHT_PAREN || after_macro == RIGHT_CURLY || after_macro == RIGHT_SQUARE)) - return std::move (invoc); + return invoc; if (invoc->get_invoc_data ().get_delim_tok_tree ().get_delim_type () == AST::CURLY && after_macro != DOT && after_macro != QUESTION_MARK) { rust_debug ("braced macro statement"); - return std::move (invoc); + return invoc; } null_denotation = std::move (invoc); @@ -7238,6 +7264,30 @@ Parser<ManagedTokenSource>::parse_block_expr ( std::move (label), locus, end_locus)); } +/* Parse a "const block", a block preceded by the `const` keyword whose + * statements can be const evaluated and used in constant contexts */ +template <typename ManagedTokenSource> +std::unique_ptr<AST::ConstBlock> +Parser<ManagedTokenSource>::parse_const_block_expr (AST::AttrVec outer_attrs, + location_t locus) +{ + auto block = parse_block_expr (); + + if (!block) + { + add_error (Error (locus, "failed to parse inner block in const block")); + skip_after_end_block (); + + return nullptr; + } + + auto block_locus = block->get_locus (); + + return std::make_unique<AST::ConstBlock> (AST::AnonConst (std::move (block), + block_locus), + locus, std::move (outer_attrs)); +} + /* Parses a "grouped" expression (expression in parentheses), used to control * precedence. */ template <typename ManagedTokenSource> @@ -7675,7 +7725,8 @@ Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs, const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case LEFT_CURLY: { + case LEFT_CURLY: + { // double selection - else // parse else block expr (required) std::unique_ptr<AST::BlockExpr> else_body = parse_block_expr (); @@ -7696,7 +7747,8 @@ Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs, std::move (else_body), std::move (outer_attrs), locus)); } - case IF: { + case IF: + { // multiple selection - else if or else if let // branch on whether next token is 'let' or not if (lexer.peek_token (1)->get_id () == LET) @@ -7857,7 +7909,8 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs, const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case LEFT_CURLY: { + case LEFT_CURLY: + { // double selection - else // parse else block expr (required) std::unique_ptr<AST::BlockExpr> else_body = parse_block_expr (); @@ -7879,7 +7932,8 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs, std::move (else_body), std::move (outer_attrs), locus)); } - case IF: { + case IF: + { // multiple selection - else if or else if let // branch on whether next token is 'let' or not if (lexer.peek_token (1)->get_id () == LET) @@ -8931,7 +8985,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) // slice type or array type - requires further disambiguation return parse_slice_or_array_type (); case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path in type AST::QualifiedPathInType path = parse_qualified_path_in_type (); if (path.is_error ()) @@ -8960,7 +9015,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) case LOGICAL_AND: // reference type return parse_reference_type (); - case LIFETIME: { + case LIFETIME: + { /* probably a lifetime bound, so probably type param bounds in * TraitObjectType */ std::vector<std::unique_ptr<AST::TypeParamBound>> bounds @@ -8976,7 +9032,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) case SELF_ALIAS: case CRATE: case DOLLAR_SIGN: - case SCOPE_RESOLUTION: { + case SCOPE_RESOLUTION: + { // macro invocation or type path - requires further disambiguation. /* for parsing path component of each rule, perhaps parse it as a * typepath and attempt conversion to simplepath if a trailing '!' is @@ -9006,7 +9063,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) t = lexer.peek_token (); switch (t->get_id ()) { - case EXCLAM: { + case EXCLAM: + { // macro invocation // convert to simple path AST::SimplePath macro_path = path.as_simple_path (); @@ -9032,7 +9090,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) std::move (tok_tree)), {}, locus); } - case PLUS: { + case PLUS: + { // type param bounds std::vector<std::unique_ptr<AST::TypeParamBound>> bounds; @@ -9117,14 +9176,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) t = lexer.peek_token (); if (t->get_id () != PLUS) { - // convert trait bound to value object - AST::TraitBound value_bound (*initial_bound); - - // DEBUG: removed as unique ptr, so should auto-delete - // delete initial_bound; - return std::unique_ptr<AST::ImplTraitTypeOneBound> ( - new AST::ImplTraitTypeOneBound (std::move (value_bound), + new AST::ImplTraitTypeOneBound (std::move (initial_bound), locus)); } @@ -9152,7 +9205,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors) new AST::ImplTraitType (std::move (bounds), locus)); } case DYN: - case QUESTION_MARK: { + case QUESTION_MARK: + { // either TraitObjectType or TraitObjectTypeOneBound bool has_dyn = false; if (t->get_id () == DYN) @@ -9405,7 +9459,8 @@ Parser<ManagedTokenSource>::parse_for_prefixed_type () case SELF: case SELF_ALIAS: case CRATE: - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { // path, so trait type // parse type path to finish parsing trait bound @@ -9751,7 +9806,8 @@ Parser<ManagedTokenSource>::parse_slice_or_array_type () return std::unique_ptr<AST::SliceType> ( new AST::SliceType (std::move (inner_type), locus)); - case SEMICOLON: { + case SEMICOLON: + { // array type lexer.skip_token (); @@ -9802,7 +9858,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds () // slice type or array type - requires further disambiguation return parse_slice_or_array_type (); case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path in type AST::QualifiedPathInType path = parse_qualified_path_in_type (); if (path.is_error ()) @@ -9843,7 +9900,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds () case SELF_ALIAS: case CRATE: case DOLLAR_SIGN: - case SCOPE_RESOLUTION: { + case SCOPE_RESOLUTION: + { // macro invocation or type path - requires further disambiguation. /* for parsing path component of each rule, perhaps parse it as a * typepath and attempt conversion to simplepath if a trailing '!' is @@ -9871,7 +9929,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds () t = lexer.peek_token (); switch (t->get_id ()) { - case EXCLAM: { + case EXCLAM: + { // macro invocation // convert to simple path AST::SimplePath macro_path = path.as_simple_path (); @@ -9955,14 +10014,12 @@ Parser<ManagedTokenSource>::parse_type_no_bounds () return nullptr; } - // convert trait bound to value object - AST::TraitBound value_bound (*initial_bound); - return std::unique_ptr<AST::ImplTraitTypeOneBound> ( - new AST::ImplTraitTypeOneBound (std::move (value_bound), locus)); + new AST::ImplTraitTypeOneBound (std::move (initial_bound), locus)); } case DYN: - case QUESTION_MARK: { + case QUESTION_MARK: + { // either TraitObjectTypeOneBound bool has_dyn = false; if (t->get_id () == DYN) @@ -10303,7 +10360,8 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound () case SELF_ALIAS: case CRATE: case SCOPE_RESOLUTION: - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { // path in expression AST::PathInExpression path = parse_path_in_expression (); if (path.is_error ()) @@ -10319,7 +10377,8 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound () new AST::RangePatternBoundPath (std::move (path))); } case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path in expression AST::QualifiedPathInExpression path = parse_qualified_path_in_expression (); @@ -10464,7 +10523,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () // slice pattern return parse_slice_pattern (); case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path in expression or qualified range pattern bound AST::QualifiedPathInExpression path = parse_qualified_path_in_expression (); @@ -10500,7 +10560,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () case SELF_ALIAS: case CRATE: case SCOPE_RESOLUTION: - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { // path in expression or range pattern bound AST::PathInExpression path = parse_path_in_expression (); @@ -10509,7 +10570,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () { case DOT_DOT_EQ: case DOT_DOT: - case ELLIPSIS: { + case ELLIPSIS: + { // qualified range pattern bound, so parse rest of range pattern AST::RangeKind kind = AST::tokenid_to_rangekind (next->get_id ()); lexer.skip_token (); @@ -10527,7 +10589,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () case EXCLAM: return parse_macro_invocation_partial (std::move (path), AST::AttrVec ()); - case LEFT_PAREN: { + case LEFT_PAREN: + { // tuple struct lexer.skip_token (); @@ -10552,7 +10615,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt () new AST::TupleStructPattern (std::move (path), std::move (items))); } - case LEFT_CURLY: { + case LEFT_CURLY: + { // struct lexer.skip_token (); @@ -10722,7 +10786,8 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () return std::unique_ptr<AST::GroupedPattern> ( new AST::GroupedPattern (std::move (initial_pattern), paren_locus)); - case COMMA: { + case COMMA: + { // tuple pattern lexer.skip_token (); @@ -10979,7 +11044,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern () { case EXCLAM: return parse_macro_invocation_partial (std::move (path), AST::AttrVec ()); - case LEFT_PAREN: { + case LEFT_PAREN: + { // tuple struct lexer.skip_token (); @@ -11012,7 +11078,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern () return std::unique_ptr<AST::TupleStructPattern> ( new AST::TupleStructPattern (std::move (path), std::move (items))); } - case LEFT_CURLY: { + case LEFT_CURLY: + { // struct lexer.skip_token (); @@ -11033,7 +11100,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern () } case DOT_DOT_EQ: case DOT_DOT: - case ELLIPSIS: { + case ELLIPSIS: + { // range AST::RangeKind kind = AST::tokenid_to_rangekind (lexer.peek_token ()->get_id ()); @@ -11050,7 +11118,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern () std::move (upper_bound), kind, t->get_locus ())); } - case PATTERN_BIND: { + case PATTERN_BIND: + { // only allow on single-segment paths if (path.is_single_segment ()) { @@ -11188,7 +11257,8 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items () case RIGHT_PAREN: return std::unique_ptr<AST::TupleStructItemsNoRange> ( new AST::TupleStructItemsNoRange (std::move (lower_patterns))); - case DOT_DOT: { + case DOT_DOT: + { // has an upper range that must be parsed separately lexer.skip_token (); @@ -11308,7 +11378,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial ( const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case INT_LITERAL: { + case INT_LITERAL: + { // tuple index std::string index_str = t->get_str (); int index = atoi (index_str.c_str ()); @@ -11342,7 +11413,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial ( // branch on next token switch (lexer.peek_token (1)->get_id ()) { - case COLON: { + case COLON: + { // identifier-pattern Identifier ident{t}; lexer.skip_token (); @@ -11367,7 +11439,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial ( t->get_locus ())); } case COMMA: - case RIGHT_CURLY: { + case RIGHT_CURLY: + { // identifier only Identifier ident = {t}; lexer.skip_token (); @@ -11386,7 +11459,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial ( return nullptr; } case REF: - case MUT: { + case MUT: + { // only identifier bool has_ref = false; if (t->get_id () == REF) @@ -11458,7 +11532,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr () t = lexer.peek_token (); switch (t->get_id ()) { - case LET: { + case LET: + { // let statement std::unique_ptr<AST::LetStmt> stmt ( parse_let_stmt (std::move (outer_attrs))); @@ -11476,42 +11551,48 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr () case STATIC_KW: case AUTO: case TRAIT: - case IMPL: { + case IMPL: + { std::unique_ptr<AST::VisItem> item ( parse_vis_item (std::move (outer_attrs))); return ExprOrStmt (std::move (item)); } - /* TODO: implement union keyword but not really because of - * context-dependence crappy hack way to parse a union written below to - * separate it from the good code. */ - // case UNION: - case UNSAFE: { // maybe - unsafe traits are a thing + /* TODO: implement union keyword but not really because of + * context-dependence crappy hack way to parse a union written below to + * separate it from the good code. */ + // case UNION: + case UNSAFE: + { // maybe - unsafe traits are a thing /* if any of these (should be all possible VisItem prefixes), parse a * VisItem - can't parse item because would require reparsing outer * attributes */ const_TokenPtr t2 = lexer.peek_token (1); switch (t2->get_id ()) { - case LEFT_CURLY: { + case LEFT_CURLY: + { // unsafe block: parse as expression expr = parse_expr (std::move (outer_attrs), restrictions); break; } case AUTO: - case TRAIT: { + case TRAIT: + { // unsafe trait std::unique_ptr<AST::VisItem> item ( parse_vis_item (std::move (outer_attrs))); return ExprOrStmt (std::move (item)); } case EXTERN_KW: - case FN_KW: { + case FN_KW: + { // unsafe function std::unique_ptr<AST::VisItem> item ( parse_vis_item (std::move (outer_attrs))); return ExprOrStmt (std::move (item)); } - case IMPL: { + case IMPL: + { // unsafe trait impl std::unique_ptr<AST::VisItem> item ( parse_vis_item (std::move (outer_attrs))); @@ -11556,7 +11637,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr () case SELF_ALIAS: case CRATE: case SCOPE_RESOLUTION: - case DOLLAR_SIGN: { + case DOLLAR_SIGN: + { AST::PathInExpression path = parse_path_in_expression (); std::unique_ptr<AST::Expr> null_denotation; @@ -11680,7 +11762,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_field () std::move (outer_attrs), t->get_locus ())); } - case INT_LITERAL: { + case INT_LITERAL: + { // parse tuple index field int index = atoi (t->get_str ().c_str ()); lexer.skip_token (); @@ -11920,7 +12003,7 @@ Parser<ManagedTokenSource>::skip_after_end_attribute () { const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_SQUARE) + while (t->get_id () != RIGHT_SQUARE && t->get_id () != END_OF_FILE) { lexer.skip_token (); t = lexer.peek_token (); @@ -12050,7 +12133,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok, case SELF_ALIAS: case DOLLAR_SIGN: case CRATE: - case SUPER: { + case SUPER: + { // DEBUG rust_debug ("beginning null denotation identifier handling"); @@ -12061,7 +12145,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok, return null_denotation_path (std::move (path), std::move (outer_attrs), restrictions); } - case SCOPE_RESOLUTION: { + case SCOPE_RESOLUTION: + { // TODO: fix: this is for global paths, i.e. std::string::whatever Error error (tok->get_locus (), "found null denotation scope resolution operator, and " @@ -12103,7 +12188,8 @@ Parser<ManagedTokenSource>::null_denotation_path ( // macro return parse_macro_invocation_partial (std::move (path), std::move (outer_attrs)); - case LEFT_CURLY: { + case LEFT_CURLY: + { bool not_a_block = lexer.peek_token (1)->get_id () == IDENTIFIER && (lexer.peek_token (2)->get_id () == COMMA || (lexer.peek_token (2)->get_id () == COLON @@ -12179,7 +12265,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( { // FIXME: Handle in null_denotation_path? case LEFT_SHIFT: - case LEFT_ANGLE: { + case LEFT_ANGLE: + { // qualified path // HACK: add outer attrs to path AST::QualifiedPathInExpression path @@ -12237,23 +12324,24 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( return parse_grouped_or_tuple_expr (std::move (outer_attrs), tok->get_locus ()); - /*case PLUS: { // unary plus operator - // invoke parse_expr recursively with appropriate priority, etc. for - below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS); + /*case PLUS: { // unary plus operator + // invoke parse_expr recursively with appropriate priority, etc. for + below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS); - if (expr == nullptr) - return nullptr; - // can only apply to integer and float expressions - if (expr->get_type() != integer_type_node || expr->get_type() != - float_type_node) { rust_error_at(tok->get_locus(), "operand of unary - plus must be int or float but it is %s", print_type(expr->get_type())); - return nullptr; - } + if (expr == nullptr) + return nullptr; + // can only apply to integer and float expressions + if (expr->get_type() != integer_type_node || expr->get_type() != + float_type_node) { rust_error_at(tok->get_locus(), "operand of unary + plus must be int or float but it is %s", print_type(expr->get_type())); + return nullptr; + } - return Tree(expr, tok->get_locus()); - }*/ - // Rust has no unary plus operator - case MINUS: { // unary minus + return Tree(expr, tok->get_locus()); + }*/ + // Rust has no unary plus operator + case MINUS: + { // unary minus ParseRestrictions entered_from_unary; entered_from_unary.entered_from_unary = true; if (!restrictions.can_be_struct_expr) @@ -12280,7 +12368,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( new AST::NegationExpr (std::move (expr), NegationOperator::NEGATE, std::move (outer_attrs), tok->get_locus ())); } - case EXCLAM: { // logical or bitwise not + case EXCLAM: + { // logical or bitwise not ParseRestrictions entered_from_unary; entered_from_unary.entered_from_unary = true; if (!restrictions.can_be_struct_expr) @@ -12305,7 +12394,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( new AST::NegationExpr (std::move (expr), NegationOperator::NOT, std::move (outer_attrs), tok->get_locus ())); } - case ASTERISK: { + case ASTERISK: + { /* pointer dereference only - HACK: as struct expressions should * always be value expressions, cannot be dereferenced */ ParseRestrictions entered_from_unary; @@ -12318,7 +12408,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( new AST::DereferenceExpr (std::move (expr), std::move (outer_attrs), tok->get_locus ())); } - case AMP: { + case AMP: + { // (single) "borrow" expression - shared (mutable) or immutable std::unique_ptr<AST::Expr> expr = nullptr; Mutability mutability = Mutability::Imm; @@ -12375,7 +12466,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( new AST::BorrowExpr (std::move (expr), mutability, raw_borrow, false, std::move (outer_attrs), tok->get_locus ())); } - case LOGICAL_AND: { + case LOGICAL_AND: + { // (double) "borrow" expression - shared (mutable) or immutable std::unique_ptr<AST::Expr> expr = nullptr; Mutability mutability = Mutability::Imm; @@ -12469,6 +12561,9 @@ Parser<ManagedTokenSource>::null_denotation_not_path ( "use of %qs is not allowed on the right-side of an assignment", tok->get_token_description ())); return nullptr; + case CONST: + return parse_const_block_expr (std::move (outer_attrs), + tok->get_locus ()); default: if (!restrictions.expr_can_be_null) add_error (Error (tok->get_locus (), @@ -12491,8 +12586,9 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok, // Token passed in has already been skipped, so peek gives "next" token switch (tok->get_id ()) { - // FIXME: allow for outer attributes to be applied - case QUESTION_MARK: { + // FIXME: allow for outer attributes to be applied + case QUESTION_MARK: + { location_t left_locus = left->get_locus (); // error propagation expression - unary postfix return std::unique_ptr<AST::ErrorPropagationExpr> ( @@ -12746,7 +12842,8 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok, "function - this should probably be handled elsewhere")); return nullptr; - case DOT: { + case DOT: + { /* field expression or method call - relies on parentheses after next * identifier or await if token after is "await" (unary postfix) or * tuple index if token after is a decimal int literal */ @@ -14062,7 +14159,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_struct_partial ( * algorithm should work too. As such, AST type not happening. */ case IDENTIFIER: case HASH: - case INT_LITERAL: { + case INT_LITERAL: + { // struct with struct expr fields // parse struct expr fields @@ -14359,7 +14457,8 @@ Parser<ManagedTokenSource>::parse_closure_expr_pratt (const_TokenPtr tok, case OR: // no parameters, don't skip token break; - case PIPE: { + case PIPE: + { // actually may have parameters // don't skip token const_TokenPtr t = lexer.peek_token (); diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc index 43d15aa..860fd11 100644 --- a/gcc/rust/parse/rust-parse.cc +++ b/gcc/rust/parse/rust-parse.cc @@ -42,8 +42,7 @@ extract_module_path (const AST::AttrVec &inner_attrs, { rust_error_at ( path_attr.get_locus (), - // Split the format string so that -Wformat-diag does not complain... - "path attributes must contain a filename: '%s'", "#![path = \"file\"]"); + "path attributes must contain a filename: %<#[path = \"file\"]%>"); return name; } @@ -67,8 +66,7 @@ extract_module_path (const AST::AttrVec &inner_attrs, { rust_error_at ( path_attr.get_locus (), - // Split the format string so that -Wformat-diag does not complain... - "path attributes must contain a filename: '%s'", "#[path = \"file\"]"); + "path attributes must contain a filename: %<#[path = \"file\"]%>"); return name; } @@ -80,6 +78,15 @@ extract_module_path (const AST::AttrVec &inner_attrs, // a character that is not an equal sign or whitespace auto filename_begin = path_value.find_first_not_of ("=\t "); + // If the path consists of only whitespace, then we have an error + if (filename_begin == std::string::npos) + { + rust_error_at ( + path_attr.get_locus (), + "path attributes must contain a filename: %<#[path = \"file\"]%>"); + return name; + } + auto path = path_value.substr (filename_begin); // On windows, the path might mix '/' and '\' separators. Replace the @@ -144,10 +151,9 @@ peculiar_fragment_match_compatible_fragment ( = contains (fragment_follow_set[last_spec.get_kind ()], spec.get_kind ()); if (!is_valid) - rust_error_at ( - match_locus, - "fragment specifier %qs is not allowed after %qs fragments", - spec.as_string ().c_str (), last_spec.as_string ().c_str ()); + rust_error_at (match_locus, + "fragment specifier %qs is not allowed after %qs fragments", + spec.as_string ().c_str (), last_spec.as_string ().c_str ()); return is_valid; } @@ -244,7 +250,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, // the error. switch (match.get_macro_match_type ()) { - case AST::MacroMatch::Tok: { + case AST::MacroMatch::Tok: + { auto tok = static_cast<const AST::Token *> (&match); if (contains (allowed_toks, tok->get_id ())) return true; @@ -254,7 +261,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, break; } break; - case AST::MacroMatch::Repetition: { + case AST::MacroMatch::Repetition: + { auto repetition = static_cast<const AST::MacroMatchRepetition *> (&match); auto &matches = repetition->get_matches (); @@ -263,7 +271,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, return peculiar_fragment_match_compatible (last_match, *first_frag); break; } - case AST::MacroMatch::Matcher: { + case AST::MacroMatch::Matcher: + { auto matcher = static_cast<const AST::MacroMatcher *> (&match); auto first_token = matcher->get_delim_type (); TokenId delim_id; @@ -289,7 +298,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, error_locus = matcher->get_match_locus (); break; } - case AST::MacroMatch::Fragment: { + case AST::MacroMatch::Fragment: + { auto last_spec = last_match.get_frag_spec (); auto fragment = static_cast<const AST::MacroMatchFragment *> (&match); if (last_spec.has_follow_set_fragment_restrictions ()) @@ -328,10 +338,11 @@ is_match_compatible (const AST::MacroMatch &last_match, switch (last_match.get_macro_match_type ()) { - // This is our main stop condition: When we are finally looking at the - // last match (or its actual last component), and it is a fragment, it - // may contain some follow up restrictions. - case AST::MacroMatch::Fragment: { + // This is our main stop condition: When we are finally looking at the + // last match (or its actual last component), and it is a fragment, it + // may contain some follow up restrictions. + case AST::MacroMatch::Fragment: + { auto fragment = static_cast<const AST::MacroMatchFragment *> (&last_match); if (fragment->get_frag_spec ().has_follow_set_restrictions ()) @@ -339,7 +350,8 @@ is_match_compatible (const AST::MacroMatch &last_match, else return true; } - case AST::MacroMatch::Repetition: { + case AST::MacroMatch::Repetition: + { // A repetition on the left hand side means we want to make sure the // last match of the repetition is compatible with the new match auto repetition diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 827d91d..4fab60f 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -17,6 +17,7 @@ along with GCC; see the file COPYING3. If not see #ifndef RUST_PARSE_H #define RUST_PARSE_H +#include "rust-ast.h" #include "rust-item.h" #include "rust-lex.h" #include "rust-ast-full.h" @@ -165,6 +166,10 @@ public: tl::optional<AST::LoopLabel> = tl::nullopt, location_t pratt_parsed_loc = UNKNOWN_LOCATION); + std::unique_ptr<AST::ConstBlock> + parse_const_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (), + location_t loc = UNKNOWN_LOCATION); + bool is_macro_rules_def (const_TokenPtr t); std::unique_ptr<AST::Item> parse_item (bool called_from_statement); std::unique_ptr<AST::Pattern> parse_pattern (); @@ -764,9 +769,9 @@ private: }; }; -std::string -extract_module_path (const AST::AttrVec &inner_attrs, - const AST::AttrVec &outer_attrs, const std::string &name); +std::string extract_module_path (const AST::AttrVec &inner_attrs, + const AST::AttrVec &outer_attrs, + const std::string &name); /** * Check if a MacroMatch is allowed to follow the last parsed MacroMatch. @@ -776,9 +781,8 @@ extract_module_path (const AST::AttrVec &inner_attrs, * * @return true if the follow-up is valid, false otherwise */ -bool -is_match_compatible (const AST::MacroMatch &last_match, - const AST::MacroMatch ¤t_match); +bool is_match_compatible (const AST::MacroMatch &last_match, + const AST::MacroMatch ¤t_match); } // namespace Rust // as now template, include implementations of all methods diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc index b781ce33..71c4c48 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ b/gcc/rust/resolve/rust-ast-resolve-base.cc @@ -232,6 +232,14 @@ ResolverBase::visit (AST::BlockExpr &) {} void +ResolverBase::visit (AST::AnonConst &) +{} + +void +ResolverBase::visit (AST::ConstBlock &) +{} + +void ResolverBase::visit (AST::ClosureExprInnerTyped &) {} diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index 5bb9e4f..e17bdcb 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -21,6 +21,7 @@ #include "rust-ast-visitor.h" #include "rust-ast.h" +#include "rust-expr.h" #include "rust-name-resolver.h" #include "rust-diagnostics.h" #include "rust-location.h" @@ -85,6 +86,8 @@ public: void visit (AST::FieldAccessExpr &); void visit (AST::ClosureExprInner &); void visit (AST::BlockExpr &); + void visit (AST::AnonConst &); + void visit (AST::ConstBlock &); void visit (AST::ClosureExprInnerTyped &); void visit (AST::ContinueExpr &); void visit (AST::BreakExpr &); diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc index 5524e18..a410193 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc @@ -315,6 +315,18 @@ ResolveExpr::visit (AST::BlockExpr &expr) } void +ResolveExpr::visit (AST::AnonConst &expr) +{ + ResolveExpr::go (expr.get_inner_expr (), prefix, canonical_prefix); +} + +void +ResolveExpr::visit (AST::ConstBlock &expr) +{ + ResolveExpr::go (expr.get_const_expr (), prefix, canonical_prefix); +} + +void translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix, const CanonicalPath &canonical_prefix) { @@ -324,38 +336,46 @@ translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix, { switch (operand.get_register_type ()) { - case RegisterType::In: { + case RegisterType::In: + { auto in = operand.get_in (); ResolveExpr::go (*in.expr, prefix, canonical_prefix); break; } - case RegisterType::Out: { + case RegisterType::Out: + { auto out = operand.get_out (); ResolveExpr::go (*out.expr, prefix, canonical_prefix); break; } - case RegisterType::InOut: { + case RegisterType::InOut: + { auto in_out = operand.get_in_out (); ResolveExpr::go (*in_out.expr, prefix, canonical_prefix); break; } - case RegisterType::SplitInOut: { + case RegisterType::SplitInOut: + { auto split_in_out = operand.get_split_in_out (); ResolveExpr::go (*split_in_out.in_expr, prefix, canonical_prefix); ResolveExpr::go (*split_in_out.out_expr, prefix, canonical_prefix); break; } - case RegisterType::Const: { + case RegisterType::Const: + { auto anon_const = operand.get_const ().anon_const; - ResolveExpr::go (*anon_const.expr, prefix, canonical_prefix); + ResolveExpr::go (anon_const.get_inner_expr (), prefix, + canonical_prefix); break; } - case RegisterType::Sym: { + case RegisterType::Sym: + { auto sym = operand.get_sym (); ResolveExpr::go (*sym.expr, prefix, canonical_prefix); break; } - case RegisterType::Label: { + case RegisterType::Label: + { auto label = operand.get_label (); ResolveExpr::go (*label.expr, prefix, canonical_prefix); break; @@ -766,7 +786,7 @@ ResolveExpr::visit (AST::ClosureExprInnerTyped &expr) resolver->push_closure_context (expr.get_node_id ()); - ResolveExpr::go (expr.get_definition_block (), prefix, canonical_prefix); + ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix); resolver->pop_closure_context (); diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index b296d66..aad1605 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -56,6 +56,8 @@ public: void visit (AST::IfLetExpr &expr) override; void visit (AST::IfLetExprConseqElse &expr) override; void visit (AST::BlockExpr &expr) override; + void visit (AST::AnonConst &expr) override; + void visit (AST::ConstBlock &expr) override; void visit (AST::InlineAsm &expr) override; void visit (AST::LlvmInlineAsm &expr) override; void visit (AST::UnsafeBlockExpr &expr) override; diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index 30f6d43..0937d65 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -608,10 +608,7 @@ ResolveItem::visit (AST::InherentImpl &impl_block) } else { - std::string seg_buf = "<impl " + self_cpath.get () + ">"; - CanonicalPath seg - = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf); - cpath = canonical_prefix.append (seg); + cpath = canonical_prefix.append (impl_type_seg); } // done setup paths @@ -732,13 +729,7 @@ ResolveItem::visit (AST::TraitImpl &impl_block) } else { - std::string projection_str = canonical_projection.get (); - std::string seg_buf - = "<impl " + projection_str.substr (1, projection_str.size () - 2) - + ">"; - CanonicalPath seg - = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf); - cpath = canonical_prefix.append (seg); + cpath = canonical_prefix.append (canonical_projection); } // DONE setup canonical-path @@ -838,29 +829,32 @@ ResolveItem::resolve_extern_item (AST::ExternalItem &item) ResolveExternItem::go (item, prefix, canonical_prefix); } -static void -flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports); -static void -flatten_rebind (const AST::UseTreeRebind &glob, std::vector<Import> &imports); -static void -flatten_list (const AST::UseTreeList &glob, std::vector<Import> &imports); +static void flatten_glob (const AST::UseTreeGlob &glob, + std::vector<Import> &imports); +static void flatten_rebind (const AST::UseTreeRebind &glob, + std::vector<Import> &imports); +static void flatten_list (const AST::UseTreeList &glob, + std::vector<Import> &imports); static void flatten (const AST::UseTree *tree, std::vector<Import> &imports) { switch (tree->get_kind ()) { - case AST::UseTree::Glob: { + case AST::UseTree::Glob: + { auto glob = static_cast<const AST::UseTreeGlob *> (tree); flatten_glob (*glob, imports); break; } - case AST::UseTree::Rebind: { + case AST::UseTree::Rebind: + { auto rebind = static_cast<const AST::UseTreeRebind *> (tree); flatten_rebind (*rebind, imports); break; } - case AST::UseTree::List: { + case AST::UseTree::List: + { auto list = static_cast<const AST::UseTreeList *> (tree); flatten_list (*list, imports); break; diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index 776dd53..d31f910 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -153,8 +153,7 @@ private: #if CHECKING_P namespace selftest { -extern void -rust_simple_path_resolve_test (void); +extern void rust_simple_path_resolve_test (void); } // namespace selftest #endif // CHECKING_P diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc index ee84be8..2b5e2bf 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc @@ -94,13 +94,15 @@ PatternDeclaration::visit (AST::TupleStructPattern &pattern) AST::TupleStructItems &items = pattern.get_items (); switch (items.get_item_type ()) { - case AST::TupleStructItems::RANGE: { + case AST::TupleStructItems::RANGE: + { // TODO rust_unreachable (); } break; - case AST::TupleStructItems::NO_RANGE: { + case AST::TupleStructItems::NO_RANGE: + { auto &items_no_range = static_cast<AST::TupleStructItemsNoRange &> (items); @@ -123,7 +125,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern) { switch (field->get_item_type ()) { - case AST::StructPatternField::ItemType::TUPLE_PAT: { + case AST::StructPatternField::ItemType::TUPLE_PAT: + { AST::StructPatternFieldTuplePat &tuple = static_cast<AST::StructPatternFieldTuplePat &> (*field); @@ -131,7 +134,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern) } break; - case AST::StructPatternField::ItemType::IDENT_PAT: { + case AST::StructPatternField::ItemType::IDENT_PAT: + { AST::StructPatternFieldIdentPat &ident = static_cast<AST::StructPatternFieldIdentPat &> (*field); @@ -139,7 +143,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern) } break; - case AST::StructPatternField::ItemType::IDENT: { + case AST::StructPatternField::ItemType::IDENT: + { auto &ident = static_cast<AST::StructPatternFieldIdent &> (*field); Mutability mut @@ -160,7 +165,8 @@ PatternDeclaration::visit (AST::TuplePattern &pattern) auto &items = pattern.get_items (); switch (items.get_pattern_type ()) { - case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: { + case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: + { auto &ref = static_cast<AST::TuplePatternItemsMultiple &> ( pattern.get_items ()); @@ -169,7 +175,8 @@ PatternDeclaration::visit (AST::TuplePattern &pattern) } break; - case AST::TuplePatternItems::TuplePatternItemType::RANGED: { + case AST::TuplePatternItems::TuplePatternItemType::RANGED: + { auto &ref = static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ()); @@ -348,14 +355,16 @@ resolve_range_pattern_bound (AST::RangePatternBound &bound) // Nothing to resolve for a literal. break; - case AST::RangePatternBound::RangePatternBoundType::PATH: { + case AST::RangePatternBound::RangePatternBoundType::PATH: + { auto &ref = static_cast<AST::RangePatternBoundPath &> (bound); ResolvePath::go (ref.get_path ()); } break; - case AST::RangePatternBound::RangePatternBoundType::QUALPATH: { + case AST::RangePatternBound::RangePatternBoundType::QUALPATH: + { auto &ref = static_cast<AST::RangePatternBoundQualPath &> (bound); ResolvePath::go (ref.get_qualified_path ()); diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc index 8fd69c3..a040228 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ b/gcc/rust/resolve/rust-ast-resolve-type.cc @@ -140,7 +140,7 @@ ResolveType::visit (AST::ImplTraitType &type) void ResolveType::visit (AST::ImplTraitTypeOneBound &type) { - ResolveTypeBound::go (type.get_trait_bound ()); + ResolveTypeBound::go (*type.get_trait_bound ().get ()); } // resolve relative type-paths @@ -210,7 +210,8 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) switch (segment->get_type ()) { - case AST::TypePathSegment::SegmentType::GENERIC: { + case AST::TypePathSegment::SegmentType::GENERIC: + { AST::TypePathSegmentGeneric *s = static_cast<AST::TypePathSegmentGeneric *> (segment.get ()); if (s->has_generic_args ()) @@ -509,7 +510,8 @@ ResolveTypeToCanonicalPath::visit (AST::TypePath &path) auto &final_seg = path.get_segments ().back (); switch (final_seg->get_type ()) { - case AST::TypePathSegment::SegmentType::GENERIC: { + case AST::TypePathSegment::SegmentType::GENERIC: + { AST::TypePathSegmentGeneric *s = static_cast<AST::TypePathSegmentGeneric *> (final_seg.get ()); @@ -651,7 +653,8 @@ ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &type) switch (additional_bound->get_bound_type ()) { - case AST::TypeParamBound::TRAIT: { + case AST::TypeParamBound::TRAIT: + { auto bound_path = CanonicalPath::create_empty (); auto &bound_type_path diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 3e3c992..2208f70 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -24,8 +24,7 @@ #include "rust-ast-resolve-expr.h" #include "rust-ast-resolve-struct-expr-field.h" -extern bool -saw_errors (void); +extern bool saw_errors (void); namespace Rust { namespace Resolver { diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 480034c..01906cf 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -25,6 +25,21 @@ namespace Rust { namespace Resolver2_0 { void +DefaultResolver::visit (AST::Crate &crate) +{ + auto inner_fn = [this, &crate] () { AST::DefaultASTVisitor::visit (crate); }; + + auto &mappings = Analysis::Mappings::get (); + + auto crate_num = mappings.lookup_crate_num (crate.get_node_id ()); + rust_assert (crate_num.has_value ()); + auto crate_name = mappings.get_crate_name (*crate_num); + rust_assert (crate_name.has_value ()); + + ctx.canonical_ctx.scope_crate (crate.get_node_id (), *crate_name, inner_fn); +} + +void DefaultResolver::visit (AST::BlockExpr &expr) { // extracting the lambda from the `scoped` call otherwise the code looks like @@ -38,19 +53,32 @@ DefaultResolver::visit (AST::BlockExpr &expr) void DefaultResolver::visit (AST::Module &module) { - auto item_fn = [this, &module] () { AST::DefaultASTVisitor::visit (module); }; + auto item_fn_1 + = [this, &module] () { AST::DefaultASTVisitor::visit (module); }; + + auto item_fn_2 = [this, &module, &item_fn_1] () { + ctx.canonical_ctx.scope (module.get_node_id (), module.get_name (), + std::move (item_fn_1)); + }; - ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn, + ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn_2, module.get_name ()); } void DefaultResolver::visit (AST::Function &function) { - auto def_fn + auto def_fn_1 = [this, &function] () { AST::DefaultASTVisitor::visit (function); }; - ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn); + auto def_fn_2 = [this, &function, &def_fn_1] () { + ctx.canonical_ctx.scope (function.get_node_id (), + function.get_function_name (), + std::move (def_fn_1)); + }; + + ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn_2, + function.get_function_name ()); } void @@ -61,73 +89,227 @@ DefaultResolver::visit (AST::ForLoopExpr &expr) } void +DefaultResolver::visit_if_let_patterns (AST::IfLetExpr &expr) +{ + for (auto &pattern : expr.get_patterns ()) + visit (pattern); +} + +void +DefaultResolver::visit (AST::IfLetExpr &expr) +{ + auto inner_vis = [this, &expr] () { + visit_if_let_patterns (expr); + visit (expr.get_if_block ()); + }; + + visit_outer_attrs (expr); + + visit (expr.get_value_expr ()); + + ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), inner_vis); +} + +void DefaultResolver::visit (AST::Trait &trait) { - auto inner_fn = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); }; + auto inner_fn_1 + = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); }; - ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn, + auto inner_fn_2 = [this, &trait, &inner_fn_1] () { + ctx.canonical_ctx.scope (trait.get_node_id (), trait.get_identifier (), + std::move (inner_fn_1)); + }; + + ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn_2, trait.get_identifier () /* FIXME: Is that valid?*/); } void DefaultResolver::visit (AST::InherentImpl &impl) { - auto inner_fn = [this, &impl] () { AST::DefaultASTVisitor::visit (impl); }; - - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn); + visit_outer_attrs (impl); + visit (impl.get_visibility ()); + visit_inner_attrs (impl); + + auto inner_fn_1 = [this, &impl] () { + for (auto &item : impl.get_impl_items ()) + visit (item); + }; + + auto inner_fn_2 = [this, &impl, &inner_fn_1] () { + maybe_insert_big_self (impl); + for (auto &generic : impl.get_generic_params ()) + visit (generic); + if (impl.has_where_clause ()) + visit (impl.get_where_clause ()); + visit_impl_type (impl.get_type ()); + + ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1); + }; + + auto inner_fn_3 = [this, &impl, &inner_fn_2] () { + ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2)); + }; + + ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3); } void DefaultResolver::visit (AST::TraitImpl &impl) { - auto inner_fn = [this, &impl] () { AST::DefaultASTVisitor::visit (impl); }; - - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn); + visit_outer_attrs (impl); + visit (impl.get_visibility ()); + visit_inner_attrs (impl); + + auto inner_fn_1 = [this, &impl] () { + for (auto &item : impl.get_impl_items ()) + visit (item); + }; + + auto inner_fn_2 = [this, &impl, &inner_fn_1] () { + maybe_insert_big_self (impl); + for (auto &generic : impl.get_generic_params ()) + visit (generic); + if (impl.has_where_clause ()) + visit (impl.get_where_clause ()); + visit_impl_type (impl.get_type ()); + visit (impl.get_trait_path ()); + + ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1); + }; + + auto inner_fn_3 = [this, &impl, &inner_fn_2] () { + ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2)); + }; + + ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3); } void DefaultResolver::visit (AST::StructStruct &type) { - auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - inner_fn, type.get_struct_name ()); + inner_fn_2, type.get_struct_name ()); } void DefaultResolver::visit (AST::TupleStruct &type) { - auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - inner_fn, type.get_struct_name ()); + inner_fn_2, type.get_struct_name ()); +} + +void +DefaultResolver::visit (AST::EnumItem &item) +{ + auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + inner_fn); +} + +void +DefaultResolver::visit (AST::EnumItemTuple &item) +{ + auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + inner_fn); +} + +void +DefaultResolver::visit (AST::EnumItemStruct &item) +{ + auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + inner_fn); +} + +void +DefaultResolver::visit (AST::EnumItemDiscriminant &item) +{ + auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + inner_fn); } void DefaultResolver::visit (AST::Enum &type) { - auto variant_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - variant_fn, type.get_identifier ()); + inner_fn_2, type.get_identifier ()); } void DefaultResolver::visit (AST::Union &type) { - auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - inner_fn, type.get_identifier ()); + inner_fn_2, type.get_identifier ()); } void DefaultResolver::visit (AST::TypeAlias &type) { - auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); }; + + auto inner_fn_2 = [this, &type, &inner_fn_1] () { + ctx.canonical_ctx.scope (type.get_node_id (), type.get_new_type_name (), + std::move (inner_fn_1)); + }; ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (), - inner_fn, type.get_new_type_name ()); + inner_fn_2, type.get_new_type_name ()); +} + +void +DefaultResolver::visit_closure_params (AST::ClosureExpr &expr) +{ + for (auto ¶m : expr.get_params ()) + visit (param); +} + +void +DefaultResolver::visit (AST::ClosureExpr &expr) +{ + auto expr_fn = [this, &expr] () { + visit_closure_params (expr); + visit (expr.get_definition_expr ()); + }; + + visit_outer_attrs (expr); + + ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), expr_fn); } void @@ -136,7 +318,7 @@ DefaultResolver::visit (AST::ClosureExprInner &expr) if (expr.is_marked_for_strip ()) return; - AST::DefaultASTVisitor::visit (expr); + visit (static_cast<AST::ClosureExpr &> (expr)); } void @@ -145,7 +327,8 @@ DefaultResolver::visit (AST::ClosureExprInnerTyped &expr) if (expr.is_marked_for_strip ()) return; - AST::DefaultASTVisitor::visit (expr); + visit (static_cast<AST::ClosureExpr &> (expr)); + visit (expr.get_return_type ()); } void @@ -162,21 +345,31 @@ DefaultResolver::visit (AST::ConstantItem &item) { if (item.has_expr ()) { - auto expr_vis + auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + auto expr_vis_2 = [this, &item, &expr_vis_1] () { + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + std::move (expr_vis_1)); + }; + // FIXME: Why do we need a Rib here? - ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis); + ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2); } } void DefaultResolver::visit (AST::StaticItem &item) { - auto expr_vis = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); }; + + auto expr_vis_2 = [this, &item, &expr_vis_1] () { + ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (), + std::move (expr_vis_1)); + }; // FIXME: Why do we need a Rib here? - ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis); + ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2); } void diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 2a987ef..99fd8e7 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -39,6 +39,7 @@ public: virtual ~DefaultResolver () {} + void visit (AST::Crate &) override; // First, our lexical scope expressions - these visit their sub nodes, always // these nodes create new scopes and ribs - they are often used to declare new // variables, such as a for loop's iterator, or a function's arguments @@ -46,7 +47,12 @@ public: void visit (AST::Module &) override; void visit (AST::Function &) override; void visit (AST::ForLoopExpr &expr) override; + virtual void visit_if_let_patterns (AST::IfLetExpr &expr); + void visit (AST::IfLetExpr &expr) override; void visit (AST::Trait &) override; + // used to handle Self insertion in TopLevel + virtual void maybe_insert_big_self (AST::Impl &) {} + virtual void visit_impl_type (AST::Type &type) { visit (type); } void visit (AST::InherentImpl &) override; void visit (AST::TraitImpl &) override; @@ -55,11 +61,17 @@ public: // type dec nodes, which visit their fields or variants by default void visit (AST::StructStruct &) override; void visit (AST::TupleStruct &) override; + void visit (AST::EnumItem &) override; + void visit (AST::EnumItemTuple &) override; + void visit (AST::EnumItemStruct &) override; + void visit (AST::EnumItemDiscriminant &) override; void visit (AST::Enum &) override; void visit (AST::Union &) override; void visit (AST::TypeAlias &) override; // Visitors that visit their expression node(s) + virtual void visit_closure_params (AST::ClosureExpr &); + virtual void visit (AST::ClosureExpr &); void visit (AST::ClosureExprInner &) override; void visit (AST::ClosureExprInnerTyped &) override; void visit (AST::MatchExpr &) override; diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 3390f09..c10379a 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -62,8 +62,9 @@ Early::go (AST::Crate &crate) // We now proceed with resolving macros, which can be nested in almost any // items textual_scope.push (); - for (auto &item : crate.items) - item->accept_vis (*this); + + visit (crate); + textual_scope.pop (); } @@ -249,7 +250,7 @@ Early::visit (AST::Module &module) void Early::visit (AST::MacroInvocation &invoc) { - auto path = invoc.get_invoc_data ().get_path (); + auto &path = invoc.get_invoc_data ().get_path (); if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin) for (auto &pending_invoc : invoc.get_pending_eager_invocations ()) @@ -272,7 +273,7 @@ Early::visit (AST::MacroInvocation &invoc) // we won't have changed `definition` from `nullopt` if there are more // than one segments in our path if (!definition.has_value ()) - definition = ctx.resolve_path (path.get_segments (), Namespace::Macros); + definition = ctx.resolve_path (path, Namespace::Macros); // if the definition still does not have a value, then it's an error if (!definition.has_value ()) @@ -314,8 +315,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs) auto traits = attr.get_traits_to_derive (); for (auto &trait : traits) { - auto definition = ctx.resolve_path (trait.get ().get_segments (), - Namespace::Macros); + auto definition + = ctx.resolve_path (trait.get (), Namespace::Macros); if (!definition.has_value ()) { // FIXME: Change to proper error message @@ -337,8 +338,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs) ->lookup_builtin (name) .is_error ()) // Do not resolve builtins { - auto definition = ctx.resolve_path (attr.get_path ().get_segments (), - Namespace::Macros); + auto definition + = ctx.resolve_path (attr.get_path (), Namespace::Macros); if (!definition.has_value ()) { // FIXME: Change to proper error message @@ -350,7 +351,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs) auto pm_def = mappings.lookup_attribute_proc_macro_def ( definition->get_node_id ()); - rust_assert (pm_def.has_value ()); + if (!pm_def.has_value ()) + return; mappings.insert_attribute_proc_macro_invocation (attr.get_path (), pm_def.value ()); @@ -419,7 +421,8 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping) declared_name = rebind.get_identifier ().as_string (); locus = rebind.get_identifier ().get_locus (); break; - case AST::UseTreeRebind::NewBindType::NONE: { + case AST::UseTreeRebind::NewBindType::NONE: + { const auto &segments = path.get_segments (); // We don't want to insert `self` with `use module::self` if (path.get_final_segment ().is_lower_self_seg ()) diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 81468e5..75dd873 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -543,6 +543,13 @@ private: Node root; }; +enum class ResolutionMode +{ + Normal, + FromRoot, + FromExtern, // extern prelude +}; + template <Namespace N> class ForeverStack { public: @@ -672,14 +679,11 @@ public: */ template <typename S> tl::optional<Rib::Definition> resolve_path ( - const std::vector<S> &segments, bool has_opening_scope_resolution, + const std::vector<S> &segments, ResolutionMode mode, std::function<void (const S &, NodeId)> insert_segment_resolution, std::vector<Error> &collect_errors); // FIXME: Documentation - tl::optional<Resolver::CanonicalPath> to_canonical_path (NodeId id) const; - - // FIXME: Documentation tl::optional<Rib &> to_rib (NodeId rib_id); tl::optional<const Rib &> to_rib (NodeId rib_id) const; @@ -739,6 +743,9 @@ private: tl::optional<Node &> parent; // `None` only if the node is a root }; + // private overload which allows specifying a starting point + tl::optional<Rib::Definition> get (Node &start, const Identifier &name); + /* Should we keep going upon seeing a Rib? */ enum class KeepGoing { diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 069111ee..8721386 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -291,12 +291,12 @@ ForeverStack<N>::update_cursor (Node &new_cursor) template <Namespace N> tl::optional<Rib::Definition> -ForeverStack<N>::get (const Identifier &name) +ForeverStack<N>::get (Node &start, const Identifier &name) { tl::optional<Rib::Definition> resolved_definition = tl::nullopt; // TODO: Can we improve the API? have `reverse_iter` return an optional? - reverse_iter ([&resolved_definition, &name] (Node ¤t) { + reverse_iter (start, [&resolved_definition, &name] (Node ¤t) { auto candidate = current.rib.get (name.as_string ()); return candidate.map_or ( @@ -320,6 +320,13 @@ ForeverStack<N>::get (const Identifier &name) template <Namespace N> tl::optional<Rib::Definition> +ForeverStack<N>::get (const Identifier &name) +{ + return get (cursor (), name); +} + +template <Namespace N> +tl::optional<Rib::Definition> ForeverStack<N>::get_lang_prelude (const Identifier &name) { return lang_prelude.rib.get (name.as_string ()); @@ -625,88 +632,118 @@ template <Namespace N> template <typename S> tl::optional<Rib::Definition> ForeverStack<N>::resolve_path ( - const std::vector<S> &segments, bool has_opening_scope_resolution, + const std::vector<S> &segments, ResolutionMode mode, std::function<void (const S &, NodeId)> insert_segment_resolution, std::vector<Error> &collect_errors) { - // TODO: What to do if segments.empty() ? + rust_assert (!segments.empty ()); - // handle paths with opening scopes - std::function<void (void)> cleanup_current = [] () {}; - if (has_opening_scope_resolution) + std::reference_wrapper<Node> starting_point = cursor (); + switch (mode) { - Node *last_current = &cursor_reference.get (); - if (get_rust_edition () == Edition::E2015) - cursor_reference = root; - else - cursor_reference = extern_prelude; - cleanup_current - = [this, last_current] () { cursor_reference = *last_current; }; + case ResolutionMode::Normal: + break; // default + case ResolutionMode::FromRoot: + starting_point = root; + break; + case ResolutionMode::FromExtern: + starting_point = extern_prelude; + break; + default: + rust_unreachable (); } // if there's only one segment, we just use `get` if (segments.size () == 1) { - auto &seg = segments.front (); - if (auto lang_item = unwrap_segment_get_lang_item (seg)) + auto &outer_seg = segments.front (); + if (auto lang_item = unwrap_segment_get_lang_item (outer_seg)) { NodeId seg_id = Analysis::Mappings::get ().get_lang_item_node ( lang_item.value ()); - insert_segment_resolution (seg, seg_id); - cleanup_current (); + insert_segment_resolution (outer_seg, seg_id); // TODO: does NonShadowable matter? return Rib::Definition::NonShadowable (seg_id); } + auto &seg = unwrap_type_segment (outer_seg); + tl::optional<Rib::Definition> res - = get (unwrap_type_segment (segments.back ()).as_string ()); + = get (starting_point.get (), seg.as_string ()); if (!res) - res = get_lang_prelude ( - unwrap_type_segment (segments.back ()).as_string ()); + res = get_lang_prelude (seg.as_string ()); + + if (!res && N == Namespace::Types) + { + if (seg.is_crate_path_seg ()) + { + insert_segment_resolution (outer_seg, root.id); + // TODO: does NonShadowable matter? + return Rib::Definition::NonShadowable (root.id); + } + else if (seg.is_lower_self_seg ()) + { + NodeId id = find_closest_module (starting_point.get ()).id; + insert_segment_resolution (outer_seg, id); + // TODO: does NonShadowable matter? + return Rib::Definition::NonShadowable (id); + } + else if (seg.is_super_path_seg ()) + { + Node &closest_module + = find_closest_module (starting_point.get ()); + if (closest_module.is_root ()) + { + rust_error_at (seg.get_locus (), ErrorCode::E0433, + "too many leading %<super%> keywords"); + return tl::nullopt; + } + + NodeId id + = find_closest_module (closest_module.parent.value ()).id; + insert_segment_resolution (outer_seg, id); + // TODO: does NonShadowable matter? + return Rib::Definition::NonShadowable (id); + } + } if (res && !res->is_ambiguous ()) - insert_segment_resolution (segments.back (), res->get_node_id ()); - cleanup_current (); + insert_segment_resolution (outer_seg, res->get_node_id ()); return res; } - std::reference_wrapper<Node> starting_point = cursor (); + return find_starting_point (segments, starting_point, + insert_segment_resolution, collect_errors) + .and_then ( + [this, &segments, &starting_point, &insert_segment_resolution, + &collect_errors] (typename std::vector<S>::const_iterator iterator) { + return resolve_segments (starting_point.get (), segments, iterator, + insert_segment_resolution, collect_errors); + }) + .and_then ([this, &segments, &insert_segment_resolution] ( + Node &final_node) -> tl::optional<Rib::Definition> { + // leave resolution within impl blocks to type checker + if (final_node.rib.kind == Rib::Kind::TraitOrImpl) + return tl::nullopt; - auto res - = find_starting_point (segments, starting_point, insert_segment_resolution, - collect_errors) - .and_then ( - [this, &segments, &starting_point, &insert_segment_resolution, - &collect_errors] (typename std::vector<S>::const_iterator iterator) { - return resolve_segments (starting_point.get (), segments, iterator, - insert_segment_resolution, collect_errors); - }) - .and_then ([this, &segments, &insert_segment_resolution] ( - Node &final_node) -> tl::optional<Rib::Definition> { - // leave resolution within impl blocks to type checker - if (final_node.rib.kind == Rib::Kind::TraitOrImpl) - return tl::nullopt; - - auto &seg = unwrap_type_segment (segments.back ()); - std::string seg_name = seg.as_string (); - - // assuming this can't be a lang item segment - tl::optional<Rib::Definition> res - = resolve_final_segment (final_node, seg_name, - seg.is_lower_self_seg ()); - // Ok we didn't find it in the rib, Lets try the prelude... - if (!res) - res = get_lang_prelude (seg_name); - - if (res && !res->is_ambiguous ()) - insert_segment_resolution (segments.back (), res->get_node_id ()); - - return res; - }); - cleanup_current (); - return res; + auto &seg = unwrap_type_segment (segments.back ()); + std::string seg_name = seg.as_string (); + + // assuming this can't be a lang item segment + tl::optional<Rib::Definition> res + = resolve_final_segment (final_node, seg_name, + seg.is_lower_self_seg ()); + // Ok we didn't find it in the rib, Lets try the prelude... + if (!res) + res = get_lang_prelude (seg_name); + + if (res && !res->is_ambiguous ()) + insert_segment_resolution (segments.back (), res->get_node_id ()); + + return res; + }); } template <Namespace N> @@ -771,67 +808,6 @@ ForeverStack<N>::dfs (const ForeverStack<N>::Node &starting_point, } template <Namespace N> -tl::optional<Resolver::CanonicalPath> -ForeverStack<N>::to_canonical_path (NodeId id) const -{ - // find the id in the current forever stack, starting from the root, - // performing either a BFS or DFS once the Node containing the ID is found, go - // back up to the root (parent().parent().parent()...) accumulate link - // segments reverse them that's your canonical path - - return dfs (root, id).map ([this, id] (ConstDfsResult tuple) { - auto containing_node = tuple.first; - auto name = tuple.second; - - auto segments = std::vector<Resolver::CanonicalPath> (); - - reverse_iter (containing_node, [&segments] (const Node ¤t) { - if (current.is_root ()) - return KeepGoing::No; - - auto children = current.parent.value ().children; - const Link *outer_link = nullptr; - - for (auto &kv : children) - { - auto &link = kv.first; - auto &child = kv.second; - - if (current.id == child.id) - { - outer_link = &link; - break; - } - } - - rust_assert (outer_link); - - outer_link->path.map ([&segments, outer_link] (Identifier path) { - segments.emplace (segments.begin (), - Resolver::CanonicalPath::new_seg (outer_link->id, - path.as_string ())); - }); - - return KeepGoing::Yes; - }); - - auto &mappings = Analysis::Mappings::get (); - CrateNum crate_num = mappings.lookup_crate_num (root.id).value (); - auto path = Resolver::CanonicalPath::new_seg ( - root.id, mappings.get_crate_name (crate_num).value ()); - path.set_crate_num (crate_num); - - for (const auto &segment : segments) - path = path.append (segment); - - // Finally, append the name - path = path.append (Resolver::CanonicalPath::new_seg (id, name)); - - return path; - }); -} - -template <Namespace N> tl::optional<Rib &> ForeverStack<N>::dfs_rib (ForeverStack<N>::Node &starting_point, NodeId to_find) { diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index a15e17f..62829e0 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -33,7 +33,9 @@ namespace Rust { namespace Resolver2_0 { -Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {} +Late::Late (NameResolutionContext &ctx) + : DefaultResolver (ctx), funny_error (false), block_big_self (false) +{} static NodeId next_node_id () @@ -114,8 +116,7 @@ Late::go (AST::Crate &crate) { setup_builtin_types (); - for (auto &item : crate.items) - item->accept_vis (*this); + visit (crate); } void @@ -145,19 +146,13 @@ Late::visit (AST::ForLoopExpr &expr) } void -Late::visit (AST::IfLetExpr &expr) +Late::visit_if_let_patterns (AST::IfLetExpr &expr) { - visit_outer_attrs (expr); + ctx.bindings.enter (BindingSource::IfLet); - ctx.bindings.enter (BindingSource::Let); - - for (auto &pattern : expr.get_patterns ()) - visit (pattern); + DefaultResolver::visit_if_let_patterns (expr); ctx.bindings.exit (); - - visit (expr.get_value_expr ()); - visit (expr.get_if_block ()); } void @@ -213,46 +208,55 @@ Late::visit (AST::LetStmt &let) // let.get_node_id (), [] () {}); } -void -Late::visit (AST::IdentifierPattern &identifier) +static void +visit_identifier_as_pattern (NameResolutionContext &ctx, + const Identifier &ident, location_t locus, + NodeId node_id) { // do we insert in labels or in values // but values does not allow shadowing... since functions cannot shadow // do we insert functions in labels as well? - if (ctx.bindings.peek ().is_and_bound (identifier.get_ident ())) + if (ctx.bindings.peek ().is_and_bound (ident)) { if (ctx.bindings.peek ().get_source () == BindingSource::Param) rust_error_at ( - identifier.get_locus (), ErrorCode::E0415, + locus, ErrorCode::E0415, "identifier %qs is bound more than once in the same parameter list", - identifier.as_string ().c_str ()); + ident.as_string ().c_str ()); else rust_error_at ( - identifier.get_locus (), ErrorCode::E0416, + locus, ErrorCode::E0416, "identifier %qs is bound more than once in the same pattern", - identifier.as_string ().c_str ()); + ident.as_string ().c_str ()); return; } - ctx.bindings.peek ().insert_ident (identifier.get_ident ()); + ctx.bindings.peek ().insert_ident (ident); - if (ctx.bindings.peek ().is_or_bound (identifier.get_ident ())) + if (ctx.bindings.peek ().is_or_bound (ident)) { - // FIXME: map usage instead - std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), - identifier.get_node_id ()); + auto res = ctx.values.get (ident); + rust_assert (res.has_value () && !res->is_ambiguous ()); + ctx.map_usage (Usage (node_id), Definition (res->get_node_id ())); } else { // We do want to ignore duplicated data because some situations rely on // it. - std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), - identifier.get_node_id ()); + std::ignore = ctx.values.insert_shadowable (ident, node_id); } } void +Late::visit (AST::IdentifierPattern &identifier) +{ + visit_identifier_as_pattern (ctx, identifier.get_ident (), + identifier.get_locus (), + identifier.get_node_id ()); +} + +void Late::visit (AST::AltPattern &pattern) { ctx.bindings.peek ().push (Binding::Kind::Or); @@ -279,9 +283,8 @@ Late::visit_function_params (AST::Function &function) void Late::visit (AST::StructPatternFieldIdent &field) { - // We do want to ignore duplicated data because some situations rely on it. - std::ignore = ctx.values.insert_shadowable (field.get_identifier (), - field.get_node_id ()); + visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (), + field.get_node_id ()); } void @@ -375,7 +378,8 @@ Late::visit (AST::IdentifierExpr &expr) } else if (funny_error) { - diagnostics::text_finalizer (global_dc) = Resolver::funny_ice_text_finalizer; + diagnostics::text_finalizer (global_dc) + = Resolver::funny_ice_text_finalizer; emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1, "are you trying to break %s? how dare you?", expr.as_string ().c_str ()); @@ -477,6 +481,16 @@ Late::visit (AST::PathInExpression &expr) } void +Late::visit_impl_type (AST::Type &type) +{ + // TODO: does this have to handle reentrancy? + rust_assert (!block_big_self); + block_big_self = true; + visit (type); + block_big_self = false; +} + +void Late::visit (AST::TypePath &type) { // should we add type path resolution in `ForeverStack` directly? Since it's @@ -486,6 +500,16 @@ Late::visit (AST::TypePath &type) DefaultResolver::visit (type); + // prevent "impl Self {}" and similar + if (type.get_segments ().size () == 1 + && !type.get_segments ().front ()->is_lang_item () + && type.get_segments ().front ()->is_big_self_seg () && block_big_self) + { + rust_error_at (type.get_locus (), + "%<Self%> is not valid in the self type of an impl block"); + return; + } + // this *should* mostly work // TODO: make sure typepath-like path resolution (?) is working auto resolved = ctx.resolve_path (type, Namespace::Types); @@ -493,15 +517,16 @@ Late::visit (AST::TypePath &type) if (!resolved.has_value ()) { if (!ctx.lookup (type.get_segments ().front ()->get_node_id ())) - rust_error_at (type.get_locus (), "could not resolve type path %qs", - type.as_string ().c_str ()); + rust_error_at (type.get_locus (), ErrorCode::E0412, + "could not resolve type path %qs", + type.make_debug_string ().c_str ()); return; } if (resolved->is_ambiguous ()) { rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous", - type.as_string ().c_str ()); + type.make_debug_string ().c_str ()); return; } @@ -518,6 +543,62 @@ Late::visit (AST::TypePath &type) } void +Late::visit (AST::Visibility &vis) +{ + if (!vis.has_path ()) + return; + + AST::SimplePath &path = vis.get_path (); + + rust_assert (path.get_segments ().size ()); + auto &first_seg = path.get_segments ()[0]; + + auto mode = ResolutionMode::Normal; + + if (path.has_opening_scope_resolution ()) + { + if (get_rust_edition () == Edition::E2015) + mode = ResolutionMode::FromRoot; + else + mode = ResolutionMode::FromExtern; + } + else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg () + && !first_seg.is_lower_self_seg ()) + { + if (get_rust_edition () == Edition::E2015) + { + mode = ResolutionMode::FromRoot; + } + else + { + rust_error_at (path.get_locus (), + "relative paths are not supported in visibilities in " + "2018 edition or later"); + return; + } + } + + auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types); + + if (!res.has_value ()) + { + rust_error_at (path.get_locus (), ErrorCode::E0433, + "could not resolve path %qs", path.as_string ().c_str ()); + return; + } + + // TODO: is this possible? + if (res->is_ambiguous ()) + { + rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous", + path.as_string ().c_str ()); + return; + } + + ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id ())); +} + +void Late::visit (AST::Trait &trait) { // kind of weird how this is done @@ -613,51 +694,27 @@ Late::visit (AST::GenericArg &arg) DefaultResolver::visit (arg); } -template <class Closure> -static void -add_captures (Closure &closure, NameResolutionContext &ctx) -{ - auto vals = ctx.values.peek ().get_values (); - for (auto &val : vals) - { - ctx.mappings.add_capture (closure.get_node_id (), - val.second.get_node_id ()); - } -} - void -Late::visit (AST::ClosureExprInner &closure) +Late::visit_closure_params (AST::ClosureExpr &closure) { - add_captures (closure, ctx); - - visit_outer_attrs (closure); - ctx.bindings.enter (BindingSource::Param); - for (auto ¶m : closure.get_params ()) - visit (param); + DefaultResolver::visit_closure_params (closure); ctx.bindings.exit (); - - visit (closure.get_definition_expr ()); } void -Late::visit (AST::ClosureExprInnerTyped &closure) +Late::visit (AST::ClosureExpr &expr) { - add_captures (closure, ctx); - - visit_outer_attrs (closure); - - ctx.bindings.enter (BindingSource::Param); - - for (auto ¶m : closure.get_params ()) - visit (param); - - ctx.bindings.exit (); + // add captures + auto vals = ctx.values.peek ().get_values (); + for (auto &val : vals) + { + ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ()); + } - visit (closure.get_return_type ()); - visit (closure.get_definition_block ()); + DefaultResolver::visit (expr); } } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 171d9bf..f2907c9 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -50,7 +50,7 @@ public: void visit (AST::SelfParam &) override; void visit (AST::MatchArm &) override; void visit (AST::ForLoopExpr &) override; - void visit (AST::IfLetExpr &) override; + void visit_if_let_patterns (AST::IfLetExpr &) override; // resolutions void visit (AST::IdentifierExpr &) override; @@ -59,7 +59,9 @@ public: void visit (AST::ContinueExpr &) override; void visit (AST::LoopLabel &) override; void visit (AST::PathInExpression &) override; + void visit_impl_type (AST::Type &) override; void visit (AST::TypePath &) override; + void visit (AST::Visibility &) override; void visit (AST::Trait &) override; void visit (AST::StructExprStruct &) override; void visit (AST::StructExprStructBase &) override; @@ -67,8 +69,8 @@ public: void visit (AST::StructStruct &) override; void visit (AST::GenericArgs &) override; void visit (AST::GenericArg &); - void visit (AST::ClosureExprInner &) override; - void visit (AST::ClosureExprInnerTyped &) override; + void visit_closure_params (AST::ClosureExpr &) override; + void visit (AST::ClosureExpr &) override; private: void resolve_label (AST::Lifetime &lifetime); @@ -77,6 +79,9 @@ private: void setup_builtin_types (); bool funny_error; + + /* used to prevent "impl Self {}", "impl (Self, i32) {}", etc */ + bool block_big_self; }; // TODO: Add missing mappings and data structures diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc index f098e48..34615ed 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -82,8 +82,63 @@ BindingLayer::get_source () const return source; } +Resolver::CanonicalPath +CanonicalPathRecordCrateRoot::as_path (const NameResolutionContext &) +{ + auto ret = Resolver::CanonicalPath::new_seg (node_id, seg); + ret.set_crate_num (crate_num); + return ret; +} + +Resolver::CanonicalPath +CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx) +{ + auto parent_path = get_parent ().as_path (ctx); + return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg)); +} + +Resolver::CanonicalPath +CanonicalPathRecordLookup::as_path (const NameResolutionContext &ctx) +{ + if (!cache) + { + auto res = ctx.lookup (lookup_id).and_then ( + [&ctx] (NodeId id) { return ctx.canonical_ctx.get_record_opt (id); }); + + if (!res) + { + // HACK: use a dummy value + // this should bring us roughly to parity with nr1.0 + // since nr1.0 doesn't seem to handle canonical paths for generics + // quite right anyways + return Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "XXX"); + } + + cache = res.value (); + } + return cache->as_path (ctx); +} + +Resolver::CanonicalPath +CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx) +{ + auto parent_path = get_parent ().as_path (ctx); + return parent_path.append ( + Resolver::CanonicalPath::inherent_impl_seg (impl_id, + type_record.as_path (ctx))); +} + +Resolver::CanonicalPath +CanonicalPathRecordTraitImpl::as_path (const NameResolutionContext &ctx) +{ + auto parent_path = get_parent ().as_path (ctx); + return parent_path.append ( + Resolver::CanonicalPath::trait_impl_projection_seg ( + impl_id, trait_path_record.as_path (ctx), type_record.as_path (ctx))); +} + NameResolutionContext::NameResolutionContext () - : mappings (Analysis::Mappings::get ()) + : mappings (Analysis::Mappings::get ()), canonical_ctx (*this) {} tl::expected<NodeId, DuplicateNameError> diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index 19ba750..bb8519a 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -24,6 +24,7 @@ #include "rust-hir-map.h" #include "rust-rib.h" #include "rust-stacked-contexts.h" +#include "rust-item.h" namespace Rust { namespace Resolver2_0 { @@ -177,6 +178,7 @@ enum class BindingSource { Match, Let, + IfLet, For, /* Closure param or function param */ Param @@ -213,6 +215,248 @@ public: BindingSource get_source () const; }; +class NameResolutionContext; +/* + * Used to handle canonical paths + * Similar to ForeverStack, but namespace independent and more specialized + */ +class CanonicalPathRecord +{ +public: + virtual Resolver::CanonicalPath as_path (const NameResolutionContext &) = 0; + + virtual bool is_root () const = 0; + + virtual ~CanonicalPathRecord () = default; +}; + +class CanonicalPathRecordWithParent : public CanonicalPathRecord +{ +public: + CanonicalPathRecordWithParent (CanonicalPathRecord &parent) : parent (&parent) + {} + + CanonicalPathRecord &get_parent () { return *parent; } + + bool is_root () const override final { return false; } + +private: + CanonicalPathRecord *parent; +}; + +class CanonicalPathRecordCrateRoot : public CanonicalPathRecord +{ +public: + CanonicalPathRecordCrateRoot (NodeId node_id, std::string seg) + : node_id (node_id), seg (std::move (seg)) + { + rust_assert (Analysis::Mappings::get ().node_is_crate (node_id)); + crate_num = Analysis::Mappings::get ().lookup_crate_num (node_id).value (); + } + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + + bool is_root () const override final { return true; } + +private: + NodeId node_id; + CrateNum crate_num; + std::string seg; +}; + +class CanonicalPathRecordNormal : public CanonicalPathRecordWithParent +{ +public: + CanonicalPathRecordNormal (CanonicalPathRecord &parent, NodeId node_id, + std::string seg) + : CanonicalPathRecordWithParent (parent), node_id (node_id), + seg (std::move (seg)) + { + rust_assert (!Analysis::Mappings::get ().node_is_crate (node_id)); + } + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + +private: + NodeId node_id; + std::string seg; +}; + +class CanonicalPathRecordLookup : public CanonicalPathRecord +{ +public: + CanonicalPathRecordLookup (NodeId lookup_id) + : lookup_id (lookup_id), cache (nullptr) + {} + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + + bool is_root () const override final { return true; } + +private: + NodeId lookup_id; + CanonicalPathRecord *cache; +}; + +class CanonicalPathRecordImpl : public CanonicalPathRecordWithParent +{ +public: + CanonicalPathRecordImpl (CanonicalPathRecord &parent, NodeId impl_id, + NodeId type_id) + : CanonicalPathRecordWithParent (parent), impl_id (impl_id), + type_record (type_id) + {} + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + +private: + NodeId impl_id; + CanonicalPathRecordLookup type_record; +}; + +class CanonicalPathRecordTraitImpl : public CanonicalPathRecordWithParent +{ +public: + CanonicalPathRecordTraitImpl (CanonicalPathRecord &parent, NodeId impl_id, + NodeId type_id, NodeId trait_path_id) + : CanonicalPathRecordWithParent (parent), impl_id (impl_id), + type_record (type_id), trait_path_record (trait_path_id) + {} + + Resolver::CanonicalPath as_path (const NameResolutionContext &) override; + +private: + NodeId impl_id; + CanonicalPathRecordLookup type_record; + CanonicalPathRecordLookup trait_path_record; +}; + +class CanonicalPathCtx +{ +public: + CanonicalPathCtx (const NameResolutionContext &ctx) + : current_record (nullptr), nr_ctx (&ctx) + {} + + Resolver::CanonicalPath get_path (NodeId id) const + { + return get_record (id).as_path (*nr_ctx); + } + + CanonicalPathRecord &get_record (NodeId id) const + { + auto it = records.find (id); + rust_assert (it != records.end ()); + return *it->second; + } + + tl::optional<CanonicalPathRecord *> get_record_opt (NodeId id) const + { + auto it = records.find (id); + if (it == records.end ()) + return tl::nullopt; + else + return it->second.get (); + } + + void insert_record (NodeId id, const Identifier &ident) + { + insert_record (id, ident.as_string ()); + } + + void insert_record (NodeId id, std::string seg) + { + rust_assert (current_record != nullptr); + + auto it = records.find (id); + if (it == records.end ()) + { + auto record = new CanonicalPathRecordNormal (*current_record, id, + std::move (seg)); + bool ok + = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record)) + .second; + rust_assert (ok); + } + } + + template <typename F> void scope (NodeId id, const Identifier &ident, F &&f) + { + scope (id, ident.as_string (), std::forward<F> (f)); + } + + template <typename F> void scope (NodeId id, std::string seg, F &&f) + { + rust_assert (current_record != nullptr); + + scope_inner (id, std::forward<F> (f), [this, id, &seg] () { + return new CanonicalPathRecordNormal (*current_record, id, + std::move (seg)); + }); + } + + template <typename F> void scope_impl (AST::InherentImpl &impl, F &&f) + { + rust_assert (current_record != nullptr); + + NodeId id = impl.get_node_id (); + scope_inner (id, std::forward<F> (f), [this, id, &impl] () { + return new CanonicalPathRecordImpl (*current_record, id, + impl.get_type ().get_node_id ()); + }); + } + + template <typename F> void scope_impl (AST::TraitImpl &impl, F &&f) + { + rust_assert (current_record != nullptr); + + NodeId id = impl.get_node_id (); + scope_inner (id, std::forward<F> (f), [this, id, &impl] () { + return new CanonicalPathRecordTraitImpl ( + *current_record, id, impl.get_type ().get_node_id (), + impl.get_trait_path ().get_node_id ()); + }); + } + + template <typename F> + void scope_crate (NodeId node_id, std::string crate_name, F &&f) + { + scope_inner (node_id, std::forward<F> (f), [node_id, &crate_name] () { + return new CanonicalPathRecordCrateRoot (node_id, std::move (crate_name)); + }); + } + +private: + template <typename FCreate, typename FCallback> + void scope_inner (NodeId id, FCallback &&f_callback, FCreate &&f_create) + { + auto it = records.find (id); + if (it == records.end ()) + { + CanonicalPathRecord *record = std::forward<FCreate> (f_create) (); + it = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record)) + .first; + } + + rust_assert (it->second->is_root () + || &static_cast<CanonicalPathRecordWithParent &> (*it->second) + .get_parent () + == current_record); + + CanonicalPathRecord *stash = it->second.get (); + std::swap (stash, current_record); + + std::forward<FCallback> (f_callback) (); + + std::swap (stash, current_record); + } + + std::unordered_map<NodeId, std::unique_ptr<CanonicalPathRecord>> records; + CanonicalPathRecord *current_record; + + const NameResolutionContext *nr_ctx; +}; + // Now our resolver, which keeps track of all the `ForeverStack`s we could want class NameResolutionContext { @@ -271,16 +515,22 @@ public: Analysis::Mappings &mappings; StackedContexts<BindingLayer> bindings; + CanonicalPathCtx canonical_ctx; + // TODO: Rename // TODO: Use newtype pattern for Usage and Definition void map_usage (Usage usage, Definition definition); tl::optional<NodeId> lookup (NodeId usage) const; + Resolver::CanonicalPath to_canonical_path (NodeId id) const + { + return canonical_ctx.get_path (id); + } + template <typename S> tl::optional<Rib::Definition> - resolve_path (const std::vector<S> &segments, - bool has_opening_scope_resolution, + resolve_path (const std::vector<S> &segments, ResolutionMode mode, std::vector<Error> &collect_errors, Namespace ns) { std::function<void (const S &, NodeId)> insert_segment_resolution @@ -292,17 +542,17 @@ public: switch (ns) { case Namespace::Values: - return values.resolve_path (segments, has_opening_scope_resolution, - insert_segment_resolution, collect_errors); + return values.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); case Namespace::Types: - return types.resolve_path (segments, has_opening_scope_resolution, - insert_segment_resolution, collect_errors); + return types.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); case Namespace::Macros: - return macros.resolve_path (segments, has_opening_scope_resolution, - insert_segment_resolution, collect_errors); + return macros.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); case Namespace::Labels: - return labels.resolve_path (segments, has_opening_scope_resolution, - insert_segment_resolution, collect_errors); + return labels.resolve_path (segments, mode, insert_segment_resolution, + collect_errors); default: rust_unreachable (); } @@ -310,8 +560,7 @@ public: template <typename S, typename... Args> tl::optional<Rib::Definition> - resolve_path (const std::vector<S> &segments, - bool has_opening_scope_resolution, + resolve_path (const std::vector<S> &segments, ResolutionMode mode, tl::optional<std::vector<Error> &> collect_errors, Namespace ns_first, Args... ns_args) { @@ -320,8 +569,7 @@ public: for (auto ns : namespaces) { std::vector<Error> collect_errors_inner; - if (auto ret = resolve_path (segments, has_opening_scope_resolution, - collect_errors_inner, ns)) + if (auto ret = resolve_path (segments, mode, collect_errors_inner, ns)) return ret; if (!collect_errors_inner.empty ()) { @@ -343,52 +591,68 @@ public: return tl::nullopt; } - template <typename... Args> + template <typename S, typename... Args> tl::optional<Rib::Definition> - resolve_path (const AST::SimplePath &path, + resolve_path (const std::vector<S> &path_segments, + bool has_opening_scope_resolution, tl::optional<std::vector<Error> &> collect_errors, Namespace ns_first, Args... ns_args) { - return resolve_path (path.get_segments (), - path.has_opening_scope_resolution (), collect_errors, - ns_first, ns_args...); + auto mode = ResolutionMode::Normal; + if (has_opening_scope_resolution) + { + if (get_rust_edition () == Edition::E2015) + mode = ResolutionMode::FromRoot; + else + mode = ResolutionMode::FromExtern; + } + return resolve_path (path_segments, mode, collect_errors, ns_first, + ns_args...); } - template <typename... Args> + template <typename S, typename... Args> tl::optional<Rib::Definition> - resolve_path (const AST::PathInExpression &path, - tl::optional<std::vector<Error> &> collect_errors, - Namespace ns_first, Args... ns_args) + resolve_path (const std::vector<S> &path_segments, + bool has_opening_scope_resolution, Namespace ns_first, + Args... ns_args) { - return resolve_path (path.get_segments (), path.opening_scope_resolution (), - collect_errors, ns_first, ns_args...); + return resolve_path (path_segments, has_opening_scope_resolution, + tl::nullopt, ns_first, ns_args...); } - template <typename... Args> + template <typename S, typename... Args> tl::optional<Rib::Definition> - resolve_path (const AST::TypePath &path, - tl::optional<std::vector<Error> &> collect_errors, + resolve_path (const std::vector<S> &path_segments, ResolutionMode mode, Namespace ns_first, Args... ns_args) { + return resolve_path (path_segments, mode, tl::nullopt, ns_first, + ns_args...); + } + + template <typename... Args> + tl::optional<Rib::Definition> resolve_path (const AST::SimplePath &path, + Args &&...args) + { return resolve_path (path.get_segments (), - path.has_opening_scope_resolution_op (), - collect_errors, ns_first, ns_args...); + path.has_opening_scope_resolution (), + std::forward<Args> (args)...); } - template <typename P, typename... Args> - tl::optional<Rib::Definition> resolve_path (const P &path, Namespace ns_first, - Args... ns_args) + template <typename... Args> + tl::optional<Rib::Definition> resolve_path (const AST::PathInExpression &path, + Args &&...args) { - return resolve_path (path, tl::nullopt, ns_first, ns_args...); + return resolve_path (path.get_segments (), path.opening_scope_resolution (), + std::forward<Args> (args)...); } - template <typename P, typename... Args> - tl::optional<Rib::Definition> - resolve_path (const P &path_segments, bool has_opening_scope_resolution, - Namespace ns_first, Args... ns_args) + template <typename... Args> + tl::optional<Rib::Definition> resolve_path (const AST::TypePath &path, + Args &&...args) { - return resolve_path (path_segments, has_opening_scope_resolution, - tl::nullopt, ns_first, ns_args...); + return resolve_path (path.get_segments (), + path.has_opening_scope_resolution_op (), + std::forward<Args> (args)...); } private: diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h index c498328..140c991 100644 --- a/gcc/rust/resolve/rust-rib.h +++ b/gcc/rust/resolve/rust-rib.h @@ -188,6 +188,8 @@ public: * restriction that you cannot `use` items from the Prelude */ Prelude, + /* Generic rib, used to store generics */ + Generics, } kind; static std::string kind_to_string (Rib::Kind kind) @@ -214,9 +216,13 @@ public: return "Forward type param ban"; case Rib::Kind::ConstParamType: return "Const Param Type"; - default: - rust_unreachable (); + case Kind::Prelude: + return "Prelude"; + case Kind::Generics: + return "Generics"; } + + rust_unreachable (); } Rib (Kind kind); diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index 2f036fe..3e5ed53 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -95,8 +95,7 @@ TopLevel::go (AST::Crate &crate) // times in a row in a fixed-point fashion, so it would make the code // responsible for this ugly and perfom a lot of error checking. - for (auto &item : crate.items) - item->accept_vis (*this); + visit (crate); } void @@ -141,33 +140,10 @@ TopLevel::visit (AST::Trait &trait) } void -TopLevel::visit (AST::InherentImpl &impl) +TopLevel::maybe_insert_big_self (AST::Impl &impl) { - auto inner_fn = [this, &impl] () { - insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()), - impl.get_type (), Namespace::Types); - - // We do want to visit with the default visitor instead of default resolver - // because we don't want to insert the scope twice. - AST::DefaultASTVisitor::visit (impl); - }; - - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn); -} - -void -TopLevel::visit (AST::TraitImpl &impl) -{ - auto inner_fn = [this, &impl] () { - insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()), - impl.get_type (), Namespace::Types); - - // We do want to visit using the default visitor instead of default resolver - // because we don't want to insert the scope twice. - AST::DefaultASTVisitor::visit (impl); - }; - - ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn); + insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()), + impl.get_type (), Namespace::Types); } void @@ -217,7 +193,7 @@ TopLevel::visit (AST::ExternCrate &crate) auto derive_macros = mappings.lookup_derive_proc_macros (num); - auto sub_visitor = [&] () { + auto sub_visitor_1 = [&] () { // TODO: Find a way to keep this part clean without the double dispatch. if (derive_macros.has_value ()) { @@ -239,11 +215,17 @@ TopLevel::visit (AST::ExternCrate &crate) } }; + auto sub_visitor_2 = [&] () { + ctx.canonical_ctx.scope_crate (crate.get_node_id (), + crate.get_referenced_crate (), + std::move (sub_visitor_1)); + }; + if (crate.has_as_clause ()) - ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor, + ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor_2, crate.get_as_clause ()); else - ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor, + ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor_2, crate.get_referenced_crate ()); } @@ -321,14 +303,7 @@ TopLevel::visit (AST::ExternalStaticItem &static_item) void TopLevel::visit (AST::StructStruct &struct_item) { - auto generic_vis = [this, &struct_item] () { - for (auto &g : struct_item.get_generic_params ()) - { - g->accept_vis (*this); - } - }; - - ctx.scoped (Rib::Kind::Item, struct_item.get_node_id (), generic_vis); + DefaultResolver::visit (struct_item); insert_or_error_out (struct_item.get_struct_name (), struct_item, Namespace::Types); @@ -374,24 +349,32 @@ void TopLevel::visit (AST::EnumItem &variant) { insert_enum_variant_or_error_out (variant.get_identifier (), variant); + + DefaultResolver::visit (variant); } void TopLevel::visit (AST::EnumItemTuple &variant) { insert_enum_variant_or_error_out (variant.get_identifier (), variant); + + DefaultResolver::visit (variant); } void TopLevel::visit (AST::EnumItemStruct &variant) { insert_enum_variant_or_error_out (variant.get_identifier (), variant); + + DefaultResolver::visit (variant); } void TopLevel::visit (AST::EnumItemDiscriminant &variant) { insert_or_error_out (variant.get_identifier (), variant, Namespace::Types); + + DefaultResolver::visit (variant); } void @@ -430,21 +413,18 @@ TopLevel::visit (AST::TypeAlias &type_item) DefaultResolver::visit (type_item); } -static void -flatten_rebind ( +static void flatten_rebind ( const AST::UseTreeRebind &glob, std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths); -static void -flatten_list ( +static void flatten_list ( const AST::UseTreeList &glob, std::vector<AST::SimplePath> &paths, std::vector<AST::SimplePath> &glob_paths, std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths, NameResolutionContext &ctx); -static void -flatten_glob (const AST::UseTreeGlob &glob, - std::vector<AST::SimplePath> &glob_paths, - NameResolutionContext &ctx); +static void flatten_glob (const AST::UseTreeGlob &glob, + std::vector<AST::SimplePath> &glob_paths, + NameResolutionContext &ctx); static void flatten ( @@ -455,17 +435,20 @@ flatten ( { switch (tree->get_kind ()) { - case AST::UseTree::Rebind: { + case AST::UseTree::Rebind: + { auto rebind = static_cast<const AST::UseTreeRebind *> (tree); flatten_rebind (*rebind, rebind_paths); break; } - case AST::UseTree::List: { + case AST::UseTree::List: + { auto list = static_cast<const AST::UseTreeList *> (tree); flatten_list (*list, paths, glob_paths, rebind_paths, ctx); break; } - case AST::UseTree::Glob: { + case AST::UseTree::Glob: + { auto glob = static_cast<const AST::UseTreeGlob *> (tree); flatten_glob (*glob, glob_paths, ctx); break; diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h index 3ff37ed..0dfd654 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -160,8 +160,7 @@ private: void visit (AST::Module &module) override; void visit (AST::Trait &trait) override; - void visit (AST::InherentImpl &impl) override; - void visit (AST::TraitImpl &impl) override; + void maybe_insert_big_self (AST::Impl &impl) override; void visit (AST::TraitItemType &trait_item) override; void visit (AST::MacroRulesDefinition ¯o) override; void visit (AST::Function &function) override; diff --git a/gcc/rust/rust-attribs.cc b/gcc/rust/rust-attribs.cc index 74cb2af..a98c1fa 100644 --- a/gcc/rust/rust-attribs.cc +++ b/gcc/rust/rust-attribs.cc @@ -38,35 +38,27 @@ along with GCC; see the file COPYING3. If not see * future. */ -extern const attribute_spec grs_langhook_common_attribute_table[]; +extern const struct scoped_attribute_specs grs_langhook_gnu_attribute_table; +extern const struct scoped_attribute_specs grs_langhook_common_attribute_table; /* Internal attribute handlers for built-in functions. */ -static tree -handle_noreturn_attribute (tree *, tree, tree, int, bool *); -static tree -handle_leaf_attribute (tree *, tree, tree, int, bool *); -static tree -handle_const_attribute (tree *, tree, tree, int, bool *); -static tree -handle_malloc_attribute (tree *, tree, tree, int, bool *); -static tree -handle_pure_attribute (tree *, tree, tree, int, bool *); -static tree -handle_novops_attribute (tree *, tree, tree, int, bool *); -static tree -handle_nonnull_attribute (tree *, tree, tree, int, bool *); -static tree -handle_nothrow_attribute (tree *, tree, tree, int, bool *); -static tree -handle_type_generic_attribute (tree *, tree, tree, int, bool *); -static tree -handle_transaction_pure_attribute (tree *, tree, tree, int, bool *); -static tree -handle_returns_twice_attribute (tree *, tree, tree, int, bool *); -static tree -handle_fnspec_attribute (tree *, tree, tree, int, bool *); -static tree -handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); +static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); +static tree handle_leaf_attribute (tree *, tree, tree, int, bool *); +static tree handle_const_attribute (tree *, tree, tree, int, bool *); +static tree handle_malloc_attribute (tree *, tree, tree, int, bool *); +static tree handle_pure_attribute (tree *, tree, tree, int, bool *); +static tree handle_novops_attribute (tree *, tree, tree, int, bool *); +static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); +static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *); +static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); +static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *); +static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *); +static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *); +static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); + +/* Rust attribute handlers for user defined attributes. */ +static tree handle_cold_attribute (tree *, tree, tree, int, bool *); +static tree handle_hot_attribute (tree *, tree, tree, int, bool *); /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ @@ -74,6 +66,10 @@ handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); name, function, type, variable \ } +// clang-format off +// Disabling clang-format because it insists in having several ATTR_EXCL() on a +// single line. + static const struct attribute_spec::exclusions attr_noreturn_exclusions[] = { // ATTR_EXCL ("alloc_size", true, true, true), ATTR_EXCL ("const", true, true, true), @@ -89,11 +85,22 @@ static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] ATTR_EXCL (NULL, false, false, false), }; +extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] = { + + ATTR_EXCL ("cold", true, true, true), + ATTR_EXCL ("hot", true, true, true), + ATTR_EXCL (NULL, false, false, false) +}; + static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = { // ATTR_EXCL ("alloc_size", true, true, true), ATTR_EXCL ("const", true, true, true), ATTR_EXCL ("noreturn", true, true, true), - ATTR_EXCL ("pure", true, true, true), ATTR_EXCL (NULL, false, false, false)}; + ATTR_EXCL ("pure", true, true, true), + ATTR_EXCL (NULL, false, false, false) +}; + +// clang-format on /* Helper to define an attribute. */ #define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \ @@ -105,7 +112,7 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = { /* Table of machine-independent attributes. For internal use (marking of built-ins) only. */ -const attribute_spec grs_langhook_common_attribute_table[] = { +static const attribute_spec grs_langhook_common_attributes[] = { ATTR_SPEC ("noreturn", 0, 0, true, false, false, false, handle_noreturn_attribute, attr_noreturn_exclusions), ATTR_SPEC ("leaf", 0, 0, true, false, false, false, handle_leaf_attribute, @@ -132,9 +139,21 @@ const attribute_spec grs_langhook_common_attribute_table[] = { NULL), ATTR_SPEC ("omp declare simd", 0, -1, true, false, false, false, handle_omp_declare_simd_attribute, NULL), - ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL), }; +const scoped_attribute_specs grs_langhook_common_attribute_table + = {"gnu", {grs_langhook_common_attributes}}; + +static const attribute_spec grs_langhook_gnu_attributes[] = { + ATTR_SPEC ("cold", 0, 0, true, false, false, false, handle_cold_attribute, + attr_cold_hot_exclusions), + ATTR_SPEC ("hot", 0, 0, true, false, false, false, handle_hot_attribute, + attr_cold_hot_exclusions), +}; + +const scoped_attribute_specs grs_langhook_gnu_attribute_table + = {"gnu", {grs_langhook_gnu_attributes}}; + /* Built-in attribute handlers. These functions take the arguments: (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */ @@ -204,7 +223,7 @@ handle_const_attribute (tree *node, tree, tree, int, bool *) /* Handle a "malloc" attribute; arguments as in struct attribute_spec.handler. */ -tree +static tree handle_malloc_attribute (tree *node, tree, tree, int, bool *) { gcc_assert (TREE_CODE (*node) == FUNCTION_DECL @@ -217,9 +236,14 @@ handle_malloc_attribute (tree *node, tree, tree, int, bool *) struct attribute_spec.handler. */ static tree -handle_pure_attribute (tree *node, tree, tree, int, bool *) +handle_pure_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + DECL_PURE_P (*node) = 1; return NULL_TREE; } @@ -228,9 +252,14 @@ handle_pure_attribute (tree *node, tree, tree, int, bool *) struct attribute_spec.handler. */ static tree -handle_novops_attribute (tree *node, tree, tree, int, bool *) +handle_novops_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + DECL_IS_NOVOPS (*node) = 1; return NULL_TREE; } @@ -301,9 +330,14 @@ handle_nonnull_attribute (tree *node, tree, tree args, int, bool *) struct attribute_spec.handler. */ static tree -handle_nothrow_attribute (tree *node, tree, tree, int, bool *) +handle_nothrow_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + TREE_NOTHROW (*node) = 1; return NULL_TREE; } @@ -339,9 +373,14 @@ handle_transaction_pure_attribute (tree *node, tree, tree, int, bool *) struct attribute_spec.handler. */ static tree -handle_returns_twice_attribute (tree *node, tree, tree, int, bool *) +handle_returns_twice_attribute (tree *node, tree name, tree, int, + bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } DECL_IS_RETURNS_TWICE (*node) = 1; @@ -351,7 +390,7 @@ handle_returns_twice_attribute (tree *node, tree, tree, int, bool *) /* Handle a "fn spec" attribute; arguments as in struct attribute_spec.handler. */ -tree +static tree handle_fnspec_attribute (tree *, tree, tree args, int, bool *) { gcc_assert (args && TREE_CODE (TREE_VALUE (args)) == STRING_CST @@ -362,9 +401,46 @@ handle_fnspec_attribute (tree *, tree, tree args, int, bool *) /* Handle an "omp declare simd" attribute; arguments as in struct attribute_spec.handler. */ -tree -handle_omp_declare_simd_attribute (tree *node, tree, tree, int, bool *) +static tree +handle_omp_declare_simd_attribute (tree *node, tree name, tree, int, + bool *no_add_attrs) { - gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Language specific attribute handlers. + These functions take the arguments: + (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */ + +/* Handle a "cold" and attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_cold_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +static tree +handle_hot_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + return NULL_TREE; } diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 414799e..a0df217 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -42,8 +42,7 @@ class Bvariable; namespace Backend { -void -init (); +void init (); // Name/type/location. Used for function parameters, struct fields, // interface methods. @@ -64,47 +63,37 @@ struct typed_identifier // debug void debug (tree); -void -debug (Bvariable *); +void debug (Bvariable *); -tree -get_identifier_node (const std::string &str); +tree get_identifier_node (const std::string &str); // Types. // Get the wchar type -tree -wchar_type (); +tree wchar_type (); // Get the Host pointer size in bits -int -get_pointer_size (); +int get_pointer_size (); // Get the raw str type const char* -tree -raw_str_type (); +tree raw_str_type (); // Get an unnamed integer type with the given signedness and number // of bits. -tree -integer_type (bool is_unsigned, int bits); +tree integer_type (bool is_unsigned, int bits); // Get an unnamed floating point type with the given number of bits // (32 or 64). -tree -float_type (int bits); +tree float_type (int bits); // Get a pointer type. -tree -pointer_type (tree to_type); +tree pointer_type (tree to_type); // Get a reference type. -tree -reference_type (tree to_type); +tree reference_type (tree to_type); // make type immutable -tree -immutable_type (tree base); +tree immutable_type (tree base); // Get a function type. The receiver, parameter, and results are // generated from the types in the Function_type. The Function_type @@ -115,41 +104,36 @@ immutable_type (tree base); // one result, RESULT_STRUCT is a struct type to hold the results, // and RESULTS may be ignored; if there are zero or one results, // RESULT_STRUCT is NULL. -tree -function_type (const typed_identifier &receiver, - const std::vector<typed_identifier> ¶meters, - const std::vector<typed_identifier> &results, tree result_struct, - location_t location); - -tree -function_type_variadic (const typed_identifier &receiver, - const std::vector<typed_identifier> ¶meters, - const std::vector<typed_identifier> &results, - tree result_struct, location_t location); - -tree -function_ptr_type (tree result, const std::vector<tree> &praameters, - location_t location); +tree function_type (const typed_identifier &receiver, + const std::vector<typed_identifier> ¶meters, + const std::vector<typed_identifier> &results, + tree result_struct, location_t location); + +tree function_type_variadic (const typed_identifier &receiver, + const std::vector<typed_identifier> ¶meters, + const std::vector<typed_identifier> &results, + tree result_struct, location_t location); + +tree function_ptr_type (tree result, const std::vector<tree> &praameters, + location_t location); // Get a struct type. -tree -struct_type (const std::vector<typed_identifier> &fields, bool layout = true); +tree struct_type (const std::vector<typed_identifier> &fields, + bool layout = true); // Get a union type. -tree -union_type (const std::vector<typed_identifier> &fields, bool layout = true); +tree union_type (const std::vector<typed_identifier> &fields, + bool layout = true); // Get an array type. -tree -array_type (tree element_type, tree length); +tree array_type (tree element_type, tree length); // Return a named version of a type. The location is the location // of the type definition. This will not be called for a type // created via placeholder_pointer_type, placeholder_struct_type, or // placeholder_array_type.. (It may be called for a pointer, // struct, or array type in a case like "type P *byte; type Q P".) -tree -named_type (const std::string &name, tree, location_t); +tree named_type (const std::string &name, tree, location_t); // Return the size of a type. int64_t type_size (tree); @@ -164,8 +148,7 @@ int64_t type_field_alignment (tree); // Return the offset of field INDEX in a struct type. INDEX is the // entry in the FIELDS std::vector parameter of struct_type or // set_placeholder_struct_type. -int64_t -type_field_offset (tree, size_t index); +int64_t type_field_offset (tree, size_t index); // Expressions. @@ -175,155 +158,128 @@ type_field_offset (tree, size_t index); tree zero_expression (tree); // Create a reference to a variable. -tree -var_expression (Bvariable *var, location_t); +tree var_expression (Bvariable *var, location_t); // Return an expression for the floating point value VAL in BTYPE. -tree -float_constant_expression (tree btype, mpfr_t val); +tree float_constant_expression (tree btype, mpfr_t val); // Return an expression for the string value VAL. -tree -string_constant_expression (const std::string &val); +tree string_constant_expression (const std::string &val); // Get a char literal -tree -char_constant_expression (char c); +tree char_constant_expression (char c); // Get a char literal -tree -wchar_constant_expression (wchar_t c); +tree wchar_constant_expression (wchar_t c); // Return an expression for the boolean value VAL. -tree -boolean_constant_expression (bool val); +tree boolean_constant_expression (bool val); // Return an expression that converts EXPR to TYPE. -tree -convert_expression (tree type, tree expr, location_t); +tree convert_expression (tree type, tree expr, location_t); // Return an expression for the field at INDEX in BSTRUCT. -tree -struct_field_expression (tree bstruct, size_t index, location_t); +tree struct_field_expression (tree bstruct, size_t index, location_t); // Create an expression that executes BSTAT before BEXPR. -tree -compound_expression (tree bstat, tree bexpr, location_t); +tree compound_expression (tree bstat, tree bexpr, location_t); // Return an expression that executes THEN_EXPR if CONDITION is true, or // ELSE_EXPR otherwise and returns the result as type BTYPE, within the // specified function FUNCTION. ELSE_EXPR may be NULL. BTYPE may be NULL. -tree -conditional_expression (tree function, tree btype, tree condition, - tree then_expr, tree else_expr, location_t); +tree conditional_expression (tree function, tree btype, tree condition, + tree then_expr, tree else_expr, location_t); // Return an expression for the negation operation OP EXPR. // Supported values of OP are enumerated in NegationOperator. -tree -negation_expression (NegationOperator op, tree expr, location_t); +tree negation_expression (NegationOperator op, tree expr, location_t); // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in ArithmeticOrLogicalOperator. -tree -arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left, - tree right, location_t loc); +tree arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, + tree left, tree right, location_t loc); // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in ArithmeticOrLogicalOperator. // This function adds overflow checking and returns a list of statements to // add to the current function context. The `receiver` variable refers to the // variable which will contain the result of that operation. -tree -arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op, - tree left, tree right, location_t loc, - Bvariable *receiver); +tree arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op, + tree left, tree right, + location_t loc, + Bvariable *receiver); // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in ComparisonOperator. -tree -comparison_expression (ComparisonOperator op, tree left, tree right, - location_t loc); +tree comparison_expression (ComparisonOperator op, tree left, tree right, + location_t loc); // Return an expression for the operation LEFT OP RIGHT. // Supported values of OP are enumerated in LazyBooleanOperator. -tree -lazy_boolean_expression (LazyBooleanOperator op, tree left, tree right, - location_t); +tree lazy_boolean_expression (LazyBooleanOperator op, tree left, tree right, + location_t); // Return an expression that constructs BTYPE with VALS. BTYPE must be the // backend representation a of struct. VALS must be in the same order as the // corresponding fields in BTYPE. -tree -constructor_expression (tree btype, bool is_variant, - const std::vector<tree> &vals, int, location_t); +tree constructor_expression (tree btype, bool is_variant, + const std::vector<tree> &vals, int, location_t); // Return an expression that constructs an array of BTYPE with INDEXES and // VALS. INDEXES and VALS must have the same amount of elements. Each index // in INDEXES must be in the same order as the corresponding value in VALS. -tree -array_constructor_expression (tree btype, - const std::vector<unsigned long> &indexes, - const std::vector<tree> &vals, location_t); +tree array_constructor_expression (tree btype, + const std::vector<unsigned long> &indexes, + const std::vector<tree> &vals, location_t); -tree -array_initializer (tree, tree, tree, tree, tree, tree *, location_t); +tree array_initializer (tree, tree, tree, tree, tree, tree *, location_t); // Return an expression for ARRAY[INDEX] as an l-value. ARRAY is a valid // fixed-length array, not a slice. -tree -array_index_expression (tree array, tree index, location_t); +tree array_index_expression (tree array, tree index, location_t); // Create an expression for a call to FN with ARGS, taking place within // caller CALLER. -tree -call_expression (tree fn, const std::vector<tree> &args, tree static_chain, - location_t); +tree call_expression (tree fn, const std::vector<tree> &args, tree static_chain, + location_t); // Statements. // Create a variable initialization statement in the specified // function. This initializes a local variable at the point in the // program flow where it is declared. -tree -init_statement (tree, Bvariable *var, tree init); +tree init_statement (tree, Bvariable *var, tree init); // Create an assignment statement within the specified function. -tree -assignment_statement (tree lhs, tree rhs, location_t); +tree assignment_statement (tree lhs, tree rhs, location_t); // Create return statement for an decl for a value (can be NULL_TREE) at a // location -tree -return_statement (tree fndecl, tree val, location_t); +tree return_statement (tree fndecl, tree val, location_t); // Create an if statement within a function. ELSE_BLOCK may be NULL. -tree -if_statement (tree, tree condition, tree then_block, tree else_block, - location_t); +tree if_statement (tree, tree condition, tree then_block, tree else_block, + location_t); // infinite loop expressions -tree -loop_expression (tree body, location_t); +tree loop_expression (tree body, location_t); // exit expressions -tree -exit_expression (tree condition, location_t); +tree exit_expression (tree condition, location_t); // Create a single statement from two statements. tree compound_statement (tree, tree); // Create a single statement from a list of statements. -tree -statement_list (const std::vector<tree> &); +tree statement_list (const std::vector<tree> &); // Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if // an exception occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and // if not NULL, it will always be executed. This is used for handling defers // in Go functions. In C++, the resulting code is of this form: // try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; } -tree -exception_handler_statement (tree bstat, tree except_stmt, tree finally_stmt, - location_t); +tree exception_handler_statement (tree bstat, tree except_stmt, + tree finally_stmt, location_t); // Blocks. @@ -337,16 +293,14 @@ exception_handler_statement (tree bstat, tree except_stmt, tree finally_stmt, // the initial curly brace. END_LOCATION is the location of the end // of the block, more or less the location of the final curly brace. // The statements will be added after the block is created. -tree -block (tree function, tree enclosing, const std::vector<Bvariable *> &vars, - location_t start_location, location_t end_location); +tree block (tree function, tree enclosing, const std::vector<Bvariable *> &vars, + location_t start_location, location_t end_location); // Add the statements to a block. The block is created first. Then // the statements are created. Then the statements are added to the // block. This will called exactly once per block. The vector may // be empty if there are no statements. -void -block_add_statements (tree, const std::vector<tree> &); +void block_add_statements (tree, const std::vector<tree> &); // Variables. @@ -360,10 +314,10 @@ block_add_statements (tree, const std::vector<tree> &); // be put into a unique section if possible; this is intended to // permit the linker to garbage collect the variable if it is not // referenced. LOCATION is where the variable was defined. -Bvariable * -global_variable (const std::string &name, const std::string &asm_name, - tree btype, bool is_external, bool is_hidden, - bool in_unique_section, location_t location); +Bvariable *global_variable (const std::string &name, + const std::string &asm_name, tree btype, + bool is_external, bool is_hidden, + bool in_unique_section, location_t location); // A global variable will 1) be initialized to zero, or 2) be // initialized to a constant value, or 3) be initialized in the init @@ -371,8 +325,7 @@ global_variable (const std::string &name, const std::string &asm_name, // global_variable_set_init to set the initial value. If this is // not called, the backend should initialize a global variable to 0. // The init function may then assign a value to it. -void -global_variable_set_init (Bvariable *, tree); +void global_variable_set_init (Bvariable *, tree); // Create a local variable. The frontend will create the local // variables first, and then create the block which contains them. @@ -386,21 +339,18 @@ global_variable_set_init (Bvariable *, tree); // the function, as otherwise the variable would be on the heap). // LOCATION is where the variable is defined. For each local variable // the frontend will call init_statement to set the initial value. -Bvariable * -local_variable (tree function, const std::string &name, tree type, - Bvariable *decl_var, location_t location); +Bvariable *local_variable (tree function, const std::string &name, tree type, + Bvariable *decl_var, location_t location); // Create a function parameter. This is an incoming parameter, not // a result parameter (result parameters are treated as local // variables). The arguments are as for local_variable. -Bvariable * -parameter_variable (tree function, const std::string &name, tree type, - location_t location); +Bvariable *parameter_variable (tree function, const std::string &name, + tree type, location_t location); // Create a static chain parameter. This is the closure parameter. -Bvariable * -static_chain_variable (tree function, const std::string &name, tree type, - location_t location); +Bvariable *static_chain_variable (tree function, const std::string &name, + tree type, location_t location); // Create a temporary variable. A temporary variable has no name, // just a type. We pass in FUNCTION and BLOCK in case they are @@ -413,18 +363,16 @@ static_chain_variable (tree function, const std::string &name, tree type, // variable, and may not be very useful. This function should // return a variable which can be referenced later and should set // *PSTATEMENT to a statement which initializes the variable. -Bvariable * -temporary_variable (tree fndecl, tree bind_tree, tree type, tree init, - bool address_is_taken, location_t location, - tree *pstatement); +Bvariable *temporary_variable (tree fndecl, tree bind_tree, tree type, + tree init, bool address_is_taken, + location_t location, tree *pstatement); // Labels. // Create a new label. NAME will be empty if this is a label // created by the frontend for a loop construct. The location is // where the label is defined. -tree -label (tree, const std::string &name, location_t); +tree label (tree, const std::string &name, location_t); // Create a statement which defines a label. This statement will be // put into the codestream at the point where the label should be @@ -464,39 +412,34 @@ static const unsigned int function_in_unique_section = 1 << 3; // string, is the name that should be used in the symbol table; this // will be non-empty if a magic extern comment is used. FLAGS is // bit flags described above. -tree -function (tree fntype, const std::string &name, const std::string &asm_name, - unsigned int flags, location_t); +tree function (tree fntype, const std::string &name, + const std::string &asm_name, unsigned int flags, location_t); // Create a statement that runs all deferred calls for FUNCTION. This should // be a statement that looks like this in C++: // finish: // try { DEFER_RETURN; } catch { CHECK_DEFER; goto finish; } -tree -function_defer_statement (tree function, tree undefer, tree check_defer, - location_t); +tree function_defer_statement (tree function, tree undefer, tree check_defer, + location_t); // Record PARAM_VARS as the variables to use for the parameters of FUNCTION. // This will only be called for a function definition. Returns true on // success, false on failure. -bool -function_set_parameters (tree function, - const std::vector<Bvariable *> ¶m_vars); +bool function_set_parameters (tree function, + const std::vector<Bvariable *> ¶m_vars); // Utility. // Write the definitions for all TYPE_DECLS, CONSTANT_DECLS, // FUNCTION_DECLS, and VARIABLE_DECLS declared globally. -void -write_global_definitions (const std::vector<tree> &type_decls, - const std::vector<tree> &constant_decls, - const std::vector<tree> &function_decls, - const std::vector<Bvariable *> &variable_decls); +void write_global_definitions (const std::vector<tree> &type_decls, + const std::vector<tree> &constant_decls, + const std::vector<tree> &function_decls, + const std::vector<Bvariable *> &variable_decls); // TODO: make static -tree -fill_in_fields (tree, const std::vector<typed_identifier> &, bool); +tree fill_in_fields (tree, const std::vector<typed_identifier> &, bool); tree fill_in_array (tree, tree, tree); diff --git a/gcc/rust/rust-diagnostics.cc b/gcc/rust/rust-diagnostics.cc index 702da71..5965bb4 100644 --- a/gcc/rust/rust-diagnostics.cc +++ b/gcc/rust/rust-diagnostics.cc @@ -48,27 +48,33 @@ expand_format (const char *fmt) c++; switch (*c) { - case '\0': { + case '\0': + { // malformed format string rust_unreachable (); } - case '%': { + case '%': + { ss << "%"; break; } - case 'm': { + case 'm': + { ss << mformat_value (); break; } - case '<': { + case '<': + { ss << rust_open_quote (); break; } - case '>': { + case '>': + { ss << rust_close_quote (); break; } - case 'q': { + case 'q': + { ss << rust_open_quote (); c++; if (*c == 'm') @@ -82,7 +88,8 @@ expand_format (const char *fmt) ss << rust_close_quote (); break; } - default: { + default: + { ss << "%" << *c; } } @@ -104,8 +111,8 @@ expand_format (const char *fmt) // calling function must need to have attribute gnu_printf as well, even // though there is already an attribute declaration for it. -static std::string -expand_message (const char *fmt, va_list ap) RUST_ATTRIBUTE_GCC_DIAG (1, 0); +static std::string expand_message (const char *fmt, va_list ap) + RUST_ATTRIBUTE_GCC_DIAG (1, 0); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsuggest-attribute=format" @@ -420,24 +427,24 @@ namespace Rust { */ // simple location -static Error -va_constructor (Error::Kind kind, location_t locus, const char *fmt, - va_list args) RUST_ATTRIBUTE_GCC_DIAG (3, 0); +static Error va_constructor (Error::Kind kind, location_t locus, + const char *fmt, va_list args) + RUST_ATTRIBUTE_GCC_DIAG (3, 0); // simple location + error code -static Error -va_constructor (Error::Kind kind, location_t locus, const ErrorCode code, - const char *fmt, va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0); +static Error va_constructor (Error::Kind kind, location_t locus, + const ErrorCode code, const char *fmt, + va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0); // rich location -static Error -va_constructor (Error::Kind kind, rich_location *r_locus, const char *fmt, - va_list args) RUST_ATTRIBUTE_GCC_DIAG (3, 0); +static Error va_constructor (Error::Kind kind, rich_location *r_locus, + const char *fmt, va_list args) + RUST_ATTRIBUTE_GCC_DIAG (3, 0); // rich location + error code -static Error -va_constructor (Error::Kind kind, rich_location *r_locus, const ErrorCode code, - const char *fmt, va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0); +static Error va_constructor (Error::Kind kind, rich_location *r_locus, + const ErrorCode code, const char *fmt, + va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0); // simple location static Error diff --git a/gcc/rust/rust-diagnostics.h b/gcc/rust/rust-diagnostics.h index a13dc6a2..0b83e8c 100644 --- a/gcc/rust/rust-diagnostics.h +++ b/gcc/rust/rust-diagnostics.h @@ -31,7 +31,7 @@ #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) #define RUST_ATTRIBUTE_GCC_DIAG(m, n) \ __attribute__ ((__format__ (__gcc_tdiag__, m, n))) \ - __attribute__ ((__nonnull__ (m))) + __attribute__ ((__nonnull__ (m))) #else #define RUST_ATTRIBUTE_GCC_DIAG(m, n) #endif @@ -119,10 +119,8 @@ rust_error_at(rich_location *richloc, const ErrorCode, const char *fmt, ...) // These interfaces provide a way for the front end to ask for // the open/close quote characters it should use when formatting // diagnostics (warnings, errors). -extern const char * -rust_open_quote (); -extern const char * -rust_close_quote (); +extern const char *rust_open_quote (); +extern const char *rust_close_quote (); // These interfaces are used by utilities above to pass warnings and // errors (once format specifiers have been expanded) to the back end, @@ -306,8 +304,7 @@ struct Error #define rust_sorry_at(location, ...) sorry_at (location, __VA_ARGS__) -void -rust_debug_loc (const location_t location, const char *fmt, - ...) ATTRIBUTE_PRINTF_2; +void rust_debug_loc (const location_t location, const char *fmt, + ...) ATTRIBUTE_PRINTF_2; #endif // !defined(RUST_DIAGNOSTICS_H) diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index e5319d3..f440f79 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -1876,7 +1876,8 @@ non_zero_size_type (tree type) } return rust_non_zero_struct; - case ARRAY_TYPE: { + case ARRAY_TYPE: + { tree element_type = non_zero_size_type (TREE_TYPE (type)); return build_array_type_nelts (element_type, 1); } diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc index f3a155d..35003ab 100644 --- a/gcc/rust/rust-lang.cc +++ b/gcc/rust/rust-lang.cc @@ -373,7 +373,13 @@ rust_localize_identifier (const char *ident) return identifier_to_locale (ident); } -extern const attribute_spec grs_langhook_common_attribute_table[]; +extern const struct scoped_attribute_specs grs_langhook_gnu_attribute_table; +extern const struct scoped_attribute_specs grs_langhook_common_attribute_table; + +const scoped_attribute_specs *const grs_langhook_attribute_table[] = { + &grs_langhook_gnu_attribute_table, + &grs_langhook_common_attribute_table, +}; /* The language hooks data structure. This is the main interface between the GCC * front-end and the GCC middle-end/back-end. A list of language hooks could be @@ -394,8 +400,7 @@ extern const attribute_spec grs_langhook_common_attribute_table[]; #undef LANG_HOOKS_WRITE_GLOBALS #undef LANG_HOOKS_GIMPLIFY_EXPR #undef LANG_HOOKS_EH_PERSONALITY - -#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE +#undef LANG_HOOKS_ATTRIBUTE_TABLE #define LANG_HOOKS_NAME "GNU Rust" #define LANG_HOOKS_INIT grs_langhook_init @@ -417,7 +422,7 @@ extern const attribute_spec grs_langhook_common_attribute_table[]; #define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr #define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality -#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE grs_langhook_common_attribute_table +#define LANG_HOOKS_ATTRIBUTE_TABLE grs_langhook_attribute_table #if CHECKING_P diff --git a/gcc/rust/rust-object-export.h b/gcc/rust/rust-object-export.h index fe055c3..784fef3 100644 --- a/gcc/rust/rust-object-export.h +++ b/gcc/rust/rust-object-export.h @@ -21,13 +21,10 @@ #include "rust-system.h" -extern unsigned int -rust_field_alignment (tree t); - -extern const char * -rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen, - int *perr); -extern void -rust_write_export_data (const char *bytes, unsigned int size); +extern unsigned int rust_field_alignment (tree t); + +extern const char *rust_read_export_data (int fd, off_t offset, char **pbuf, + size_t *plen, int *perr); +extern void rust_write_export_data (const char *bytes, unsigned int size); #endif // RUST_OBJECT_EXPORT_H diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 48acbf34..d42ae6a 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -20,6 +20,7 @@ #include "rust-collect-lang-items.h" #include "rust-desugar-for-loops.h" #include "rust-desugar-question-mark.h" +#include "rust-desugar-apit.h" #include "rust-diagnostics.h" #include "rust-hir-pattern-analysis.h" #include "rust-immutable-name-resolution-context.h" @@ -61,11 +62,9 @@ #include "tm.h" #include "rust-target.h" -extern bool -saw_errors (void); +extern bool saw_errors (void); -extern Linemap * -rust_get_linemap (); +extern Linemap *rust_get_linemap (); namespace Rust { @@ -150,9 +149,9 @@ validate_crate_name (const std::string &crate_name, Error &error) { if (!(is_alphabetic (c.value) || is_numeric (c.value) || c.value == '_')) { - error = Error (UNDEF_LOCATION, - "invalid character %qs in crate name: %qs", - c.as_string ().c_str (), crate_name.c_str ()); + error + = Error (UNDEF_LOCATION, "invalid character %qs in crate name: %qs", + c.as_string ().c_str (), crate_name.c_str ()); return false; } } @@ -203,14 +202,16 @@ Session::handle_option ( switch (code) { case OPT_I: - case OPT_L: { + case OPT_L: + { // TODO: add search path const std::string p = std::string (arg); add_search_path (p); } break; - case OPT_frust_extern_: { + case OPT_frust_extern_: + { std::string input (arg); ret = handle_extern_option (input); } @@ -251,7 +252,8 @@ Session::handle_option ( Compile::Mangler::set_mangling (flag_rust_mangling); break; - case OPT_frust_cfg_: { + case OPT_frust_cfg_: + { auto string_arg = std::string (arg); ret = handle_cfg_option (string_arg); break; @@ -619,6 +621,7 @@ Session::compile_crate (const char *filename) AST::DesugarForLoops ().go (parsed_crate); AST::DesugarQuestionMark ().go (parsed_crate); + AST::DesugarApit ().go (parsed_crate); rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m"); if (options.dump_option_enabled (CompileOptions::EXPANSION_DUMP)) @@ -1108,8 +1111,7 @@ Session::load_extern_crate (const std::string &crate_name, location_t locus) if (stream == NULL // No stream and && proc_macros.empty ()) // no proc macros { - rust_error_at (locus, "failed to locate crate %qs", - import_name.c_str ()); + rust_error_at (locus, "failed to locate crate %qs", import_name.c_str ()); return UNKNOWN_NODEID; } diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index 83ba121..9af103c 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -441,8 +441,7 @@ private: #if CHECKING_P namespace selftest { -extern void -rust_crate_name_validation_test (void); +extern void rust_crate_name_validation_test (void); } #endif // CHECKING_P diff --git a/gcc/rust/rust-system.h b/gcc/rust/rust-system.h index 986428b..a455123 100644 --- a/gcc/rust/rust-system.h +++ b/gcc/rust/rust-system.h @@ -88,10 +88,8 @@ constexpr static const char *file_separator = "/"; */ #define rust_unreachable() (fancy_abort (__FILE__, __LINE__, __FUNCTION__)) -extern void -rust_preserve_from_gc (tree t); +extern void rust_preserve_from_gc (tree t); -extern const char * -rust_localize_identifier (const char *ident); +extern const char *rust_localize_identifier (const char *ident); #endif // !defined(RUST_SYSTEM_H) diff --git a/gcc/rust/rust-target.h b/gcc/rust/rust-target.h index dbc2baf..e61ea51 100644 --- a/gcc/rust/rust-target.h +++ b/gcc/rust/rust-target.h @@ -26,8 +26,7 @@ #include "rust-target.def" /* Used by target to add target-related info. */ -extern void -rust_add_target_info (const char *, const char *); +extern void rust_add_target_info (const char *, const char *); /* Each target can provide their own. */ extern struct gcc_targetrustm targetrustm; diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc index 6aa20a8..8256074 100644 --- a/gcc/rust/typecheck/rust-autoderef.cc +++ b/gcc/rust/typecheck/rust-autoderef.cc @@ -26,8 +26,7 @@ namespace Rust { namespace Resolver { -static bool -resolve_operator_overload_fn ( +static bool resolve_operator_overload_fn ( LangItem::Kind lang_item_type, TyTy::BaseType *ty, TyTy::FnType **resolved_fn, Adjustment::AdjustmentType *requires_ref_adjustment); diff --git a/gcc/rust/typecheck/rust-casts.cc b/gcc/rust/typecheck/rust-casts.cc index 90bdef1..d0a9f5d 100644 --- a/gcc/rust/typecheck/rust-casts.cc +++ b/gcc/rust/typecheck/rust-casts.cc @@ -73,7 +73,8 @@ TypeCastRules::cast_rules () to.get_ty ()->debug_str ().c_str ()); switch (from_type->get_kind ()) { - case TyTy::TypeKind::INFER: { + case TyTy::TypeKind::INFER: + { TyTy::InferType *from_infer = static_cast<TyTy::InferType *> (from_type); switch (from_infer->get_infer_kind ()) @@ -85,7 +86,8 @@ TypeCastRules::cast_rules () case TyTy::InferType::InferTypeKind::INTEGRAL: switch (to.get_ty ()->get_kind ()) { - case TyTy::TypeKind::CHAR: { + case TyTy::TypeKind::CHAR: + { // only u8 and char bool was_uint = from.get_ty ()->get_kind () == TyTy::TypeKind::UINT; @@ -108,7 +110,8 @@ TypeCastRules::cast_rules () return TypeCoercionRules::CoercionResult{ {}, to.get_ty ()->clone ()}; - case TyTy::TypeKind::INFER: { + case TyTy::TypeKind::INFER: + { TyTy::InferType *to_infer = static_cast<TyTy::InferType *> (to.get_ty ()); @@ -140,7 +143,8 @@ TypeCastRules::cast_rules () return TypeCoercionRules::CoercionResult{ {}, to.get_ty ()->clone ()}; - case TyTy::TypeKind::INFER: { + case TyTy::TypeKind::INFER: + { TyTy::InferType *to_infer = static_cast<TyTy::InferType *> (to.get_ty ()); @@ -187,7 +191,8 @@ TypeCastRules::cast_rules () case TyTy::TypeKind::INT: switch (to.get_ty ()->get_kind ()) { - case TyTy::TypeKind::CHAR: { + case TyTy::TypeKind::CHAR: + { // only u8 and char bool was_uint = from.get_ty ()->get_kind () == TyTy::TypeKind::UINT; bool was_u8 = was_uint @@ -200,7 +205,8 @@ TypeCastRules::cast_rules () } break; - case TyTy::TypeKind::FLOAT: { + case TyTy::TypeKind::FLOAT: + { // can only do this for number types not char bool from_char = from.get_ty ()->get_kind () == TyTy::TypeKind::CHAR; @@ -210,7 +216,8 @@ TypeCastRules::cast_rules () } break; - case TyTy::TypeKind::POINTER: { + case TyTy::TypeKind::POINTER: + { // char can't be casted as a ptr bool from_char = from.get_ty ()->get_kind () == TyTy::TypeKind::CHAR; @@ -244,7 +251,8 @@ TypeCastRules::cast_rules () case TyTy::TypeKind::FLOAT: return TypeCoercionRules::CoercionResult{{}, to.get_ty ()->clone ()}; - case TyTy::TypeKind::INFER: { + case TyTy::TypeKind::INFER: + { TyTy::InferType *to_infer = static_cast<TyTy::InferType *> (to.get_ty ()); @@ -273,7 +281,8 @@ TypeCastRules::cast_rules () case TyTy::TypeKind::USIZE: case TyTy::TypeKind::ISIZE: case TyTy::TypeKind::UINT: - case TyTy::TypeKind::INT: { + case TyTy::TypeKind::INT: + { // refs should not cast to numeric type bool from_ptr = from.get_ty ()->get_kind () == TyTy::TypeKind::POINTER; diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc index 5905992..50c74ed 100644 --- a/gcc/rust/typecheck/rust-coercion.cc +++ b/gcc/rust/typecheck/rust-coercion.cc @@ -125,13 +125,15 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver) // pointers switch (expected->get_kind ()) { - case TyTy::TypeKind::POINTER: { + case TyTy::TypeKind::POINTER: + { TyTy::PointerType *ptr = static_cast<TyTy::PointerType *> (expected); try_result = coerce_unsafe_ptr (receiver, ptr, ptr->mutability ()); return !try_result.is_error (); } - case TyTy::TypeKind::REF: { + case TyTy::TypeKind::REF: + { TyTy::ReferenceType *ptr = static_cast<TyTy::ReferenceType *> (expected); try_result @@ -147,7 +149,8 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver) // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L210 switch (receiver->get_kind ()) { - default: { + default: + { rust_debug ( "do_coercion default unify and infer expected: %s receiver %s", receiver->debug_str ().c_str (), expected->debug_str ().c_str ()); @@ -182,7 +185,8 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver, TyTy::BaseType *element = nullptr; switch (receiver->get_kind ()) { - case TyTy::TypeKind::REF: { + case TyTy::TypeKind::REF: + { TyTy::ReferenceType *ref = static_cast<TyTy::ReferenceType *> (receiver); from_mutbl = ref->mutability (); @@ -190,14 +194,16 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver, } break; - case TyTy::TypeKind::POINTER: { + case TyTy::TypeKind::POINTER: + { TyTy::PointerType *ref = static_cast<TyTy::PointerType *> (receiver); from_mutbl = ref->mutability (); element = ref->get_base (); } break; - default: { + default: + { // FIXME this can probably turn into a unify_and if (receiver->can_eq (expected, false)) return CoercionResult{{}, expected->clone ()}; @@ -264,14 +270,16 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver, Mutability from_mutbl = Mutability::Imm; switch (receiver->get_kind ()) { - case TyTy::TypeKind::REF: { + case TyTy::TypeKind::REF: + { TyTy::ReferenceType *from = static_cast<TyTy::ReferenceType *> (receiver); from_mutbl = from->mutability (); } break; - default: { + default: + { // FIXME // we might be able to replace this with a can_eq because we default // back to a final unity anyway @@ -393,7 +401,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, if (expect_dyn && need_unsize) { - bool bounds_compatible = b->bounds_compatible (*a, locus, true); + bool bounds_compatible = b->bounds_compatible (*a, locus, false); if (!bounds_compatible) { unsafe_error = true; diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index 032bb58..35c9b0a 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -224,7 +224,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference) // handling. break; - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { auto &typaram = static_cast<HIR::TypeParam &> (*generic_param); bool is_self = typaram.get_type_representation ().as_string ().compare ("Self") @@ -543,7 +544,8 @@ AssociatedImplTrait::setup_associated_types ( // handling. break; - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { TyTy::BaseType *l = nullptr; bool ok = context->lookup_type ( generic_param->get_mappings ().get_hirid (), &l); @@ -753,7 +755,8 @@ TraitItemReference::is_object_safe () const // https://doc.rust-lang.org/reference/items/traits.html#object-safety switch (get_trait_item_type ()) { - case TraitItemReference::TraitItemType::FN: { + case TraitItemReference::TraitItemType::FN: + { // lets be boring and just check that this is indeed a method will do // for now const HIR::TraitItem *item = get_hir_trait_item (); diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index 14b8ab8..6d5806f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -124,7 +124,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, TyTy::BaseType *infered = nullptr; switch (literal.get_lit_type ()) { - case HIR::Literal::LitType::INT: { + case HIR::Literal::LitType::INT: + { bool ok = false; switch (literal.get_type_hint ()) @@ -191,7 +192,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, } break; - case HIR::Literal::LitType::FLOAT: { + case HIR::Literal::LitType::FLOAT: + { bool ok = false; switch (literal.get_type_hint ()) @@ -216,25 +218,29 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, } break; - case HIR::Literal::LitType::BOOL: { + case HIR::Literal::LitType::BOOL: + { auto ok = context->lookup_builtin ("bool", &infered); rust_assert (ok); } break; - case HIR::Literal::LitType::CHAR: { + case HIR::Literal::LitType::CHAR: + { auto ok = context->lookup_builtin ("char", &infered); rust_assert (ok); } break; - case HIR::Literal::LitType::BYTE: { + case HIR::Literal::LitType::BYTE: + { auto ok = context->lookup_builtin ("u8", &infered); rust_assert (ok); } break; - case HIR::Literal::LitType::STRING: { + case HIR::Literal::LitType::STRING: + { TyTy::BaseType *base = nullptr; auto ok = context->lookup_builtin ("str", &base); rust_assert (ok); @@ -246,7 +252,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, } break; - case HIR::Literal::LitType::BYTE_STRING: { + case HIR::Literal::LitType::BYTE_STRING: + { /* This is an arraytype of u8 reference (&[u8;size]). It isn't in UTF-8, but really just a byte array. Code to construct the array reference copied from ArrayElemsValues and ArrayType. */ @@ -440,7 +447,8 @@ TypeCheckBase::resolve_generic_params ( { switch (generic_param->get_kind ()) { - case HIR::GenericParam::GenericKind::LIFETIME: { + case HIR::GenericParam::GenericKind::LIFETIME: + { auto lifetime_param = static_cast<HIR::LifetimeParam &> (*generic_param); auto lifetime = lifetime_param.get_lifetime (); @@ -449,7 +457,8 @@ TypeCheckBase::resolve_generic_params ( } break; - case HIR::GenericParam::GenericKind::CONST: { + case HIR::GenericParam::GenericKind::CONST: + { if (is_foreign && abi != Rust::ABI::INTRINSIC) { rust_error_at (generic_param->get_locus (), ErrorCode::E0044, @@ -478,7 +487,8 @@ TypeCheckBase::resolve_generic_params ( } break; - case HIR::GenericParam::GenericKind::TYPE: { + case HIR::GenericParam::GenericKind::TYPE: + { if (is_foreign && abi != Rust::ABI::INTRINSIC) { rust_error_at (generic_param->get_locus (), ErrorCode::E0044, diff --git a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc index c80a12f..2dbd84d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc @@ -87,7 +87,7 @@ TypeCheckEnumItem::visit (HIR::EnumItem &item) = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ()); } else { @@ -131,7 +131,7 @@ TypeCheckEnumItem::visit (HIR::EnumItemDiscriminant &item) = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ()); } else { @@ -193,7 +193,7 @@ TypeCheckEnumItem::visit (HIR::EnumItemTuple &item) = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ()); } else { @@ -253,7 +253,7 @@ TypeCheckEnumItem::visit (HIR::EnumItemStruct &item) = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ()); } else { diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index cbf529a7..81d95c8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -373,7 +373,8 @@ TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) switch (expr.get_expr_type ()) { case ArithmeticOrLogicalOperator::LEFT_SHIFT: - case ArithmeticOrLogicalOperator::RIGHT_SHIFT: { + case ArithmeticOrLogicalOperator::RIGHT_SHIFT: + { TyTy::TyWithLocation from (rhs, expr.get_rhs ().get_locus ()); TyTy::TyWithLocation to (lhs, expr.get_lhs ().get_locus ()); infered = cast_site (expr.get_mappings ().get_hirid (), from, to, @@ -381,7 +382,8 @@ TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) } break; - default: { + default: + { infered = unify_site ( expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (lhs, expr.get_lhs ().get_locus ()), @@ -470,7 +472,8 @@ TypeCheckExpr::visit (HIR::NegationExpr &expr) // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators switch (expr.get_expr_type ()) { - case NegationOperator::NEGATE: { + case NegationOperator::NEGATE: + { bool valid = (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT) @@ -492,7 +495,8 @@ TypeCheckExpr::visit (HIR::NegationExpr &expr) } break; - case NegationOperator::NOT: { + case NegationOperator::NOT: + { bool valid = (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL) || (negated_expr_ty->get_kind () == TyTy::TypeKind::INT) @@ -643,6 +647,18 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) } void +TypeCheckExpr::visit (HIR::AnonConst &expr) +{ + infered = TypeCheckExpr::Resolve (expr.get_inner_expr ()); +} + +void +TypeCheckExpr::visit (HIR::ConstBlock &expr) +{ + infered = TypeCheckExpr::Resolve (expr.get_const_expr ()); +} + +void TypeCheckExpr::visit (HIR::RangeFromToExpr &expr) { auto lang_item_type = LangItem::Kind::RANGE; @@ -790,38 +806,45 @@ typecheck_inline_asm_operand (HIR::InlineAsm &expr) { switch (operand.get_register_type ()) { - case RegisterType::In: { + case RegisterType::In: + { auto in = operand.get_in (); TypeCheckExpr::Resolve (*in.expr); break; } - case RegisterType::Out: { + case RegisterType::Out: + { auto out = operand.get_out (); TypeCheckExpr::Resolve (*out.expr); break; } - case RegisterType::InOut: { + case RegisterType::InOut: + { auto in_out = operand.get_in_out (); TypeCheckExpr::Resolve (*in_out.expr); break; } - case RegisterType::SplitInOut: { + case RegisterType::SplitInOut: + { auto split_in_out = operand.get_split_in_out (); TypeCheckExpr::Resolve (*split_in_out.in_expr); TypeCheckExpr::Resolve (*split_in_out.out_expr); break; } - case RegisterType::Const: { + case RegisterType::Const: + { auto anon_const = operand.get_const ().anon_const; - TypeCheckExpr::Resolve (*anon_const.expr); + TypeCheckExpr::Resolve (anon_const.get_inner_expr ()); break; } - case RegisterType::Sym: { + case RegisterType::Sym: + { auto sym = operand.get_sym (); TypeCheckExpr::Resolve (*sym.expr); break; } - case RegisterType::Label: { + case RegisterType::Label: + { auto label = operand.get_label (); TypeCheckExpr::Resolve (*label.expr); break; @@ -837,7 +860,7 @@ TypeCheckExpr::visit (HIR::InlineAsm &expr) // NOTE: Hoise out if we have noreturn as an option // to return a never type // TODO : new keyword for memory seems sooooo shaky - if (expr.options.count (AST::InlineAsmOption::NORETURN) == 1) + if (expr.options.count (AST::InlineAsm::Option::NORETURN) == 1) infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ()); else infered = TyTy::TupleType::get_unit_type (); @@ -996,8 +1019,7 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr) rich_location r (line_table, expr.get_locus ()); r.add_range (expr.get_array_expr ().get_locus ()); r.add_range (expr.get_index_expr ().get_locus ()); - rust_error_at (r, ErrorCode::E0277, - "the type %qs cannot be indexed by %qs", + rust_error_at (r, ErrorCode::E0277, "the type %qs cannot be indexed by %qs", array_expr_ty->get_name ().c_str (), index_expr_ty->get_name ().c_str ()); } @@ -1011,7 +1033,8 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) TyTy::BaseType *element_type = nullptr; switch (elements.get_array_expr_type ()) { - case HIR::ArrayElems::ArrayExprType::COPIED: { + case HIR::ArrayElems::ArrayExprType::COPIED: + { HIR::ArrayElemsCopied &elems = static_cast<HIR::ArrayElemsCopied &> (elements); element_type = TypeCheckExpr::Resolve (elems.get_elem_to_copy ()); @@ -1035,7 +1058,8 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) } break; - case HIR::ArrayElems::ArrayExprType::VALUES: { + case HIR::ArrayElems::ArrayExprType::VALUES: + { HIR::ArrayElemsValues &elems = static_cast<HIR::ArrayElemsValues &> (elements); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 79121b3..e0a3278 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -46,6 +46,8 @@ public: void visit (HIR::IfExpr &expr) override; void visit (HIR::IfExprConseqElse &expr) override; void visit (HIR::BlockExpr &expr) override; + void visit (HIR::AnonConst &expr) override; + void visit (HIR::ConstBlock &expr) override; void visit (HIR::UnsafeBlockExpr &expr) override; void visit (HIR::ArrayIndexExpr &expr) override; void visit (HIR::ArrayExpr &expr) override; diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc index bc7f6dc..00f0cc6 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc @@ -266,7 +266,8 @@ TypeCheckImplItem::visit (HIR::Function &function) self_type = self->clone (); break; - case HIR::SelfParam::IMM_REF: { + case HIR::SelfParam::IMM_REF: + { tl::optional<TyTy::Region> region; if (self_param.has_lifetime ()) { @@ -290,7 +291,8 @@ TypeCheckImplItem::visit (HIR::Function &function) } break; - case HIR::SelfParam::MUT_REF: { + case HIR::SelfParam::MUT_REF: + { tl::optional<TyTy::Region> region; if (self_param.has_lifetime ()) { @@ -343,8 +345,8 @@ TypeCheckImplItem::visit (HIR::Function &function) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - canonical_path = nr_ctx.values.to_canonical_path ( - function.get_mappings ().get_nodeid ()); + canonical_path + = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ()); } else { @@ -494,10 +496,9 @@ TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant) rich_location r (line_table, constant.get_locus ()); r.add_range (resolved_trait_item.get_locus ()); - rust_error_at ( - r, "constant %qs has an incompatible type for trait %qs", - constant.get_identifier ().as_string ().c_str (), - trait_reference.get_name ().c_str ()); + rust_error_at (r, "constant %qs has an incompatible type for trait %qs", + constant.get_identifier ().as_string ().c_str (), + trait_reference.get_name ().c_str ()); } } @@ -545,10 +546,9 @@ TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type) rich_location r (line_table, type.get_locus ()); r.add_range (resolved_trait_item.get_locus ()); - rust_error_at ( - r, "type alias %qs has an incompatible type for trait %qs", - type.get_new_type_name ().as_string ().c_str (), - trait_reference.get_name ().c_str ()); + rust_error_at (r, "type alias %qs has an incompatible type for trait %qs", + type.get_new_type_name ().as_string ().c_str (), + trait_reference.get_name ().c_str ()); } // its actually a projection, since we need a way to actually bind the diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index aaa04af..5595dad 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -203,9 +203,8 @@ TypeCheckItem::visit (HIR::TupleStruct &struct_decl) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - path = nr_ctx.values - .to_canonical_path (struct_decl.get_mappings ().get_nodeid ()) - .value (); + path + = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ()); } else { @@ -283,12 +282,8 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl) { auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto canonical_path = nr_ctx.types.to_canonical_path ( - struct_decl.get_mappings ().get_nodeid ()); - - if (!canonical_path.has_value ()) - rust_unreachable (); - path = canonical_path.value (); + path + = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ()); } else { @@ -375,8 +370,8 @@ TypeCheckItem::visit (HIR::Enum &enum_decl) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - canonical_path = nr_ctx.types.to_canonical_path ( - enum_decl.get_mappings ().get_nodeid ()); + canonical_path + = nr_ctx.to_canonical_path (enum_decl.get_mappings ().get_nodeid ()); } else { @@ -439,8 +434,8 @@ TypeCheckItem::visit (HIR::Union &union_decl) auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - canonical_path = nr_ctx.types.to_canonical_path ( - union_decl.get_mappings ().get_nodeid ()); + canonical_path + = nr_ctx.to_canonical_path (union_decl.get_mappings ().get_nodeid ()); } else { @@ -614,10 +609,7 @@ TypeCheckItem::visit (HIR::Function &function) { auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - auto canonical_path = nr_ctx.values.to_canonical_path ( - function.get_mappings ().get_nodeid ()); - - path = canonical_path.value (); + path = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ()); } else { diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index bd13f7a..15d8620 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -213,13 +213,15 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern) auto &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: { + case HIR::TupleStructItems::RANGED: + { // TODO rust_unreachable (); } break; - case HIR::TupleStructItems::MULTIPLE: { + case HIR::TupleStructItems::MULTIPLE: + { HIR::TupleStructItemsNoRange &items_no_range = static_cast<HIR::TupleStructItemsNoRange &> (items); @@ -333,13 +335,15 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) { switch (field->get_item_type ()) { - case HIR::StructPatternField::ItemType::TUPLE_PAT: { + case HIR::StructPatternField::ItemType::TUPLE_PAT: + { // TODO rust_unreachable (); } break; - case HIR::StructPatternField::ItemType::IDENT_PAT: { + case HIR::StructPatternField::ItemType::IDENT_PAT: + { HIR::StructPatternFieldIdentPat &ident = static_cast<HIR::StructPatternFieldIdentPat &> (*field); @@ -358,7 +362,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) } break; - case HIR::StructPatternField::ItemType::IDENT: { + case HIR::StructPatternField::ItemType::IDENT: + { HIR::StructPatternFieldIdent &ident = static_cast<HIR::StructPatternFieldIdent &> (*field); @@ -397,7 +402,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) case HIR::StructPatternField::ItemType::IDENT: case HIR::StructPatternField::ItemType::IDENT_PAT: break; - default: { + default: + { auto first_elem = struct_pattern_elems.get_struct_pattern_fields () .at (0) @@ -459,7 +465,8 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) std::unique_ptr<HIR::TuplePatternItems> items; switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::MULTIPLE: { + case HIR::TuplePatternItems::ItemType::MULTIPLE: + { auto &ref = static_cast<HIR::TuplePatternItemsMultiple &> ( pattern.get_items ()); @@ -498,7 +505,8 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) } break; - case HIR::TuplePatternItems::ItemType::RANGED: { + case HIR::TuplePatternItems::ItemType::RANGED: + { // HIR::TuplePatternItemsRanged &ref // = *static_cast<HIR::TuplePatternItemsRanged *> ( // pattern.get_items ().get ()); @@ -538,6 +546,11 @@ TypeCheckPattern::visit (HIR::RangePattern &pattern) void TypeCheckPattern::visit (HIR::IdentifierPattern &pattern) { + if (pattern.has_subpattern ()) + { + TypeCheckPattern::Resolve (pattern.get_subpattern (), parent); + } + if (!pattern.get_is_ref ()) { infered = parent; @@ -608,7 +621,8 @@ TypeCheckPattern::typecheck_range_pattern_bound ( TyTy::BaseType *resolved_bound = nullptr; switch (bound.get_bound_type ()) { - case HIR::RangePatternBound::RangePatternBoundType::LITERAL: { + case HIR::RangePatternBound::RangePatternBoundType::LITERAL: + { auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound); HIR::Literal lit = ref.get_literal (); @@ -617,14 +631,16 @@ TypeCheckPattern::typecheck_range_pattern_bound ( } break; - case HIR::RangePatternBound::RangePatternBoundType::PATH: { + case HIR::RangePatternBound::RangePatternBoundType::PATH: + { auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound); resolved_bound = TypeCheckExpr::Resolve (ref.get_path ()); } break; - case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: { + case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: + { auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound); resolved_bound = TypeCheckExpr::Resolve (ref.get_qualified_path ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index df1636a..e3a08e6 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -329,8 +329,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) repeat_location.add_range (prev_field_locus); rust_error_at (repeat_location, ErrorCode::E0062, - "field %qs specified more than once", - field_name.c_str ()); + "field %qs specified more than once", field_name.c_str ()); return false; } diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 6919093..18e0458 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -908,7 +908,8 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam ¶m, { switch (bound->get_bound_type ()) { - case HIR::TypeParamBound::BoundType::TRAITBOUND: { + case HIR::TypeParamBound::BoundType::TRAITBOUND: + { HIR::TraitBound &b = static_cast<HIR::TraitBound &> (*bound); TyTy::TypeBoundPredicate predicate = get_predicate_from_bound ( @@ -920,7 +921,8 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam ¶m, { switch (predicate.get_polarity ()) { - case BoundPolarity::AntiBound: { + case BoundPolarity::AntiBound: + { bool found = predicates.find (predicate.get_id ()) != predicates.end (); if (found) @@ -937,7 +939,8 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam ¶m, } break; - default: { + default: + { if (predicates.find (predicate.get_id ()) == predicates.end ()) { @@ -1033,7 +1036,8 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item) { switch (bound->get_bound_type ()) { - case HIR::TypeParamBound::BoundType::TRAITBOUND: { + case HIR::TypeParamBound::BoundType::TRAITBOUND: + { auto *b = static_cast<HIR::TraitBound *> (bound.get ()); TyTy::TypeBoundPredicate predicate @@ -1042,7 +1046,8 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item) specified_bounds.push_back (std::move (predicate)); } break; - case HIR::TypeParamBound::BoundType::LIFETIME: { + case HIR::TypeParamBound::BoundType::LIFETIME: + { if (auto param = binding->try_as<TyTy::ParamType> ()) { auto *b = static_cast<HIR::Lifetime *> (bound.get ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index fbaf323..27879e3 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -29,8 +29,7 @@ // for flag_name_resolution_2_0 #include "options.h" -extern bool -saw_errors (void); +extern bool saw_errors (void); namespace Rust { namespace Resolver { @@ -231,7 +230,8 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const break; case HIR::SelfParam::IMM_REF: - case HIR::SelfParam::MUT_REF: { + case HIR::SelfParam::MUT_REF: + { auto mutability = self_param.get_self_kind () == HIR::SelfParam::IMM_REF ? Mutability::Imm @@ -284,7 +284,7 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path - = nr_ctx.values.to_canonical_path (fn.get_mappings ().get_nodeid ()); + = nr_ctx.to_canonical_path (fn.get_mappings ().get_nodeid ()); } else { diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 18a65fe..356c558 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -263,13 +263,15 @@ public: WARN_UNUSED_RESULT std::vector<TyTy::Region> regions_from_generic_args (const HIR::GenericArgs &args) const; - void compute_inference_variables (bool error); + void compute_inference_variables (bool emit_error); TyTy::VarianceAnalysis::CrateCtx &get_variance_analysis_ctx (); private: TypeCheckContext (); + bool compute_infer_var (HirId id, TyTy::BaseType *ty, bool emit_error); + std::map<NodeId, HirId> node_id_refs; std::map<HirId, TyTy::BaseType *> resolved; std::vector<std::unique_ptr<TyTy::BaseType>> builtins; diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc index f0bd1f8..bdfde55 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.cc +++ b/gcc/rust/typecheck/rust-substitution-mapper.cc @@ -374,7 +374,7 @@ SubstMapperInternal::visit (TyTy::DynamicObjectType &type) void SubstMapperInternal::visit (TyTy::OpaqueType &type) { - resolved = type.handle_substitions (mappings); + resolved = type.clone (); } // SubstMapperFromExisting diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc index c6c5b4b..a549449 100644 --- a/gcc/rust/typecheck/rust-type-util.cc +++ b/gcc/rust/typecheck/rust-type-util.cc @@ -40,12 +40,12 @@ query_type (HirId reference, TyTy::BaseType **result) auto &resolver = *Resolver::get (); TypeCheckContext *context = TypeCheckContext::get (); - if (context->query_in_progress (reference)) - return false; - if (context->lookup_type (reference, result)) return true; + if (context->query_in_progress (reference)) + return false; + context->insert_query (reference); std::pair<HIR::Enum *, HIR::EnumItem *> enum_candidiate diff --git a/gcc/rust/typecheck/rust-type-util.h b/gcc/rust/typecheck/rust-type-util.h index 03874a4..dd97f1e 100644 --- a/gcc/rust/typecheck/rust-type-util.h +++ b/gcc/rust/typecheck/rust-type-util.h @@ -25,33 +25,30 @@ namespace Rust { namespace Resolver { -bool -query_type (HirId reference, TyTy::BaseType **result); +bool query_type (HirId reference, TyTy::BaseType **result); -bool -types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t unify_locus, bool emit_errors); +bool types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, + location_t unify_locus, bool emit_errors); -TyTy::BaseType * -unify_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t unify_locus); +TyTy::BaseType *unify_site (HirId id, TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, location_t unify_locus); -TyTy::BaseType * -unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t unify_locus, bool emit_errors, bool commit_if_ok, - bool implicit_infer_vars, bool cleanup); +TyTy::BaseType *unify_site_and (HirId id, TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, + location_t unify_locus, bool emit_errors, + bool commit_if_ok, bool implicit_infer_vars, + bool cleanup); -TyTy::BaseType * -coercion_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t coercion_locus); +TyTy::BaseType *coercion_site (HirId id, TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, + location_t coercion_locus); -TyTy::BaseType * -try_coercion (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t coercion_locus); +TyTy::BaseType *try_coercion (HirId id, TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs, + location_t coercion_locus); -TyTy::BaseType * -cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to, - location_t cast_locus); +TyTy::BaseType *cast_site (HirId id, TyTy::TyWithLocation from, + TyTy::TyWithLocation to, location_t cast_locus); AssociatedImplTrait * lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound, diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc index 9112b99..7b35848 100644 --- a/gcc/rust/typecheck/rust-typecheck-context.cc +++ b/gcc/rust/typecheck/rust-typecheck-context.cc @@ -575,43 +575,48 @@ TypeCheckContext::regions_from_generic_args (const HIR::GenericArgs &args) const } void -TypeCheckContext::compute_inference_variables (bool error) +TypeCheckContext::compute_inference_variables (bool emit_error) { - auto &mappings = Analysis::Mappings::get (); - // default inference variables if possible iterate ([&] (HirId id, TyTy::BaseType *ty) mutable -> bool { - // nothing to do - if (ty->get_kind () != TyTy::TypeKind::INFER) - return true; + return compute_infer_var (id, ty, emit_error); + }); +} - TyTy::InferType *infer_var = static_cast<TyTy::InferType *> (ty); - TyTy::BaseType *default_type; - - rust_debug_loc (mappings.lookup_location (id), - "trying to default infer-var: %s", - infer_var->as_string ().c_str ()); - bool ok = infer_var->default_type (&default_type); - if (!ok) - { - if (error) - rust_error_at (mappings.lookup_location (id), ErrorCode::E0282, - "type annotations needed"); - return true; - } - - auto result - = unify_site (id, TyTy::TyWithLocation (ty), - TyTy::TyWithLocation (default_type), UNDEF_LOCATION); - rust_assert (result); - rust_assert (result->get_kind () != TyTy::TypeKind::ERROR); - result->set_ref (id); - insert_type (Analysis::NodeMapping (mappings.get_current_crate (), 0, id, - UNKNOWN_LOCAL_DEFID), - result); +bool +TypeCheckContext::compute_infer_var (HirId id, TyTy::BaseType *ty, + bool emit_error) +{ + auto &mappings = Analysis::Mappings::get (); + // nothing to do + if (ty->get_kind () != TyTy::TypeKind::INFER) return true; - }); + + TyTy::InferType *infer_var = static_cast<TyTy::InferType *> (ty); + TyTy::BaseType *default_type; + + rust_debug_loc (mappings.lookup_location (id), + "trying to default infer-var: %s", + infer_var->as_string ().c_str ()); + bool ok = infer_var->default_type (&default_type); + if (!ok) + { + if (emit_error) + rust_error_at (mappings.lookup_location (id), ErrorCode::E0282, + "type annotations needed"); + return true; + } + + auto result + = unify_site (id, TyTy::TyWithLocation (ty), + TyTy::TyWithLocation (default_type), UNDEF_LOCATION); + rust_assert (result); + rust_assert (result->get_kind () != TyTy::TypeKind::ERROR); + result->set_ref (id); + insert_implicit_type (id, result); + + return true; } TyTy::VarianceAnalysis::CrateCtx & diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index e028a0a..5d42f80 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -226,7 +226,8 @@ TypeCheckBase::get_predicate_from_bound ( auto &final_seg = type_path.get_final_segment (); switch (final_seg.get_type ()) { - case HIR::TypePathSegment::SegmentType::GENERIC: { + case HIR::TypePathSegment::SegmentType::GENERIC: + { auto &final_generic_seg = static_cast<HIR::TypePathSegmentGeneric &> (final_seg); if (final_generic_seg.has_generic_args ()) @@ -251,7 +252,8 @@ TypeCheckBase::get_predicate_from_bound ( } break; - case HIR::TypePathSegment::SegmentType::FUNCTION: { + case HIR::TypePathSegment::SegmentType::FUNCTION: + { auto &final_function_seg = static_cast<HIR::TypePathSegmentFunction &> (final_seg); auto &fn = final_function_seg.get_function_path (); diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc index 2e0830e..63bb1ff 100644 --- a/gcc/rust/typecheck/rust-tyty-call.cc +++ b/gcc/rust/typecheck/rust-tyty-call.cc @@ -171,7 +171,8 @@ TypeCheckCallExpr::visit (FnType &type) { case TyTy::TypeKind::ERROR: return; - case TyTy::TypeKind::INT: { + case TyTy::TypeKind::INT: + { auto &int_ty = static_cast<TyTy::IntType &> (*argument_expr_tyty); if ((int_ty.get_int_kind () == TyTy::IntType::IntKind::I8) @@ -186,7 +187,8 @@ TypeCheckCallExpr::visit (FnType &type) } break; } - case TyTy::TypeKind::UINT: { + case TyTy::TypeKind::UINT: + { auto &uint_ty = static_cast<TyTy::UintType &> (*argument_expr_tyty); if ((uint_ty.get_uint_kind () == TyTy::UintType::UintKind::U8) @@ -202,7 +204,8 @@ TypeCheckCallExpr::visit (FnType &type) } break; } - case TyTy::TypeKind::FLOAT: { + case TyTy::TypeKind::FLOAT: + { if (static_cast<TyTy::FloatType &> (*argument_expr_tyty) .get_float_kind () == TyTy::FloatType::FloatKind::F32) @@ -216,14 +219,16 @@ TypeCheckCallExpr::visit (FnType &type) } break; } - case TyTy::TypeKind::BOOL: { + case TyTy::TypeKind::BOOL: + { rich_location richloc (line_table, arg_locus); richloc.add_fixit_replace ("cast the value to c_int: as c_int"); rust_error_at (arg_locus, ErrorCode::E0617, "expected %<c_int%> variadic argument"); return; } - case TyTy::TypeKind::FNDEF: { + case TyTy::TypeKind::FNDEF: + { rust_error_at ( arg_locus, ErrorCode::E0617, "unexpected function definition type as variadic " @@ -246,7 +251,7 @@ TypeCheckCallExpr::visit (FnType &type) } type.monomorphize (); - resolved = type.get_return_type ()->clone (); + resolved = type.get_return_type ()->monomorphized_clone (); } void diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h index c897c13..aeefaa9 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -621,7 +621,8 @@ public: ok = true; return; - case InferType::InferTypeKind::INTEGRAL: { + case InferType::InferTypeKind::INTEGRAL: + { if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL) { ok = true; @@ -635,7 +636,8 @@ public: } break; - case InferType::InferTypeKind::FLOAT: { + case InferType::InferTypeKind::FLOAT: + { if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) { ok = true; diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index bdb6474..28d311a 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -72,6 +72,12 @@ SubstitutionParamMapping::get_generic_param () return generic; } +const HIR::TypeParam & +SubstitutionParamMapping::get_generic_param () const +{ + return generic; +} + bool SubstitutionParamMapping::needs_substitution () const { @@ -618,7 +624,6 @@ SubstitutionRef::get_mappings_from_generic_args ( if (args.get_binding_args ().size () > get_num_associated_bindings ()) { rich_location r (line_table, args.get_locus ()); - rust_error_at (r, "generic item takes at most %lu type binding " "arguments but %lu were supplied", @@ -702,7 +707,19 @@ SubstitutionRef::get_mappings_from_generic_args ( return SubstitutionArgumentMappings::error (); } - SubstitutionArg subst_arg (&substitutions.at (offs), resolved); + const auto ¶m_mapping = substitutions.at (offs); + const auto &type_param = param_mapping.get_generic_param (); + if (type_param.from_impl_trait ()) + { + rich_location r (line_table, arg->get_locus ()); + r.add_fixit_remove (arg->get_locus ()); + rust_error_at (r, ErrorCode::E0632, + "cannot provide explicit generic arguments when " + "%<impl Trait%> is used in argument position"); + return SubstitutionArgumentMappings::error (); + } + + SubstitutionArg subst_arg (¶m_mapping, resolved); offs++; mappings.push_back (std::move (subst_arg)); } diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h index e6ed1fc..2f5de23 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.h +++ b/gcc/rust/typecheck/rust-tyty-subst.h @@ -60,6 +60,7 @@ public: const ParamType *get_param_ty () const; HIR::TypeParam &get_generic_param (); + const HIR::TypeParam &get_generic_param () const; // this is used for the backend to override the HirId ref of the param to // what the concrete type is for the rest of the context diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis.h b/gcc/rust/typecheck/rust-tyty-variance-analysis.h index 9059a2f..282c6f3 100644 --- a/gcc/rust/typecheck/rust-tyty-variance-analysis.h +++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.h @@ -41,9 +41,10 @@ private: std::unique_ptr<GenericTyPerCrateCtx> private_ctx; }; -std::vector<size_t> -query_field_regions (const ADTType *parent, size_t variant_index, - size_t field_index, const FreeRegions &parent_regions); +std::vector<size_t> query_field_regions (const ADTType *parent, + size_t variant_index, + size_t field_index, + const FreeRegions &parent_regions); /** Variance semilattice */ class Variance diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index f0f4a07..91c68ef 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -230,11 +230,13 @@ BaseType::is_unit () const case NEVER: return true; - case TUPLE: { + case TUPLE: + { return x->as<const TupleType> ()->num_fields () == 0; } - case ADT: { + case ADT: + { auto adt = x->as<const ADTType> (); if (adt->is_enum ()) return false; @@ -546,17 +548,14 @@ BaseType::destructure () const { x = p->get (); } - // else if (auto p = x->try_as<const OpaqueType> ()) - // { - // auto pr = p->resolve (); - - // rust_debug ("XXXXXX") - - // if (pr == x) - // return pr; + else if (auto p = x->try_as<const OpaqueType> ()) + { + auto pr = p->resolve (); + if (pr == x) + return pr; - // x = pr; - // } + x = pr; + } else { return x; @@ -894,28 +893,32 @@ BaseType::has_substitutions_defined () const case OPAQUE: return false; - case PROJECTION: { + case PROJECTION: + { const ProjectionType &p = *static_cast<const ProjectionType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (p); return ref.has_substitutions (); } break; - case FNDEF: { + case FNDEF: + { const FnType &fn = *static_cast<const FnType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (fn); return ref.has_substitutions (); } break; - case ADT: { + case ADT: + { const ADTType &adt = *static_cast<const ADTType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (adt); return ref.has_substitutions (); } break; - case CLOSURE: { + case CLOSURE: + { const ClosureType &closure = *static_cast<const ClosureType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (closure); @@ -956,28 +959,32 @@ BaseType::needs_generic_substitutions () const case OPAQUE: return false; - case PROJECTION: { + case PROJECTION: + { const ProjectionType &p = *static_cast<const ProjectionType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (p); return ref.needs_substitution (); } break; - case FNDEF: { + case FNDEF: + { const FnType &fn = *static_cast<const FnType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (fn); return ref.needs_substitution (); } break; - case ADT: { + case ADT: + { const ADTType &adt = *static_cast<const ADTType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (adt); return ref.needs_substitution (); } break; - case CLOSURE: { + case CLOSURE: + { const ClosureType &closure = *static_cast<const ClosureType *> (x); const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (closure); @@ -996,28 +1003,32 @@ BaseType::get_subst_argument_mappings () const const TyTy::BaseType *x = destructure (); switch (x->get_kind ()) { - case PROJECTION: { + case PROJECTION: + { const auto &p = *static_cast<const ProjectionType *> (x); const auto &ref = static_cast<const SubstitutionRef &> (p); return ref.get_substitution_arguments (); } break; - case FNDEF: { + case FNDEF: + { const auto &fn = *static_cast<const FnType *> (x); const auto &ref = static_cast<const SubstitutionRef &> (fn); return ref.get_substitution_arguments (); } break; - case ADT: { + case ADT: + { const auto &adt = *static_cast<const ADTType *> (x); const auto &ref = static_cast<const SubstitutionRef &> (adt); return ref.get_substitution_arguments (); } break; - case CLOSURE: { + case CLOSURE: + { const auto &closure = *static_cast<const ClosureType *> (x); const auto &ref = static_cast<const SubstitutionRef &> (closure); return ref.get_substitution_arguments (); @@ -1140,13 +1151,15 @@ InferType::default_type (BaseType **type) const case GENERAL: return false; - case INTEGRAL: { + case INTEGRAL: + { ok = context->lookup_builtin ("i32", type); rust_assert (ok); return ok; } - case FLOAT: { + case FLOAT: + { ok = context->lookup_builtin ("f64", type); rust_assert (ok); return ok; @@ -1269,7 +1282,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint) default_hint.kind = hint.get_kind (); break; - case INT: { + case INT: + { infer_kind = INTEGRAL; default_hint.kind = hint.get_kind (); default_hint.shint = TypeHint::SignedHint::SIGNED; @@ -1294,7 +1308,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint) } break; - case UINT: { + case UINT: + { infer_kind = INTEGRAL; default_hint.kind = hint.get_kind (); default_hint.shint = TypeHint::SignedHint::UNSIGNED; @@ -1319,7 +1334,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint) } break; - case TypeKind::FLOAT: { + case TypeKind::FLOAT: + { infer_kind = FLOAT; default_hint.shint = TypeHint::SignedHint::SIGNED; default_hint.kind = hint.get_kind (); @@ -1992,7 +2008,7 @@ TupleType::get_name () const std::string fields_buffer; for (const TyVar &field : get_fields ()) { - fields_buffer += field.get_tyty ()->as_string (); + fields_buffer += field.get_tyty ()->get_name (); bool has_next = (i + 1) < get_fields ().size (); fields_buffer += has_next ? ", " : ""; i++; @@ -3624,28 +3640,7 @@ BaseType * OpaqueType::resolve () const { TyVar var (get_ty_ref ()); - BaseType *r = var.get_tyty (); - - while (r->get_kind () == TypeKind::OPAQUE) - { - OpaqueType *rr = static_cast<OpaqueType *> (r); - if (!rr->can_resolve ()) - break; - - TyVar v (rr->get_ty_ref ()); - BaseType *n = v.get_tyty (); - - // fix infinite loop - if (r == n) - break; - - r = n; - } - - if (r->get_kind () == TypeKind::OPAQUE && (r->get_ref () == r->get_ty_ref ())) - return TyVar (r->get_ty_ref ()).get_tyty (); - - return r; + return var.get_tyty (); } bool @@ -3655,41 +3650,9 @@ OpaqueType::is_equal (const BaseType &other) const if (can_resolve () != other2.can_resolve ()) return false; - if (can_resolve ()) - return resolve ()->can_eq (other2.resolve (), false); - return bounds_compatible (other, UNDEF_LOCATION, false); } -OpaqueType * -OpaqueType::handle_substitions (SubstitutionArgumentMappings &subst_mappings) -{ - // SubstitutionArg arg = SubstitutionArg::error (); - // bool ok = subst_mappings.get_argument_for_symbol (this, &arg); - // if (!ok || arg.is_error ()) - // return this; - - // OpaqueType *p = static_cast<OpaqueType *> (clone ()); - // subst_mappings.on_param_subst (*p, arg); - - // // there are two cases one where we substitute directly to a new PARAM and - // // otherwise - // if (arg.get_tyty ()->get_kind () == TyTy::TypeKind::PARAM) - // { - // p->set_ty_ref (arg.get_tyty ()->get_ref ()); - // return p; - // } - - // // this is the new subst that this needs to pass - // p->set_ref (mappings.get_next_hir_id ()); - // p->set_ty_ref (arg.get_tyty ()->get_ref ()); - - // return p; - - rust_unreachable (); - return nullptr; -} - // StrType StrType::StrType (HirId ref, std::set<HirId> refs) diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 1cada9a..c759521 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -78,8 +78,7 @@ enum TypeKind ERROR }; -extern bool -is_primitive_type_kind (TypeKind kind); +extern bool is_primitive_type_kind (TypeKind kind); class TypeKindFormat { @@ -268,8 +267,8 @@ public: {} WARN_UNUSED_RESULT virtual size_t get_num_params () const = 0; - WARN_UNUSED_RESULT virtual BaseType * - get_param_type_at (size_t index) const = 0; + WARN_UNUSED_RESULT virtual BaseType *get_param_type_at (size_t index) const + = 0; WARN_UNUSED_RESULT virtual BaseType *get_return_type () const = 0; }; @@ -441,8 +440,6 @@ public: std::string get_name () const override final; bool is_equal (const BaseType &other) const override; - - OpaqueType *handle_substitions (SubstitutionArgumentMappings &mappings); }; class StructFieldType diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 294b677..9144f2e 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -53,6 +53,22 @@ UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, } TyTy::BaseType * +UnifyRules::resolve_subtype (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs) +{ + TyTy::BaseType *result + = UnifyRules::Resolve (lhs, rhs, locus, commit_flag, emit_error, infer_flag, + commits, infers); + + // If the recursive call resulted in an error and would have emitted an error + // message, disable error emission for the current level to avoid duplicate + // errors + if (result->get_kind () == TyTy::TypeKind::ERROR && emit_error) + emit_error = false; + + return result; +} + +TyTy::BaseType * UnifyRules::get_base () { return lhs.get_ty ()->destructure (); @@ -69,7 +85,6 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other, TyTy::BaseType *resolved) { TypeCheckContext &context = *TypeCheckContext::get (); - Analysis::Mappings &mappings = Analysis::Mappings::get (); TyTy::BaseType *b = base->destructure (); TyTy::BaseType *o = other->destructure (); @@ -102,13 +117,8 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other, continue; // if any of the types are inference variables lets fix them - if (ref_tyty->get_kind () == TyTy::TypeKind::INFER) - { - auto node = Analysis::NodeMapping (mappings.get_current_crate (), - UNKNOWN_NODEID, ref, - UNKNOWN_LOCAL_DEFID); - context.insert_type (node, resolved->clone ()); - } + if (ref_tyty->is<TyTy::InferType> ()) + context.insert_implicit_type (ref, resolved); } } } @@ -328,30 +338,33 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); switch (ltype->get_infer_kind ()) { case TyTy::InferType::InferTypeKind::GENERAL: return rtype->clone (); - case TyTy::InferType::InferTypeKind::INTEGRAL: { + case TyTy::InferType::InferTypeKind::INTEGRAL: + { bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL || r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return rtype->clone (); + return rtype; } break; - case TyTy::InferType::InferTypeKind::FLOAT: { + case TyTy::InferType::InferTypeKind::FLOAT: + { bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT || r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return rtype->clone (); + return rtype; } break; } @@ -361,7 +374,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, case TyTy::INT: case TyTy::UINT: case TyTy::USIZE: - case TyTy::ISIZE: { + case TyTy::ISIZE: + { bool is_valid = (ltype->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) || (ltype->get_infer_kind () @@ -369,12 +383,13 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, if (is_valid) { ltype->apply_primitive_type_hint (*rtype); - return rtype->clone (); + return rtype; } } break; - case TyTy::FLOAT: { + case TyTy::FLOAT: + { bool is_valid = (ltype->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) || (ltype->get_infer_kind () @@ -382,7 +397,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, if (is_valid) { ltype->apply_primitive_type_hint (*rtype); - return rtype->clone (); + return rtype; } } break; @@ -404,7 +419,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, case TyTy::PROJECTION: case TyTy::DYNAMIC: case TyTy::CLOSURE: - case TyTy::OPAQUE: { + case TyTy::OPAQUE: + { bool is_valid = (ltype->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); if (is_valid) @@ -424,7 +440,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -433,7 +450,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::ADT: { + case TyTy::ADT: + { TyTy::ADTType &type = *static_cast<TyTy::ADTType *> (rtype); if (ltype->get_adt_kind () != type.get_adt_kind ()) { @@ -469,11 +487,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) TyTy::BaseType *other_field_ty = other_field->get_field_type (); TyTy::BaseType *unified_ty - = UnifyRules::Resolve (TyTy::TyWithLocation (this_field_ty), - TyTy::TyWithLocation (other_field_ty), - locus, commit_flag, - false /* emit_error */, infer_flag, - commits, infers); + = resolve_subtype (TyTy::TyWithLocation (this_field_ty), + TyTy::TyWithLocation (other_field_ty)); if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -495,11 +510,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) auto pa = a.get_param_ty (); auto pb = b.get_param_ty (); - auto res - = UnifyRules::Resolve (TyTy::TyWithLocation (pa), - TyTy::TyWithLocation (pb), locus, - commit_flag, false /* emit_error */, - infer_flag, commits, infers); + auto res = resolve_subtype (TyTy::TyWithLocation (pa), + TyTy::TyWithLocation (pb)); if (res->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -544,7 +556,8 @@ UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -589,7 +602,8 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -598,16 +612,15 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::REF: { + case TyTy::REF: + { TyTy::ReferenceType &type = *static_cast<TyTy::ReferenceType *> (rtype); auto base_type = ltype->get_base (); auto other_base_type = type.get_base (); TyTy::BaseType *base_resolved - = UnifyRules::Resolve (TyTy::TyWithLocation (base_type), - TyTy::TyWithLocation (other_base_type), locus, - commit_flag, false /* emit_error */, - infer_flag, commits, infers); + = resolve_subtype (TyTy::TyWithLocation (base_type), + TyTy::TyWithLocation (other_base_type)); if (base_resolved->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -660,7 +673,8 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -669,16 +683,15 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::POINTER: { + case TyTy::POINTER: + { TyTy::PointerType &type = *static_cast<TyTy::PointerType *> (rtype); auto base_type = ltype->get_base (); auto other_base_type = type.get_base (); TyTy::BaseType *base_resolved - = UnifyRules::Resolve (TyTy::TyWithLocation (base_type), - TyTy::TyWithLocation (other_base_type), locus, - commit_flag, false /* emit_error */, - infer_flag, commits, infers); + = resolve_subtype (TyTy::TyWithLocation (base_type), + TyTy::TyWithLocation (other_base_type)); if (base_resolved->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -731,7 +744,8 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -740,7 +754,8 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::PARAM: { + case TyTy::PARAM: + { TyTy::ParamType &type = *static_cast<TyTy::ParamType *> (rtype); // bool symbol_matches // = ltype->get_symbol ().compare (type.get_symbol ()) == 0; @@ -793,7 +808,8 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -802,12 +818,12 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::ARRAY: { + case TyTy::ARRAY: + { TyTy::ArrayType &type = *static_cast<TyTy::ArrayType *> (rtype); - TyTy::BaseType *element_unify = UnifyRules::Resolve ( - TyTy::TyWithLocation (ltype->get_element_type ()), - TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag, - false /* emit_error*/, infer_flag, commits, infers); + TyTy::BaseType *element_unify + = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()), + TyTy::TyWithLocation (type.get_element_type ())); if (element_unify->get_kind () != TyTy::TypeKind::ERROR) { @@ -853,7 +869,8 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -862,12 +879,12 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::SLICE: { + case TyTy::SLICE: + { TyTy::SliceType &type = *static_cast<TyTy::SliceType *> (rtype); - TyTy::BaseType *element_unify = UnifyRules::Resolve ( - TyTy::TyWithLocation (ltype->get_element_type ()), - TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag, - false /* emit_error*/, infer_flag, commits, infers); + TyTy::BaseType *element_unify + = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()), + TyTy::TyWithLocation (type.get_element_type ())); if (element_unify->get_kind () != TyTy::TypeKind::ERROR) { @@ -912,7 +929,8 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -921,7 +939,8 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::FNDEF: { + case TyTy::FNDEF: + { TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype); if (ltype->num_params () != type.num_params ()) { @@ -933,21 +952,17 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) auto a = ltype->param_at (i).get_type (); auto b = type.param_at (i).get_type (); - auto unified_param - = UnifyRules::Resolve (TyTy::TyWithLocation (a), - TyTy::TyWithLocation (b), locus, - commit_flag, false /* emit_errors */, - infer_flag, commits, infers); + auto unified_param = resolve_subtype (TyTy::TyWithLocation (a), + TyTy::TyWithLocation (b)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); } } - auto unified_return = UnifyRules::Resolve ( - TyTy::TyWithLocation (ltype->get_return_type ()), - TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag, - false /* emit_errors */, infer_flag, commits, infers); + auto unified_return + = resolve_subtype (TyTy::TyWithLocation (ltype->get_return_type ()), + TyTy::TyWithLocation (type.get_return_type ())); if (unified_return->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -1003,7 +1018,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1012,7 +1028,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) } break; - case TyTy::FNPTR: { + case TyTy::FNPTR: + { TyTy::FnPtr &type = *static_cast<TyTy::FnPtr *> (rtype); if (ltype->num_params () != type.num_params ()) { @@ -1024,21 +1041,17 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) auto a = ltype->get_param_type_at (i); auto b = type.get_param_type_at (i); - auto unified_param - = UnifyRules::Resolve (TyTy::TyWithLocation (a), - TyTy::TyWithLocation (b), locus, - commit_flag, false /* emit_errors */, - infer_flag, commits, infers); + auto unified_param = resolve_subtype (TyTy::TyWithLocation (a), + TyTy::TyWithLocation (b)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); } } - auto unified_return = UnifyRules::Resolve ( - TyTy::TyWithLocation (ltype->get_return_type ()), - TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag, - false /* emit_errors */, infer_flag, commits, infers); + auto unified_return + = resolve_subtype (TyTy::TyWithLocation (ltype->get_return_type ()), + TyTy::TyWithLocation (type.get_return_type ())); if (unified_return->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -1048,16 +1061,15 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) } break; - case TyTy::FNDEF: { + case TyTy::FNDEF: + { TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype); auto this_ret_type = ltype->get_return_type (); auto other_ret_type = type.get_return_type (); auto unified_result - = UnifyRules::Resolve (TyTy::TyWithLocation (this_ret_type), - TyTy::TyWithLocation (other_ret_type), locus, - commit_flag, false /*emit_errors*/, infer_flag, - commits, infers); + = resolve_subtype (TyTy::TyWithLocation (this_ret_type), + TyTy::TyWithLocation (other_ret_type)); if (unified_result->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -1074,10 +1086,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) auto other_param = type.param_at (i).get_type (); auto unified_param - = UnifyRules::Resolve (TyTy::TyWithLocation (this_param), - TyTy::TyWithLocation (other_param), locus, - commit_flag, false /* emit_errors */, - infer_flag, commits, infers); + = resolve_subtype (TyTy::TyWithLocation (this_param), + TyTy::TyWithLocation (other_param)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -1120,7 +1130,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1129,7 +1140,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::TUPLE: { + case TyTy::TUPLE: + { TyTy::TupleType &type = *static_cast<TyTy::TupleType *> (rtype); if (ltype->num_fields () != type.num_fields ()) { @@ -1143,10 +1155,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) TyTy::BaseType *fo = type.get_field (i); TyTy::BaseType *unified_ty - = UnifyRules::Resolve (TyTy::TyWithLocation (bo), - TyTy::TyWithLocation (fo), locus, - commit_flag, false /* emit_errors */, - infer_flag, commits, infers); + = resolve_subtype (TyTy::TyWithLocation (bo), + TyTy::TyWithLocation (fo)); if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) return new TyTy::ErrorType (0); @@ -1191,7 +1201,8 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1239,7 +1250,8 @@ UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1287,7 +1299,8 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL @@ -1300,7 +1313,8 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::INT: { + case TyTy::INT: + { TyTy::IntType &type = *static_cast<TyTy::IntType *> (rtype); bool is_valid = ltype->get_int_kind () == type.get_int_kind (); if (is_valid) @@ -1342,7 +1356,8 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL @@ -1355,7 +1370,8 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::UINT: { + case TyTy::UINT: + { TyTy::UintType &type = *static_cast<TyTy::UintType *> (rtype); bool is_valid = ltype->get_uint_kind () == type.get_uint_kind (); if (is_valid) @@ -1397,7 +1413,8 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL @@ -1410,7 +1427,8 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::FLOAT: { + case TyTy::FLOAT: + { TyTy::FloatType &type = *static_cast<TyTy::FloatType *> (rtype); bool is_valid = ltype->get_float_kind () == type.get_float_kind (); if (is_valid) @@ -1452,7 +1470,8 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT; @@ -1500,7 +1519,8 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT; @@ -1548,7 +1568,8 @@ UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1569,7 +1590,8 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype, { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1619,7 +1641,8 @@ UnifyRules::expect_projection (TyTy::ProjectionType *ltype, { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1666,7 +1689,8 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1675,7 +1699,8 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::DYNAMIC: { + case TyTy::DYNAMIC: + { TyTy::DynamicObjectType &type = *static_cast<TyTy::DynamicObjectType *> (rtype); if (ltype->num_specified_bounds () != type.num_specified_bounds ()) @@ -1725,7 +1750,8 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) { switch (rtype->get_kind ()) { - case TyTy::INFER: { + case TyTy::INFER: + { TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; @@ -1734,26 +1760,25 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) } break; - case TyTy::CLOSURE: { + case TyTy::CLOSURE: + { TyTy::ClosureType &type = *static_cast<TyTy::ClosureType *> (rtype); if (ltype->get_def_id () != type.get_def_id ()) { return new TyTy::ErrorType (0); } - TyTy::BaseType *args_res = UnifyRules::Resolve ( - TyTy::TyWithLocation (<ype->get_parameters ()), - TyTy::TyWithLocation (&type.get_parameters ()), locus, commit_flag, - false /* emit_error */, infer_flag, commits, infers); + TyTy::BaseType *args_res + = resolve_subtype (TyTy::TyWithLocation (<ype->get_parameters ()), + TyTy::TyWithLocation (&type.get_parameters ())); if (args_res->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); } - TyTy::BaseType *res = UnifyRules::Resolve ( - TyTy::TyWithLocation (<ype->get_result_type ()), - TyTy::TyWithLocation (&type.get_result_type ()), locus, commit_flag, - false /* emit_error */, infer_flag, commits, infers); + TyTy::BaseType *res + = resolve_subtype (TyTy::TyWithLocation (<ype->get_result_type ()), + TyTy::TyWithLocation (&type.get_result_type ())); if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR) { return new TyTy::ErrorType (0); @@ -1794,59 +1819,47 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) TyTy::BaseType * UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) { - switch (rtype->get_kind ()) + if (rtype->is<TyTy::OpaqueType> ()) { - case TyTy::INFER: { - TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype); - bool is_valid - = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; - if (is_valid) - return ltype->clone (); - } - break; + TyTy::OpaqueType *ro = rtype->as<TyTy::OpaqueType> (); + if (!ltype->is_equal (*ro)) + return new TyTy::ErrorType (0); - case TyTy::OPAQUE: { - auto &type = *static_cast<TyTy::OpaqueType *> (rtype); - if (ltype->num_specified_bounds () != type.num_specified_bounds ()) - { - return new TyTy::ErrorType (0); - } + if (ltype->can_resolve () && ro->can_resolve ()) + { + auto lr = ltype->resolve (); + auto rr = ro->resolve (); - if (!ltype->bounds_compatible (type, locus, true)) - { + auto res = resolve_subtype (TyTy::TyWithLocation (lr), + TyTy::TyWithLocation (rr)); + if (res->get_kind () == TyTy::TypeKind::ERROR) return new TyTy::ErrorType (0); - } - - return ltype->clone (); - } - break; - - case TyTy::CLOSURE: - case TyTy::SLICE: - case TyTy::PARAM: - case TyTy::POINTER: - case TyTy::STR: - case TyTy::ADT: - case TyTy::REF: - case TyTy::ARRAY: - case TyTy::FNDEF: - case TyTy::FNPTR: - case TyTy::TUPLE: - case TyTy::BOOL: - case TyTy::CHAR: - case TyTy::INT: - case TyTy::UINT: - case TyTy::FLOAT: - case TyTy::USIZE: - case TyTy::ISIZE: - case TyTy::NEVER: - case TyTy::PLACEHOLDER: - case TyTy::PROJECTION: - case TyTy::DYNAMIC: - case TyTy::ERROR: - return new TyTy::ErrorType (0); + } + else if (ltype->can_resolve ()) + { + auto lr = ltype->resolve (); + ro->set_ty_ref (lr->get_ref ()); + } + else if (ro->can_resolve ()) + { + auto rr = ro->resolve (); + ltype->set_ty_ref (rr->get_ref ()); + } } - return new TyTy::ErrorType (0); + else if (ltype->can_resolve ()) + { + auto underly = ltype->resolve (); + auto res = resolve_subtype (TyTy::TyWithLocation (underly), + TyTy::TyWithLocation (rtype)); + if (res->get_kind () == TyTy::TypeKind::ERROR) + return new TyTy::ErrorType (0); + } + else + { + ltype->set_ty_ref (rtype->get_ref ()); + } + + return ltype; } } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h index 5ff3b7c..f64f0ed 100644 --- a/gcc/rust/typecheck/rust-unify.h +++ b/gcc/rust/typecheck/rust-unify.h @@ -91,6 +91,9 @@ private: std::vector<CommitSite> &commits, std::vector<InferenceSite> &infers); + TyTy::BaseType *resolve_subtype (TyTy::TyWithLocation lhs, + TyTy::TyWithLocation rhs); + void emit_type_mismatch () const; void emit_abi_mismatch (const TyTy::FnType &expected, const TyTy::FnType &got) const; diff --git a/gcc/rust/util/rust-abi.h b/gcc/rust/util/rust-abi.h index a0180ed..357a5db 100644 --- a/gcc/rust/util/rust-abi.h +++ b/gcc/rust/util/rust-abi.h @@ -34,11 +34,9 @@ enum ABI SYSV64 }; -extern Rust::ABI -get_abi_from_string (const std::string &abi); +extern Rust::ABI get_abi_from_string (const std::string &abi); -extern std::string -get_string_from_abi (Rust::ABI abi); +extern std::string get_string_from_abi (Rust::ABI abi); } // namespace Rust diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index c77e99c..9bf4f77 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -221,7 +221,8 @@ check_doc_attribute (const AST::Attribute &attribute) break; // FIXME: Handle them as well - case AST::AttrInput::TOKEN_TREE: { + case AST::AttrInput::TOKEN_TREE: + { // FIXME: This doesn't check for #[doc(alias(...))] const auto &option = static_cast<const AST::DelimTokenTree &> ( attribute.get_attr_input ()); diff --git a/gcc/rust/util/rust-base62.h b/gcc/rust/util/rust-base62.h index e751c95..5fd7a37 100644 --- a/gcc/rust/util/rust-base62.h +++ b/gcc/rust/util/rust-base62.h @@ -26,8 +26,7 @@ namespace Rust { /** * Get the Base62 representation of an integer */ -std::string -base62_integer (uint64_t value); +std::string base62_integer (uint64_t value); } // namespace Rust diff --git a/gcc/rust/util/rust-canonical-path.h b/gcc/rust/util/rust-canonical-path.h index 4d8f954..079ae76 100644 --- a/gcc/rust/util/rust-canonical-path.h +++ b/gcc/rust/util/rust-canonical-path.h @@ -57,10 +57,11 @@ public: return *this; } - static CanonicalPath new_seg (NodeId id, const std::string &path) + static CanonicalPath new_seg (NodeId id, std::string path) { rust_assert (!path.empty ()); - return CanonicalPath ({std::pair<NodeId, std::string> (id, path)}, + return CanonicalPath ({std::pair<NodeId, std::string> (id, + std::move (path))}, UNKNOWN_CRATENUM); } @@ -68,14 +69,18 @@ public: trait_impl_projection_seg (NodeId id, const CanonicalPath &trait_seg, const CanonicalPath &impl_type_seg) { - return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + " as " + // https://doc.rust-lang.org/reference/paths.html#canonical-paths + // should be "<X>"? + return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + " as " + trait_seg.get () + ">"); } static CanonicalPath inherent_impl_seg (NodeId id, const CanonicalPath &impl_type_seg) { - return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + ">"); + // https://doc.rust-lang.org/reference/paths.html#canonical-paths + // should be "<X as Y>"? + return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + ">"); } std::string get () const diff --git a/gcc/rust/util/rust-dir-owner.h b/gcc/rust/util/rust-dir-owner.h index dcb45d8..fb72bb1 100644 --- a/gcc/rust/util/rust-dir-owner.h +++ b/gcc/rust/util/rust-dir-owner.h @@ -26,8 +26,7 @@ namespace Rust { // extracts the owned subdirectory name from a file name -bool -get_file_subdir (const std::string &filename, std::string &subdir); +bool get_file_subdir (const std::string &filename, std::string &subdir); } // namespace Rust diff --git a/gcc/rust/util/rust-edition.h b/gcc/rust/util/rust-edition.h index d034ea0..532fedb 100644 --- a/gcc/rust/util/rust-edition.h +++ b/gcc/rust/util/rust-edition.h @@ -33,8 +33,7 @@ enum class Edition E2021 }; -Edition -get_rust_edition (); +Edition get_rust_edition (); } // namespace Rust diff --git a/gcc/rust/util/rust-punycode.h b/gcc/rust/util/rust-punycode.h index a939f05..75260ce 100644 --- a/gcc/rust/util/rust-punycode.h +++ b/gcc/rust/util/rust-punycode.h @@ -27,8 +27,7 @@ namespace Rust { /* Encode a string as punycode. Returns a string if encoding is successful. * Returns nullopt otherwise. Note that a returned string contains only ASCII * characters and does not start with `xn--`. */ -tl::optional<std::string> -encode_punycode (const Utf8String &src); +tl::optional<std::string> encode_punycode (const Utf8String &src); } // namespace Rust @@ -36,8 +35,7 @@ encode_punycode (const Utf8String &src); namespace selftest { -void -rust_punycode_encode_test (); +void rust_punycode_encode_test (); } // namespace selftest diff --git a/gcc/rust/util/rust-token-converter.cc b/gcc/rust/util/rust-token-converter.cc index fc34adb..52172f4 100644 --- a/gcc/rust/util/rust-token-converter.cc +++ b/gcc/rust/util/rust-token-converter.cc @@ -202,7 +202,8 @@ convert (const std::vector<const_TokenPtr> &tokens) case PERCENT_EQ: case SCOPE_RESOLUTION: case NOT_EQUAL: - case EQUAL_EQUAL: { + case EQUAL_EQUAL: + { auto str = token->as_string (); auto it = str.cbegin (); for (; it != str.cend () - 1; it++) @@ -260,9 +261,8 @@ convert (const std::vector<const_TokenPtr> &tokens) return trees.back (); } -static void -from_tokenstream (const ProcMacro::TokenStream &ts, - std::vector<const_TokenPtr> &result); +static void from_tokenstream (const ProcMacro::TokenStream &ts, + std::vector<const_TokenPtr> &result); /** * Append the token corresponding to a given Ident to a vector. diff --git a/gcc/rust/util/rust-token-converter.h b/gcc/rust/util/rust-token-converter.h index 5405d6e..6e4af50 100644 --- a/gcc/rust/util/rust-token-converter.h +++ b/gcc/rust/util/rust-token-converter.h @@ -23,14 +23,11 @@ namespace Rust { -ProcMacro::TokenStream -convert (const std::vector<const_TokenPtr> &tokens); +ProcMacro::TokenStream convert (const std::vector<const_TokenPtr> &tokens); -std::vector<const_TokenPtr> -convert (const ProcMacro::TokenStream &ts); +std::vector<const_TokenPtr> convert (const ProcMacro::TokenStream &ts); -ProcMacro::Literal -convert_literal (const_TokenPtr lit); +ProcMacro::Literal convert_literal (const_TokenPtr lit); } // namespace Rust diff --git a/gcc/rust/util/rust-unicode.h b/gcc/rust/util/rust-unicode.h index 6a6526d..6579b80 100644 --- a/gcc/rust/util/rust-unicode.h +++ b/gcc/rust/util/rust-unicode.h @@ -59,20 +59,15 @@ public: Utf8String nfc_normalize () const; }; -bool -is_alphabetic (uint32_t codepoint); +bool is_alphabetic (uint32_t codepoint); -bool -is_ascii_only (const std::string &str); +bool is_ascii_only (const std::string &str); -bool -is_numeric (uint32_t codepoint); +bool is_numeric (uint32_t codepoint); -bool -is_nfc_qc_no (uint32_t codepoint); +bool is_nfc_qc_no (uint32_t codepoint); -bool -is_nfc_qc_maybe (uint32_t codepoint); +bool is_nfc_qc_maybe (uint32_t codepoint); enum class QuickCheckResult { @@ -81,8 +76,7 @@ enum class QuickCheckResult MAYBE }; -QuickCheckResult -nfc_quick_check (const std::vector<Codepoint> &s); +QuickCheckResult nfc_quick_check (const std::vector<Codepoint> &s); } // namespace Rust @@ -90,14 +84,11 @@ nfc_quick_check (const std::vector<Codepoint> &s); namespace selftest { -void -rust_nfc_qc_test (); +void rust_nfc_qc_test (); -void -rust_utf8_normalize_test (); +void rust_utf8_normalize_test (); -void -rust_utf8_property_test (); +void rust_utf8_property_test (); } // namespace selftest diff --git a/gcc/rust/util/rust-unwrap-segment.h b/gcc/rust/util/rust-unwrap-segment.h index bebdc3a..af3a237 100644 --- a/gcc/rust/util/rust-unwrap-segment.h +++ b/gcc/rust/util/rust-unwrap-segment.h @@ -83,14 +83,11 @@ public: /* * Used to get the node id of a path segment object */ -NodeId -unwrap_segment_node_id (const AST::TypePathSegment &seg); +NodeId unwrap_segment_node_id (const AST::TypePathSegment &seg); -NodeId -unwrap_segment_node_id (const AST::SimplePathSegment &seg); +NodeId unwrap_segment_node_id (const AST::SimplePathSegment &seg); -NodeId -unwrap_segment_node_id (const AST::PathExprSegment &seg); +NodeId unwrap_segment_node_id (const AST::PathExprSegment &seg); template <class T> NodeId diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b43cbb7..f9f3de6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,193 @@ +2025-08-04 Patrick Palka <ppalka@redhat.com> + + PR c++/121351 + * g++.dg/cpp2a/concepts-using6.C: New test. + +2025-08-04 Patrick Palka <ppalka@redhat.com> + + PR c++/121351 + PR c++/119859 + * g++.dg/cpp2a/concepts-using5.C: New test. + * g++.dg/cpp2a/concepts-using5a.C: New test. + +2025-08-04 Patrick Palka <ppalka@redhat.com> + + PR c++/120620 + * g++.dg/cpp2a/constexpr-dynamic19.C: New test. + * g++.dg/cpp2a/constexpr-dynamic1a.C: New test. + +2025-08-04 David Malcolm <dmalcolm@redhat.com> + + PR diagnostics/116253 + * gcc.dg/plugin/diagnostic-test-nesting-html.c: New test. + * gcc.dg/plugin/diagnostic-test-nesting-html.py: New test script. + * gcc.dg/plugin/plugin.exp: Add it. + * libgdiagnostics.dg/test-multiple-lines.c: Update expected output + to show fix-it hint. + * sarif-replay.dg/2.1.0-valid/nested-diagnostics-1.sarif: New test. + +2025-08-04 David Malcolm <dmalcolm@redhat.com> + + PR diagnostics/116792 + * gcc.dg/plugin/diagnostic-test-graphs-html.py: Remove trailing + space from expected text of message. + * sarif-replay.dg/2.1.0-valid/embedded-links-check-html.py: + Likewise. + * sarif-replay.dg/2.1.0-valid/graphs-check-html.py: Likewise. + +2025-08-04 Konstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu> + + PR rtl-optimization/121303 + * gcc.target/i386/pr121303.c: New test. + +2025-08-04 Jakub Jelinek <jakub@redhat.com> + + PR preprocessor/120778 + * g++.dg/DRs/dr2580.C: New test. + +2025-08-04 Jakub Jelinek <jakub@redhat.com> + + PR preprocessor/120778 + * g++.dg/DRs/dr2578.C: New test. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/acle/general/dupq_13.c: New test. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/acle/general/dup_1.c: New test. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/acle/general/pnext_3.c: New test. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve2/acle/general/match_4.c: New test. + * gcc.target/aarch64/sve2/acle/general/nmatch_1.c: Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/acle/general/acge_1.c: New test. + * gcc.target/aarch64/sve/acle/general/acgt_1.c: Likewise. + * gcc.target/aarch64/sve/acle/general/acle_1.c: Likewise. + * gcc.target/aarch64/sve/acle/general/aclt_1.c: Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/acle/general/cmpeq_6.c: New test. + * gcc.target/aarch64/sve/acle/general/cmpge_9.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpgt_9.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmple_9.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmplt_9.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpne_5.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpuo_1.c: Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/acle/general/cmpeq_5.c: New test. + * gcc.target/aarch64/sve/acle/general/cmpge_7.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpge_8.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpgt_7.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpgt_8.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmple_7.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmple_8.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmplt_7.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmplt_8.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpne_4.c: Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/acle/general/cmpeq_1.c: Check the number + of PTRUEs. + * gcc.target/aarch64/sve/acle/general/cmpge_5.c: New test. + * gcc.target/aarch64/sve/acle/general/cmpge_6.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpgt_5.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpgt_6.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmple_5.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmple_6.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmplt_5.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmplt_6.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpne_3.c: Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/acle/general/cmpeq_1.c: Add more tests. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/pred_clobber_1.c: Disable combine. + * gcc.target/aarch64/sve/pred_clobber_2.c: Likewise. + * gcc.target/aarch64/sve/pred_clobber_3.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpeq_2.c: Add more cases. + * gcc.target/aarch64/sve/acle/general/cmpeq_4.c: New test. + * gcc.target/aarch64/sve/acle/general/cmpge_1.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpge_2.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpge_3.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpge_4.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpgt_1.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpgt_2.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpgt_3.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpgt_4.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmple_1.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmple_2.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmple_3.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmple_4.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmplt_1.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmplt_2.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmplt_3.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmplt_4.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpne_1.c: Likewise. + * gcc.target/aarch64/sve/acle/general/cmpne_2.c: Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/acle/general/unpkhi_1.c: New test. + * gcc.target/aarch64/sve/acle/general/unpklo_1.c: Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + PR target/121294 + * gcc.target/aarch64/sve/acle/general/rev_2.c: New test. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + PR target/121294 + * gcc.target/aarch64/sve/acle/general/perm_2.c: New test. + * gcc.target/aarch64/sve/acle/general/perm_3.c: Likewise. + * gcc.target/aarch64/sve/acle/general/perm_4.c: Likewise. + * gcc.target/aarch64/sve/acle/general/perm_5.c: Likewise. + * gcc.target/aarch64/sve/acle/general/perm_6.c: Likewise. + * gcc.target/aarch64/sve/acle/general/perm_7.c: Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + PR testsuite/121118 + * gcc.target/aarch64/sve/acle/general/pr121118_1.c: New test. + * gcc.target/aarch64/sve/acle/general/whilele_13.c: Likewise. + * gcc.target/aarch64/sve/acle/general/whilelt_6.c: Likewise. + * gcc.target/aarch64/sve2/acle/general/whilege_1.c: Likewise. + * gcc.target/aarch64/sve2/acle/general/whilegt_1.c: Likewise. + * gcc.target/aarch64/sve2/acle/general/whilerw_5.c: Likewise. + * gcc.target/aarch64/sve2/acle/general/whilewr_5.c: Likewise. + +2025-08-04 Richard Sandiford <richard.sandiford@arm.com> + + PR target/121293 + * gcc.target/aarch64/sve/acle/general/dupq_lane_9.c: New test. + +2025-08-04 Richard Biener <rguenther@suse.de> + + PR tree-optimization/121362 + * gcc.dg/tree-ssa/ssa-fre-105.c: New testcase. + * gcc.dg/tree-ssa/ssa-fre-106.c: Likewise. + +2025-08-04 H.J. Lu <hjl.tools@gmail.com> + + PR target/120941 + * gcc.target/i386/pr120941-1.c: New test. + 2025-08-03 Jakub Jelinek <jakub@redhat.com> PR preprocessor/120778 diff --git a/gcc/testsuite/c-c++-common/cpp/va-opt-6.c b/gcc/testsuite/c-c++-common/cpp/va-opt-6.c index 8a7761b..9a92431 100644 --- a/gcc/testsuite/c-c++-common/cpp/va-opt-6.c +++ b/gcc/testsuite/c-c++-common/cpp/va-opt-6.c @@ -3,15 +3,15 @@ /* { dg-options "-std=c++20" { target c++ } } */ #define a "" -#define b(...) a ## #__VA_OPT__(1) /* { dg-error "pasting \"a\" and \"\"\"\" does not give a valid preprocessing token" } */ -#define c(...) a ## #__VA_OPT__(1) /* { dg-error "pasting \"a\" and \"\"1\"\" does not give a valid preprocessing token" } */ +#define b(...) a ## #__VA_OPT__(1) /* { dg-error "pasting 'a' and '\"\"' does not give a valid preprocessing token" } */ +#define c(...) a ## #__VA_OPT__(1) /* { dg-error "pasting 'a' and '\"1\"' does not give a valid preprocessing token" } */ #define d(...) #__VA_OPT__(1) ## ! #define e(...) #__VA_OPT__(1) ## ! #define f(...) #__VA_OPT__(. ## !) #define g(...) #__VA_OPT__(. ## !) b() c(1) -d( ) /* { dg-error "pasting \"\"\"\" and \"!\" does not give a valid preprocessing token" } */ -e( 1 ) /* { dg-error "pasting \"\"1\"\" and \"!\" does not give a valid preprocessing token" } */ +d( ) /* { dg-error "pasting '\"\"' and '!' does not give a valid preprocessing token" } */ +e( 1 ) /* { dg-error "pasting '\"1\"' and '!' does not give a valid preprocessing token" } */ f() -g(0) /* { dg-error "pasting \".\" and \"!\" does not give a valid preprocessing token" } */ +g(0) /* { dg-error "pasting '.' and '!' does not give a valid preprocessing token" } */ diff --git a/gcc/testsuite/g++.dg/DRs/dr2579.C b/gcc/testsuite/g++.dg/DRs/dr2579.C new file mode 100644 index 0000000..dda3643 --- /dev/null +++ b/gcc/testsuite/g++.dg/DRs/dr2579.C @@ -0,0 +1,9 @@ +// DR 2579 - Undefined behavior when token pasting does not create a preprocessing token +// { dg-do preprocess } +// { dg-options "-pedantic-errors" } + +#define A(a, b) a ## b +A(5,6) +A(-,32) // { dg-error "pasting '-' and '32' does not give a valid preprocessing token" } +A("","") // { dg-error "pasting '\"\"' and '\"\"' does not give a valid preprocessing token" } +A(\,u0393) diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-using6.C b/gcc/testsuite/g++.dg/cpp2a/concepts-using6.C new file mode 100644 index 0000000..a40519a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-using6.C @@ -0,0 +1,20 @@ +// PR c++/121351 +// { dg-do compile { target c++20 } } + +template<class T> concept C = true; + +template<class T> +struct A { + template<class U> void f(U) requires C<T>; // #1 +}; + +template<class T> +struct B : A<T*> { + using A<T*>::f; + template<class U> void f(U) requires C<T>; // #2 +}; + +int main() { + B<int> b; + b.f(42); // { dg-error "ambiguous" } #1 and #2 don't correspond +} diff --git a/gcc/testsuite/gcc.dg/bitintext.h b/gcc/testsuite/gcc.dg/bitintext.h index 99fedb3..d5f2689d 100644 --- a/gcc/testsuite/gcc.dg/bitintext.h +++ b/gcc/testsuite/gcc.dg/bitintext.h @@ -4,6 +4,24 @@ do_copy (void *p, const void *q, __SIZE_TYPE__ r) __builtin_memcpy (p, q, r); } +/* Obtain the value of N from a _BitInt(N)-typed expression X + at compile time. */ +#define S(x) \ + ((typeof (x)) -1 < 0 \ + ? __builtin_clrsbg (__builtin_choose_expr ((typeof (x)) -1 < 0, \ + (typeof (x)) -1, -1)) + 1 \ + : __builtin_popcountg (__builtin_choose_expr ((typeof (x)) -1 < 0, \ + 0U, (typeof (x)) -1))) + +#define CEIL(x,y) (((x) + (y) - 1) / (y)) + +/* Promote a _BitInt type to include its padding bits. */ +#if defined (__s390x__) || defined(__arm__) +#define PROMOTED_SIZE(x) sizeof (x) +#elif defined(__loongarch__) +#define PROMOTED_SIZE(x) (sizeof (x) > 8 ? CEIL (S (x), 64) * 8 : sizeof (x)) +#endif + /* Macro to test whether (on targets where psABI requires it) _BitInt with padding bits have those filled with sign or zero extension. */ #if defined(__s390x__) || defined(__arm__) || defined(__loongarch__) @@ -11,14 +29,14 @@ do_copy (void *p, const void *q, __SIZE_TYPE__ r) do { \ if ((typeof (x)) -1 < 0) \ { \ - _BitInt(sizeof (x) * __CHAR_BIT__) __x; \ + _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x; \ do_copy (&__x, &(x), sizeof (__x)); \ if (__x != (x)) \ __builtin_abort (); \ } \ else \ { \ - unsigned _BitInt(sizeof (x) * __CHAR_BIT__) __x; \ + unsigned _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x; \ do_copy (&__x, &(x), sizeof (__x)); \ if (__x != (x)) \ __builtin_abort (); \ diff --git a/gcc/testsuite/gcc.dg/c23-attr-syntax-6.c b/gcc/testsuite/gcc.dg/c23-attr-syntax-6.c index f8c5b0f..4e6b80b 100644 --- a/gcc/testsuite/gcc.dg/c23-attr-syntax-6.c +++ b/gcc/testsuite/gcc.dg/c23-attr-syntax-6.c @@ -45,7 +45,7 @@ typedef int [[__extension__ __extension__]] b2; /* { dg-error {'extension' attri typedef int [[__extension__ unknown_attribute]] b3; /* { dg-error {'unknown_attribute' attribute ignored} } */ typedef int [[__extension__ gnu:vector_size(4)]] b4; /* { dg-error {expected '\]' before ':'} } */ /* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */ -typedef int [[__extension__ gnu JOIN2(:,:) vector_size (4)]] b5; /* { dg-error {pasting ":" and ":" does not give a valid preprocessing token} } */ +typedef int [[__extension__ gnu JOIN2(:,:) vector_size (4)]] b5; /* { dg-error {pasting ':' and ':' does not give a valid preprocessing token} } */ /* { dg-error {expected '\]' before ':'} "" { target *-*-* } .-1 } */ /* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-2 } */ typedef int [[__extension__ gnu : : vector_size (4)]] b6; /* { dg-error {expected '\]' before ':'} } */ @@ -81,7 +81,7 @@ typedef int [[gnu :: vector_size (4)]] b18; /* { dg-error {attributes before C23 typedef int [[gnu FOO vector_size (4)]] b19; /* { dg-error {attributes before C23} } */ typedef int [[gnu :: vector_size (sizeof (void (*)(...)))]] b20; /* { dg-error {attributes before C23} } */ /* { dg-error {requires a named argument before} "" { target *-*-* } .-1 } */ -typedef int [[gnu JOIN2(:,:) vector_size (4)]] b21; /* { dg-error {pasting ":" and ":" does not give a valid preprocessing token} } */ +typedef int [[gnu JOIN2(:,:) vector_size (4)]] b21; /* { dg-error {pasting ':' and ':' does not give a valid preprocessing token} } */ /* { dg-error {expected '\]' before ':'} "" { target *-*-* } .-1 } */ /* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-2 } */ /* { dg-error {attributes before C23} "" { target *-*-* } .-3 } */ diff --git a/gcc/testsuite/gcc.dg/cpp/paste12-2.c b/gcc/testsuite/gcc.dg/cpp/paste12-2.c index 6e2e4f1..f46645a 100644 --- a/gcc/testsuite/gcc.dg/cpp/paste12-2.c +++ b/gcc/testsuite/gcc.dg/cpp/paste12-2.c @@ -6,6 +6,6 @@ /* Test correct diagnostics when pasting in #include. Source: PR preprocessor/6780. */ -#define inc2(a,b) <##a.b> /* { dg-error "pasting \"<\" and \"stdio\" does not" } */ +#define inc2(a,b) <##a.b> /* { dg-error "pasting '<' and 'stdio' does not" } */ #define INC(X) inc2(X,h) #include INC(stdio) diff --git a/gcc/testsuite/gcc.dg/cpp/paste12.c b/gcc/testsuite/gcc.dg/cpp/paste12.c index 3e0f7b9..f6b3696 100644 --- a/gcc/testsuite/gcc.dg/cpp/paste12.c +++ b/gcc/testsuite/gcc.dg/cpp/paste12.c @@ -8,4 +8,4 @@ #define inc2(a,b) <##a.b> #define INC(X) inc2(X,h) -#include INC(stdio) /* { dg-error "pasting \"<\" and \"stdio\" does not" } */ +#include INC(stdio) /* { dg-error "pasting '<' and 'stdio' does not" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/paste14-2.c b/gcc/testsuite/gcc.dg/cpp/paste14-2.c index 3b23ada..bb51999 100644 --- a/gcc/testsuite/gcc.dg/cpp/paste14-2.c +++ b/gcc/testsuite/gcc.dg/cpp/paste14-2.c @@ -4,8 +4,8 @@ { dg-do preprocess } */ -#define foo - ## >> /* { dg-error "pasting \"-\" and \">>\"" } */ +#define foo - ## >> /* { dg-error "pasting '-' and '>>'" } */ foo -#define bar = ## == /* { dg-error "pasting \"=\" and \"==\"" } */ +#define bar = ## == /* { dg-error "pasting '=' and '=='" } */ bar diff --git a/gcc/testsuite/gcc.dg/cpp/paste14.c b/gcc/testsuite/gcc.dg/cpp/paste14.c index 043d5e5..d60b328 100644 --- a/gcc/testsuite/gcc.dg/cpp/paste14.c +++ b/gcc/testsuite/gcc.dg/cpp/paste14.c @@ -5,6 +5,6 @@ */ #define foo - ## >> -foo /* { dg-error "pasting \"-\" and \">>\"" } */ +foo /* { dg-error "pasting '-' and '>>'" } */ #define bar = ## == -bar /* { dg-error "pasting \"=\" and \"==\"" } */ +bar /* { dg-error "pasting '=' and '=='" } */ diff --git a/gcc/testsuite/gcc.dg/torture/pr121370.c b/gcc/testsuite/gcc.dg/torture/pr121370.c new file mode 100644 index 0000000..d40f3b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr121370.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-require-effective-target int32plus } */ + +int a; +int main() +{ + int c = -2147483647; + int d = -2147483647; + int e = 2147483647; + if (0) + f: + e = d + e - 2; +g: + if (d - c - e > 0) { + a = -c; + if (a + d) { + d = 1; + goto g; + } + return 0; + } + if (e) + goto f; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr121382.c b/gcc/testsuite/gcc.dg/torture/pr121382.c new file mode 100644 index 0000000..20b49b1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr121382.c @@ -0,0 +1,23 @@ +/* { dg-do run } */ +/* { dg-require-effective-target int32plus } */ + +int a, b, c; +__attribute__((noipa)) +static void d(int e, int f) +{ + if (e != 5 && e != 2147483647) + __builtin_abort(); + f = 2147483647; + do { + f = f - e; + if (c - 9 * f) { + __builtin_abort(); + } + } while (c); +} +__attribute__((noipa)) +int main(void) +{ + d(2147483647, 2147483647); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr59984.c b/gcc/testsuite/gcc.dg/vect/pr59984.c index c00c2267..8ca446e 100644 --- a/gcc/testsuite/gcc.dg/vect/pr59984.c +++ b/gcc/testsuite/gcc.dg/vect/pr59984.c @@ -64,3 +64,7 @@ main () return 0; } +/* { dg-final { scan-tree-dump "31:17: optimized: loop vectorized" "vect" } } */ +/* { dg-final { scan-tree-dump "37:7: optimized: loop vectorized" "vect" } } */ +/* { dg-final { scan-tree-dump "44:17: optimized: loop vectorized" "vect" } } */ +/* { dg-final { scan-tree-dump "50:7: optimized: loop vectorized" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/avr/torture/pr118591-1.c b/gcc/testsuite/gcc.target/avr/torture/pr118591-1.c index 814f041..6f54c63 100644 --- a/gcc/testsuite/gcc.target/avr/torture/pr118591-1.c +++ b/gcc/testsuite/gcc.target/avr/torture/pr118591-1.c @@ -1,5 +1,5 @@ /* { dg-do run { target { ! avr_tiny } } } */ -/* { dg-additional-options "-std=c99 -mlra" } */ +/* { dg-additional-options "-std=c99" } */ __attribute__((noipa)) void func2 (long long a1, long long a2, long b) diff --git a/gcc/testsuite/gcc.target/avr/torture/pr118591-2.c b/gcc/testsuite/gcc.target/avr/torture/pr118591-2.c index 83d3606..222af09 100644 --- a/gcc/testsuite/gcc.target/avr/torture/pr118591-2.c +++ b/gcc/testsuite/gcc.target/avr/torture/pr118591-2.c @@ -1,6 +1,6 @@ /* Test case failed on avrtiny. */ /* { dg-do run } */ -/* { dg-additional-options "-std=c99 -mlra" } */ +/* { dg-additional-options "-std=c99" } */ __attribute__((noipa)) void func2 (long a, long b) diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u32-from-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u32-from-u64.c index 8d5449b..fa3758a 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u32-from-u64.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u32-from-u64.c @@ -9,3 +9,5 @@ DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT) /* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */ +/* { dg-final { scan-assembler-not "\.L\[0-9\]+" } } */ +/* { dg-final { scan-assembler-times "mulhu" 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c index d8a01d1..b1bf4fa 100644 --- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c +++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c @@ -10,3 +10,4 @@ DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT) /* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */ /* { dg-final { scan-assembler-not "\.L\[0-9\]+" } } */ +/* { dg-final { scan-assembler-times "mulhu" 1 } } */ diff --git a/gcc/testsuite/lib/rust.exp b/gcc/testsuite/lib/rust.exp index 9513e1c..692030c 100644 --- a/gcc/testsuite/lib/rust.exp +++ b/gcc/testsuite/lib/rust.exp @@ -168,10 +168,7 @@ proc rust_target_compile { source dest type options } { global gluefile wrap_flags global ALWAYS_RUSTFLAGS global RUST_UNDER_TEST - global individual_timeout - - # HACK: guard against infinite loops in the compiler - set individual_timeout 10 + if { [target_info needs_status_wrapper] != "" && [info exists gluefile] } { lappend options "libs=${gluefile}" diff --git a/gcc/testsuite/rust/compile/bad-rpit1.rs b/gcc/testsuite/rust/compile/bad-rpit1.rs new file mode 100644 index 0000000..d8c21b1 --- /dev/null +++ b/gcc/testsuite/rust/compile/bad-rpit1.rs @@ -0,0 +1,26 @@ +#[lang = "sized"] +trait Sized {} + +trait Foo { + fn id(&self) -> i32; +} + +struct A; +struct B; + +impl Foo for A { + fn id(&self) -> i32 { + 1 + } +} + +impl Foo for B { + fn id(&self) -> i32 { + 2 + } +} + +fn make_foo(cond: bool) -> impl Foo { + if cond { A } else { B } + // { dg-error "mismatched types, expected .A. but got .B. .E0308." "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust/compile/const_generics_3.rs b/gcc/testsuite/rust/compile/const_generics_3.rs index 524d48d..bd91729 100644 --- a/gcc/testsuite/rust/compile/const_generics_3.rs +++ b/gcc/testsuite/rust/compile/const_generics_3.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-w -frust-name-resolution-2.0" } +// { dg-additional-options "-w -frust-name-resolution-2.0 -frust-compile-until=compilation" } #[lang = "sized"] trait Sized {} diff --git a/gcc/testsuite/rust/compile/impl_trait_diag.rs b/gcc/testsuite/rust/compile/impl_trait_diag.rs new file mode 100644 index 0000000..54a0cd2 --- /dev/null +++ b/gcc/testsuite/rust/compile/impl_trait_diag.rs @@ -0,0 +1,17 @@ +#[lang = "sized"] +pub trait Sized {} + +trait Foo { + fn method(&self); +} + +struct Bar; +impl Foo for Bar {} + +fn main() { + let x: impl Foo = Bar; // { dg-error ".impl Trait. not allowed outside of function and inherent method return types .E0562." } + + struct Wrapper { + field: impl Foo, // { dg-error ".impl Trait. not allowed outside of function and inherent method return types .E0562." } + } +} diff --git a/gcc/testsuite/rust/compile/impl_trait_generic_arg.rs b/gcc/testsuite/rust/compile/impl_trait_generic_arg.rs new file mode 100644 index 0000000..ecdb088 --- /dev/null +++ b/gcc/testsuite/rust/compile/impl_trait_generic_arg.rs @@ -0,0 +1,24 @@ +#[lang = "sized"] +trait Sized {} + +trait Foo { + fn id(&self) -> u8; +} + +struct Bar; + +impl Foo for Bar { + fn id(&self) -> u8 { + 1 + } +} + +fn takes(val: impl Foo) -> u8 { + val.id() +} + +fn main() { + let b = Bar; + let x = takes::<Bar>(b); + // { dg-error "cannot provide explicit generic arguments when .impl Trait. is used in argument position .E0632." "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust/compile/issue-1485.rs b/gcc/testsuite/rust/compile/issue-1485.rs new file mode 100644 index 0000000..a0cd5a0 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-1485.rs @@ -0,0 +1,16 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce<Args> { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +struct BinOpInvalid { + lhs: i32, + rhs: i32, + f: impl FnOnce(i32) -> i32, // { dg-error ".impl Trait. not allowed outside of function and inherent method return types .E0562." } +} diff --git a/gcc/testsuite/rust/compile/issue-1487.rs b/gcc/testsuite/rust/compile/issue-1487.rs new file mode 100644 index 0000000..4a4d759 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-1487.rs @@ -0,0 +1,15 @@ +// { dg-options "-w" } +#[lang = "sized"] +trait Sized {} + +trait Printable { + fn print(&self); +} + +struct Foo; + +impl Printable for Foo { + fn print(&self) {} +} + +fn take_printable(_: impl Printable) {} diff --git a/gcc/testsuite/rust/compile/issue-2015.rs b/gcc/testsuite/rust/compile/issue-2015.rs index 7789ecd..7e03651 100644 --- a/gcc/testsuite/rust/compile/issue-2015.rs +++ b/gcc/testsuite/rust/compile/issue-2015.rs @@ -1,4 +1,5 @@ -// { dg-additional-options "-frust-compile-until=lowering" } +#[lang = "sized"] +trait Sized {} macro_rules! impl_foo { () => { impl Foo } diff --git a/gcc/testsuite/rust/compile/issue-3454.rs b/gcc/testsuite/rust/compile/issue-3454.rs new file mode 100644 index 0000000..2a3c0c7 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3454.rs @@ -0,0 +1,20 @@ +#[lang = "sized"] +pub trait Sized {} + +macro_rules! impl_foo { + () => { impl Foo } +} + +pub trait Foo {} + +pub trait Bar { + type Baz; +} + +pub fn foo(_value: impl Bar<Baz = impl_foo!()>) -> i32 { + 15 +} + +pub fn bar(_value: impl Bar<Baz = impl Foo>) -> i32 { + 16 +} diff --git a/gcc/testsuite/rust/compile/issue-3618.rs b/gcc/testsuite/rust/compile/issue-3618.rs new file mode 100644 index 0000000..9728613 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3618.rs @@ -0,0 +1 @@ +static _X: () = loop {}; // { dg-error "loop iteration count exceeds limit" } diff --git a/gcc/testsuite/rust/compile/issue-3660.rs b/gcc/testsuite/rust/compile/issue-3660.rs new file mode 100644 index 0000000..1f1c583 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3660.rs @@ -0,0 +1,3 @@ +pub static A: [u32; 2] = [1, 2]; + +pub static B: [u8; 2] = [3, 4]; diff --git a/gcc/testsuite/rust/compile/issue-3661.rs b/gcc/testsuite/rust/compile/issue-3661.rs new file mode 100644 index 0000000..8d03c36 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3661.rs @@ -0,0 +1,10 @@ +pub macro m($inner_str:expr) { + #[m = $inner_str] + // { dg-error "macro not found" "" { target *-*-* } .-1 } + + struct S; +} + +fn main() { + m!(stringify!(foo)); +} diff --git a/gcc/testsuite/rust/compile/issue-3671.rs b/gcc/testsuite/rust/compile/issue-3671.rs index e800d53..8015653 100644 --- a/gcc/testsuite/rust/compile/issue-3671.rs +++ b/gcc/testsuite/rust/compile/issue-3671.rs @@ -1,2 +1,2 @@ -impl Self<0> {} +impl Foo<0> {} // { dg-error "could not resolve type path" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/macros/mbe/meta-param.rs b/gcc/testsuite/rust/compile/macros/mbe/meta-param.rs new file mode 100644 index 0000000..ed6e100 --- /dev/null +++ b/gcc/testsuite/rust/compile/macros/mbe/meta-param.rs @@ -0,0 +1,7 @@ +macro_rules! foo { + ($x:meta) => {0} +} + +pub fn main() -> i32 { + foo!(Clone) +} diff --git a/gcc/testsuite/rust/compile/match-identifierpattern.rs b/gcc/testsuite/rust/compile/match-identifierpattern.rs new file mode 100644 index 0000000..6c558ac --- /dev/null +++ b/gcc/testsuite/rust/compile/match-identifierpattern.rs @@ -0,0 +1,9 @@ +fn main() { + let x = 1; + + match x { + 2 => {}, + a @ 3 => {}, + _ => {}, + } +} diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index c020e36..31d7a26 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -1,17 +1,9 @@ -canonical_paths1.rs issue-3315-2.rs -privacy5.rs -privacy8.rs -pub_restricted_1.rs -pub_restricted_2.rs -pub_restricted_3.rs -issue-2905-2.rs -derive-default1.rs -derive-eq-invalid.rs torture/alt_patterns1.rs torture/name_resolve1.rs -issue-3663.rs -issue-3671.rs issue-3652.rs -issue-3649.rs +issue-1487.rs +issue-2015.rs +issue-3454.rs +impl_trait_generic_arg.rs # please don't delete the trailing newline diff --git a/gcc/testsuite/rust/compile/pub_restricted_1.rs b/gcc/testsuite/rust/compile/pub_restricted_1.rs index 9bda968..44989a8 100644 --- a/gcc/testsuite/rust/compile/pub_restricted_1.rs +++ b/gcc/testsuite/rust/compile/pub_restricted_1.rs @@ -1,3 +1,5 @@ +// { dg-additional-options "-frust-name-resolution-2.0" } + pub mod foo { pub mod bar { pub fn baz() {} @@ -6,8 +8,8 @@ pub mod foo { } } -pub(in foo::fah::baz) struct A1; // { dg-error "cannot find simple path segment .fah." } -pub(in fro::bulator::saindoux) struct A2; // { dg-error "cannot find simple path segment .fro." } -pub(in foo::bar::saindoux) struct A3; // { dg-error "cannot find simple path segment .saindoux." } +pub(in foo::fah::baz) struct A1; // { dg-error "could not resolve path .foo::fah::baz." } +pub(in fro::bulator::saindoux) struct A2; // { dg-error "could not resolve path .fro::bulator::saindoux." } +pub(in foo::bar::saindoux) struct A3; // { dg-error "could not resolve path .foo::bar::saindoux." } fn main() {} diff --git a/gcc/testsuite/rust/compile/pub_restricted_2.rs b/gcc/testsuite/rust/compile/pub_restricted_2.rs index 8588f27..91f072e 100644 --- a/gcc/testsuite/rust/compile/pub_restricted_2.rs +++ b/gcc/testsuite/rust/compile/pub_restricted_2.rs @@ -1,18 +1,18 @@ -// { dg-additional-options "-w" } +// { dg-additional-options "-w -frust-name-resolution-2.0" } mod foo { mod bar { mod baz { - pub(in baz) struct A0; - pub(in bar::baz) struct A1; + pub(in super::baz) struct A0; + pub(in super::super::bar::baz) struct A1; pub(in foo::bar::baz) struct A2; mod sain { mod doux {} } - pub(in sain) struct A3; // { dg-error "restricted path is not an ancestor of the current module" } - pub(in sain::doux) struct A4; // { dg-error "restricted path is not an ancestor of the current module" } + pub(in self::sain) struct A3; // { dg-error "restricted path is not an ancestor of the current module" } + pub(in self::sain::doux) struct A4; // { dg-error "restricted path is not an ancestor of the current module" } } } } diff --git a/gcc/testsuite/rust/execute/same_field_name.rs b/gcc/testsuite/rust/compile/same_field_name.rs index d57562b..8e5b78c 100644 --- a/gcc/testsuite/rust/execute/same_field_name.rs +++ b/gcc/testsuite/rust/compile/same_field_name.rs @@ -1,7 +1,7 @@ // https://doc.rust-lang.org/error_codes/E0124.html fn main() { struct Foo { - field1: i32, // { dg-error "field .field1. is already declared" } + field1: i32, field1: i32, // { dg-error "field .field1. is already declared" } field1: i32, // { dg-error "field .field1. is already declared" } } diff --git a/gcc/testsuite/rust/compile/self-in-impl.rs b/gcc/testsuite/rust/compile/self-in-impl.rs new file mode 100644 index 0000000..f888162 --- /dev/null +++ b/gcc/testsuite/rust/compile/self-in-impl.rs @@ -0,0 +1,17 @@ +// { dg-additional-options "-frust-name-resolution-2.0" } + +// the error message here is what rustc >=1.66 emits +// rustc <1.66 emits a "cycle detected" error when +// trying to calculate the impl type +// +// since we aren't trying to match error messages too closely +// and the >=1.66 error message is nicer +// we may as well mimic that + +impl ((Self, i32)) {} +// { dg-error ".Self. is not valid in the self" "" { target *-*-* } .-1 } + +trait Foo {} + +impl Foo for ((Self, i32)) {} +// { dg-error ".Self. is not valid in the self" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/torture/extern_mod2.rs b/gcc/testsuite/rust/compile/torture/extern_mod2.rs index 4984d5d..f3a4f79 100644 --- a/gcc/testsuite/rust/compile/torture/extern_mod2.rs +++ b/gcc/testsuite/rust/compile/torture/extern_mod2.rs @@ -12,6 +12,12 @@ mod no_leading_equal; #[path = "modules/valid_path.rs"] mod extra_spaces; +#[path = ""] // { dg-error "path attributes must contain a filename" } +mod empty_path; // { dg-error "no candidate found" } + +#[path = " "] // { dg-error "path attributes must contain a filename" } +mod path_with_spaces; // { dg-error "no candidate found" } + #[path] // { dg-error "path attributes must contain a filename" } mod error; // { dg-error "no candidate found" } diff --git a/gcc/testsuite/rust/compile/torture/unended-raw-byte-string.rs b/gcc/testsuite/rust/compile/torture/unended-raw-byte-string.rs new file mode 100644 index 0000000..91a3c9a --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/unended-raw-byte-string.rs @@ -0,0 +1,6 @@ +// { dg-excess-errors "...." } +fn main() { + // { dg-error "unended raw byte string literal" "" { target *-*-* } .+1 } + let s = br##"123"# +} + diff --git a/gcc/testsuite/rust/compile/traits9.rs b/gcc/testsuite/rust/compile/traits9.rs index bb3034d..f4308e8 100644 --- a/gcc/testsuite/rust/compile/traits9.rs +++ b/gcc/testsuite/rust/compile/traits9.rs @@ -11,6 +11,5 @@ fn main() { a = Foo(123); let b: &dyn Bar = &a; - // { dg-error "bounds not satisfied for Foo .Bar. is not satisfied" "" { target *-*-* } .-1 } - // { dg-error "expected" "" { target *-*-* } .-2 } + // { dg-error "bounds not satisfied for Foo .Bar. is not satisfied .E0277." "" { target *-*-* } .-1 } } diff --git a/gcc/testsuite/rust/compile/unify-errors1.rs b/gcc/testsuite/rust/compile/unify-errors1.rs new file mode 100644 index 0000000..0fe95ef --- /dev/null +++ b/gcc/testsuite/rust/compile/unify-errors1.rs @@ -0,0 +1,49 @@ +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +trait MyTrait {} + +struct Wrapper<T: MyTrait> { + value: T, +} + +struct NotImpl; + +trait A {} +trait B {} + +struct Wrapper2<T: A + B> { + value: T, +} + +struct NotImpl2; + +impl A for NotImpl2 {} + +fn takes_tuple(x: (i32, bool)) {} + +fn requires_copy<T: Copy>(value: T) {} + +pub fn test() { + takes_tuple((1, 2)); + // { dg-error "mismatched types, expected .bool. but got .<integer>. .E0308." "" { target *-*-* } .-1 } + + takes_tuple((1, 2, 3)); + // { dg-error "mismatched types, expected ..i32, bool.. but got ..<integer>, <integer>, <integer>.. .E0308." "" { target *-*-* } .-1 } + + takes_tuple("hello"); + // { dg-error "mismatched types, expected ..i32, bool.. but got .& str. .E0308." "" { target *-*-* } .-1 } + + let x = &mut 5; + requires_copy(x); + // { dg-error "bounds not satisfied for &mut <integer> .Copy. is not satisfied .E0277." "" { target *-*-* } .-1 } + + let _x = Wrapper { value: NotImpl }; + // { dg-error "bounds not satisfied for NotImpl .MyTrait. is not satisfied .E0277." "" { target *-*-* } .-1 } + + let _x = Wrapper2 { value: NotImpl2 }; + // { dg-error "bounds not satisfied for NotImpl2 .B. is not satisfied .E0277." "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs b/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs new file mode 100644 index 0000000..efb825b --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs @@ -0,0 +1,176 @@ +/* { dg-output "less\r*" }*/ +mod core { + mod option { + pub enum Option<T> { + None, + Some(T), + } + } + + mod marker { + #[lang = "phantom_data"] + pub struct PhantomData<T: ?Sized>; + + #[lang = "structural_peq"] + pub trait StructuralPartialEq {} + + #[lang = "structural_teq"] + pub trait StructuralEq {} + + #[lang = "sized"] + pub trait Sized {} + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + pub enum Ordering { + Less = -1, + Equal = 0, + Greater = 1, + } + + #[lang = "eq"] + pub trait PartialEq<Rhs: ?Sized = Self> { + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + pub trait Eq: PartialEq<Self> { + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { + fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; + + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) | Option::Some(Ordering::Equal) => true, + _ => false, + } + } + + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) | Option::Some(Ordering::Equal) => true, + _ => false, + } + } + } + + pub trait Ord: Eq + PartialOrd<Self> { + fn cmp(&self, other: &Self) -> Ordering; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::option::Option; + +// Needed impls for primitives +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + if *self < *other { + Option::Some(Ordering::Less) + } else if *self > *other { + Option::Some(Ordering::Greater) + } else { + Option::Some(Ordering::Equal) + } + } +} + +impl Eq for i32 {} +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self < *other { + Ordering::Less + } else if *self > *other { + Ordering::Greater + } else { + Ordering::Equal + } + } +} + +// Manual impl for struct Bar +struct Bar { + a: i32, + b: i32, +} + +impl PartialEq for Bar { + fn eq(&self, other: &Self) -> bool { + self.a.eq(&other.a) && self.b.eq(&other.b) + } +} + +impl Eq for Bar {} + +impl PartialOrd for Bar { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + match self.a.partial_cmp(&other.a) { + Option::Some(Ordering::Equal) => self.b.partial_cmp(&other.b), + ord => ord, + } + } +} + +impl Ord for Bar { + fn cmp(&self, other: &Self) -> Ordering { + match self.a.cmp(&other.a) { + Ordering::Equal => self.b.cmp(&other.b), + ord => ord, + } + } +} + +// External print shim +extern "C" { + fn puts(s: *const i8); +} + +fn print(s: &str) { + unsafe { + puts(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let x = Bar { a: 1, b: 2 }; + let y = Bar { a: 1, b: 3 }; + + match x.partial_cmp(&y) { + Option::Some(Ordering::Less) => print("less"), + Option::Some(Ordering::Greater) => print("greater"), + Option::Some(Ordering::Equal) => print("equal"), + _ => print("none"), + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs b/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs new file mode 100644 index 0000000..b8c3672 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs @@ -0,0 +1,184 @@ +/* { dg-output "<><=>=\r*" } */ +/* { dg-options "-w" } */ +mod core { + mod option { + pub enum Option<T> { + None, + Some(T), + } + } + + mod marker { + #[lang = "phantom_data"] + pub struct PhantomData<T: ?Sized>; + + #[lang = "structural_peq"] + pub trait StructuralPartialEq {} + + #[lang = "structural_teq"] + pub trait StructuralEq {} + + #[lang = "sized"] + pub trait Sized {} + } + + mod cmp { + use super::marker::Sized; + use super::option::Option; + + pub enum Ordering { + Less = -1, + Equal = 0, + Greater = 1, + } + + #[lang = "eq"] + pub trait PartialEq<Rhs: ?Sized = Self> { + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } + } + + pub trait Eq: PartialEq<Self> { + fn assert_receiver_is_total_eq(&self) {} + } + + #[lang = "partial_ord"] + pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { + fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>; + + fn lt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) => true, + _ => false, + } + } + + fn le(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Less) | Option::Some(Ordering::Equal) => true, + _ => false, + } + } + + fn gt(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) => true, + _ => false, + } + } + + fn ge(&self, other: &Rhs) -> bool { + match self.partial_cmp(other) { + Option::Some(Ordering::Greater) | Option::Some(Ordering::Equal) => true, + _ => false, + } + } + } + + pub trait Ord: Eq + PartialOrd<Self> { + fn cmp(&self, other: &Self) -> Ordering; + } + } +} + +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::option::Option; + +// Needed impls for primitives +impl PartialEq for i32 { + fn eq(&self, other: &Self) -> bool { + *self == *other + } +} + +impl PartialOrd for i32 { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + if *self < *other { + Option::Some(Ordering::Less) + } else if *self > *other { + Option::Some(Ordering::Greater) + } else { + Option::Some(Ordering::Equal) + } + } +} + +impl Eq for i32 {} +impl Ord for i32 { + fn cmp(&self, other: &Self) -> Ordering { + if *self < *other { + Ordering::Less + } else if *self > *other { + Ordering::Greater + } else { + Ordering::Equal + } + } +} + +// Manual impl for struct Bar +struct Bar { + a: i32, + b: i32, +} + +impl PartialEq for Bar { + fn eq(&self, other: &Self) -> bool { + self.a.eq(&other.a) && self.b.eq(&other.b) + } +} + +impl Eq for Bar {} + +impl PartialOrd for Bar { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + match self.a.partial_cmp(&other.a) { + Option::Some(Ordering::Equal) => self.b.partial_cmp(&other.b), + ord => ord, + } + } +} + +impl Ord for Bar { + fn cmp(&self, other: &Self) -> Ordering { + match self.a.cmp(&other.a) { + Ordering::Equal => self.b.cmp(&other.b), + ord => ord, + } + } +} + +// External print shim +extern "C" { + fn printf(s: *const i8); +} + +fn print(s: &str) { + unsafe { + printf(s as *const str as *const i8); + } +} + +fn main() -> i32 { + let a = Bar { a: 1, b: 2 }; + let b = Bar { a: 1, b: 3 }; + let c = Bar { a: 1, b: 2 }; + + if a < b { + print("<"); + } + if b > a { + print(">"); + } + if a <= c { + print("<="); + } + if b >= c { + print(">="); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/builtin_abort.rs b/gcc/testsuite/rust/execute/torture/builtin_abort.rs index 9f2d8c2..8c8259a 100644 --- a/gcc/testsuite/rust/execute/torture/builtin_abort.rs +++ b/gcc/testsuite/rust/execute/torture/builtin_abort.rs @@ -9,6 +9,6 @@ mod intrinsics { } pub fn main () -> i32 { - abort(); + intrinsics::abort(); 0 } diff --git a/gcc/testsuite/rust/execute/torture/const_block1.rs b/gcc/testsuite/rust/execute/torture/const_block1.rs new file mode 100644 index 0000000..eaf3432 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/const_block1.rs @@ -0,0 +1,9 @@ +const X: i32 = const { + let a = 15; + let b = 14; + a + b +}; + +fn main() -> i32 { + X - 29 +} diff --git a/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs b/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs new file mode 100644 index 0000000..70ed7dc --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs @@ -0,0 +1,66 @@ +// { dg-output "true\r*\nfalse\r*\nfalse\r*\nfalse\r*\nfalse\r*\n" } + +#![feature(intrinsics)] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[lang = "structural_peq"] +trait StructuralPartialEq {} + +#[lang = "eq"] +pub trait PartialEq<Rhs: ?Sized = Self> { + /// This method tests for `self` and `other` values to be equal, and is used + /// by `==`. + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn eq(&self, other: &Rhs) -> bool; + + /// This method tests for `!=`. + #[inline] + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } +} + +#[derive(PartialEq)] +enum Foo { + A { a: i32, b: i32 }, + B(i32, i32), + C, +} + +extern "C" { + fn puts(s: *const i8); +} + +fn print(b: bool) { + if b { + unsafe { puts("true\0" as *const str as *const i8) } + } else { + unsafe { puts("false\0" as *const str as *const i8) } + } +} + +fn main() -> i32 { + let x = Foo::A { a: 15, b: 14 }; + + let b1 = x == Foo::A { a: 15, b: 14 }; + let b12 = x == Foo::A { a: 15, b: 19 }; + let b13 = x == Foo::A { a: 19, b: 14 }; + let b2 = x == Foo::B(15, 14); + let b3 = x == Foo::C; + + print(b1); + print(b12); + print(b13); + print(b2); + print(b3); + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/for-loop1.rs b/gcc/testsuite/rust/execute/torture/for-loop1.rs index 5a6a70c..3342189 100644 --- a/gcc/testsuite/rust/execute/torture/for-loop1.rs +++ b/gcc/testsuite/rust/execute/torture/for-loop1.rs @@ -102,30 +102,30 @@ mod ptr { #[lang = "const_ptr"] impl<T> *const T { pub unsafe fn offset(self, count: isize) -> *const T { - intrinsics::offset(self, count) + crate::intrinsics::offset(self, count) } } #[lang = "mut_ptr"] impl<T> *mut T { pub unsafe fn offset(self, count: isize) -> *mut T { - intrinsics::offset(self, count) as *mut T + crate::intrinsics::offset(self, count) as *mut T } } pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) { let x = x as *mut u8; let y = y as *mut u8; - let len = mem::size_of::<T>() * count; + let len = crate::mem::size_of::<T>() * count; swap_nonoverlapping_bytes(x, y, len) } pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) { // For types smaller than the block optimization below, // just swap directly to avoid pessimizing codegen. - if mem::size_of::<T>() < 32 { + if crate::mem::size_of::<T>() < 32 { let z = read(x); - intrinsics::copy_nonoverlapping(y, x, 1); + crate::intrinsics::copy_nonoverlapping(y, x, 1); write(y, z); } else { swap_nonoverlapping(x, y, 1); @@ -133,12 +133,12 @@ mod ptr { } pub unsafe fn write<T>(dst: *mut T, src: T) { - intrinsics::move_val_init(&mut *dst, src) + crate::intrinsics::move_val_init(&mut *dst, src) } pub unsafe fn read<T>(src: *const T) -> T { - let mut tmp: T = mem::uninitialized(); - intrinsics::copy_nonoverlapping(src, &mut tmp, 1); + let mut tmp: T = crate::mem::uninitialized(); + crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1); tmp } @@ -146,7 +146,7 @@ mod ptr { struct Block(u64, u64, u64, u64); struct UnalignedBlock(u64, u64, u64, u64); - let block_size = mem::size_of::<Block>(); + let block_size = crate::mem::size_of::<Block>(); // Loop through x & y, copying them `Block` at a time // The optimizer should unroll the loop fully for most types @@ -155,31 +155,31 @@ mod ptr { while i + block_size <= len { // Create some uninitialized memory as scratch space // Declaring `t` here avoids aligning the stack when this loop is unused - let mut t: Block = mem::uninitialized(); + let mut t: Block = crate::mem::uninitialized(); let t = &mut t as *mut _ as *mut u8; let x = x.offset(i as isize); let y = y.offset(i as isize); // Swap a block of bytes of x & y, using t as a temporary buffer // This should be optimized into efficient SIMD operations where available - intrinsics::copy_nonoverlapping(x, t, block_size); - intrinsics::copy_nonoverlapping(y, x, block_size); - intrinsics::copy_nonoverlapping(t, y, block_size); + crate::intrinsics::copy_nonoverlapping(x, t, block_size); + crate::intrinsics::copy_nonoverlapping(y, x, block_size); + crate::intrinsics::copy_nonoverlapping(t, y, block_size); i += block_size; } if i < len { // Swap any remaining bytes - let mut t: UnalignedBlock = mem::uninitialized(); + let mut t: UnalignedBlock = crate::mem::uninitialized(); let rem = len - i; let t = &mut t as *mut _ as *mut u8; let x = x.offset(i as isize); let y = y.offset(i as isize); - intrinsics::copy_nonoverlapping(x, t, rem); - intrinsics::copy_nonoverlapping(y, x, rem); - intrinsics::copy_nonoverlapping(t, y, rem); + crate::intrinsics::copy_nonoverlapping(x, t, rem); + crate::intrinsics::copy_nonoverlapping(y, x, rem); + crate::intrinsics::copy_nonoverlapping(t, y, rem); } } } @@ -194,7 +194,7 @@ mod mem { pub fn swap<T>(x: &mut T, y: &mut T) { unsafe { - ptr::swap_nonoverlapping_one(x, y); + crate::ptr::swap_nonoverlapping_one(x, y); } } @@ -204,7 +204,7 @@ mod mem { } pub unsafe fn uninitialized<T>() -> T { - intrinsics::uninit() + crate::intrinsics::uninit() } } diff --git a/gcc/testsuite/rust/execute/torture/for-loop2.rs b/gcc/testsuite/rust/execute/torture/for-loop2.rs index 5ba2cd1..4f5dfe1 100644 --- a/gcc/testsuite/rust/execute/torture/for-loop2.rs +++ b/gcc/testsuite/rust/execute/torture/for-loop2.rs @@ -101,30 +101,30 @@ mod ptr { #[lang = "const_ptr"] impl<T> *const T { pub unsafe fn offset(self, count: isize) -> *const T { - intrinsics::offset(self, count) + crate::intrinsics::offset(self, count) } } #[lang = "mut_ptr"] impl<T> *mut T { pub unsafe fn offset(self, count: isize) -> *mut T { - intrinsics::offset(self, count) as *mut T + crate::intrinsics::offset(self, count) as *mut T } } pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) { let x = x as *mut u8; let y = y as *mut u8; - let len = mem::size_of::<T>() * count; + let len = crate::mem::size_of::<T>() * count; swap_nonoverlapping_bytes(x, y, len) } pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) { // For types smaller than the block optimization below, // just swap directly to avoid pessimizing codegen. - if mem::size_of::<T>() < 32 { + if crate::mem::size_of::<T>() < 32 { let z = read(x); - intrinsics::copy_nonoverlapping(y, x, 1); + crate::intrinsics::copy_nonoverlapping(y, x, 1); write(y, z); } else { swap_nonoverlapping(x, y, 1); @@ -132,12 +132,12 @@ mod ptr { } pub unsafe fn write<T>(dst: *mut T, src: T) { - intrinsics::move_val_init(&mut *dst, src) + crate::intrinsics::move_val_init(&mut *dst, src) } pub unsafe fn read<T>(src: *const T) -> T { - let mut tmp: T = mem::uninitialized(); - intrinsics::copy_nonoverlapping(src, &mut tmp, 1); + let mut tmp: T = crate::mem::uninitialized(); + crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1); tmp } @@ -145,7 +145,7 @@ mod ptr { struct Block(u64, u64, u64, u64); struct UnalignedBlock(u64, u64, u64, u64); - let block_size = mem::size_of::<Block>(); + let block_size = crate::mem::size_of::<Block>(); // Loop through x & y, copying them `Block` at a time // The optimizer should unroll the loop fully for most types @@ -154,31 +154,31 @@ mod ptr { while i + block_size <= len { // Create some uninitialized memory as scratch space // Declaring `t` here avoids aligning the stack when this loop is unused - let mut t: Block = mem::uninitialized(); + let mut t: Block = crate::mem::uninitialized(); let t = &mut t as *mut _ as *mut u8; let x = x.offset(i as isize); let y = y.offset(i as isize); // Swap a block of bytes of x & y, using t as a temporary buffer // This should be optimized into efficient SIMD operations where available - intrinsics::copy_nonoverlapping(x, t, block_size); - intrinsics::copy_nonoverlapping(y, x, block_size); - intrinsics::copy_nonoverlapping(t, y, block_size); + crate::intrinsics::copy_nonoverlapping(x, t, block_size); + crate::intrinsics::copy_nonoverlapping(y, x, block_size); + crate::intrinsics::copy_nonoverlapping(t, y, block_size); i += block_size; } if i < len { // Swap any remaining bytes - let mut t: UnalignedBlock = mem::uninitialized(); + let mut t: UnalignedBlock = crate::mem::uninitialized(); let rem = len - i; let t = &mut t as *mut _ as *mut u8; let x = x.offset(i as isize); let y = y.offset(i as isize); - intrinsics::copy_nonoverlapping(x, t, rem); - intrinsics::copy_nonoverlapping(y, x, rem); - intrinsics::copy_nonoverlapping(t, y, rem); + crate::intrinsics::copy_nonoverlapping(x, t, rem); + crate::intrinsics::copy_nonoverlapping(y, x, rem); + crate::intrinsics::copy_nonoverlapping(t, y, rem); } } } @@ -193,7 +193,7 @@ mod mem { pub fn swap<T>(x: &mut T, y: &mut T) { unsafe { - ptr::swap_nonoverlapping_one(x, y); + crate::ptr::swap_nonoverlapping_one(x, y); } } @@ -203,7 +203,7 @@ mod mem { } pub unsafe fn uninitialized<T>() -> T { - intrinsics::uninit() + crate::intrinsics::uninit() } } diff --git a/gcc/testsuite/rust/execute/torture/impl_desugar-2.rs b/gcc/testsuite/rust/execute/torture/impl_desugar-2.rs new file mode 100644 index 0000000..c73ea34 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_desugar-2.rs @@ -0,0 +1,32 @@ +#[lang = "sized"] +trait Sized {} + +macro_rules! impl_foo { + () => { impl Foo } +} + +pub trait Foo {} + +pub trait Bar { + type Baz; +} + +struct MyBaz; // { dg-warning "struct is never constructed" } +impl Foo for MyBaz {} + +struct MyBar; + +impl Bar for MyBar { + type Baz = MyBaz; +} + +pub fn foo(_value: impl Bar<Baz = impl_foo!()>) -> i32 { + 15 +} + +fn main() -> i32 { + let bar = MyBar; + let result: i32 = foo(bar); + + result - 15 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_desugar.rs b/gcc/testsuite/rust/execute/torture/impl_desugar.rs new file mode 100644 index 0000000..22d3951 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_desugar.rs @@ -0,0 +1,32 @@ +#[lang = "sized"] +trait Sized {} + +pub trait Foo {} + +pub trait Bar { + type Baz; +} + +struct MyBaz; // { dg-warning "struct is never constructed" } +impl Foo for MyBaz {} + +struct MyBar; + +impl Bar for MyBar { + type Baz = MyBaz; +} + +pub fn foo<T, U>(_value: T) -> i32 +where + T: Bar<Baz = U>, + U: Foo, +{ + 15 +} + +fn main() -> i32 { + let bar = MyBar; + let result: i32 = foo::<MyBar, MyBaz>(bar); + + result - 15 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_rpit1.rs b/gcc/testsuite/rust/execute/torture/impl_rpit1.rs new file mode 100644 index 0000000..8ce5f21 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_rpit1.rs @@ -0,0 +1,28 @@ +#[lang = "sized"] +trait Sized {} + +trait Foo { + fn id(&self) -> i32; +} + +struct Thing(i32); + +impl Foo for Thing { + fn id(&self) -> i32 { + self.0 + } +} + +fn make_thing(a: i32) -> impl Foo { + Thing(a) +} + +fn use_foo(f: impl Foo) -> i32 { + f.id() +} + +fn main() -> i32 { + let value = make_thing(42); + let val = use_foo(value); + val - 42 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_rpit2.rs b/gcc/testsuite/rust/execute/torture/impl_rpit2.rs new file mode 100644 index 0000000..f7cbbb6 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_rpit2.rs @@ -0,0 +1,36 @@ +#[lang = "sized"] +trait Sized {} + +trait Foo { + fn id(&self) -> i32; +} + +struct Thing(i32); + +impl Thing { + fn double(&self) -> i32 { + // { dg-warning "associated function is never used: .double." "" { target *-*-* } .-1 } + self.0 * 2 + } +} + +impl Foo for Thing { + fn id(&self) -> i32 { + self.0 + } +} + +fn make_thing(a: i32) -> impl Foo { + Thing(a) +} + +fn use_foo(f: impl Foo) -> i32 { + f.id() +} + +fn main() -> i32 { + let value = make_thing(21); + let id = use_foo(value); + + id - 21 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_rpit3.rs b/gcc/testsuite/rust/execute/torture/impl_rpit3.rs new file mode 100644 index 0000000..dd68eb2 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_rpit3.rs @@ -0,0 +1,25 @@ +#[lang = "sized"] +trait Sized {} + +trait Foo { + fn id(&self) -> i32; +} + +struct Thing(i32); + +impl Foo for Thing { + fn id(&self) -> i32 { + self.0 + } +} + +fn make_thing() -> impl Foo { + Thing(99) +} + +fn main() -> i32 { + let v = make_thing(); + let r = &v; + let val = r.id(); + val - 99 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_trait1.rs b/gcc/testsuite/rust/execute/torture/impl_trait1.rs new file mode 100644 index 0000000..33a5c8c --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_trait1.rs @@ -0,0 +1,31 @@ +#[lang = "sized"] +trait Sized {} + +pub trait Value { + fn get(&self) -> i32; +} + +struct Foo(i32); +struct Bar(i32); + +impl Value for Foo { + fn get(&self) -> i32 { + self.0 + } +} +impl Value for Bar { + fn get(&self) -> i32 { + self.0 + } +} + +pub fn foo(a: impl Value, b: impl Value) -> i32 { + a.get() + b.get() +} + +fn main() -> i32 { + let a = Foo(1); + let b = Bar(2); + + foo(a, b) - 3 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_trait2.rs b/gcc/testsuite/rust/execute/torture/impl_trait2.rs new file mode 100644 index 0000000..29f393d --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_trait2.rs @@ -0,0 +1,31 @@ +#[lang = "sized"] +trait Sized {} + +pub trait Value { + fn get(&self) -> i32; +} + +struct Foo(i32); +struct Bar(i32); + +impl Value for Foo { + fn get(&self) -> i32 { + self.0 + } +} +impl Value for Bar { + fn get(&self) -> i32 { + self.0 + } +} + +pub fn foo(a: &impl Value, b: &impl Value) -> i32 { + a.get() + b.get() +} + +fn main() -> i32 { + let a = Foo(1); + let b = Bar(2); + + foo(&a, &b) - 3 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_trait3.rs b/gcc/testsuite/rust/execute/torture/impl_trait3.rs new file mode 100644 index 0000000..97e2972 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_trait3.rs @@ -0,0 +1,46 @@ +/* { dg-output "Hello from Message\r*\n" } */ +#[lang = "sized"] +pub trait Sized {} + +extern "C" { + fn printf(s: *const i8, ...); +} + +trait Speak { + fn speak(&self) -> &'static str; +} + +trait Printer { + fn print(&self, input: impl Speak); +} + +struct Console; + +impl Printer for Console { + fn print(&self, input: impl Speak) { + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + unsafe { + let a = input.speak(); + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + } +} + +struct Message(&'static str); + +impl Speak for Message { + fn speak(&self) -> &'static str { + self.0 + } +} + +fn main() -> i32 { + let c = Console; + let msg = Message("Hello from Message\n"); + c.print(msg); + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/impl_trait4.rs b/gcc/testsuite/rust/execute/torture/impl_trait4.rs new file mode 100644 index 0000000..67d0095 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/impl_trait4.rs @@ -0,0 +1,31 @@ +#[lang = "sized"] +trait Sized {} + +trait Foo { + fn id(&self) -> i32; +} + +struct A(i32); +struct B(i32); + +impl Foo for A { + fn id(&self) -> i32 { + self.0 + } +} + +impl Foo for B { + fn id(&self) -> i32 { + self.0 + } +} + +fn takes_tuple(pair: (impl Foo, impl Foo)) -> i32 { + pair.0.id() + pair.1.id() +} + +fn main() -> i32 { + let a = A(1); + let b = B(2); + takes_tuple((a, b)) - 3 +} diff --git a/gcc/testsuite/rust/execute/torture/issue-1482.rs b/gcc/testsuite/rust/execute/torture/issue-1482.rs new file mode 100644 index 0000000..ed8dc81 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-1482.rs @@ -0,0 +1,23 @@ +#[lang = "sized"] +trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce<Args> { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +fn takes_fn(a: i32, f: impl FnOnce(i32) -> i32) -> i32 { + f(a) +} + +pub fn main() -> i32 { + let capture = 2; + let a = |i: i32| { + let b = i + capture; + b + }; + takes_fn(1, a) - 3 +} diff --git a/gcc/testsuite/rust/execute/torture/iter1.rs b/gcc/testsuite/rust/execute/torture/iter1.rs index c3b6c7b..233eb60 100644 --- a/gcc/testsuite/rust/execute/torture/iter1.rs +++ b/gcc/testsuite/rust/execute/torture/iter1.rs @@ -99,30 +99,30 @@ mod ptr { #[lang = "const_ptr"] impl<T> *const T { pub unsafe fn offset(self, count: isize) -> *const T { - intrinsics::offset(self, count) + crate::intrinsics::offset(self, count) } } #[lang = "mut_ptr"] impl<T> *mut T { pub unsafe fn offset(self, count: isize) -> *mut T { - intrinsics::offset(self, count) as *mut T + crate::intrinsics::offset(self, count) as *mut T } } pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) { let x = x as *mut u8; let y = y as *mut u8; - let len = mem::size_of::<T>() * count; + let len = crate::mem::size_of::<T>() * count; swap_nonoverlapping_bytes(x, y, len) } pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) { // For types smaller than the block optimization below, // just swap directly to avoid pessimizing codegen. - if mem::size_of::<T>() < 32 { + if crate::mem::size_of::<T>() < 32 { let z = read(x); - intrinsics::copy_nonoverlapping(y, x, 1); + crate::intrinsics::copy_nonoverlapping(y, x, 1); write(y, z); } else { swap_nonoverlapping(x, y, 1); @@ -130,12 +130,12 @@ mod ptr { } pub unsafe fn write<T>(dst: *mut T, src: T) { - intrinsics::move_val_init(&mut *dst, src) + crate::intrinsics::move_val_init(&mut *dst, src) } pub unsafe fn read<T>(src: *const T) -> T { - let mut tmp: T = mem::uninitialized(); - intrinsics::copy_nonoverlapping(src, &mut tmp, 1); + let mut tmp: T = crate::mem::uninitialized(); + crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1); tmp } @@ -143,7 +143,7 @@ mod ptr { struct Block(u64, u64, u64, u64); struct UnalignedBlock(u64, u64, u64, u64); - let block_size = mem::size_of::<Block>(); + let block_size = crate::mem::size_of::<Block>(); // Loop through x & y, copying them `Block` at a time // The optimizer should unroll the loop fully for most types @@ -152,31 +152,31 @@ mod ptr { while i + block_size <= len { // Create some uninitialized memory as scratch space // Declaring `t` here avoids aligning the stack when this loop is unused - let mut t: Block = mem::uninitialized(); + let mut t: Block = crate::mem::uninitialized(); let t = &mut t as *mut _ as *mut u8; let x = x.offset(i as isize); let y = y.offset(i as isize); // Swap a block of bytes of x & y, using t as a temporary buffer // This should be optimized into efficient SIMD operations where available - intrinsics::copy_nonoverlapping(x, t, block_size); - intrinsics::copy_nonoverlapping(y, x, block_size); - intrinsics::copy_nonoverlapping(t, y, block_size); + crate::intrinsics::copy_nonoverlapping(x, t, block_size); + crate::intrinsics::copy_nonoverlapping(y, x, block_size); + crate::intrinsics::copy_nonoverlapping(t, y, block_size); i += block_size; } if i < len { // Swap any remaining bytes - let mut t: UnalignedBlock = mem::uninitialized(); + let mut t: UnalignedBlock = crate::mem::uninitialized(); let rem = len - i; let t = &mut t as *mut _ as *mut u8; let x = x.offset(i as isize); let y = y.offset(i as isize); - intrinsics::copy_nonoverlapping(x, t, rem); - intrinsics::copy_nonoverlapping(y, x, rem); - intrinsics::copy_nonoverlapping(t, y, rem); + crate::intrinsics::copy_nonoverlapping(x, t, rem); + crate::intrinsics::copy_nonoverlapping(y, x, rem); + crate::intrinsics::copy_nonoverlapping(t, y, rem); } } } @@ -191,7 +191,7 @@ mod mem { pub fn swap<T>(x: &mut T, y: &mut T) { unsafe { - ptr::swap_nonoverlapping_one(x, y); + crate::ptr::swap_nonoverlapping_one(x, y); } } @@ -201,7 +201,7 @@ mod mem { } pub unsafe fn uninitialized<T>() -> T { - intrinsics::uninit() + crate::intrinsics::uninit() } } diff --git a/gcc/testsuite/rust/execute/torture/match-identifierpattern.rs b/gcc/testsuite/rust/execute/torture/match-identifierpattern.rs new file mode 100644 index 0000000..b102ad1 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/match-identifierpattern.rs @@ -0,0 +1,10 @@ +fn main() -> i32 { + let mut x = 2; + + match x { + a @ 2 => { x = a + 1 }, + _ => {} + } + + x - 3 +} diff --git a/gcc/testsuite/rust/execute/torture/struct-pattern-match.rs b/gcc/testsuite/rust/execute/torture/struct-pattern-match.rs new file mode 100644 index 0000000..6aec51f --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/struct-pattern-match.rs @@ -0,0 +1,13 @@ +enum Foo { + A { x: i32 }, + B { y: i32 } +} + +fn main() -> i32 { + let x = Foo::A { x: 12 }; + match x { + Foo::A { x: 10 } => 1, + Foo::B { y: 11 } => 2, + Foo::A { x: abc } => { abc - 12 } + } +} diff --git a/gcc/testsuite/rust/execute/torture/struct_pattern1.rs b/gcc/testsuite/rust/execute/torture/struct_pattern1.rs new file mode 100644 index 0000000..7a74092 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/struct_pattern1.rs @@ -0,0 +1,19 @@ +struct A { + // the two warnings are invalid but this should be fixed by our lint rework + // with this year's GSoC so ok for now + a: i32, // { dg-warning "never read" } + b: i32, // { dg-warning "never read" } +} + +fn main() -> i32 { + let a = A { a: 15, b: 14 }; + + let result = match a { + A { + a: self_a, + b: self_b, + } => self_a + self_b, + }; + + result - 29 +} diff --git a/gcc/tree-scalar-evolution.cc b/gcc/tree-scalar-evolution.cc index 413ca49..3b3748a 100644 --- a/gcc/tree-scalar-evolution.cc +++ b/gcc/tree-scalar-evolution.cc @@ -670,6 +670,17 @@ scev_dfs::add_to_evolution_1 (tree chrec_before, tree to_add, gimple *at_stmt) to_add = chrec_convert (type, to_add, at_stmt); right = chrec_convert_rhs (type, right, at_stmt); right = chrec_fold_plus (chrec_type (right), right, to_add); + /* When we have an evolution in a non-wrapping type and + in the process of accumulating CHREC_RIGHT there was + overflow this indicates in the association that happened + in building the CHREC clearly involved UB. Avoid this. + In building a CHREC we basically turn (a + INCR1) + INCR2 + into a + (INCR1 + INCR2) which is not always valid. + Note this check only catches few invalid cases. */ + if ((INTEGRAL_TYPE_P (type) && ! TYPE_OVERFLOW_WRAPS (type)) + && TREE_CODE (right) == INTEGER_CST + && TREE_OVERFLOW (right)) + return chrec_dont_know; return build_polynomial_chrec (var, left, right); } else diff --git a/gcc/tree-ssa-loop-ivopts.cc b/gcc/tree-ssa-loop-ivopts.cc index 879668c..2fe2655 100644 --- a/gcc/tree-ssa-loop-ivopts.cc +++ b/gcc/tree-ssa-loop-ivopts.cc @@ -132,6 +132,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-vectorizer.h" #include "dbgcnt.h" #include "cfganal.h" +#include "gimple-fold.h" /* For lang_hooks.types.type_for_mode. */ #include "langhooks.h" @@ -7252,7 +7253,24 @@ create_new_iv (struct ivopts_data *data, struct iv_cand *cand) base = unshare_expr (cand->iv->base); - create_iv (base, PLUS_EXPR, unshare_expr (cand->iv->step), + /* The step computation could invoke UB when the loop does not iterate. + Avoid inserting it on the preheader in its native form but rewrite + it to a well-defined form. This also helps masking SCEV issues + which freely re-associates the IV computations when building up + CHRECs without much regard for signed overflow invoking UB. */ + gimple_seq stmts = NULL; + tree step = force_gimple_operand (unshare_expr (cand->iv->step), &stmts, + true, NULL_TREE); + if (stmts) + { + for (auto gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi)) + if (gimple_needing_rewrite_undefined (gsi_stmt (gsi))) + rewrite_to_defined_unconditional (&gsi); + gsi_insert_seq_on_edge_immediate + (loop_preheader_edge (data->current_loop), stmts); + } + + create_iv (base, PLUS_EXPR, step, cand->var_before, data->current_loop, &incr_pos, after, &cand->var_before, &cand->var_after); } diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc index da700cd..dc82bf6 100644 --- a/gcc/tree-vect-data-refs.cc +++ b/gcc/tree-vect-data-refs.cc @@ -1856,21 +1856,14 @@ vect_get_data_access_cost (vec_info *vinfo, dr_vec_info *dr_info, stmt_vector_for_cost *prologue_cost_vec) { stmt_vec_info stmt_info = dr_info->stmt; - loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo); - int ncopies; - - if (PURE_SLP_STMT (stmt_info)) - ncopies = 1; - else - ncopies = vect_get_num_copies (loop_vinfo, STMT_VINFO_VECTYPE (stmt_info)); if (DR_IS_READ (dr_info->dr)) - vect_get_load_cost (vinfo, stmt_info, NULL, ncopies, + vect_get_load_cost (vinfo, stmt_info, NULL, 1, alignment_support_scheme, misalignment, true, inside_cost, outside_cost, prologue_cost_vec, body_cost_vec, false); else - vect_get_store_cost (vinfo,stmt_info, NULL, ncopies, + vect_get_store_cost (vinfo,stmt_info, NULL, 1, alignment_support_scheme, misalignment, inside_cost, body_cost_vec); diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 460de57..85f3e90 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -2512,9 +2512,8 @@ start_over: if (!vect_make_slp_decision (loop_vinfo)) return opt_result::failure_at (vect_location, "no stmts to vectorize.\n"); - /* Find stmts that need to be both vectorized and SLPed. */ - if (!vect_detect_hybrid_slp (loop_vinfo)) - return opt_result::failure_at (vect_location, "needs non-SLP handling\n"); + if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, "Loop contains only SLP stmts\n"); /* Determine the vectorization factor from the SLP decision. */ LOOP_VINFO_VECT_FACTOR (loop_vinfo) @@ -2923,7 +2922,7 @@ again: !gsi_end_p (si); gsi_next (&si)) { stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si)); - STMT_SLP_TYPE (stmt_info) = loop_vect; + STMT_SLP_TYPE (stmt_info) = not_vect; if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def || STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def) { @@ -2942,7 +2941,7 @@ again: if (is_gimple_debug (gsi_stmt (si))) continue; stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si)); - STMT_SLP_TYPE (stmt_info) = loop_vect; + STMT_SLP_TYPE (stmt_info) = not_vect; if (STMT_VINFO_IN_PATTERN_P (stmt_info)) { stmt_vec_info pattern_stmt_info @@ -2951,11 +2950,11 @@ again: STMT_VINFO_IN_PATTERN_P (stmt_info) = false; gimple *pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info); - STMT_SLP_TYPE (pattern_stmt_info) = loop_vect; + STMT_SLP_TYPE (pattern_stmt_info) = not_vect; for (gimple_stmt_iterator pi = gsi_start (pattern_def_seq); !gsi_end_p (pi); gsi_next (&pi)) STMT_SLP_TYPE (loop_vinfo->lookup_stmt (gsi_stmt (pi))) - = loop_vect; + = not_vect; } } } diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc index 3f3a509..794a073 100644 --- a/gcc/tree-vect-slp.cc +++ b/gcc/tree-vect-slp.cc @@ -1140,7 +1140,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap, soft_fail_nunits_vectype = nunits_vectype; } - gcc_assert (vectype); + gcc_assert (vectype || !gimple_get_lhs (first_stmt_info->stmt)); *node_vectype = vectype; /* For every stmt in NODE find its def stmt/s. */ @@ -1187,10 +1187,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap, gcall *call_stmt = dyn_cast <gcall *> (stmt); tree lhs = gimple_get_lhs (stmt); - if (lhs == NULL_TREE - && (!call_stmt - || !gimple_call_internal_p (stmt) - || !internal_store_fn_p (gimple_call_internal_fn (stmt)))) + if (lhs == NULL_TREE && !call_stmt) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, @@ -4917,6 +4914,22 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size, return opt_result::failure_at (vect_location, "SLP build failed.\n"); } + + stmt_vec_info stmt_info; + FOR_EACH_VEC_ELT (LOOP_VINFO_ALTERNATE_DEFS (loop_vinfo), i, stmt_info) + { + vec<stmt_vec_info> stmts; + vec<stmt_vec_info> roots = vNULL; + vec<tree> remain = vNULL; + stmts.create (1); + stmts.quick_push (stmt_info); + if (! vect_build_slp_instance (vinfo, slp_inst_kind_store, + stmts, roots, remain, max_tree_size, + &limit, bst_map, NULL, + force_single_lane)) + return opt_result::failure_at (vect_location, + "SLP build failed.\n"); + } } if (bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo)) @@ -7634,7 +7647,8 @@ vect_make_slp_decision (loop_vec_info loop_vinfo) /* If all instances ended up with vector(1) T roots make sure to not vectorize. RVV for example relies on loop vectorization when some instances are essentially kept scalar. See PR121048. */ - if (known_gt (TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (root)), 1U)) + if (SLP_TREE_VECTYPE (root) + && known_gt (TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (root)), 1U)) decided_to_slp++; } @@ -7652,232 +7666,6 @@ vect_make_slp_decision (loop_vec_info loop_vinfo) return (decided_to_slp > 0); } -/* Private data for vect_detect_hybrid_slp. */ -struct vdhs_data -{ - loop_vec_info loop_vinfo; - vec<stmt_vec_info> *worklist; -}; - -/* Walker for walk_gimple_op. */ - -static tree -vect_detect_hybrid_slp (tree *tp, int *, void *data) -{ - walk_stmt_info *wi = (walk_stmt_info *)data; - vdhs_data *dat = (vdhs_data *)wi->info; - - if (wi->is_lhs) - return NULL_TREE; - - stmt_vec_info def_stmt_info = dat->loop_vinfo->lookup_def (*tp); - if (!def_stmt_info) - return NULL_TREE; - def_stmt_info = vect_stmt_to_vectorize (def_stmt_info); - if (PURE_SLP_STMT (def_stmt_info)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, "marking hybrid: %G", - def_stmt_info->stmt); - STMT_SLP_TYPE (def_stmt_info) = hybrid; - dat->worklist->safe_push (def_stmt_info); - } - - return NULL_TREE; -} - -/* Look if STMT_INFO is consumed by SLP indirectly and mark it pure_slp - if so, otherwise pushing it to WORKLIST. */ - -static void -maybe_push_to_hybrid_worklist (vec_info *vinfo, - vec<stmt_vec_info> &worklist, - stmt_vec_info stmt_info) -{ - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "Processing hybrid candidate : %G", stmt_info->stmt); - stmt_vec_info orig_info = vect_orig_stmt (stmt_info); - imm_use_iterator iter2; - ssa_op_iter iter1; - use_operand_p use_p; - def_operand_p def_p; - bool any_def = false; - FOR_EACH_PHI_OR_STMT_DEF (def_p, orig_info->stmt, iter1, SSA_OP_DEF) - { - any_def = true; - FOR_EACH_IMM_USE_FAST (use_p, iter2, DEF_FROM_PTR (def_p)) - { - if (is_gimple_debug (USE_STMT (use_p))) - continue; - stmt_vec_info use_info = vinfo->lookup_stmt (USE_STMT (use_p)); - /* An out-of loop use means this is a loop_vect sink. */ - if (!use_info) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "Found loop_vect sink: %G", stmt_info->stmt); - worklist.safe_push (stmt_info); - return; - } - else if (!STMT_SLP_TYPE (vect_stmt_to_vectorize (use_info))) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "Found loop_vect use: %G", use_info->stmt); - worklist.safe_push (stmt_info); - return; - } - } - } - /* No def means this is a loop_vect sink. Gimple conditionals also don't have a - def but shouldn't be considered sinks. */ - if (!any_def && STMT_VINFO_DEF_TYPE (stmt_info) != vect_condition_def) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "Found loop_vect sink: %G", stmt_info->stmt); - worklist.safe_push (stmt_info); - return; - } - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "Marked SLP consumed stmt pure: %G", stmt_info->stmt); - STMT_SLP_TYPE (stmt_info) = pure_slp; -} - -/* Find stmts that must be both vectorized and SLPed. */ - -bool -vect_detect_hybrid_slp (loop_vec_info loop_vinfo) -{ - DUMP_VECT_SCOPE ("vect_detect_hybrid_slp"); - - /* All stmts participating in SLP are marked pure_slp, all other - stmts are loop_vect. - First collect all loop_vect stmts into a worklist. - SLP patterns cause not all original scalar stmts to appear in - SLP_TREE_SCALAR_STMTS and thus not all of them are marked pure_slp. - Rectify this here and do a backward walk over the IL only considering - stmts as loop_vect when they are used by a loop_vect stmt and otherwise - mark them as pure_slp. */ - auto_vec<stmt_vec_info> worklist; - for (int i = LOOP_VINFO_LOOP (loop_vinfo)->num_nodes - 1; i >= 0; --i) - { - basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i]; - for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi); - gsi_next (&gsi)) - { - gphi *phi = gsi.phi (); - stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (phi); - if (!STMT_SLP_TYPE (stmt_info) && STMT_VINFO_RELEVANT (stmt_info)) - maybe_push_to_hybrid_worklist (loop_vinfo, - worklist, stmt_info); - } - for (gimple_stmt_iterator gsi = gsi_last_bb (bb); !gsi_end_p (gsi); - gsi_prev (&gsi)) - { - gimple *stmt = gsi_stmt (gsi); - if (is_gimple_debug (stmt)) - continue; - stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (stmt); - if (STMT_VINFO_IN_PATTERN_P (stmt_info)) - { - for (gimple_stmt_iterator gsi2 - = gsi_start (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info)); - !gsi_end_p (gsi2); gsi_next (&gsi2)) - { - stmt_vec_info patt_info - = loop_vinfo->lookup_stmt (gsi_stmt (gsi2)); - if (!STMT_SLP_TYPE (patt_info) - && STMT_VINFO_RELEVANT (patt_info)) - maybe_push_to_hybrid_worklist (loop_vinfo, - worklist, patt_info); - } - stmt_info = STMT_VINFO_RELATED_STMT (stmt_info); - } - if (!STMT_SLP_TYPE (stmt_info) && STMT_VINFO_RELEVANT (stmt_info)) - maybe_push_to_hybrid_worklist (loop_vinfo, - worklist, stmt_info); - } - } - - /* Now we have a worklist of non-SLP stmts, follow use->def chains and - mark any SLP vectorized stmt as hybrid. - ??? We're visiting def stmts N times (once for each non-SLP and - once for each hybrid-SLP use). */ - walk_stmt_info wi; - vdhs_data dat; - dat.worklist = &worklist; - dat.loop_vinfo = loop_vinfo; - memset (&wi, 0, sizeof (wi)); - wi.info = (void *)&dat; - while (!worklist.is_empty ()) - { - stmt_vec_info stmt_info = worklist.pop (); - /* Since SSA operands are not set up for pattern stmts we need - to use walk_gimple_op. */ - wi.is_lhs = 0; - walk_gimple_op (stmt_info->stmt, vect_detect_hybrid_slp, &wi); - /* For gather/scatter make sure to walk the offset operand, that - can be a scaling and conversion away. */ - gather_scatter_info gs_info; - if (STMT_VINFO_GATHER_SCATTER_P (stmt_info) - && vect_check_gather_scatter (stmt_info, loop_vinfo, &gs_info)) - { - int dummy; - vect_detect_hybrid_slp (&gs_info.offset, &dummy, &wi); - } - } - - /* Determine if all the stmts in the loop can be SLPed. */ - for (unsigned i = 0; i < LOOP_VINFO_LOOP (loop_vinfo)->num_nodes; i++) - { - basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i]; - for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si); - gsi_next (&si)) - { - stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (si.phi ()); - if (!stmt_info) - continue; - if ((STMT_VINFO_RELEVANT_P (stmt_info) - || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info))) - && !PURE_SLP_STMT (stmt_info)) - { - /* STMT needs both SLP and loop-based vectorization. */ - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "Loop contains SLP and non-SLP stmts\n"); - return false; - } - } - for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); - gsi_next (&si)) - { - if (is_gimple_debug (gsi_stmt (si))) - continue; - stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si)); - stmt_info = vect_stmt_to_vectorize (stmt_info); - if ((STMT_VINFO_RELEVANT_P (stmt_info) - || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info))) - && !PURE_SLP_STMT (stmt_info)) - { - /* STMT needs both SLP and loop-based vectorization. */ - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "Loop contains SLP and non-SLP stmts\n"); - return false; - } - } - } - - if (dump_enabled_p ()) - dump_printf_loc (MSG_NOTE, vect_location, - "Loop contains only SLP stmts\n"); - return true; -} - - /* Initialize a bb_vec_info struct for the statements in BBS basic blocks. */ _bb_vec_info::_bb_vec_info (vec<basic_block> _bbs, vec_info_shared *shared) @@ -7961,7 +7749,10 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node, elements in a vector. For single-defuse-cycle, lane-reducing op, and PHI statement that starts reduction comprised of only lane-reducing ops, the number is more than effective vector statements actually required. */ - SLP_TREE_NUMBER_OF_VEC_STMTS (node) = vect_get_num_copies (vinfo, node); + if (SLP_TREE_VECTYPE (node)) + SLP_TREE_NUMBER_OF_VEC_STMTS (node) = vect_get_num_copies (vinfo, node); + else + SLP_TREE_NUMBER_OF_VEC_STMTS (node) = 0; /* Handle purely internal nodes. */ if (SLP_TREE_CODE (node) == VEC_PERM_EXPR) @@ -11318,8 +11109,10 @@ vect_schedule_slp_node (vec_info *vinfo, stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (node); - gcc_assert (SLP_TREE_NUMBER_OF_VEC_STMTS (node) != 0); - SLP_TREE_VEC_DEFS (node).create (SLP_TREE_NUMBER_OF_VEC_STMTS (node)); + gcc_assert (!SLP_TREE_VECTYPE (node) + || SLP_TREE_NUMBER_OF_VEC_STMTS (node) != 0); + if (SLP_TREE_NUMBER_OF_VEC_STMTS (node) != 0) + SLP_TREE_VEC_DEFS (node).create (SLP_TREE_NUMBER_OF_VEC_STMTS (node)); if (SLP_TREE_CODE (node) != VEC_PERM_EXPR && STMT_VINFO_DATA_REF (stmt_info)) @@ -11564,8 +11357,6 @@ vect_remove_slp_scalar_calls (vec_info *vinfo, { if (!stmt_info) continue; - if (!PURE_SLP_STMT (stmt_info)) - continue; stmt_info = vect_orig_stmt (stmt_info); gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt); if (!stmt || gimple_bb (stmt) == NULL) diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 97222f6..f7a052b 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -386,6 +386,9 @@ vect_stmt_relevant_p (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, dump_printf_loc (MSG_NOTE, vect_location, "vec_stmt_relevant_p: stmt has vdefs.\n"); *relevant = vect_used_in_scope; + if (! STMT_VINFO_DATA_REF (stmt_info) + && zero_ssa_operands (stmt_info->stmt, SSA_OP_DEF)) + LOOP_VINFO_ALTERNATE_DEFS (loop_vinfo).safe_push (stmt_info); } /* uses outside the loop. */ @@ -4752,7 +4755,8 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info, } } - SLP_TREE_VEC_DEFS (slp_node).quick_push (gimple_get_lhs (new_stmt)); + if (gimple_get_lhs (new_stmt)) + SLP_TREE_VEC_DEFS (slp_node).quick_push (gimple_get_lhs (new_stmt)); } for (i = 0; i < nargs; ++i) @@ -7780,10 +7784,6 @@ vectorizable_store (vec_info *vinfo, return false; } - /* Cannot have hybrid store SLP -- that would mean storing to the - same location twice. */ - gcc_assert (PURE_SLP_STMT (stmt_info)); - tree vectype = SLP_TREE_VECTYPE (stmt_info), rhs_vectype = NULL_TREE; poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype); diff --git a/gcc/tree-vectorizer.cc b/gcc/tree-vectorizer.cc index f992856..50985a6 100644 --- a/gcc/tree-vectorizer.cc +++ b/gcc/tree-vectorizer.cc @@ -733,7 +733,7 @@ vec_info::new_stmt_vec_info (gimple *stmt) else STMT_VINFO_DEF_TYPE (res) = vect_internal_def; - STMT_SLP_TYPE (res) = loop_vect; + STMT_SLP_TYPE (res) = not_vect; /* This is really "uninitialized" until vect_compute_data_ref_alignment. */ res->dr_aux.misalignment = DR_MISALIGNMENT_UNINITIALIZED; diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 0a75ee1..52e1075 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -947,6 +947,10 @@ public: stmt in the chain. */ auto_vec<stmt_vec_info> reduction_chains; + /* Defs that could not be analyzed such as OMP SIMD calls without + a LHS. */ + auto_vec<stmt_vec_info> alternate_defs; + /* Cost vector for a single scalar iteration. */ auto_vec<stmt_info_for_cost> scalar_cost_vec; @@ -1186,6 +1190,7 @@ public: #define LOOP_VINFO_INNER_LOOP_COST_FACTOR(L) (L)->inner_loop_cost_factor #define LOOP_VINFO_INV_PATTERN_DEF_SEQ(L) (L)->inv_pattern_def_seq #define LOOP_VINFO_DRS_ADVANCED_BY(L) (L)->drs_advanced_by +#define LOOP_VINFO_ALTERNATE_DEFS(L) (L)->alternate_defs #define LOOP_VINFO_FULLY_MASKED_P(L) \ (LOOP_VINFO_USING_PARTIAL_VECTORS_P (L) \ @@ -1288,26 +1293,12 @@ enum vect_relevant { vect_used_in_scope }; -/* The type of vectorization that can be applied to the stmt: regular loop-based - vectorization; pure SLP - the stmt is a part of SLP instances and does not - have uses outside SLP instances; or hybrid SLP and loop-based - the stmt is - a part of SLP instance and also must be loop-based vectorized, since it has - uses outside SLP sequences. - - In the loop context the meanings of pure and hybrid SLP are slightly - different. By saying that pure SLP is applied to the loop, we mean that we - exploit only intra-iteration parallelism in the loop; i.e., the loop can be - vectorized without doing any conceptual unrolling, cause we don't pack - together stmts from different iterations, only within a single iteration. - Loop hybrid SLP means that we exploit both intra-iteration and - inter-iteration parallelism (e.g., number of elements in the vector is 4 - and the slp-group-size is 2, in which case we don't have enough parallelism - within an iteration, so we obtain the rest of the parallelism from subsequent - iterations by unrolling the loop by 2). */ +/* The type of vectorization. pure_slp means the stmt is covered by the + SLP graph, not_vect means it is not. This is mostly used by BB + vectorization. */ enum slp_vect_type { - loop_vect = 0, + not_vect = 0, pure_slp, - hybrid }; /* Says whether a statement is a load, a store of a vectorized statement @@ -1655,7 +1646,6 @@ struct gather_scatter_info { #define STMT_VINFO_RELEVANT_P(S) ((S)->relevant != vect_unused_in_scope) -#define HYBRID_SLP_STMT(S) ((S)->slp_type == hybrid) #define PURE_SLP_STMT(S) ((S)->slp_type == pure_slp) #define STMT_SLP_TYPE(S) (S)->slp_type diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index b5188fd..e58fad1 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,9 @@ +2025-08-04 Jakub Jelinek <jakub@redhat.com> + + PR preprocessor/120778 + * macro.cc (stringify_arg): For C++26 emit a pedarn instead of warning + for \ at the end of stringification. + 2025-08-03 Jakub Jelinek <jakub@redhat.com> PR c++/120845 diff --git a/libcpp/macro.cc b/libcpp/macro.cc index d869b02..158c821 100644 --- a/libcpp/macro.cc +++ b/libcpp/macro.cc @@ -1071,7 +1071,7 @@ paste_tokens (cpp_reader *pfile, location_t location, /* Mandatory error for all apart from assembler. */ if (CPP_OPTION (pfile, lang) != CLK_ASM) cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0, - "pasting \"%.*s\" and \"%.*s\" does not give " + "pasting %<%.*s%> and %<%.*s%> does not give " "a valid preprocessing token", (int) (lhsend - buf), buf, (int) (end - rhsstart), rhsstart); diff --git a/libgrust/libproc_macro_internal/ffistring.h b/libgrust/libproc_macro_internal/ffistring.h index e176bc2..b133b35 100644 --- a/libgrust/libproc_macro_internal/ffistring.h +++ b/libgrust/libproc_macro_internal/ffistring.h @@ -43,11 +43,9 @@ public: }; extern "C" { -FFIString -FFIString__new (const unsigned char *data, std::uint64_t len); +FFIString FFIString__new (const unsigned char *data, std::uint64_t len); -void -FFIString__drop (FFIString *str); +void FFIString__drop (FFIString *str); } } // namespace ProcMacro diff --git a/libgrust/libproc_macro_internal/ident.h b/libgrust/libproc_macro_internal/ident.h index cdc9b0d..8394716 100644 --- a/libgrust/libproc_macro_internal/ident.h +++ b/libgrust/libproc_macro_internal/ident.h @@ -47,17 +47,13 @@ public: extern "C" { -Ident -Ident__new (FFIString str, Span span); +Ident Ident__new (FFIString str, Span span); -Ident -Ident__new_raw (FFIString str, Span span); +Ident Ident__new_raw (FFIString str, Span span); -void -Ident__drop (Ident *ident); +void Ident__drop (Ident *ident); -Ident -Ident__clone (const Ident *ident); +Ident Ident__clone (const Ident *ident); } } // namespace ProcMacro diff --git a/libgrust/libproc_macro_internal/literal.h b/libgrust/libproc_macro_internal/literal.h index c857947..b30c69a 100644 --- a/libgrust/libproc_macro_internal/literal.h +++ b/libgrust/libproc_macro_internal/literal.h @@ -105,8 +105,7 @@ public: }; extern "C" { -bool -Literal__from_string (FFIString str, Literal *lit); +bool Literal__from_string (FFIString str, Literal *lit); } } // namespace ProcMacro diff --git a/libgrust/libproc_macro_internal/proc_macro.h b/libgrust/libproc_macro_internal/proc_macro.h index ce9adb2..d5f2e20 100644 --- a/libgrust/libproc_macro_internal/proc_macro.h +++ b/libgrust/libproc_macro_internal/proc_macro.h @@ -96,8 +96,7 @@ struct ProcmacroArray Procmacro *macros; }; -extern "C" bool -bridge_is_available (); +extern "C" bool bridge_is_available (); } // namespace ProcMacro diff --git a/libgrust/libproc_macro_internal/tokenstream.h b/libgrust/libproc_macro_internal/tokenstream.h index 4e13ce7..f24d4ab 100644 --- a/libgrust/libproc_macro_internal/tokenstream.h +++ b/libgrust/libproc_macro_internal/tokenstream.h @@ -51,23 +51,17 @@ public: static void drop (TokenStream *stream); }; -extern "C" TokenStream -TokenStream__new (); +extern "C" TokenStream TokenStream__new (); -extern "C" TokenStream -TokenStream__with_capacity (std::uint64_t capacity); +extern "C" TokenStream TokenStream__with_capacity (std::uint64_t capacity); -extern "C" void -TokenSream__push (TokenStream *stream, TokenTree tree); +extern "C" void TokenSream__push (TokenStream *stream, TokenTree tree); -extern "C" bool -TokenStream__from_string (FFIString str, TokenStream *ts); +extern "C" bool TokenStream__from_string (FFIString str, TokenStream *ts); -extern "C" TokenStream -TokenStream__clone (const TokenStream *ts); +extern "C" TokenStream TokenStream__clone (const TokenStream *ts); -extern "C" void -TokenStream__drop (TokenStream *stream); +extern "C" void TokenStream__drop (TokenStream *stream); } // namespace ProcMacro diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index cd1f142..2dba9dc 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,27 @@ +2025-08-04 Jakub Jelinek <jakub@redhat.com> + hexne <printfne@gmail.com> + + PR libstdc++/121373 + * src/c++23/std.cc.in (std::ranges::shift_left, + std::ranges::shift_right): Only export for C++23 and later. + (std::ranges::fold_left_first_with_iter_result, + std::ranges::fold_left_with_iter_result): Export. + (std::byteswap): Export for C++23 and later. + (std::ranges::iter_move, std::ranges::iter_swap): Export. + (std::projected_value_t): Export for C++26 and later. + (std::out_ptr_t, std::inout_ptr_t): Export. + (std::ranges::iota_result): Export. + (std::regex_constants): Export a lot of constants. + (std::is_scoped_enum, std::is_scoped_enum_v): Export. + +2025-08-04 Tomasz KamiĆski <tkaminsk@redhat.com> + + PR libstdc++/121128 + * include/bits/indirect.h (indirect::operator*): + Cast __self to approparietly qualified indirect. + * testsuite/std/memory/indirect/access.cc: New test. + * testsuite/std/memory/polymorphic/access.cc: New test. + 2025-08-03 Jakub Jelinek <jakub@redhat.com> * src/c++23/std.cc.in (std::owner_equal, std::owner_hash): Export. diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in index 2300126..405bb6e 100644 --- a/libstdc++-v3/src/c++23/std.cc.in +++ b/libstdc++-v3/src/c++23/std.cc.in @@ -1697,8 +1697,6 @@ export namespace std { using std::ranges::advance; using std::ranges::distance; - using std::ranges::iter_move; - using std::ranges::iter_swap; using std::ranges::next; using std::ranges::prev; } |