diff options
Diffstat (limited to 'gcc')
407 files changed, 14100 insertions, 14383 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f05b25b..00f62e1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,355 @@ +2025-10-31 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR tree-optimization/122437 + * fold-const.h (div_if_zero_remainder): Remove. + +2025-10-31 Tamar Christina <tamar.christina@arm.com> + + PR target/121853 + * config/aarch64/aarch64-simd.md (extendbfsf2): New. + +2025-10-31 Richard Biener <rguenther@suse.de> + + PR tree-optimization/122502 + * tree-scalar-evolution.cc (final_value_replacement_loop): + Avoid folding from within FOR_EACH_IMM_USE_STMT due to active + ranger. + +2025-10-31 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR tree-optimization/122437 + * fold-const.cc (div_if_zero_remainder): Remove. + +2025-10-31 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR tree-optimization/122497 + * tree-scalar-evolution.cc (final_value_replacement_loop): Call replace_uses_by + only after the replacement statement was created. + +2025-10-31 Lulu Cheng <chenglulu@loongson.cn> + + * config/loongarch/lasx.md: Support. + * config/loongarch/loongarch.cc + (loongarch_expand_vec_widen_hilo): Remove unused code. + * config/loongarch/lsx.md: Support. + +2025-10-31 Lulu Cheng <chenglulu@loongson.cn> + + * config/loongarch/lasx.md (ILASX_HB): Move to ... + * config/loongarch/lsx.md (ILSX_HB): Move to ... + * config/loongarch/simd.md (ILSX_HB): ... here. + (ILASX_HB): ... here. + (IVEC_HB): New iterator. + (WVEC_QUARTER): New attr. + (wvec_quarter): Likewise. + (simdfmt_qw): Likewise. + (<su>dot_prod<wvec_quarter><mode>): New template. + +2025-10-31 Lulu Cheng <chenglulu@loongson.cn> + + * config/loongarch/lasx.md (hi_lo): Move to ... + * config/loongarch/simd.md (hi_lo): ... here. + * config/loongarch/loongarch.cc + (loongarch_expand_vec_widen_hilo): Add 128-bit data processing. + * config/loongarch/lsx.md + (vec_widen_<su><optab>_<hi_lo>_<mode>): New define_expand. + (vec_widen_<su>mult_<hi_lo>_<mode>): Likewise. + +2025-10-31 Lulu Cheng <chenglulu@loongson.cn> + + * config/loongarch/lasx.md (vec_widen_<su>add_hi_<mode>): + Move. + (vec_widen_<su>add_lo_<mode>): Move. + (vec_widen_<su>sub_hi_<mode>): Move. + (vec_widen_<su>sub_lo_<mode>): Move. + (vec_widen_<su>mult_hi_<mode>): Move. + (vec_widen_<su>mult_lo_<mode>): Move. + (hi_lo): New define_int_attr. + (vec_widen_<su><optab>_<hi_lo>_<mode>): New define_expand. + (vec_widen_<su>mult_<hi_lo>_<mode>): Likewise. + * config/loongarch/loongarch-protos.h + (loongarch_expand_vec_widen_hilo): Modify the function + parameter list. + * config/loongarch/loongarch.cc + (loongarch_expand_vec_widen_hilo): Optimized. + +2025-10-30 David Faust <david.faust@oracle.com> + + PR debug/122248 + * dwarf2out.cc (gen_btf_tag_dies): Always replace an existing + AT_GNU_annotation on the target die. + +2025-10-30 David Faust <david.faust@oracle.com> + + * btfout.cc (btf_add_used_type_1): Do not consider creating + fixups at typedefs. + +2025-10-30 Michal Jires <mjires@suse.cz> + + * lto-cgraph.cc (output_symtab): Remove asm_nodes_out. + * lto-streamer-out.cc (lto_output_toplevel_asms): Use + partitioning. + (create_order_remap): Remove asm_nodes_out. + (lto_output): In LGEN add asm_nodes into partition. + * lto-streamer.h (lto_output_toplevel_asms): Add encoder. + +2025-10-30 Michal Jires <mjires@suse.cz> + + * lto-cgraph.cc (compute_ltrans_boundary): Add asm_node. + +2025-10-30 Michal Jires <mjires@suse.cz> + + * ipa-icf.cc (sem_item_optimizer::write_summary): Use + toplevel_node. + (sem_item_optimizer::read_section): Likewise. + * ipa-modref.cc (modref_write): Likewise. + * ipa-prop.cc (ipa_write_return_summaries): Likewise. + (ipcp_write_transformation_summaries): Likewise. + * ipa-reference.cc (ipa_reference_write_optimization_summary): + Likewise. + * lto-cgraph.cc (lto_symtab_encoder_new): Likewise. + (lto_symtab_encoder_encode): Likewise. + (lto_symtab_encoder_delete_node): Likewise. + (lto_symtab_encoder_in_partition_p): Likewise. + (lto_set_symtab_encoder_in_partition): Likewise. + (output_refs): Likewise. + (compute_ltrans_boundary): Likewise. + (output_symtab): Likewise. + (output_cgraph_opt_summary): Likewise. + * lto-streamer-out.cc (lto_output): Likewise. + (produce_symtab): Likewise. + (produce_symtab_extension): Likewise. + * lto-streamer.h (struct lto_encoder_entry): Likewise. + (struct lto_symtab_encoder_d): Likewise. + (lto_symtab_encoder_encode): Likewise. + (lto_symtab_encoder_delete_node): Likewise. + (lto_symtab_encoder_in_partition_p): Likewise. + (lto_symtab_encoder_lookup): Likewise. + (lsei_next): Likewise. + (lsei_varpool_node): Likewise. + +2025-10-30 Michal Jires <mjires@suse.cz> + + * cgraph.h (enum symtab_type): Replace with toplevel_type. + (enum toplevel_type): New. + (struct toplevel_node): New. + (struct asm_node): Inherits from toplevel_node. + (test): New. + (symbol_table::finalize_toplevel_asm): Use constructor. + * coretypes.h (struct toplevel_node): New. + (struct asm_node): New. + * lto-streamer-in.cc (lto_input_toplevel_asms): Add + lto_file_data. + +2025-10-30 Michal Jires <mjires@suse.cz> + + * cgraph.cc (cgraph_node::release_body): Keep lto_file_data. + (cgraph_node::remove): likewise. + * lto-section-in.cc (lto_free_function_in_decl_state_for_node): + likewise. + * varpool.cc (varpool_node::remove): likewise. + +2025-10-30 Qing Zhao <qing.zhao@oracle.com> + + * doc/extend.texi: Clarification when the counted_by attribute is applied + on a void pointer. + +2025-10-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR target/116075 + * fold-const-call.cc (fold_const_vec_shl_insert): New function. + (fold_const_call): Call fold_const_vec_shl_insert for CFN_VEC_SHL_INSERT. + * match.pd (`VEC_SHL_INSERT (dup (A), A)`): New pattern. + +2025-10-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR tree-optimization/122247 + * tree-ssa-forwprop.cc (do_simple_agr_dse): Allow phi node for the usage + if the usage of the phi result is just the "same" as the original clobber. + +2025-10-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR tree-optimization/122247 + * tree-ssa-forwprop.cc (do_simple_agr_dse): Allow + use to be a clobber of the same kind to the same lhs. + +2025-10-30 Robin Dapp <rdapp@ventanamicro.com> + + * tree-ssa-loop-niter.cc (shifted_range_nonzero_p): New + function. + (number_of_iterations_cltz): Call new function. + * tree-ssa-loop.cc (pass_scev_cprop::execute): Enable ranger. + +2025-10-30 Robin Dapp <rdapp.gcc@gmail.com> + + PR target/122445 + * config/riscv/riscv-avlprop.cc (pass_avlprop::get_vlmax_ta_preferred_avl): + Scale AVL of subreg uses. + +2025-10-30 Artemiy Volkov <artemiy.volkov@arm.com> + + PR tree-optimization/122478 + * match.pd: Fix the view_convert (BIT_FIELD_REF) pattern. + +2025-10-30 Richard Biener <rguenther@suse.de> + + * config/i386/i386-options.cc (ix86_option_override_internal): + Fix check during opts->x_ix86_move_max initialization. + +2025-10-30 Stefan Schulze Frielinghaus <stefansf@gcc.gnu.org> + + PR rtl-optimization/121198 + * lra-constraints.cc (process_alt_operands): Compute least upper + bound of all register classes over all required registers in + order to determine register class for a hard register constraint. + +2025-10-30 Richard Biener <rguenther@suse.de> + Eric Botcazou <ebotcazou@adacore.com> + + * tree-vect-slp.cc (vect_get_operand_map): Handle commutative + operands when swapping is requested. + (vect_build_slp_tree_1): Allow STMT_VINFO_REDUC_IDX differences + when operand swapping makes them match and request swapping. + (vect_build_slp_instance): Indicate we have successfully + discovered a SLP reduction group. + +2025-10-30 Uros Bizjak <ubizjak@gmail.com> + + PR target/116815 + * config/i386/i386.md (ovf_add_cmp): New code attribute. + (udf_sub_cmp): Ditto. + (ovf_comm): New int iterator. + (*plus_within_<code><mode>3_<ovf_comm>): New insn and split pattern. + (*minus_within_<code><mode>3): Ditto. + +2025-10-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + * gimple-fold.cc (gimple_fold_builtin_assume_aligned): Remove. + (gimple_fold_builtin): Don't fold __builtin_assume_aligned + +2025-10-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + Revert: + 2025-10-27 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR middle-end/107389 + PR tree-optimization/122086 + * tree-ssa-forwprop.cc (forwprop_may_propagate_copy): New function. + (pass_forwprop::execute): Use forwprop_may_propagate_copy + instead of may_propagate_copy. + +2025-10-30 Richard Biener <rguenther@suse.de> + + PR tree-optimization/120687 + * tree-vect-slp.cc (vect_optimize_slp_pass::is_compatible_layout): + New overload for checking a whole partition. + (vect_optimize_slp_pass::legitimize): New function trying + a single layout for all partitions for now. + (vect_optimize_slp_pass::run): Try legitimizing to a single + layout before propagating. + (vect_slp_analyze_operations): For dumping deal with + SLP_TREE_SCALAR_STMTS being empty or element zero being NULL. + +2025-10-30 liuhongt <hongtao.liu@intel.com> + + PR target/122457 + * config/i386/sse.md (VI2_AVX10_2): New mode iterator. + (usdot_prod<sseunpackmodelower><mode>): Use VI2_AVX10_2 + instead of VI2_AVX512F. + (udot_prod<sseunpackmodelower><mode>): Ditto. + +2025-10-30 Guo Jie <guojie@loongson.cn> + + * config/loongarch/lasx.md (fnma<mode>4): Remove. + * config/loongarch/lsx.md (fnma<mode>4): Remove. + * config/loongarch/simd.md (fnma<mode>4): Simplify and correct. + +2025-10-30 Jinyang He <hejinyang@loongson.cn> + Peng Fan <fanpeng@loongson.cn> + + * config/loongarch/loongarch.cc + (loongarch_expand_conditional_move): Only allow valid binary + op when optimize conditional move. + +2025-10-29 Jeff Law <jlaw@ventanamicro.com> + + Revert: + 2025-10-29 Jeff Law <jlaw@ventanamicro.com> + + PR target/116662 + * config/riscv/riscv.cc (riscv_option_override): Override + default value for destructive interference size. + +2025-10-29 Jeff Law <jlaw@ventanamicro.com> + + Revert: + 2025-10-29 Jeff Law <jlaw@ventanamicro.com> + + PR target/116662 + * config/riscv/riscv.cc (riscv_option_override): Apply correct version + of the patch. + +2025-10-29 Jeff Law <jlaw@ventanamicro.com> + + PR target/116662 + * config/riscv/riscv.cc (riscv_option_override): Apply correct version + of the patch. + +2025-10-29 Jeff Law <jlaw@ventanamicro.com> + + PR target/116662 + * config/riscv/riscv.cc (riscv_option_override): Override + default value for destructive interference size. + +2025-10-29 Andrew MacLeod <amacleod@redhat.com> + + PR tree-optimization/91191 + * gimple-range-op.cc (gimple_range_op_handler): Descend one + operand lower for a VIEW_CONVERT_EXPR. + * range-op-mixed.h (class operator_view): New. + * range-op.cc (range_op_table): Add VIEW_CONVERT_EXPR case. + (operator_view::fold_range): New. + (operator_view::op1_range): New. + (operator_view::update_bitmask): New. + +2025-10-29 Richard Biener <rguenther@suse.de> + + * tree-vect-slp.cc (vect_analyze_slp): Mark stmts in BB roots + as released after vect_build_slp_instance. + (vect_build_slp_instance): Release scalar_stmts when exiting + early. + +2025-10-29 Lulu Cheng <chenglulu@loongson.cn> + + PR target/122097 + * config/loongarch/loongarch.cc + (loongarch_const_vector_bitimm_set_p): Add support for vector float. + (loongarch_const_vector_bitimm_clr_p): Likewise. + (loongarch_print_operand): Likewise. + * config/loongarch/simd.md (and<mode>3): Likewise. + +2025-10-29 Lulu Cheng <chenglulu@loongson.cn> + + * config/loongarch/lasx.md (xor<mode>3): Delete. + (ior<mode>3): Delete. + (and<mode>3): Delete. + * config/loongarch/lsx.md (xor<mode>3): Delete. + (ior<mode>3): Delete. + (and<mode>3): Delete. + * config/loongarch/simd.md (xor<mode>3): Define. + (ior<mode>3): Likewise. + (and<mode>3): Likewise. + +2025-10-29 Xi Ruoyao <xry111@xry111.site> + + * config/loongarch/genopts/loongarch.opt.in (-mbreak-code=): + New. + * config/loongarch/loongarch.opt: Regenerate. + * config/loongarch/loongarch.md (trap): Separate to a + define_insn and a define_expand which takes la_break_code. + * doc/invoke.texi (-mbreak-code=): Document. + * config/loongarch/loongarch.opt.urls: Regenerate. + 2025-10-28 Richard Biener <rguenther@suse.de> * tree-vect-loop-manip.cc (vect_update_ivs_after_vectorizer): diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index aa425f4..38eec11 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251029 +20251101 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index fc58e04..f91fc31 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,21 @@ +2025-10-30 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/15610 + * sem_type.adb (Collect_Interps): Apply the same visibility + criterion to expanded names as Find_Expanded_Name. + +2025-10-30 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/54178 + * sem_ch12.adb (Instantiate_Object): Strip qualification to detect + aggregates used as actuals. + +2025-10-30 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/16214 + * sem_ch8.adb (Find_Expanded_Name): Consolidate and streamline the + processing required for references to instances within themselves. + 2025-10-28 Eric Botcazou <ebotcazou@adacore.com> PR ada/48039 diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index cbb0deb..deb19ee 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -13223,7 +13223,7 @@ package body Sem_Ch12 is -- to capture local names that may be hidden if the generic is -- a child unit. - if Nkind (Actual) = N_Aggregate then + if Nkind (Unqualify (Actual)) = N_Aggregate then Preanalyze_And_Resolve (Actual, Typ); end if; diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index 86344b5..e9d00d0 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -7225,6 +7225,8 @@ package body Sem_Ch8 is begin while Present (Id) loop + -- The immediate case is when Id is an entity of the prefix + if Scope (Id) = P_Name then Candidate := Id; Is_New_Candidate := True; @@ -7250,6 +7252,53 @@ package body Sem_Ch8 is end if; end if; + -- If the name of a generic child unit appears within an instance + -- of itself, then it is resolved to the renaming of the name of + -- the instance built in Sem_Ch12, so we get to the generic parent + -- through the renaming. + + elsif Ekind (Id) in E_Function | E_Package | E_Procedure + and then Present (Renamed_Entity (Id)) + and then Is_Generic_Instance (Renamed_Entity (Id)) + and then In_Open_Scopes (Renamed_Entity (Id)) + then + declare + Gen_Inst : constant Entity_Id := Renamed_Entity (Id); + Gen_Par : constant Entity_Id := + Generic_Parent + (Specification (Unit_Declaration_Node (Gen_Inst))); + + begin + -- The easy case is when Gen_Par is an entity of the prefix + + if Scope (Gen_Par) = P_Name then + Is_New_Candidate := True; + + -- Now the prefix may also be within an instance of itself, + -- but we do not need to go through the renaming for it, as + -- this was done on entry to the procedure. + + elsif Is_Generic_Instance (P_Name) + and then In_Open_Scopes (P_Name) + then + declare + Gen_Par_P : constant Entity_Id := + Generic_Parent + (Specification (Unit_Declaration_Node (P_Name))); + + begin + if Scope (Gen_Par) = Gen_Par_P then + Is_New_Candidate := True; + else + Is_New_Candidate := False; + end if; + end; + + else + Is_New_Candidate := False; + end if; + end; + -- Ada 2005 (AI-217): Handle shadow entities associated with -- types declared in limited-withed nested packages. We don't need -- to handle E_Incomplete_Subtype entities because the entities @@ -7284,22 +7333,6 @@ package body Sem_Ch8 is Candidate := Get_Full_View (Id); Is_New_Candidate := True; - -- An unusual case arises with a fully qualified name for an - -- entity local to a generic child unit package, within an - -- instantiation of that package. The name of the unit now - -- denotes the renaming created within the instance. This is - -- only relevant in an instance body, see below. - - elsif Is_Generic_Instance (Scope (Id)) - and then In_Open_Scopes (Scope (Id)) - and then In_Instance_Body - and then Ekind (Scope (Id)) = E_Package - and then Ekind (Id) = E_Package - and then Renamed_Entity (Id) = Scope (Id) - and then Is_Immediately_Visible (P_Name) - then - Is_New_Candidate := True; - else Is_New_Candidate := False; end if; @@ -7434,55 +7467,6 @@ package body Sem_Ch8 is end if; else - -- Within the instantiation of a child unit, the prefix may - -- denote the parent instance, but the selector has the name - -- of the original child. That is to say, when A.B appears - -- within an instantiation of generic child unit B, the scope - -- stack includes an instance of A (P_Name) and an instance - -- of B under some other name. We scan the scope to find this - -- child instance, which is the desired entity. - -- Note that the parent may itself be a child instance, if - -- the reference is of the form A.B.C, in which case A.B has - -- already been rewritten with the proper entity. - - if In_Open_Scopes (P_Name) - and then Is_Generic_Instance (P_Name) - then - declare - Gen_Par : constant Entity_Id := - Generic_Parent (Specification - (Unit_Declaration_Node (P_Name))); - S : Entity_Id := Current_Scope; - P : Entity_Id; - - begin - for J in reverse 0 .. Scope_Stack.Last loop - S := Scope_Stack.Table (J).Entity; - - exit when S = Standard_Standard; - - if Ekind (S) in E_Function | E_Package | E_Procedure - then - P := - Generic_Parent (Specification - (Unit_Declaration_Node (S))); - - -- Check that P is a generic child of the generic - -- parent of the prefix. - - if Present (P) - and then Chars (P) = Chars (Selector) - and then Scope (P) = Gen_Par - then - Id := S; - goto Found; - end if; - end if; - - end loop; - end; - end if; - -- If this is a selection from Ada, System or Interfaces, then -- we assume a missing with for the corresponding package. @@ -7589,7 +7573,6 @@ package body Sem_Ch8 is end if; end if; - <<Found>> if Comes_From_Source (N) and then Is_Remote_Access_To_Subprogram_Type (Id) and then Ekind (Id) = E_Access_Subprogram_Type diff --git a/gcc/ada/sem_type.adb b/gcc/ada/sem_type.adb index 32d0833..31a2acd 100644 --- a/gcc/ada/sem_type.adb +++ b/gcc/ada/sem_type.adb @@ -610,14 +610,17 @@ package body Sem_Type is First_Interp := All_Interp.Last; Add_One_Interp (N, Ent, Etype (N)); - -- For expanded name, pick up all additional entities from the - -- same scope, since these are obviously also visible. Note that - -- these are not necessarily contiguous on the homonym chain. + -- For an expanded name, pick up additional visible entities from + -- the same scope. Note that these are not necessarily contiguous + -- on the homonym chain. if Nkind (N) = N_Expanded_Name then H := Homonym (Ent); while Present (H) loop - if Scope (H) = Scope (Entity (N)) then + if Scope (H) = Scope (Entity (N)) + and then (not Is_Hidden (H) + or else Is_Immediately_Visible (H)) + then Add_One_Interp (N, H, Etype (H)); end if; diff --git a/gcc/btfout.cc b/gcc/btfout.cc index 5a210cd..eb794ff 100644 --- a/gcc/btfout.cc +++ b/gcc/btfout.cc @@ -1138,7 +1138,8 @@ btf_add_used_type_1 (ctf_container_ref ctfc, ctf_dtdef_ref dtd, /* Try to avoid chasing pointers to struct/union types if the underlying type isn't used. */ - if (check_ptr && seen_ptr && create_fixups) + if (check_ptr && seen_ptr && create_fixups + && kind != BTF_KIND_TYPEDEF) { ctf_dtdef_ref ref = dtd->ref_type; uint32_t ref_kind = btf_dtd_kind (ref); diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 912d071..d4982eb 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2025-10-30 Qing Zhao <qing.zhao@oracle.com> + + * c-attribs.cc (handle_counted_by_attribute): Allow counted_by for + void pointer. Issue warnings when -Wpointer-arith is present. + 2025-10-27 Richard Biener <rguenther@suse.de> PR middle-end/122325 diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 8ca767a..28a034f 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -2963,14 +2963,16 @@ handle_counted_by_attribute (tree *node, tree name, " array member field", name); *no_add_attrs = true; } - /* This attribute cannot be applied to a pointer to void type. */ + /* This attribute can be applied to a pointer to void type, but issue + warning when -Wpointer-arith is presenting. */ else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == VOID_TYPE) { - error_at (DECL_SOURCE_LOCATION (decl), - "%qE attribute is not allowed for a pointer to void", - name); - *no_add_attrs = true; + if (warn_pointer_arith) + warning_at (DECL_SOURCE_LOCATION (decl), + OPT_Wpointer_arith, + "%qE attribute is used for a pointer to void", + name); } /* This attribute cannot be applied to a pointer to function type. */ else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 3c37ba0..274e2a7 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,8 @@ +2025-10-30 Qing Zhao <qing.zhao@oracle.com> + + * c-typeck.cc (build_access_with_size_for_counted_by): When the element + type is void, assign size one as the element_size. + 2025-10-27 H.J. Lu <hjl.tools@gmail.com> PR c/122427 diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 2b31a43..1e1da2d 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -6536,6 +6536,10 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const, return error_mark_node; } + if ((TREE_STATIC (decl) || C_DECL_DECLARED_CONSTEXPR (decl)) + && C_TYPE_VARIABLE_SIZE (type)) + error_at (loc, "storage size isn%'t constant"); + if (TREE_STATIC (decl) && !verify_type_context (loc, TCTX_STATIC_STORAGE, type)) return error_mark_node; diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 0cf3f92..9b3a786 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -1767,7 +1767,7 @@ static tree c_parser_simple_asm_expr (c_parser *); static tree c_parser_gnu_attributes (c_parser *); static struct c_expr c_parser_initializer (c_parser *, tree); static struct c_expr c_parser_braced_init (c_parser *, tree, bool, - struct obstack *, tree); + struct obstack *, bool); static void c_parser_initelt (c_parser *, struct obstack *); static void c_parser_initval (c_parser *, struct c_expr *, struct obstack *); @@ -6459,7 +6459,9 @@ static struct c_expr c_parser_initializer (c_parser *parser, tree decl) { if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) - return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl); + return c_parser_braced_init (parser, NULL_TREE, false, NULL, + decl != error_mark_node + && C_DECL_VARIABLE_SIZE (decl)); else { struct c_expr ret; @@ -6499,12 +6501,12 @@ location_t last_init_list_comma; compound literal, and NULL_TREE for other initializers and for nested braced lists. NESTED_P is true for nested braced lists, false for the list of a compound literal or the list that is the - top-level initializer in a declaration. DECL is the declaration for - the top-level initializer for a declaration, otherwise NULL_TREE. */ + top-level initializer in a declaration. VARSIZE_P indicates + wether the object to be initialized has a variable size. */ static struct c_expr c_parser_braced_init (c_parser *parser, tree type, bool nested_p, - struct obstack *outer_obstack, tree decl) + struct obstack *outer_obstack, bool varsize_p) { struct c_expr ret; struct obstack braced_init_obstack; @@ -6532,7 +6534,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p, } else { - if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl)) + if (varsize_p) error_at (brace_loc, "variable-sized object may not be initialized except " "with an empty initializer"); @@ -6826,7 +6828,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after, if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after) init = c_parser_braced_init (parser, NULL_TREE, true, - braced_init_obstack, NULL_TREE); + braced_init_obstack, false); else { init = c_parser_expr_no_commas (parser, after); @@ -11793,15 +11795,9 @@ c_parser_postfix_expression (c_parser *parser) else { tree type_expr = NULL_TREE; + tree type = groktypename (t1, &type_expr, NULL); expr.value = c_build_va_arg (start_loc, e1.value, loc, - groktypename (t1, &type_expr, NULL)); - if (type_expr) - { - expr.value = build2 (C_MAYBE_CONST_EXPR, - TREE_TYPE (expr.value), type_expr, - expr.value); - C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true; - } + type, type_expr); set_c_expr_source_range (&expr, start_loc, end_loc); } } @@ -13516,10 +13512,11 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser, || (scspecs && scspecs->storage_class == csc_static) || constexpr_p), constexpr_p, &richloc); type = groktypename (type_name, &type_expr, &type_expr_const); + bool varsize_p = false; if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type)) { - error_at (type_loc, "compound literal has variable size"); - type = error_mark_node; + pedwarn (type_loc, OPT_Wpedantic, "compound literal has variable size"); + varsize_p = true; } else if (TREE_CODE (type) == FUNCTION_TYPE) { @@ -13544,7 +13541,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser, (TYPE_QUALS (type_no_array) | TYPE_QUAL_CONST)); } - init = c_parser_braced_init (parser, type, false, NULL, NULL_TREE); + init = c_parser_braced_init (parser, type, false, NULL, varsize_p); if (constexpr_p) finish_underspecified_init (NULL_TREE, underspec_state); finish_init (); diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index f367cda..ff63d69 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -917,7 +917,7 @@ extern tree c_omp_finish_mapper_clauses (tree); extern tree c_omp_mapper_lookup (tree, tree); extern tree c_omp_extract_mapper_directive (tree); extern tree c_omp_map_array_section (location_t, tree); -extern tree c_build_va_arg (location_t, tree, location_t, tree); +extern tree c_build_va_arg (location_t, tree, location_t, tree, tree); extern tree c_finish_transaction (location_t, tree, int); extern bool c_tree_equal (tree, tree); extern tree c_build_function_call_vec (location_t, const vec<location_t>&, diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 371583b..2cef463 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -3179,7 +3179,10 @@ build_access_with_size_for_counted_by (location_t loc, tree ref, tree result_type = is_fam ? c_build_pointer_type (TREE_TYPE (ref)) : TREE_TYPE (ref); - tree element_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref))); + tree element_type = TREE_TYPE (TREE_TYPE (ref)); + tree element_size = VOID_TYPE_P (element_type) + ? build_one_cst (size_type_node) + : TYPE_SIZE_UNIT (element_type); tree first_param = is_fam ? c_fully_fold (array_to_pointer_conversion (loc, ref), @@ -12731,7 +12734,9 @@ retry: if (constructor_max_index != NULL_TREE && (tree_int_cst_lt (constructor_max_index, constructor_index) - || integer_all_onesp (constructor_max_index))) + || integer_all_onesp (constructor_max_index)) + /* For VLA we got an error already. */ + && !C_TYPE_VARIABLE_SIZE (constructor_type)) { pedwarn_init (loc, 0, "excess elements in array initializer"); @@ -18432,7 +18437,8 @@ c_build_qualified_type (tree type, int type_quals, tree orig_qual_type, /* Build a VA_ARG_EXPR for the C parser. */ tree -c_build_va_arg (location_t loc1, tree expr, location_t loc2, tree type) +c_build_va_arg (location_t loc1, tree expr, location_t loc2, tree type, + tree type_expr) { if (error_operand_p (type)) return error_mark_node; @@ -18456,10 +18462,36 @@ c_build_va_arg (location_t loc1, tree expr, location_t loc2, tree type) type); return error_mark_node; } + else if (TREE_CODE (type) == ARRAY_TYPE && C_TYPE_VARIABLE_SIZE (type) + && !flag_isoc99) + { + error_at (loc2, "second argument to %<va_arg%> is an array type %qT", + type); + return error_mark_node; + } else if (warn_cxx_compat && TREE_CODE (type) == ENUMERAL_TYPE) warning_at (loc2, OPT_Wc___compat, "C++ requires promoted type, not enum type, in %<va_arg%>"); - return build_va_arg (loc2, expr, type); + + if (flag_isoc99 && TREE_CODE (type) == ARRAY_TYPE) + { + warning_at (loc2, 0, "second argument to %<va_arg%> is an array type %qT", + type); + /* We create a trap but evaluate side effects first. */ + tree trapfn = builtin_decl_explicit (BUILT_IN_TRAP); + trapfn = build_call_expr_loc (loc2, trapfn, 0); + tree e2 = build2 (COMPOUND_EXPR, void_type_node, expr, trapfn); + /* Return a compound literal of the right type. */ + tree e1 = build_compound_literal (loc2, type, NULL, true, 0, NULL); + expr = build2 (COMPOUND_EXPR, type, e2, e1); + } + else + expr = build_va_arg (loc2, expr, type); + + if (type_expr) + expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), type_expr, expr); + + return expr; } /* Return truthvalue of whether T1 is the same tree structure as T2. diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc index d1b2e2a..ab09376 100644 --- a/gcc/cgraph.cc +++ b/gcc/cgraph.cc @@ -2220,11 +2220,7 @@ cgraph_node::release_body (bool keep_arguments) if (!used_as_abstract_origin && DECL_INITIAL (decl)) DECL_INITIAL (decl) = error_mark_node; release_function_body (decl); - if (lto_file_data) - { - lto_free_function_in_decl_state_for_node (this); - lto_file_data = NULL; - } + lto_free_function_in_decl_state_for_node (this); if (flag_checking && clones) { /* It is invalid to release body before materializing clones except @@ -2336,10 +2332,7 @@ cgraph_node::remove (void) release_body (); } else - { - lto_free_function_in_decl_state_for_node (this); - lto_file_data = NULL; - } + lto_free_function_in_decl_state_for_node (this); decl = NULL; if (call_site_hash) diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 069e007..aa2207b 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -37,13 +37,18 @@ extern void debuginfo_early_stop (void); class ipa_opt_pass_d; typedef ipa_opt_pass_d *ipa_opt_pass; -/* Symbol table consists of functions and variables. +/* Toplevel consists of functions, variables and assembly. + Make sure toplevel_type_names in symtab.cc is kept in sync + with this. TODO: add labels and CONST_DECLs. */ -enum symtab_type +enum toplevel_type { + TOPLEVEL_BASE, + TOPLEVEL_ASM, SYMTAB_SYMBOL, SYMTAB_FUNCTION, - SYMTAB_VARIABLE + SYMTAB_VARIABLE, + TOPLEVEL_MAX }; /* Section names are stored as reference counted strings in GGC safe hashtable @@ -100,18 +105,37 @@ enum symbol_partitioning_class SYMBOL_DUPLICATE }; +/* Base of all toplevel entries. + Inherited by symtab_node and asm_node. */ +struct GTY ((desc ("%h.type"), tag ("TOPLEVEL_BASE"))) toplevel_node { + /* Constructor. */ + explicit toplevel_node (toplevel_type t) + : lto_file_data (NULL), order (-1), type (t) + {} + + /* File stream where this node is being written to. */ + struct lto_file_decl_data * lto_file_data; + + /* Ordering of all cgraph nodes. */ + int order; + + /* Type of the node. */ + ENUM_BITFIELD (toplevel_type) type : 8; +}; + /* Base of all entries in the symbol table. The symtab_node is inherited by cgraph and varpol nodes. */ -struct GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"), +struct GTY ((tag ("SYMTAB_SYMBOL"), chain_next ("%h.next"), chain_prev ("%h.previous"))) - symtab_node + symtab_node: public toplevel_node { public: friend class symbol_table; /* Constructor. */ - explicit symtab_node (symtab_type t) - : type (t), resolution (LDPR_UNKNOWN), definition (false), alias (false), + explicit symtab_node (toplevel_type t) + : toplevel_node (t), + resolution (LDPR_UNKNOWN), definition (false), alias (false), transparent_alias (false), weakref (false), cpp_implicit_alias (false), symver (false), analyzed (false), writeonly (false), refuse_visibility_changes (false), externally_visible (false), @@ -121,9 +145,9 @@ public: used_from_other_partition (false), in_other_partition (false), address_taken (false), in_init_priority_hash (false), need_lto_streaming (false), offloadable (false), ifunc_resolver (false), - order (-1), next_sharing_asm_name (NULL), + next_sharing_asm_name (NULL), previous_sharing_asm_name (NULL), same_comdat_group (NULL), ref_list (), - alias_target (NULL), lto_file_data (NULL), aux (NULL), + alias_target (NULL), aux (NULL), x_comdat_group (NULL_TREE), x_section (NULL), m_uid (-1) {} @@ -498,9 +522,6 @@ public: return m_uid; } - /* Type of the symbol. */ - ENUM_BITFIELD (symtab_type) type : 8; - /* The symbols resolution. */ ENUM_BITFIELD (ld_plugin_symbol_resolution) resolution : 8; @@ -609,9 +630,6 @@ public: unsigned ifunc_resolver : 1; - /* Ordering of all symtab entries. */ - int order; - /* Declaration representing the symbol. */ tree decl; @@ -642,9 +660,6 @@ public: Once alias is resolved, this pointer become NULL. */ tree alias_target; - /* File stream where this node is being written to. */ - struct lto_file_decl_data * lto_file_data; - void *GTY ((skip)) aux; /* Comdat group the symbol is in. Can be private if GGC allowed that. */ @@ -2224,13 +2239,14 @@ private: /* Every top level asm statement is put into a asm_node. */ -struct GTY(()) asm_node { +struct GTY ((tag ("TOPLEVEL_ASM"))) asm_node: public toplevel_node { + explicit asm_node (tree asm_str) + : toplevel_node (TOPLEVEL_ASM), next (NULL), asm_str (asm_str) + {} /* Next asm node. */ asm_node *next; /* String for this asm node. */ tree asm_str; - /* Ordering of all cgraph nodes. */ - int order; }; /* Report whether or not THIS symtab node is a function, aka cgraph_node. */ @@ -2253,6 +2269,47 @@ is_a_helper <varpool_node *>::test (symtab_node *p) return p && p->type == SYMTAB_VARIABLE; } +/* Report whether or not THIS toplevel node is a function, aka cgraph_node. */ + +template <> +template <> +inline bool +is_a_helper <cgraph_node *>::test (toplevel_node *p) +{ + return p && p->type == SYMTAB_FUNCTION; +} + +/* Report whether or not THIS toplevel node is a variable, aka varpool_node. */ + +template <> +template <> +inline bool +is_a_helper <varpool_node *>::test (toplevel_node *p) +{ + return p && p->type == SYMTAB_VARIABLE; +} + +/* Report whether or not THIS toplevel node is a symtab_node. */ + +template <> +template <> +inline bool +is_a_helper <symtab_node *>::test (toplevel_node *p) +{ + return p && p->type >= SYMTAB_SYMBOL; +} + +/* Report whether or not THIS toplevel node is a toplevel assembly, aka + asm_node. */ + +template <> +template <> +inline bool +is_a_helper <asm_node *>::test (toplevel_node *p) +{ + return p && p->type == TOPLEVEL_ASM; +} + typedef void (*cgraph_edge_hook)(cgraph_edge *, void *); typedef void (*cgraph_node_hook)(cgraph_node *, void *); typedef void (*varpool_node_hook)(varpool_node *, void *); @@ -2919,10 +2976,8 @@ symbol_table::finalize_toplevel_asm (tree asm_str) { asm_node *node; - node = ggc_cleared_alloc<asm_node> (); - node->asm_str = asm_str; + node = new (ggc_cleared_alloc<asm_node> ()) asm_node (asm_str); node->order = order++; - node->next = NULL; if (asmnodes == NULL) asmnodes = node; diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index a121a18..e7c459d 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -3223,6 +3223,7 @@ DONE; } ) + (define_insn "extend<mode><Vwide>2" [(set (match_operand:<VWIDE> 0 "register_operand" "=w") (float_extend:<VWIDE> @@ -3232,6 +3233,29 @@ [(set_attr "type" "neon_fp_cvt_widen_s")] ) +/* A BF->SF is a shift left of 16, however shifts are expensive and the generic + middle-end expansion would force through DI move. Instead use EXT to do the + shift to get better throughput and don't go through GPRs. */ + +(define_expand "extendbfsf2" + [(set (match_operand:SF 0 "register_operand" "=w") + (float_extend:SF + (match_operand:BF 1 "register_operand" "w")))] + "TARGET_SIMD" +{ + rtx tmp0 = aarch64_gen_shareable_zero (V8BFmode); + rtx op0 = force_lowpart_subreg (V8BFmode, operands[1], BFmode); + rtx res = gen_reg_rtx (V8BFmode); + emit_insn (gen_aarch64_extv8bf (res, tmp0, op0, gen_int_mode (7, SImode))); + /* Subregs between floating point modes aren't allowed to change size, so go + through V4SFmode. */ + res = force_lowpart_subreg (V4SFmode, res, V8BFmode); + res = force_lowpart_subreg (SFmode, res, V4SFmode); + emit_move_insn (operands[0], res); + DONE; +}) + + ;; Float narrowing operations. (define_insn "aarch64_float_trunc_rodd_df" diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index dadcf76..ba598a8 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -2917,7 +2917,7 @@ ix86_option_override_internal (bool main_args_p, else { opts->x_ix86_move_max = opts->x_prefer_vector_width_type; - if (opts_set->x_ix86_move_max == PVW_NONE) + if (opts->x_ix86_move_max == PVW_NONE) { if (TARGET_AVX512F_P (opts->x_ix86_isa_flags)) opts->x_ix86_move_max = PVW_AVX512; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 218377a..b812d8b 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -27353,6 +27353,72 @@ (match_dup 0))] "peep2_reg_dead_p (2, operands[0])" [(set (match_dup 2) (match_dup 1))]) + +;; umax (a, add (a, b)) => [sum, ovf] = add (a, b); ovf ? a : sum +;; umin (a, add (a, b)) => [sum, ovf] = add (a, b); ovf ? sum : a + +(define_code_attr ovf_add_cmp [(umax "geu") (umin "ltu")]) + +(define_int_iterator ovf_comm [1 2]) + +(define_insn_and_split "*plus_within_<code><mode>3_<ovf_comm>" + [(set (match_operand:SWI248 0 "register_operand") + (umaxmin:SWI248 + (plus:SWI248 (match_operand:SWI248 1 "nonimmediate_operand") + (match_operand:SWI248 2 "<general_operand>")) + (match_dup ovf_comm))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_CMOVE + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(parallel + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plus:SWI248 (match_dup 1) (match_dup 2)) + (match_dup ovf_comm))) + (set (match_dup 3) + (plus:SWI248 (match_dup 1) (match_dup 2)))]) + (set (match_dup 0) + (if_then_else:SWI248 + (<ovf_add_cmp> (reg:CCC FLAGS_REG) (const_int 0)) + (match_dup 3) + (match_dup ovf_comm)))] +{ + operands[<ovf_comm>] = force_reg (<MODE>mode, operands[<ovf_comm>]); + operands[3] = gen_reg_rtx (<MODE>mode); +}) + +;; umax (a, sub (a, b)) => [diff, udf] = sub (a, b); udf ? diff : a +;; umin (a, sub (a, b)) => [diff, udf] = sub (a, b); udf ? a : diff + +(define_code_attr udf_sub_cmp [(umax "ltu") (umin "geu")]) + +(define_insn_and_split "*minus_within_<code><mode>3" + [(set (match_operand:SWI248 0 "register_operand") + (umaxmin:SWI248 + (minus:SWI248 (match_operand:SWI248 1 "nonimmediate_operand") + (match_operand:SWI248 2 "<general_operand>")) + (match_dup 1))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_CMOVE + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(parallel + [(set (reg:CC FLAGS_REG) + (compare:CC (match_dup 1) (match_dup 2))) + (set (match_dup 3) + (minus:SWI248 (match_dup 1) (match_dup 2)))]) + (set (match_dup 0) + (if_then_else:SWI248 + (<udf_sub_cmp> (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 3) + (match_dup 1)))] +{ + operands[1] = force_reg (<MODE>mode, operands[1]); + operands[3] = gen_reg_rtx (<MODE>mode); +}) ;; Misc patterns (?) diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 5eba992..7d91585 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -643,6 +643,9 @@ (define_mode_iterator VI2_AVX512F [(V32HI "TARGET_AVX512F") (V16HI "TARGET_AVX2") V8HI]) +(define_mode_iterator VI2_AVX10_2 + [(V32HI "TARGET_AVX10_2") (V16HI "TARGET_AVX2") V8HI]) + (define_mode_iterator VI2_AVX512VNNIBW [(V32HI "TARGET_AVX512BW || TARGET_AVX512VNNI") (V16HI "TARGET_AVX2") V8HI]) @@ -32334,8 +32337,8 @@ (define_expand "usdot_prod<sseunpackmodelower><mode>" [(match_operand:<sseunpackmode> 0 "register_operand") - (match_operand:VI2_AVX512F 1 "register_operand") - (match_operand:VI2_AVX512F 2 "register_operand") + (match_operand:VI2_AVX10_2 1 "register_operand") + (match_operand:VI2_AVX10_2 2 "register_operand") (match_operand:<sseunpackmode> 3 "register_operand")] "TARGET_AVXVNNIINT16 || TARGET_AVX10_2" { @@ -32352,8 +32355,8 @@ (define_expand "udot_prod<sseunpackmodelower><mode>" [(match_operand:<sseunpackmode> 0 "register_operand") - (match_operand:VI2_AVX512F 1 "register_operand") - (match_operand:VI2_AVX512F 2 "register_operand") + (match_operand:VI2_AVX10_2 1 "register_operand") + (match_operand:VI2_AVX10_2 2 "register_operand") (match_operand:<sseunpackmode> 3 "register_operand")] "TARGET_AVXVNNIINT16 || TARGET_AVX10_2" { diff --git a/gcc/config/loongarch/lasx.md b/gcc/config/loongarch/lasx.md index 3048c48..7a91473 100644 --- a/gcc/config/loongarch/lasx.md +++ b/gcc/config/loongarch/lasx.md @@ -146,9 +146,6 @@ ;; Only integer modes equal or larger than a word. (define_mode_iterator ILASX_DW [V4DI V8SI]) -;; Only integer modes smaller than a word. -(define_mode_iterator ILASX_HB [V16HI V32QI]) - ;; Only used for immediate set shuffle elements instruction. (define_mode_iterator LASX_WHB_W [V8SI V16HI V32QI V8SF]) @@ -982,16 +979,6 @@ [(set_attr "type" "simd_fmadd") (set_attr "mode" "<MODE>")]) -(define_insn "fnma<mode>4" - [(set (match_operand:FLASX 0 "register_operand" "=f") - (fma:FLASX (neg:FLASX (match_operand:FLASX 1 "register_operand" "f")) - (match_operand:FLASX 2 "register_operand" "f") - (match_operand:FLASX 3 "register_operand" "0")))] - "ISA_HAS_LASX" - "xvfnmsub.<flasxfmt>\t%u0,%u1,%u2,%u0" - [(set_attr "type" "simd_fmadd") - (set_attr "mode" "<MODE>")]) - (define_expand "sqrt<mode>2" [(set (match_operand:FLASX 0 "register_operand") (sqrt:FLASX (match_operand:FLASX 1 "register_operand")))] @@ -3580,69 +3567,38 @@ [(set_attr "type" "simd_store") (set_attr "mode" "DI")]) -(define_expand "vec_widen_<su>add_hi_<mode>" +(define_expand "vec_widen_<su><optab>_<hi_lo>_<mode>" [(match_operand:<VDMODE256> 0 "register_operand") - (any_extend:<VDMODE256> (match_operand:ILASX_HB 1 "register_operand")) - (any_extend:<VDMODE256> (match_operand:ILASX_HB 2 "register_operand"))] - "ISA_HAS_LASX" -{ - loongarch_expand_vec_widen_hilo (operands[0], operands[1], operands[2], - <u_bool>, true, "add"); - DONE; -}) - -(define_expand "vec_widen_<su>add_lo_<mode>" - [(match_operand:<VDMODE256> 0 "register_operand") - (any_extend:<VDMODE256> (match_operand:ILASX_HB 1 "register_operand")) - (any_extend:<VDMODE256> (match_operand:ILASX_HB 2 "register_operand"))] - "ISA_HAS_LASX" -{ - loongarch_expand_vec_widen_hilo (operands[0], operands[1], operands[2], - <u_bool>, false, "add"); - DONE; -}) - -(define_expand "vec_widen_<su>sub_hi_<mode>" - [(match_operand:<VDMODE256> 0 "register_operand") - (any_extend:<VDMODE256> (match_operand:ILASX_HB 1 "register_operand")) - (any_extend:<VDMODE256> (match_operand:ILASX_HB 2 "register_operand"))] - "ISA_HAS_LASX" -{ - loongarch_expand_vec_widen_hilo (operands[0], operands[1], operands[2], - <u_bool>, true, "sub"); - DONE; -}) - -(define_expand "vec_widen_<su>sub_lo_<mode>" - [(match_operand:<VDMODE256> 0 "register_operand") - (any_extend:<VDMODE256> (match_operand:ILASX_HB 1 "register_operand")) - (any_extend:<VDMODE256> (match_operand:ILASX_HB 2 "register_operand"))] - "ISA_HAS_LASX" -{ - loongarch_expand_vec_widen_hilo (operands[0], operands[1], operands[2], - <u_bool>, false, "sub"); - DONE; -}) - -(define_expand "vec_widen_<su>mult_hi_<mode>" - [(match_operand:<VDMODE256> 0 "register_operand") - (any_extend:<VDMODE256> (match_operand:ILASX_HB 1 "register_operand")) - (any_extend:<VDMODE256> (match_operand:ILASX_HB 2 "register_operand"))] + (match_operand:ILASX_WHB 1 "register_operand") + (match_operand:ILASX_WHB 2 "register_operand") + (any_extend (const_int 0)) + (addsub (const_int 0) (const_int 0)) + (const_int zero_one)] "ISA_HAS_LASX" { + rtx (*fn_even) (rtx, rtx, rtx) = +gen_lasx_xv<optab>wev_<dlasxfmt>_<lasxfmt><u>; + rtx (*fn_odd) (rtx, rtx, rtx) = +gen_lasx_xv<optab>wod_<dlasxfmt>_<lasxfmt><u>; loongarch_expand_vec_widen_hilo (operands[0], operands[1], operands[2], - <u_bool>, true, "mult"); + <zero_one>, fn_even, fn_odd); DONE; }) -(define_expand "vec_widen_<su>mult_lo_<mode>" +(define_expand "vec_widen_<su>mult_<hi_lo>_<mode>" [(match_operand:<VDMODE256> 0 "register_operand") - (any_extend:<VDMODE256> (match_operand:ILASX_HB 1 "register_operand")) - (any_extend:<VDMODE256> (match_operand:ILASX_HB 2 "register_operand"))] + (match_operand:ILASX_WHB 1 "register_operand") + (match_operand:ILASX_WHB 2 "register_operand") + (any_extend (const_int 0)) + (const_int zero_one)] "ISA_HAS_LASX" { + rtx (*fn_even) (rtx, rtx, rtx) = +gen_lasx_xvmulwev_<dlasxfmt>_<lasxfmt><u>; + rtx (*fn_odd) (rtx, rtx, rtx) = +gen_lasx_xvmulwod_<dlasxfmt>_<lasxfmt><u>; loongarch_expand_vec_widen_hilo (operands[0], operands[1], operands[2], - <u_bool>, false, "mult"); + <zero_one>, fn_even, fn_odd); DONE; }) diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h index 6ecbe27..bec4368 100644 --- a/gcc/config/loongarch/loongarch-protos.h +++ b/gcc/config/loongarch/loongarch-protos.h @@ -198,7 +198,8 @@ extern void loongarch_register_frame_header_opt (void); extern void loongarch_expand_vec_cond_expr (machine_mode, machine_mode, rtx *); extern void loongarch_expand_vec_cond_mask_expr (machine_mode, machine_mode, rtx *); -extern void loongarch_expand_vec_widen_hilo (rtx, rtx, rtx, bool, bool, const char *); +extern void loongarch_expand_vec_widen_hilo (rtx, rtx, rtx, bool, + rtx (*)(rtx, rtx, rtx), rtx (*)(rtx, rtx, rtx)); /* Routines implemented in loongarch-c.c. */ void loongarch_cpu_cpp_builtins (cpp_reader *); @@ -217,7 +218,8 @@ extern void loongarch_emit_swdivsf (rtx, rtx, rtx, machine_mode); extern bool loongarch_explicit_relocs_p (enum loongarch_symbol_type); extern bool loongarch_symbol_extreme_p (enum loongarch_symbol_type); extern bool loongarch_option_valid_attribute_p (tree, tree, tree, int); -extern void loongarch_option_override_internal (struct loongarch_target *, struct gcc_options *, struct gcc_options *); +extern void loongarch_option_override_internal (struct loongarch_target *, + struct gcc_options *, struct gcc_options *); extern void loongarch_reset_previous_fndecl (void); extern void loongarch_save_restore_target_globals (tree new_tree); extern void loongarch_register_pragmas (void); diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index bdf2906..f7ce3aa 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -5533,12 +5533,32 @@ loongarch_expand_conditional_move (rtx *operands) } } + auto is_binary_op_0_keep_orig = [](enum rtx_code code) + { + switch (code) + { + case PLUS: + case MINUS: + case IOR: + case XOR: + case ROTATE: + case ROTATERT: + case ASHIFT: + case ASHIFTRT: + case LSHIFTRT: + return true; + default: + return false; + } + }; + /* Check if the optimization conditions are met. */ if (value_if_true_insn && value_if_false_insn - /* Make sure that value_if_false and var are the same. */ - && BINARY_P (value_if_true_insn_src - = SET_SRC (single_set (value_if_true_insn))) + /* Make sure that the orig value OP 0 keep orig. */ + && (value_if_true_insn_src + = SET_SRC (single_set (value_if_true_insn))) + && is_binary_op_0_keep_orig ( GET_CODE (value_if_true_insn_src)) /* Make sure that both value_if_true and value_if_false has the same var. */ && rtx_equal_p (XEXP (value_if_true_insn_src, 0), @@ -8883,105 +8903,22 @@ loongarch_expand_vec_interleave (rtx target, rtx op0, rtx op1, bool high_p) void loongarch_expand_vec_widen_hilo (rtx dest, rtx op1, rtx op2, - bool uns_p, bool high_p, const char *optab) + bool high_p, rtx (*fn_even) (rtx, rtx, rtx), + rtx (*fn_odd) (rtx, rtx, rtx)) { machine_mode wmode = GET_MODE (dest); machine_mode mode = GET_MODE (op1); - rtx t1, t2, t3; - t1 = gen_reg_rtx (wmode); - t2 = gen_reg_rtx (wmode); - t3 = gen_reg_rtx (wmode); - switch (mode) - { - case V16HImode: - if (!strcmp (optab, "add")) - { - if (!uns_p) - { - emit_insn (gen_lasx_xvaddwev_w_h (t1, op1, op2)); - emit_insn (gen_lasx_xvaddwod_w_h (t2, op1, op2)); - } - else - { - emit_insn (gen_lasx_xvaddwev_w_hu (t1, op1, op2)); - emit_insn (gen_lasx_xvaddwod_w_hu (t2, op1, op2)); - } - } - else if (!strcmp (optab, "mult")) - { - if (!uns_p) - { - emit_insn (gen_lasx_xvmulwev_w_h (t1, op1, op2)); - emit_insn (gen_lasx_xvmulwod_w_h (t2, op1, op2)); - } - else - { - emit_insn (gen_lasx_xvmulwev_w_hu (t1, op1, op2)); - emit_insn (gen_lasx_xvmulwod_w_hu (t2, op1, op2)); - } - } - else if (!strcmp (optab, "sub")) - { - if (!uns_p) - { - emit_insn (gen_lasx_xvsubwev_w_h (t1, op1, op2)); - emit_insn (gen_lasx_xvsubwod_w_h (t2, op1, op2)); - } - else - { - emit_insn (gen_lasx_xvsubwev_w_hu (t1, op1, op2)); - emit_insn (gen_lasx_xvsubwod_w_hu (t2, op1, op2)); - } - } - break; - - case V32QImode: - if (!strcmp (optab, "add")) - { - if (!uns_p) - { - emit_insn (gen_lasx_xvaddwev_h_b (t1, op1, op2)); - emit_insn (gen_lasx_xvaddwod_h_b (t2, op1, op2)); - } - else - { - emit_insn (gen_lasx_xvaddwev_h_bu (t1, op1, op2)); - emit_insn (gen_lasx_xvaddwod_h_bu (t2, op1, op2)); - } - } - else if (!strcmp (optab, "mult")) - { - if (!uns_p) - { - emit_insn (gen_lasx_xvmulwev_h_b (t1, op1, op2)); - emit_insn (gen_lasx_xvmulwod_h_b (t2, op1, op2)); - } - else - { - emit_insn (gen_lasx_xvmulwev_h_bu (t1, op1, op2)); - emit_insn (gen_lasx_xvmulwod_h_bu (t2, op1, op2)); - } - } - else if (!strcmp (optab, "sub")) - { - if (!uns_p) - { - emit_insn (gen_lasx_xvsubwev_h_b (t1, op1, op2)); - emit_insn (gen_lasx_xvsubwod_h_b (t2, op1, op2)); - } - else - { - emit_insn (gen_lasx_xvsubwev_h_bu (t1, op1, op2)); - emit_insn (gen_lasx_xvsubwod_h_bu (t2, op1, op2)); - } - } - break; + gcc_assert (ISA_HAS_LASX + && GET_MODE_SIZE (mode) == 32 + && mode != V4DImode); - default: - gcc_unreachable (); - } + rtx t1 = gen_reg_rtx (wmode); + rtx t2 = gen_reg_rtx (wmode); + rtx t3 = gen_reg_rtx (wmode); + emit_insn (fn_even (t1, op1, op2)); + emit_insn (fn_odd (t2, op1, op2)); loongarch_expand_vec_interleave (t3, t1, t2, high_p); emit_move_insn (dest, gen_lowpart (wmode, t3)); } diff --git a/gcc/config/loongarch/lsx.md b/gcc/config/loongarch/lsx.md index 7131a53..cd87757 100644 --- a/gcc/config/loongarch/lsx.md +++ b/gcc/config/loongarch/lsx.md @@ -145,9 +145,6 @@ ;; Only integer modes equal or larger than a word. (define_mode_iterator ILSX_DW [V2DI V4SI]) -;; Only integer modes smaller than a word. -(define_mode_iterator ILSX_HB [V8HI V16QI]) - ;;;; Only integer modes for fixed-point madd_q/maddr_q. ;;(define_mode_iterator ILSX_WH [V4SI V8HI]) @@ -799,16 +796,6 @@ [(set_attr "type" "simd_fmadd") (set_attr "mode" "<MODE>")]) -(define_insn "fnma<mode>4" - [(set (match_operand:FLSX 0 "register_operand" "=f") - (fma:FLSX (neg:FLSX (match_operand:FLSX 1 "register_operand" "f")) - (match_operand:FLSX 2 "register_operand" "f") - (match_operand:FLSX 3 "register_operand" "0")))] - "ISA_HAS_LSX" - "vfnmsub.<flsxfmt>\t%w0,%w1,%w2,%w0" - [(set_attr "type" "simd_fmadd") - (set_attr "mode" "<MODE>")]) - (define_expand "sqrt<mode>2" [(set (match_operand:FLSX 0 "register_operand") (sqrt:FLSX (match_operand:FLSX 1 "register_operand")))] @@ -3167,3 +3154,48 @@ [(set (match_dup 0) (vec_duplicate:V2DI (match_dup 1)))] "") + +(define_expand "vec_widen_<su><optab>_<hi_lo>_<mode>" + [(match_operand:<VDMODE> 0 "register_operand") + (match_operand:ILSX_WHB 1 "register_operand") + (match_operand:ILSX_WHB 2 "register_operand") + (any_extend (const_int 0)) + (addsub (const_int 0) (const_int 0)) + (const_int zero_one)] + "ISA_HAS_LSX" +{ + rtx t_even = gen_reg_rtx (<VDMODE>mode); + rtx t_odd = gen_reg_rtx (<VDMODE>mode); + emit_insn (gen_lsx_v<optab>wev_<dlsxfmt>_<lsxfmt><u> (t_even, operands[1], + operands[2])); + emit_insn (gen_lsx_v<optab>wod_<dlsxfmt>_<lsxfmt><u> (t_odd, operands[1], + operands[2])); + if (<zero_one>) + emit_insn (gen_lsx_vilvh_<dlsxfmt> (operands[0], t_even, t_odd)); + else + emit_insn (gen_lsx_vilvl_<dlsxfmt> (operands[0], t_even, t_odd)); + + DONE; +}) + +(define_expand "vec_widen_<su>mult_<hi_lo>_<mode>" + [(match_operand:<VDMODE> 0 "register_operand") + (match_operand:ILSX_WHB 1 "register_operand") + (match_operand:ILSX_WHB 2 "register_operand") + (any_extend (const_int 0)) + (const_int zero_one)] + "ISA_HAS_LSX" +{ + rtx t_even = gen_reg_rtx (<VDMODE>mode); + rtx t_odd = gen_reg_rtx (<VDMODE>mode); + emit_insn (gen_lsx_vmulwev_<dlsxfmt>_<lsxfmt><u> (t_even, operands[1], + operands[2])); + emit_insn (gen_lsx_vmulwod_<dlsxfmt>_<lsxfmt><u> (t_odd, operands[1], + operands[2])); + if (<zero_one>) + emit_insn (gen_lsx_vilvh_<dlsxfmt> (operands[0], t_even, t_odd)); + else + emit_insn (gen_lsx_vilvl_<dlsxfmt> (operands[0], t_even, t_odd)); + + DONE; +}) diff --git a/gcc/config/loongarch/simd.md b/gcc/config/loongarch/simd.md index 9f4525a..b73f65a 100644 --- a/gcc/config/loongarch/simd.md +++ b/gcc/config/loongarch/simd.md @@ -23,6 +23,10 @@ ;; Integer modes supported by LASX. (define_mode_iterator ILASX [V4DI V8SI V16HI V32QI]) +;; Only integer modes smaller than a word. +(define_mode_iterator ILSX_HB [V8HI V16QI]) +(define_mode_iterator ILASX_HB [V16HI V32QI]) + ;; FP modes supported by LSX (define_mode_iterator FLSX [V2DF V4SF]) @@ -38,6 +42,10 @@ ;; All integer modes available (define_mode_iterator IVEC [(ILSX "ISA_HAS_LSX") (ILASX "ISA_HAS_LASX")]) +;; All integer modes smaller than a word. +(define_mode_iterator IVEC_HB [(ILSX_HB "ISA_HAS_LSX") + (ILASX_HB "ISA_HAS_LASX")]) + ;; All FP modes available (define_mode_iterator FVEC [(FLSX "ISA_HAS_LSX") (FLASX "ISA_HAS_LASX")]) @@ -90,12 +98,18 @@ (V8HI "V4SI") (V16HI "V8SI") (V16QI "V8HI") (V32QI "V16HI")]) +(define_mode_attr WVEC_QUARTER [(V8HI "V2DI") (V16HI "V4DI") + (V16QI "V4SI") (V32QI "V8SI")]) + ;; Lower-case version. (define_mode_attr wvec_half [(V2DI "v1ti") (V4DI "v2ti") (V4SI "v2di") (V8SI "v4di") (V8HI "v4si") (V16HI "v8si") (V16QI "v8hi") (V32QI "v16hi")]) +(define_mode_attr wvec_quarter [(V8HI "v2di") (V16HI "v4di") + (V16QI "v4si") (V32QI "v8si")]) + ;; Integer vector modes with the same length and unit size as a mode. (define_mode_attr VIMODE [(V2DI "V2DI") (V4SI "V4SI") (V8HI "V8HI") (V16QI "V16QI") @@ -124,12 +138,16 @@ (V8HI "h") (V16HI "h") (V16QI "b") (V32QI "b")]) -;; Suffix for widening LSX or LASX instructions. +;; Suffix for double widening LSX or LASX instructions. (define_mode_attr simdfmt_w [(V2DI "q") (V4DI "q") (V4SI "d") (V8SI "d") (V8HI "w") (V16HI "w") (V16QI "h") (V32QI "h")]) +;; Suffix for quadruple widening LSX or LASX instructions. +(define_mode_attr simdfmt_qw [(V8HI "d") (V16HI "d") + (V16QI "w") (V32QI "w")]) + ;; Suffix for integer mode in LSX or LASX instructions with FP input but ;; integer output. (define_mode_attr simdifmt_for_f [(V2DF "l") (V4DF "l") @@ -169,6 +187,8 @@ (V4SI "uimm5") (V8SI "uimm5") (V2DI "uimm6") (V4DI "uimm6")]) +(define_int_attr hi_lo [(0 "lo") (1 "hi")]) + ;; ======================================================================= ;; For many LASX instructions, the only difference of it from the LSX ;; counterpart is the length of vector operands. Describe these LSX/LASX @@ -431,6 +451,17 @@ [(set_attr "type" "simd_int_arith") (set_attr "mode" "<MODE>")]) +;; <x>vfnmsub.{s/d} +(define_insn "fnma<mode>4" + [(set (match_operand:FVEC 0 "register_operand" "=f") + (fma:FVEC (neg:FVEC (match_operand:FVEC 1 "register_operand" "f")) + (match_operand:FVEC 2 "register_operand" "f") + (match_operand:FVEC 3 "register_operand" "f")))] + "!HONOR_SIGNED_ZEROS (<MODE>mode)" + "<x>vfnmsub.<simdfmt>\t%<wu>0,%<wu>1,%<wu>2,%<wu>3" + [(set_attr "type" "simd_fmadd") + (set_attr "mode" "<MODE>")]) + ;; <x>vfcmp.*.{s/d} with defined RTX code ;; There are no fcmp.{sugt/suge/cgt/cge}.{s/d} menmonics in GAS, so we have ;; to reverse the operands ourselves :(. @@ -826,6 +857,39 @@ DONE; }) +(define_expand "<su>dot_prod<wvec_quarter><mode>" + [(match_operand:<WVEC_QUARTER> 0 "register_operand" "=f,f") + (match_operand:IVEC_HB 1 "register_operand" "f,f") + (match_operand:IVEC_HB 2 "register_operand" "f,f") + (match_operand:<WVEC_QUARTER> 3 "reg_or_0_operand" "f, YG") + (any_extend (const_int 0))] + "" +{ + rtx *op = operands; + rtx res_mulev = gen_reg_rtx (<WVEC_HALF>mode); + rtx res_mulod = gen_reg_rtx (<WVEC_HALF>mode); + rtx res_addev = gen_reg_rtx (<WVEC_QUARTER>mode); + rtx res_addod = gen_reg_rtx (<WVEC_QUARTER>mode); + emit_insn (gen_<simd_isa>_<x>vmulwev_<simdfmt_w>_<simdfmt><u> + (res_mulev, op[1], op[2])); + emit_insn (gen_<simd_isa>_<x>vmulwod_<simdfmt_w>_<simdfmt><u> + (res_mulod, op[1], op[2])); + emit_insn (gen_<simd_isa>_<x>vhaddw_<simdfmt_qw><u>_<simdfmt_w><u> + (res_addev, res_mulev, res_mulev)); + emit_insn (gen_<simd_isa>_<x>vhaddw_<simdfmt_qw><u>_<simdfmt_w><u> + (res_addod, res_mulod, res_mulod)); + if (op[3] == CONST0_RTX (<WVEC_QUARTER>mode)) + emit_insn (gen_add<wvec_quarter>3 (op[0], res_addev, + res_addod)); + else + { + emit_insn (gen_add<wvec_quarter>3 (res_addev, res_addev, + res_addod)); + emit_insn (gen_add<wvec_quarter>3 (op[0], res_addev, op[3])); + } + DONE; +}) + (define_insn "simd_maddw_evod_<mode>_hetero" [(set (match_operand:<WVEC_HALF> 0 "register_operand" "=f") (plus:<WVEC_HALF> diff --git a/gcc/config/riscv/riscv-avlprop.cc b/gcc/config/riscv/riscv-avlprop.cc index b8547a7..a42764e 100644 --- a/gcc/config/riscv/riscv-avlprop.cc +++ b/gcc/config/riscv/riscv-avlprop.cc @@ -77,6 +77,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-pass.h" #include "df.h" #include "rtl-ssa.h" +#include "rtl-iter.h" #include "cfgcleanup.h" #include "insn-attr.h" #include "tm-constrs.h" @@ -412,6 +413,46 @@ pass_avlprop::get_vlmax_ta_preferred_avl (insn_info *insn) const && def1->insn ()->compare_with (insn) >= 0) return NULL_RTX; } + else + { + /* If the use is in a subreg e.g. in a store it is possible that + we punned the vector mode with a larger mode like + (subreg:V1SI (reg:V4QI 123)). + For an AVL of 1 that means we actually store one SImode + element and not 1 QImode elements. But the latter is what we + would propagate if we took the AVL operand literally. + Instead we scale it by the ratio of inner and outer mode + (4 in the example above). */ + int factor = 1; + if (use->includes_subregs ()) + { + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, use_insn->rtl (), NONCONST) + { + const_rtx x = *iter; + if (x + && SUBREG_P (x) + && REG_P (SUBREG_REG (x)) + && REGNO (SUBREG_REG (x)) == use->regno () + && known_eq (GET_MODE_SIZE (use->mode ()), + GET_MODE_SIZE (GET_MODE (x)))) + { + if (can_div_trunc_p (GET_MODE_NUNITS (use->mode ()), + GET_MODE_NUNITS (GET_MODE (x)), + &factor)) + { + gcc_assert (factor > 0); + break; + } + else + return NULL_RTX; + } + } + } + + if (factor > 1) + new_use_avl = GEN_INT (INTVAL (new_use_avl) * factor); + } if (!use_avl) use_avl = new_use_avl; diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 4ba7f54..c713451 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -43,6 +43,7 @@ UNSPEC_FRAME_BLOCKAGE UNSPEC_CEIL UNSPEC_FLOOR + UNSPEC_ROUND ]) (define_c_enum "unspecv" [ @@ -104,8 +105,11 @@ ;; This iterator and attribute allow FP-to-integer rounding of two types ;; to be generated from one template. -(define_int_iterator ANY_ROUND [UNSPEC_CEIL UNSPEC_FLOOR]) -(define_int_attr m_round [(UNSPEC_CEIL "ceil") (UNSPEC_FLOOR "floor")]) +(define_int_iterator ANY_ROUND [UNSPEC_CEIL UNSPEC_FLOOR UNSPEC_ROUND]) +(define_int_attr m_round [(UNSPEC_CEIL "ceil") (UNSPEC_FLOOR "floor") + (UNSPEC_ROUND "round")]) +(define_int_attr c_round [(UNSPEC_CEIL "1") (UNSPEC_FLOOR "1") + (UNSPEC_ROUND "flag_unsafe_math_optimizations")]) ;; Attributes. @@ -691,13 +695,15 @@ }) (define_insn "negsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (match_operand:SF 1 "register_operand" "f")))] + [(set (match_operand:SF 0 "register_operand") + (neg:SF (match_operand:SF 1 "register_operand"))) + (clobber (match_scratch:SI 2))] "TARGET_HARD_FLOAT" - "neg.s\t%0, %1" - [(set_attr "type" "farith") - (set_attr "mode" "SF") - (set_attr "length" "3")]) + {@ [cons: =0, 1, =2; attrs: type, length] + [D, D, &a; arith , 7] movi.n\t%2, 1\;slli\t%2, %2, 31\;add.n\t%0, %1, %2 + [f, f, X; farith, 3] neg.s\t%0, %1 + } + [(set_attr "mode" "SF")]) ;; Logical instructions. @@ -1139,7 +1145,7 @@ (define_insn "*fix<s_fix>_truncsfsi2_scaled" [(set (match_operand:SI 0 "register_operand" "=a") (any_fix:SI (mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "fix_scaling_operand" "F"))))] + (match_operand:SF 2 "fix_scaling_operand" ""))))] "TARGET_HARD_FLOAT" "<m_fix>.s\t%0, %1, %U2" [(set_attr "type" "fconv") @@ -1158,7 +1164,7 @@ (define_insn "*float<s_float>sisf2_scaled" [(set (match_operand:SF 0 "register_operand" "=f") (mult:SF (any_float:SF (match_operand:SI 1 "register_operand" "a")) - (match_operand:SF 2 "float_scaling_operand" "F")))] + (match_operand:SF 2 "float_scaling_operand" "")))] "TARGET_HARD_FLOAT" "<m_float>.s\t%0, %1, %V2" [(set_attr "type" "fconv") @@ -1168,7 +1174,7 @@ (define_insn "l<m_round>sfsi2" [(set (match_operand:SI 0 "register_operand" "=a") (unspec:SI [(match_operand:SF 1 "register_operand" "f")] ANY_ROUND))] - "TARGET_HARD_FLOAT" + "TARGET_HARD_FLOAT && <c_round>" "<m_round>.s\t%0, %1, 0" [(set_attr "type" "fconv") (set_attr "mode" "SF") @@ -1178,7 +1184,7 @@ [(set (match_operand:SI 0 "register_operand" "=a") (unspec:SI [(plus:SF (match_operand:SF 1 "register_operand" "f") (match_dup 1))] ANY_ROUND))] - "TARGET_HARD_FLOAT" + "TARGET_HARD_FLOAT && <c_round>" "<m_round>.s\t%0, %1, 1" [(set_attr "type" "fconv") (set_attr "mode" "SF") @@ -1187,8 +1193,8 @@ (define_insn "*l<m_round>sfsi2_scaled" [(set (match_operand:SI 0 "register_operand" "=a") (unspec:SI [(mult:SF (match_operand:SF 1 "register_operand" "f") - (match_operand:SF 2 "fix_scaling_operand" "F"))] ANY_ROUND))] - "TARGET_HARD_FLOAT" + (match_operand:SF 2 "fix_scaling_operand" ""))] ANY_ROUND))] + "TARGET_HARD_FLOAT && <c_round>" "<m_round>.s\t%0, %1, %U2" [(set_attr "type" "fconv") (set_attr "mode" "SF") diff --git a/gcc/coretypes.h b/gcc/coretypes.h index 8c3633b..779abb9 100644 --- a/gcc/coretypes.h +++ b/gcc/coretypes.h @@ -147,12 +147,14 @@ using dw_cfi_ref = struct dw_cfi_node *; enum dw_cfi_oprnd_type: int; enum dwarf_call_frame_info: int; -/* Subclasses of symtab_node, using indentation to show the class +/* Subclasses of toplevel_node, using indentation to show the class hierarchy. */ -struct symtab_node; - struct cgraph_node; - struct varpool_node; +struct toplevel_node; + struct asm_node; + struct symtab_node; + struct cgraph_node; + struct varpool_node; struct cgraph_edge; union section; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ae4581a..73c2a03 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2025-10-30 Jakub Jelinek <jakub@redhat.com> + + * std-name-hint.gperf: Remove duplicate entries for ispanstream + and istringstream. + * std-name-hint.h: Regenerate. + 2025-10-28 Marek Polacek <polacek@redhat.com> Jakub Jelinek <jakub@redhat.com> diff --git a/gcc/cp/std-name-hint.gperf b/gcc/cp/std-name-hint.gperf index 3e06e61..641f3c5 100644 --- a/gcc/cp/std-name-hint.gperf +++ b/gcc/cp/std-name-hint.gperf @@ -420,7 +420,6 @@ basic_ospanstream, "<spanstream>", cxx23 basic_spanbuf, "<spanstream>", cxx23 basic_spanstream, "<spanstream>", cxx23 ispanstream, "<spanstream>", cxx23 -ispanstream, "<spanstream>", cxx23 ospanstream, "<spanstream>", cxx23 spanbuf, "<spanstream>", cxx23 spanstream, "<spanstream>", cxx23 @@ -433,7 +432,6 @@ basic_ostringstream, "<sstream>", cxx98 basic_stringbuf, "<sstream>", cxx98 basic_stringstream, "<sstream>", cxx98 istringstream, "<sstream>", cxx98 -istringstream, "<sstream>", cxx98 ostringstream, "<sstream>", cxx98 stringbuf, "<sstream>", cxx98 stringstream, "<sstream>", cxx98 diff --git a/gcc/cp/std-name-hint.h b/gcc/cp/std-name-hint.h index e354032..8e64b56 100644 --- a/gcc/cp/std-name-hint.h +++ b/gcc/cp/std-name-hint.h @@ -61,7 +61,7 @@ struct std_name_hint /* The dialect of C++ in which this was added. */ enum cxx_dialect min_dialect; }; -/* maximum key range = 2080, duplicates = 7 */ +/* maximum key range = 2080, duplicates = 5 */ class std_name_hint_lookup { @@ -135,7 +135,7 @@ std_name_hint_lookup::find (const char *str, size_t len) { enum { - TOTAL_KEYWORDS = 488, + TOTAL_KEYWORDS = 486, MIN_WORD_LENGTH = 2, MAX_WORD_LENGTH = 39, MIN_HASH_VALUE = 7, @@ -148,7 +148,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"regular", "<concepts>", cxx20}, #line 292 "std-name-hint.gperf" {"reverse_iterator", "<iterator>", cxx98}, -#line 454 "std-name-hint.gperf" +#line 452 "std-name-hint.gperf" {"range_error", "<stdexcept>", cxx98}, #line 408 "std-name-hint.gperf" {"set", "<set>", cxx98}, @@ -164,13 +164,13 @@ std_name_hint_lookup::find (const char *str, size_t len) {"formatter", "<format>", cxx20}, #line 196 "std-name-hint.gperf" {"basic_filebuf", "<fstream>", cxx98}, -#line 575 "std-name-hint.gperf" +#line 573 "std-name-hint.gperf" {"pair", "<utility>", cxx98}, #line 276 "std-name-hint.gperf" {"begin", "<iterator>", cxx11}, #line 179 "std-name-hint.gperf" {"formattable", "<format>", cxx23}, -#line 541 "std-name-hint.gperf" +#line 539 "std-name-hint.gperf" {"bad_cast", "<typeinfo>", cxx98}, #line 233 "std-name-hint.gperf" {"setiosflags", "<iomanip>", cxx98}, @@ -178,7 +178,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"print", "<print>", cxx23}, #line 221 "std-name-hint.gperf" {"promise", "<future>", cxx11}, -#line 582 "std-name-hint.gperf" +#line 580 "std-name-hint.gperf" {"bad_variant_access", "<variant>", cxx17}, #line 328 "std-name-hint.gperf" {"to_address", "<memory>", cxx20}, @@ -196,9 +196,9 @@ std_name_hint_lookup::find (const char *str, size_t len) {"nouppercase", "<ios>", cxx98}, #line 250 "std-name-hint.gperf" {"nounitbuf", "<ios>", cxx98}, -#line 433 "std-name-hint.gperf" +#line 432 "std-name-hint.gperf" {"basic_stringbuf", "<sstream>", cxx98}, -#line 593 "std-name-hint.gperf" +#line 591 "std-name-hint.gperf" {"vector", "<vector>", cxx98}, #line 246 "std-name-hint.gperf" {"noshowbase", "<ios>", cxx98}, @@ -210,9 +210,9 @@ std_name_hint_lookup::find (const char *str, size_t len) {"pmr::get_default_resource", "<memory_resource>", cxx17}, #line 343 "std-name-hint.gperf" {"pmr::set_default_resource", "<memory_resource>", cxx17}, -#line 455 "std-name-hint.gperf" +#line 453 "std-name-hint.gperf" {"runtime_error", "<stdexcept>", cxx98}, -#line 516 "std-name-hint.gperf" +#line 514 "std-name-hint.gperf" {"tuple", "<tuple>", cxx11}, #line 132 "std-name-hint.gperf" {"regular_invocable", "<concepts>", cxx20}, @@ -224,15 +224,15 @@ std_name_hint_lookup::find (const char *str, size_t len) {"not_fn", "<functional>", cxx17}, #line 142 "std-name-hint.gperf" {"byte", "<cstddef>", cxx17}, -#line 518 "std-name-hint.gperf" +#line 516 "std-name-hint.gperf" {"tuple_element", "<tuple>", cxx11}, -#line 519 "std-name-hint.gperf" +#line 517 "std-name-hint.gperf" {"tuple_element_t", "<tuple>", cxx14}, -#line 585 "std-name-hint.gperf" +#line 583 "std-name-hint.gperf" {"variant", "<variant>", cxx17}, #line 386 "std-name-hint.gperf" {"ends", "<ostream>", cxx98}, -#line 520 "std-name-hint.gperf" +#line 518 "std-name-hint.gperf" {"tuple_size", "<tuple>", cxx11}, #line 123 "std-name-hint.gperf" {"equality_comparable", "<concepts>", cxx20}, @@ -244,37 +244,37 @@ std_name_hint_lookup::find (const char *str, size_t len) {"noshowpos", "<ios>", cxx98}, #line 388 "std-name-hint.gperf" {"flush_emit", "<ostream>", cxx20}, -#line 586 "std-name-hint.gperf" +#line 584 "std-name-hint.gperf" {"variant_alternative", "<variant>", cxx17}, -#line 537 "std-name-hint.gperf" +#line 535 "std-name-hint.gperf" {"void_t", "<type_traits>", cxx17}, -#line 587 "std-name-hint.gperf" +#line 585 "std-name-hint.gperf" {"variant_alternative_t", "<variant>", cxx17}, #line 134 "std-name-hint.gperf" {"relation", "<concepts>", cxx20}, -#line 461 "std-name-hint.gperf" - {"float32_t", "<stdfloat>", cxx23}, #line 459 "std-name-hint.gperf" + {"float32_t", "<stdfloat>", cxx23}, +#line 457 "std-name-hint.gperf" {"float128_t", "<stdfloat>", cxx23}, #line 381 "std-name-hint.gperf" {"nullopt", "<optional>", cxx17}, #line 291 "std-name-hint.gperf" {"prev", "<iterator>", cxx11}, -#line 425 "std-name-hint.gperf" +#line 424 "std-name-hint.gperf" {"spanbuf", "<spanstream>", cxx23}, -#line 513 "std-name-hint.gperf" +#line 511 "std-name-hint.gperf" {"make_from_tuple", "<tuple>", cxx17}, #line 253 "std-name-hint.gperf" {"right", "<ios>", cxx98}, #line 210 "std-name-hint.gperf" {"mem_fn", "<functional>", cxx11}, -#line 515 "std-name-hint.gperf" +#line 513 "std-name-hint.gperf" {"tie", "<tuple>", cxx11}, #line 197 "std-name-hint.gperf" {"basic_fstream", "<fstream>", cxx98}, -#line 573 "std-name-hint.gperf" +#line 571 "std-name-hint.gperf" {"move", "<utility>", cxx11}, -#line 462 "std-name-hint.gperf" +#line 460 "std-name-hint.gperf" {"float64_t", "<stdfloat>", cxx23}, #line 127 "std-name-hint.gperf" {"movable", "<concepts>", cxx20}, @@ -282,13 +282,13 @@ std_name_hint_lookup::find (const char *str, size_t len) {"front_inserter", "<iterator>", cxx98}, #line 296 "std-name-hint.gperf" {"map", "<map>", cxx98}, -#line 460 "std-name-hint.gperf" +#line 458 "std-name-hint.gperf" {"float16_t", "<stdfloat>", cxx23}, #line 56 "std-name-hint.gperf" {"bitset", "<bitset>", cxx11}, #line 205 "std-name-hint.gperf" {"bind_front", "<functional>", cxx20}, -#line 574 "std-name-hint.gperf" +#line 572 "std-name-hint.gperf" {"move_if_noexcept", "<utility>", cxx11}, #line 274 "std-name-hint.gperf" {"advance", "<iterator>", cxx98}, @@ -296,7 +296,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"move_iterator", "<iterator>", cxx11}, #line 161 "std-name-hint.gperf" {"terminate", "<exception>", cxx98}, -#line 531 "std-name-hint.gperf" +#line 529 "std-name-hint.gperf" {"negation", "<type_traits>", cxx17}, #line 318 "std-name-hint.gperf" {"make_obj_using_allocator", "<memory>", cxx20}, @@ -310,7 +310,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"range_formatter", "<format>", cxx23}, #line 299 "std-name-hint.gperf" {"addressof", "<memory>", cxx11}, -#line 571 "std-name-hint.gperf" +#line 569 "std-name-hint.gperf" {"make_integer_sequence", "<utility>", cxx14}, #line 184 "std-name-hint.gperf" {"range_format", "<format>", cxx23}, @@ -320,25 +320,25 @@ std_name_hint_lookup::find (const char *str, size_t len) {"basic_spanstream", "<spanstream>", cxx23}, #line 257 "std-name-hint.gperf" {"showpos", "<ios>", cxx98}, -#line 550 "std-name-hint.gperf" +#line 548 "std-name-hint.gperf" {"as_const", "<utility>", cxx17}, #line 308 "std-name-hint.gperf" {"bad_weak_ptr", "<memory>", cxx11}, #line 168 "std-name-hint.gperf" {"basic_format_context", "<format>", cxx20}, -#line 434 "std-name-hint.gperf" +#line 433 "std-name-hint.gperf" {"basic_stringstream", "<sstream>", cxx98}, -#line 539 "std-name-hint.gperf" +#line 537 "std-name-hint.gperf" {"type_index", "<typeindex>", cxx11}, #line 169 "std-name-hint.gperf" {"basic_format_parse_context", "<format>", cxx20}, #line 160 "std-name-hint.gperf" {"make_exception_ptr", "<exception>", cxx11}, -#line 468 "std-name-hint.gperf" +#line 466 "std-name-hint.gperf" {"basic_streambuf", "<streambuf>", cxx98}, #line 167 "std-name-hint.gperf" {"basic_format_args", "<format>", cxx20}, -#line 589 "std-name-hint.gperf" +#line 587 "std-name-hint.gperf" {"variant_size", "<variant>", cxx17}, #line 407 "std-name-hint.gperf" {"multiset", "<set>", cxx98}, @@ -350,23 +350,23 @@ std_name_hint_lookup::find (const char *str, size_t len) {"recursive_timed_mutex", "<mutex>", cxx11}, #line 399 "std-name-hint.gperf" {"ranges::enable_borrowed_range", "<ranges>", cxx20}, -#line 533 "std-name-hint.gperf" +#line 531 "std-name-hint.gperf" {"remove_cvref", "<type_traits>", cxx20}, #line 206 "std-name-hint.gperf" {"function", "<functional>", cxx11}, -#line 532 "std-name-hint.gperf" +#line 530 "std-name-hint.gperf" {"negation_v", "<type_traits>", cxx17}, -#line 534 "std-name-hint.gperf" +#line 532 "std-name-hint.gperf" {"remove_cvref_t", "<type_traits>", cxx20}, #line 289 "std-name-hint.gperf" {"ostream_iterator", "<iterator>", cxx98}, -#line 588 "std-name-hint.gperf" +#line 586 "std-name-hint.gperf" {"variant_npos", "<variant>", cxx17}, #line 244 "std-name-hint.gperf" {"left", "<ios>", cxx98}, #line 200 "std-name-hint.gperf" {"fstream", "<fstream>", cxx98}, -#line 591 "std-name-hint.gperf" +#line 589 "std-name-hint.gperf" {"visit", "<variant>", cxx17}, #line 208 "std-name-hint.gperf" {"invoke", "<functional>", cxx17}, @@ -388,7 +388,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"pointer_traits", "<memory>", cxx11}, #line 131 "std-name-hint.gperf" {"invocable", "<concepts>", cxx20}, -#line 426 "std-name-hint.gperf" +#line 425 "std-name-hint.gperf" {"spanstream", "<spanstream>", cxx23}, #line 182 "std-name-hint.gperf" {"make_format_args", "<format>", cxx20}, @@ -400,9 +400,9 @@ std_name_hint_lookup::find (const char *str, size_t len) {"skipws", "<ios>", cxx98}, #line 241 "std-name-hint.gperf" {"hex", "<ios>", cxx98}, -#line 568 "std-name-hint.gperf" +#line 566 "std-name-hint.gperf" {"index_sequence_for", "<utility>", cxx14}, -#line 567 "std-name-hint.gperf" +#line 565 "std-name-hint.gperf" {"index_sequence", "<utility>", cxx14}, #line 350 "std-name-hint.gperf" {"mutex", "<mutex>", cxx11}, @@ -412,7 +412,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"weak_ptr", "<memory>", cxx11}, #line 173 "std-name-hint.gperf" {"format_context", "<format>", cxx20}, -#line 451 "std-name-hint.gperf" +#line 449 "std-name-hint.gperf" {"logic_error", "<stdexcept>", cxx98}, #line 372 "std-name-hint.gperf" {"numbers::ln2_v", "<numbers>", cxx20}, @@ -444,11 +444,11 @@ std_name_hint_lookup::find (const char *str, size_t len) {"pmr::polymorphic_allocator", "<memory_resource>", cxx17}, #line 419 "std-name-hint.gperf" {"basic_ospanstream", "<spanstream>", cxx23}, -#line 572 "std-name-hint.gperf" +#line 570 "std-name-hint.gperf" {"make_pair", "<utility>", cxx98}, #line 172 "std-name-hint.gperf" {"format_args", "<format>", cxx20}, -#line 475 "std-name-hint.gperf" +#line 473 "std-name-hint.gperf" {"stof", "<string>", cxx11}, #line 339 "std-name-hint.gperf" {"pmr::monotonic_buffer_resource", "<memory_resource>", cxx17}, @@ -456,9 +456,9 @@ std_name_hint_lookup::find (const char *str, size_t len) {"pmr::pool_options", "<memory_resource>", cxx17}, #line 256 "std-name-hint.gperf" {"showpoint", "<ios>", cxx98}, -#line 446 "std-name-hint.gperf" +#line 444 "std-name-hint.gperf" {"stacktrace", "<stacktrace>", cxx23}, -#line 590 "std-name-hint.gperf" +#line 588 "std-name-hint.gperf" {"variant_size_v", "<variant>", cxx17}, #line 212 "std-name-hint.gperf" {"reference_wrapper", "<functional>", cxx11}, @@ -466,19 +466,19 @@ std_name_hint_lookup::find (const char *str, size_t len) {"cerr", "<iostream>", cxx98}, #line 300 "std-name-hint.gperf" {"align", "<memory>", cxx11}, -#line 438 "std-name-hint.gperf" +#line 436 "std-name-hint.gperf" {"stringbuf", "<sstream>", cxx98}, -#line 469 "std-name-hint.gperf" +#line 467 "std-name-hint.gperf" {"streambuf", "<streambuf>", cxx98}, #line 306 "std-name-hint.gperf" {"allocator_traits", "<memory>", cxx11}, #line 183 "std-name-hint.gperf" {"make_wformat_args", "<format>", cxx20}, -#line 584 "std-name-hint.gperf" +#line 582 "std-name-hint.gperf" {"monostate", "<variant>", cxx17}, #line 387 "std-name-hint.gperf" {"flush", "<ostream>", cxx98}, -#line 527 "std-name-hint.gperf" +#line 525 "std-name-hint.gperf" {"enable_if", "<type_traits>", cxx11}, #line 352 "std-name-hint.gperf" {"recursive_mutex", "<mutex>", cxx11}, @@ -490,15 +490,15 @@ std_name_hint_lookup::find (const char *str, size_t len) {"pmr::memory_resource", "<memory_resource>", cxx17}, #line 124 "std-name-hint.gperf" {"equality_comparable_with", "<concepts>", cxx20}, -#line 493 "std-name-hint.gperf" +#line 491 "std-name-hint.gperf" {"errc", "<system_error>", cxx11}, #line 344 "std-name-hint.gperf" {"pmr::synchronized_pool_resource", "<memory_resource>", cxx17}, #line 385 "std-name-hint.gperf" {"endl", "<ostream>", cxx98}, -#line 495 "std-name-hint.gperf" +#line 493 "std-name-hint.gperf" {"error_code", "<system_error>", cxx11}, -#line 528 "std-name-hint.gperf" +#line 526 "std-name-hint.gperf" {"enable_if_t", "<type_traits>", cxx14}, #line 390 "std-name-hint.gperf" {"ostream", "<ostream>", cxx98}, @@ -508,27 +508,27 @@ std_name_hint_lookup::find (const char *str, size_t len) {"numbers::log10e_v", "<numbers>", cxx20}, #line 364 "std-name-hint.gperf" {"nothrow_t", "<new>", cxx98}, -#line 512 "std-name-hint.gperf" +#line 510 "std-name-hint.gperf" {"ignore", "<tuple>", cxx11}, #line 360 "std-name-hint.gperf" {"hardware_constructive_interference_size", "<new>", cxx17}, #line 396 "std-name-hint.gperf" {"priority_queue", "<queue>", cxx98}, -#line 424 "std-name-hint.gperf" +#line 423 "std-name-hint.gperf" {"ospanstream", "<spanstream>", cxx23}, #line 316 "std-name-hint.gperf" {"enable_shared_from_this", "<memory>", cxx11}, #line 265 "std-name-hint.gperf" {"cout", "<iostream>", cxx98}, -#line 552 "std-name-hint.gperf" +#line 550 "std-name-hint.gperf" {"cmp_greater", "<utility>", cxx20}, -#line 490 "std-name-hint.gperf" +#line 488 "std-name-hint.gperf" {"basic_string_view", "<string_view>", cxx17}, #line 249 "std-name-hint.gperf" {"noskipws", "<ios>", cxx98}, #line 177 "std-name-hint.gperf" {"format_to", "<format>", cxx20}, -#line 502 "std-name-hint.gperf" +#line 500 "std-name-hint.gperf" {"make_error_code", "<system_error>", cxx11}, #line 174 "std-name-hint.gperf" {"format_error", "<format>", cxx20}, @@ -542,7 +542,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"hexfloat", "<ios>", cxx11}, #line 326 "std-name-hint.gperf" {"shared_ptr", "<memory>", cxx11}, -#line 569 "std-name-hint.gperf" +#line 567 "std-name-hint.gperf" {"integer_sequence", "<utility>", cxx14}, #line 271 "std-name-hint.gperf" {"istream", "<istream>", cxx98}, @@ -552,19 +552,17 @@ std_name_hint_lookup::find (const char *str, size_t len) {"unitbuf", "<ios>", cxx98}, #line 294 "std-name-hint.gperf" {"list", "<list>", cxx98}, -#line 554 "std-name-hint.gperf" +#line 552 "std-name-hint.gperf" {"cmp_less", "<utility>", cxx20}, #line 422 "std-name-hint.gperf" {"ispanstream", "<spanstream>", cxx23}, -#line 423 "std-name-hint.gperf" - {"ispanstream", "<spanstream>", cxx23}, -#line 470 "std-name-hint.gperf" +#line 468 "std-name-hint.gperf" {"wstreambuf", "<streambuf>", cxx98}, -#line 432 "std-name-hint.gperf" +#line 431 "std-name-hint.gperf" {"basic_ostringstream", "<sstream>", cxx98}, -#line 503 "std-name-hint.gperf" +#line 501 "std-name-hint.gperf" {"make_error_condition", "<system_error>", cxx11}, -#line 570 "std-name-hint.gperf" +#line 568 "std-name-hint.gperf" {"make_index_sequence", "<utility>", cxx14}, #line 405 "std-name-hint.gperf" {"counting_semaphore", "<semaphore>", cxx20}, @@ -578,17 +576,17 @@ std_name_hint_lookup::find (const char *str, size_t len) {"const_pointer_cast", "<memory>", cxx11}, #line 45 "std-name-hint.gperf" {"make_any", "<any>", cxx17}, -#line 465 "std-name-hint.gperf" +#line 463 "std-name-hint.gperf" {"stop_source", "<stop_token>", cxx20}, -#line 548 "std-name-hint.gperf" +#line 546 "std-name-hint.gperf" {"unordered_set", "<unordered_set>", cxx11}, -#line 583 "std-name-hint.gperf" +#line 581 "std-name-hint.gperf" {"holds_alternative", "<variant>", cxx17}, -#line 514 "std-name-hint.gperf" +#line 512 "std-name-hint.gperf" {"make_tuple", "<tuple>", cxx11}, #line 47 "std-name-hint.gperf" {"array", "<array>", cxx11}, -#line 517 "std-name-hint.gperf" +#line 515 "std-name-hint.gperf" {"tuple_cat", "<tuple>", cxx11}, #line 323 "std-name-hint.gperf" {"owner_less", "<memory>", cxx11}, @@ -598,15 +596,15 @@ std_name_hint_lookup::find (const char *str, size_t len) {"exception_ptr", "<exception>", cxx11}, #line 207 "std-name-hint.gperf" {"hash", "<functional>", cxx11}, -#line 521 "std-name-hint.gperf" +#line 519 "std-name-hint.gperf" {"tuple_size_v", "<tuple>", cxx17}, -#line 431 "std-name-hint.gperf" +#line 430 "std-name-hint.gperf" {"basic_istringstream", "<sstream>", cxx98}, #line 153 "std-name-hint.gperf" {"uintptr_t", "<cstdint>", cxx11}, -#line 476 "std-name-hint.gperf" +#line 474 "std-name-hint.gperf" {"stoi", "<string>", cxx11}, -#line 466 "std-name-hint.gperf" +#line 464 "std-name-hint.gperf" {"stop_token", "<stop_token>", cxx20}, #line 151 "std-name-hint.gperf" {"uint_least8_t", "<cstdint>", cxx11}, @@ -622,7 +620,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"shared_mutex", "<shared_mutex>", cxx17}, #line 375 "std-name-hint.gperf" {"numbers::phi_v", "<numbers>", cxx20}, -#line 499 "std-name-hint.gperf" +#line 497 "std-name-hint.gperf" {"is_error_code_enum_v", "<system_error>", cxx17}, #line 155 "std-name-hint.gperf" {"deque", "<deque>", cxx98}, @@ -630,7 +628,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"shared_timed_mutex", "<shared_mutex>", cxx14}, #line 290 "std-name-hint.gperf" {"ostreambuf_iterator", "<iterator>", cxx98}, -#line 501 "std-name-hint.gperf" +#line 499 "std-name-hint.gperf" {"is_error_condition_enum_v", "<system_error>", cxx17}, #line 148 "std-name-hint.gperf" {"uint_least16_t", "<cstdint>", cxx11}, @@ -640,7 +638,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"numbers::e_v", "<numbers>", cxx20}, #line 209 "std-name-hint.gperf" {"invoke_r", "<functional>", cxx23}, -#line 441 "std-name-hint.gperf" +#line 439 "std-name-hint.gperf" {"wostringstream", "<sstream>", cxx98}, #line 122 "std-name-hint.gperf" {"copy_constructible", "<concepts>", cxx20}, @@ -650,13 +648,13 @@ std_name_hint_lookup::find (const char *str, size_t len) {"convertible_to", "<concepts>", cxx20}, #line 234 "std-name-hint.gperf" {"setprecision", "<iomanip>", cxx98}, -#line 498 "std-name-hint.gperf" +#line 496 "std-name-hint.gperf" {"is_error_code_enum", "<system_error>", cxx11}, -#line 453 "std-name-hint.gperf" +#line 451 "std-name-hint.gperf" {"overflow_error", "<stdexcept>", cxx98}, #line 414 "std-name-hint.gperf" {"source_location", "<source_location>", cxx20}, -#line 500 "std-name-hint.gperf" +#line 498 "std-name-hint.gperf" {"is_error_condition_enum", "<system_error>", cxx11}, #line 400 "std-name-hint.gperf" {"ranges::enable_view", "<ranges>", cxx20}, @@ -672,7 +670,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"chrono::parse", "<chrono>", cxx20}, #line 285 "std-name-hint.gperf" {"istreambuf_iterator", "<iterator>", cxx98}, -#line 473 "std-name-hint.gperf" +#line 471 "std-name-hint.gperf" {"char_traits", "<string>", cxx98}, #line 263 "std-name-hint.gperf" {"cin", "<iostream>", cxx98}, @@ -692,37 +690,37 @@ std_name_hint_lookup::find (const char *str, size_t len) {"chrono::get_tzdb", "<chrono>", cxx20}, #line 302 "std-name-hint.gperf" {"allocate_shared_for_overwrite", "<memory>", cxx20}, -#line 547 "std-name-hint.gperf" +#line 545 "std-name-hint.gperf" {"unordered_multiset", "<unordered_set>", cxx11}, #line 194 "std-name-hint.gperf" {"forward_list", "<forward_list>", cxx11}, -#line 496 "std-name-hint.gperf" +#line 494 "std-name-hint.gperf" {"error_condition", "<system_error>", cxx11}, -#line 542 "std-name-hint.gperf" +#line 540 "std-name-hint.gperf" {"bad_typeid", "<typeinfo>", cxx98}, #line 60 "std-name-hint.gperf" {"chrono::duration", "<chrono>", cxx11}, -#line 510 "std-name-hint.gperf" +#line 508 "std-name-hint.gperf" {"apply", "<tuple>", cxx17}, #line 95 "std-name-hint.gperf" {"chrono::zoned_time", "<chrono>", cxx20}, -#line 477 "std-name-hint.gperf" +#line 475 "std-name-hint.gperf" {"stol", "<string>", cxx11}, -#line 479 "std-name-hint.gperf" +#line 477 "std-name-hint.gperf" {"stoll", "<string>", cxx11}, -#line 480 "std-name-hint.gperf" +#line 478 "std-name-hint.gperf" {"stoul", "<string>", cxx11}, -#line 481 "std-name-hint.gperf" +#line 479 "std-name-hint.gperf" {"stoull", "<string>", cxx11}, #line 220 "std-name-hint.gperf" {"packaged_task", "<future>", cxx11}, -#line 544 "std-name-hint.gperf" +#line 542 "std-name-hint.gperf" {"unordered_map", "<unordered_map>", cxx11}, #line 77 "std-name-hint.gperf" {"chrono::months", "<chrono>", cxx20}, #line 76 "std-name-hint.gperf" {"chrono::minutes", "<chrono>", cxx11}, -#line 545 "std-name-hint.gperf" +#line 543 "std-name-hint.gperf" {"unordered_multimap", "<unordered_map>", cxx11}, #line 78 "std-name-hint.gperf" {"chrono::nanoseconds", "<chrono>", cxx11}, @@ -732,21 +730,21 @@ std_name_hint_lookup::find (const char *str, size_t len) {"binary_semaphore", "<semaphore>", cxx20}, #line 281 "std-name-hint.gperf" {"end", "<iterator>", cxx11}, -#line 429 "std-name-hint.gperf" +#line 428 "std-name-hint.gperf" {"wspanbuf", "<spanstream>", cxx23}, #line 252 "std-name-hint.gperf" {"oct", "<ios>", cxx98}, #line 245 "std-name-hint.gperf" {"noboolalpha", "<ios>", cxx98}, -#line 450 "std-name-hint.gperf" +#line 448 "std-name-hint.gperf" {"length_error", "<stdexcept>", cxx98}, -#line 560 "std-name-hint.gperf" +#line 558 "std-name-hint.gperf" {"in_place", "<utility>", cxx17}, -#line 563 "std-name-hint.gperf" +#line 561 "std-name-hint.gperf" {"in_place_t", "<utility>", cxx17}, #line 384 "std-name-hint.gperf" {"emit_on_flush", "<ostream>", cxx20}, -#line 440 "std-name-hint.gperf" +#line 438 "std-name-hint.gperf" {"wistringstream", "<sstream>", cxx98}, #line 327 "std-name-hint.gperf" {"static_pointer_cast", "<memory>", cxx11}, @@ -762,7 +760,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"wostream", "<ostream>", cxx98}, #line 348 "std-name-hint.gperf" {"lock", "<mutex>", cxx11}, -#line 504 "std-name-hint.gperf" +#line 502 "std-name-hint.gperf" {"system_category", "<system_error>", cxx11}, #line 128 "std-name-hint.gperf" {"copyable", "<concepts>", cxx20}, @@ -770,21 +768,21 @@ std_name_hint_lookup::find (const char *str, size_t len) {"condition_variable", "<condition_variable>", cxx11}, #line 240 "std-name-hint.gperf" {"fixed", "<ios>", cxx98}, -#line 553 "std-name-hint.gperf" +#line 551 "std-name-hint.gperf" {"cmp_greater_equal", "<utility>", cxx20}, -#line 508 "std-name-hint.gperf" +#line 506 "std-name-hint.gperf" {"thread", "<thread>", cxx11}, -#line 439 "std-name-hint.gperf" +#line 437 "std-name-hint.gperf" {"stringstream", "<sstream>", cxx98}, #line 58 "std-name-hint.gperf" {"chrono::clock_cast", "<chrono>", cxx20}, -#line 579 "std-name-hint.gperf" +#line 577 "std-name-hint.gperf" {"unreachable", "<utility>", cxx23}, -#line 428 "std-name-hint.gperf" +#line 427 "std-name-hint.gperf" {"wospanstream", "<spanstream>", cxx23}, #line 330 "std-name-hint.gperf" {"unique_ptr", "<memory>", cxx11}, -#line 562 "std-name-hint.gperf" +#line 560 "std-name-hint.gperf" {"in_place_index_t", "<utility>", cxx17}, #line 363 "std-name-hint.gperf" {"nothrow", "<new>", cxx98}, @@ -800,7 +798,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"uint_fast32_t", "<cstdint>", cxx11}, #line 87 "std-name-hint.gperf" {"chrono::time_point", "<chrono>", cxx11}, -#line 444 "std-name-hint.gperf" +#line 442 "std-name-hint.gperf" {"stack", "<stack>", cxx98}, #line 215 "std-name-hint.gperf" {"unwrap_reference", "<functional>", cxx20}, @@ -814,7 +812,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"optional", "<optional>", cxx17}, #line 112 "std-name-hint.gperf" {"signed_integral", "<concepts>", cxx20}, -#line 456 "std-name-hint.gperf" +#line 454 "std-name-hint.gperf" {"underflow_error", "<stdexcept>", cxx98}, #line 239 "std-name-hint.gperf" {"defaultfloat", "<ios>", cxx11}, @@ -832,19 +830,19 @@ std_name_hint_lookup::find (const char *str, size_t len) {"uninitialized_construct_using_allocator", "<memory>", cxx20}, #line 81 "std-name-hint.gperf" {"chrono::remote_version", "<chrono>", cxx20}, -#line 458 "std-name-hint.gperf" +#line 456 "std-name-hint.gperf" {"bfloat16_t", "<stdfloat>", cxx23}, -#line 576 "std-name-hint.gperf" +#line 574 "std-name-hint.gperf" {"piecewise_construct", "<utility>", cxx11}, -#line 577 "std-name-hint.gperf" +#line 575 "std-name-hint.gperf" {"piecewise_construct_t", "<utility>", cxx11}, #line 278 "std-name-hint.gperf" {"const_iterator", "<iterator>", cxx23}, -#line 484 "std-name-hint.gperf" +#line 482 "std-name-hint.gperf" {"to_wstring", "<string>", cxx17}, #line 356 "std-name-hint.gperf" {"try_lock", "<mutex>", cxx11}, -#line 561 "std-name-hint.gperf" +#line 559 "std-name-hint.gperf" {"in_place_index", "<utility>", cxx17}, #line 51 "std-name-hint.gperf" {"atomic_ref", "<atomic>", cxx20}, @@ -862,7 +860,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"uncaught_exceptions", "<exception>", cxx17}, #line 331 "std-name-hint.gperf" {"uses_allocator", "<memory>", cxx11}, -#line 472 "std-name-hint.gperf" +#line 470 "std-name-hint.gperf" {"basic_string", "<string>", cxx98}, #line 311 "std-name-hint.gperf" {"default_delete", "<memory>", cxx11}, @@ -870,17 +868,17 @@ std_name_hint_lookup::find (const char *str, size_t len) {"expected", "<expected>", cxx23}, #line 313 "std-name-hint.gperf" {"destroy_at", "<memory>", cxx20}, -#line 536 "std-name-hint.gperf" +#line 534 "std-name-hint.gperf" {"type_identity_t", "<type_traits>", cxx20}, #line 63 "std-name-hint.gperf" {"chrono::from_stream", "<chrono>", cxx20}, -#line 427 "std-name-hint.gperf" +#line 426 "std-name-hint.gperf" {"wispanstream", "<spanstream>", cxx23}, #line 52 "std-name-hint.gperf" {"atomic_signed_lock_free", "<atomic>", cxx11}, #line 266 "std-name-hint.gperf" {"wcerr", "<iostream>", cxx98}, -#line 511 "std-name-hint.gperf" +#line 509 "std-name-hint.gperf" {"forward_as_tuple", "<tuple>", cxx11}, #line 187 "std-name-hint.gperf" {"vformat", "<format>", cxx20}, @@ -892,25 +890,25 @@ std_name_hint_lookup::find (const char *str, size_t len) {"destroy_n", "<memory>", cxx20}, #line 226 "std-name-hint.gperf" {"get_time", "<iomanip>", cxx11}, -#line 555 "std-name-hint.gperf" +#line 553 "std-name-hint.gperf" {"cmp_less_equal", "<utility>", cxx20}, #line 80 "std-name-hint.gperf" {"chrono::reload_tzdb", "<chrono>", cxx20}, -#line 523 "std-name-hint.gperf" +#line 521 "std-name-hint.gperf" {"conjunction", "<type_traits>", cxx17}, #line 75 "std-name-hint.gperf" {"chrono::milliseconds", "<chrono>", cxx11}, #line 59 "std-name-hint.gperf" {"chrono::days", "<chrono>", cxx20}, -#line 474 "std-name-hint.gperf" +#line 472 "std-name-hint.gperf" {"stod", "<string>", cxx11}, -#line 478 "std-name-hint.gperf" +#line 476 "std-name-hint.gperf" {"stold", "<string>", cxx11}, #line 267 "std-name-hint.gperf" {"wcin", "<iostream>", cxx98}, -#line 529 "std-name-hint.gperf" +#line 527 "std-name-hint.gperf" {"invoke_result", "<type_traits>", cxx17}, -#line 530 "std-name-hint.gperf" +#line 528 "std-name-hint.gperf" {"invoke_result_t", "<type_traits>", cxx17}, #line 50 "std-name-hint.gperf" {"atomic", "<atomic>", cxx11}, @@ -930,17 +928,17 @@ std_name_hint_lookup::find (const char *str, size_t len) {"chrono::hours", "<chrono>", cxx11}, #line 109 "std-name-hint.gperf" {"common_reference_with", "<concepts>", cxx20}, -#line 483 "std-name-hint.gperf" +#line 481 "std-name-hint.gperf" {"to_string", "<string>", cxx17}, -#line 524 "std-name-hint.gperf" +#line 522 "std-name-hint.gperf" {"conjunction_v", "<type_traits>", cxx17}, -#line 578 "std-name-hint.gperf" +#line 576 "std-name-hint.gperf" {"to_underlying", "<utility>", cxx23}, #line 402 "std-name-hint.gperf" {"scoped_allocator_adaptor", "<scoped_allocator>", cxx11}, #line 310 "std-name-hint.gperf" {"construct_at", "<memory>", cxx20}, -#line 564 "std-name-hint.gperf" +#line 562 "std-name-hint.gperf" {"in_place_type", "<utility>", cxx17}, #line 320 "std-name-hint.gperf" {"make_shared_for_overwrite", "<memory>", cxx20}, @@ -952,15 +950,15 @@ std_name_hint_lookup::find (const char *str, size_t len) {"chrono::local_t", "<chrono>", cxx20}, #line 170 "std-name-hint.gperf" {"basic_format_string", "<format>", cxx20}, -#line 565 "std-name-hint.gperf" +#line 563 "std-name-hint.gperf" {"in_place_type_t", "<utility>", cxx17}, #line 279 "std-name-hint.gperf" {"counted_iterator", "<iterator>", cxx20}, -#line 448 "std-name-hint.gperf" +#line 446 "std-name-hint.gperf" {"domain_error", "<stdexcept>", cxx98}, #line 84 "std-name-hint.gperf" {"chrono::steady_clock", "<chrono>", cxx11}, -#line 580 "std-name-hint.gperf" +#line 578 "std-name-hint.gperf" {"observable_checkpoint", "<utility>", cxx26}, #line 188 "std-name-hint.gperf" {"vformat_to", "<format>", cxx20}, @@ -982,51 +980,49 @@ std_name_hint_lookup::find (const char *str, size_t len) {"unwrap_ref_decay_t", "<functional>", cxx20}, #line 136 "std-name-hint.gperf" {"strict_weak_order", "<concepts>", cxx20}, -#line 437 "std-name-hint.gperf" +#line 435 "std-name-hint.gperf" {"ostringstream", "<sstream>", cxx98}, #line 317 "std-name-hint.gperf" {"get_deleter", "<memory>", cxx11}, #line 367 "std-name-hint.gperf" {"numbers::egamma_v", "<numbers>", cxx20}, -#line 566 "std-name-hint.gperf" +#line 564 "std-name-hint.gperf" {"in_range", "<utility>", cxx20}, -#line 558 "std-name-hint.gperf" +#line 556 "std-name-hint.gperf" {"exchange", "<utility>", cxx14}, -#line 551 "std-name-hint.gperf" +#line 549 "std-name-hint.gperf" {"cmp_equal", "<utility>", cxx20}, -#line 556 "std-name-hint.gperf" +#line 554 "std-name-hint.gperf" {"cmp_not_equal", "<utility>", cxx20}, -#line 435 "std-name-hint.gperf" - {"istringstream", "<sstream>", cxx98}, -#line 436 "std-name-hint.gperf" +#line 434 "std-name-hint.gperf" {"istringstream", "<sstream>", cxx98}, -#line 442 "std-name-hint.gperf" +#line 440 "std-name-hint.gperf" {"wstringbuf", "<sstream>", cxx98}, #line 225 "std-name-hint.gperf" {"get_money", "<iomanip>", cxx11}, #line 191 "std-name-hint.gperf" {"wformat_parse_context", "<format>", cxx20}, -#line 482 "std-name-hint.gperf" +#line 480 "std-name-hint.gperf" {"string", "<string>", cxx98}, #line 280 "std-name-hint.gperf" {"distance", "<iterator>", cxx98}, -#line 557 "std-name-hint.gperf" +#line 555 "std-name-hint.gperf" {"declval", "<utility>", cxx11}, #line 254 "std-name-hint.gperf" {"scientific", "<ios>", cxx98}, #line 98 "std-name-hint.gperf" {"strong_equality", "<compare>", cxx20}, -#line 487 "std-name-hint.gperf" +#line 485 "std-name-hint.gperf" {"u8string", "<string>", cxx20}, #line 190 "std-name-hint.gperf" {"wformat_context", "<format>", cxx20}, #line 312 "std-name-hint.gperf" {"destroy", "<memory>", cxx20}, -#line 559 "std-name-hint.gperf" +#line 557 "std-name-hint.gperf" {"forward", "<utility>", cxx11}, -#line 535 "std-name-hint.gperf" +#line 533 "std-name-hint.gperf" {"type_identity", "<type_traits>", cxx20}, -#line 464 "std-name-hint.gperf" +#line 462 "std-name-hint.gperf" {"stop_callback", "<stop_token>", cxx20}, #line 86 "std-name-hint.gperf" {"chrono::tai_clock", "<chrono>", cxx20}, @@ -1038,7 +1034,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"chrono::tzdb", "<chrono>", cxx20}, #line 126 "std-name-hint.gperf" {"totally_ordered_with", "<concepts>", cxx20}, -#line 525 "std-name-hint.gperf" +#line 523 "std-name-hint.gperf" {"disjunction", "<type_traits>", cxx17}, #line 110 "std-name-hint.gperf" {"common_with", "<concepts>", cxx20}, @@ -1058,23 +1054,23 @@ std_name_hint_lookup::find (const char *str, size_t len) {"weak_ordering", "<compare>", cxx20}, #line 201 "std-name-hint.gperf" {"ifstream", "<fstream>", cxx98}, -#line 452 "std-name-hint.gperf" +#line 450 "std-name-hint.gperf" {"out_of_range", "<stdexcept>", cxx98}, #line 264 "std-name-hint.gperf" {"clog", "<iostream>", cxx98}, #line 62 "std-name-hint.gperf" {"chrono::file_clock", "<chrono>", cxx20}, -#line 526 "std-name-hint.gperf" +#line 524 "std-name-hint.gperf" {"disjunction_v", "<type_traits>", cxx17}, -#line 485 "std-name-hint.gperf" +#line 483 "std-name-hint.gperf" {"u16string", "<string>", cxx11}, #line 351 "std-name-hint.gperf" {"once_flag", "<mutex>", cxx11}, -#line 491 "std-name-hint.gperf" +#line 489 "std-name-hint.gperf" {"string_view", "<string_view>", cxx17}, #line 304 "std-name-hint.gperf" {"allocator_arg", "<memory>", cxx11}, -#line 486 "std-name-hint.gperf" +#line 484 "std-name-hint.gperf" {"u32string", "<string>", cxx11}, #line 213 "std-name-hint.gperf" {"unwrap_ref_decay", "<functional>", cxx20}, @@ -1086,11 +1082,11 @@ std_name_hint_lookup::find (const char *str, size_t len) {"derived_from", "<concepts>", cxx20}, #line 99 "std-name-hint.gperf" {"strong_ordering", "<compare>", cxx20}, -#line 497 "std-name-hint.gperf" +#line 495 "std-name-hint.gperf" {"generic_category", "<system_error>", cxx11}, #line 125 "std-name-hint.gperf" {"totally_ordered", "<concepts>", cxx20}, -#line 494 "std-name-hint.gperf" +#line 492 "std-name-hint.gperf" {"error_category", "<system_error>", cxx11}, #line 82 "std-name-hint.gperf" {"chrono::round", "<chrono>", cxx17}, @@ -1098,15 +1094,15 @@ std_name_hint_lookup::find (const char *str, size_t len) {"unique_lock", "<mutex>", cxx11}, #line 319 "std-name-hint.gperf" {"make_shared", "<memory>", cxx11}, -#line 507 "std-name-hint.gperf" +#line 505 "std-name-hint.gperf" {"this_thread", "<thread>", cxx11}, -#line 449 "std-name-hint.gperf" +#line 447 "std-name-hint.gperf" {"invalid_argument", "<stdexcept>", cxx98}, #line 354 "std-name-hint.gperf" {"scoped_lock", "<mutex>", cxx17}, #line 268 "std-name-hint.gperf" {"wclog", "<iostream>", cxx98}, -#line 506 "std-name-hint.gperf" +#line 504 "std-name-hint.gperf" {"jthread", "<thread>", cxx20}, #line 97 "std-name-hint.gperf" {"partial_ordering", "<compare>", cxx20}, @@ -1114,7 +1110,7 @@ std_name_hint_lookup::find (const char *str, size_t len) {"chrono::high_resolution_clock", "<chrono>", cxx11}, #line 307 "std-name-hint.gperf" {"assume_aligned", "<memory>", cxx20}, -#line 488 "std-name-hint.gperf" +#line 486 "std-name-hint.gperf" {"wstring", "<string>", cxx98}, #line 192 "std-name-hint.gperf" {"wformat_string", "<format>", cxx20}, @@ -1144,7 +1140,7 @@ std_name_hint_lookup::find (const char *str, size_t len) -1, -1, 24, -1, -1, -1, -1, -1, -1, -1, 25, 26, 27, -1, -1, -1, 28, 29, -1, -1, 30, - -630, -457, -2, 33, -1, 34, -1, + -628, -455, -2, 33, -1, 34, -1, 35, -1, 36, -1, -1, -1, -1, 37, -1, 38, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, @@ -1186,8 +1182,8 @@ std_name_hint_lookup::find (const char *str, size_t len) -1, 152, 153, -1, -1, -1, -1, -1, -1, 154, -1, 155, 156, -1, -1, -1, 157, -1, -1, 158, -1, - 159, 160, -1, -1, -1, -934, -1, - 163, 164, -1, 165, -327, -2, -1, + 159, 160, -1, -1, -1, -932, -1, + 163, 164, -1, 165, -325, -2, -1, -1, 166, -1, -1, -1, -1, 167, 168, -1, 169, -1, -1, -1, 170, 171, 172, 173, -1, -1, -1, 174, @@ -1197,157 +1193,157 @@ std_name_hint_lookup::find (const char *str, size_t len) -1, 185, -1, 186, 187, -1, 188, 189, 190, 191, 192, -1, 193, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 194, -1, -1006, -293, + -1, -1, -1, 194, -1, -1004, -291, -2, -1, -1, -1, 197, -1, -1, 198, 199, 200, 201, -1, -1, -1, 202, 203, -1, -1, -1, -1, 204, - -1, -1, -1031, -283, -2, -1, 207, - -1, -1, -1, 208, 209, -1, -1, - -1, 210, -1, -1, -1, 211, -1, - 212, -1, -1, 213, -1, -1, 214, - -1, 215, -1, 216, 217, -1, 218, - -1, -1, 219, -1, -1, -1, 220, - -1, 221, -1, 222, 223, 224, -1, - -1, -1, 225, -1, 226, -1, -1, - -1, -1, 227, -1, 228, -1, -1, - -1, 229, 230, -1, -1, -1, -1, - -1, 231, -1, 232, 233, -1, -1, - -1, -1, 234, -1, 235, 236, 237, - 238, -1, 239, -1, 240, 241, 242, - 243, -1, -1, 244, -1, 245, -1, - 246, 247, 248, -1, -1, -1, 249, - -1, -1, -1, -1, 250, 251, -1, - -1, -1, -1, -1, -1, -1, 252, - 253, 254, 255, -1, -1, 256, 257, - 258, -1, 259, 260, -1, -1, -1, - 261, -1, -1, -1, -1, -1, 262, - 263, -1, 264, 265, -1, -1, -1, - -1, -1, -1, -1, -1, 266, -1, - 267, -1, 268, -1, -1, -1, 269, - -1, 270, -1, 271, -1, -1, 272, - -1, 273, -1, -1, -1, -1, 274, - 275, 276, -1, 277, -1, -1, -1, - -1, -1, -1, -1, -1, 278, -1, - -1, -1, -1, -1, 279, 280, 281, - -1226, 284, -206, -2, -1, -1, -1, - -1, 285, -1, -1, -1, -1, 286, - 287, 288, -1, -1, 289, 290, 291, - -1, -1, -1, -1, 292, -1, -1, - -1, -1, 293, -1, -1, 294, -1, - 295, 296, 297, 298, -1, -1, -1, - -1, -1, -1, 299, -1, -1, -1, - -1, -1, -1, 300, 301, 302, -1, - -1, -1, -1, 303, 304, -1, -1, - 305, 306, -1, -1, -1, 307, -1, - -1, -1, -1, -1, 308, -1, -1, - 309, 310, -1, -1, -1, -1, 311, - -1, -1, 312, 313, 314, -1, -1, - -1, 315, 316, -1, 317, -1, 318, - -1, -1, 319, 320, 321, 322, -1, - 323, -1, 324, 325, -1, -1, -1, - 326, 327, -1, 328, 329, -1, 330, - -1, -1, 331, -1, 332, -1, -1, - -1, -1, 333, 334, 335, -1, -1, - -1, 336, -1, -1, 337, 338, -1, - -1, -1, -1, -1368, -149, -2, -1, - 341, -1, -1, -1, -1, -1, -1, - 342, -1, -1, 343, -1, -1, -1, - -1, 344, 345, -1, 346, -1, -1, - -1, 347, -1, -1, 348, 349, -1, - -1, -1, -1, -1, 350, 351, -1, - 352, 353, -1, -1, -1, -1, 354, - -1, 355, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 356, -1, 357, -1, - -1, -1, -1, -1, 358, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 359, -1, - 360, 361, -1, 362, -1, -1, -1, - -1, -1, -1, -1, 363, -1, 364, - -1, 365, -1, 366, -1, -1, -1, - 367, 368, 369, -1, -1, 370, -1, - -1, -1, -1, 371, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, - 372, -1, 373, -1, -1, -1, 374, - -1, -1, -1, -1, 375, -1, 376, - -1, -1, -1, 377, -1, -1, -1, - 378, -1, 379, 380, -1, -1, -1, - 381, -1, 382, -1, 383, 384, -1, - -1, 385, -1, -1, -1, -1, -1, - 386, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 387, 388, - -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 389, 390, -1, + -1, -1, 205, -1, -1, -1, 206, + -1, -1, -1, 207, 208, -1, -1, + -1, 209, -1, -1, -1, 210, -1, + 211, -1, -1, 212, -1, -1, 213, + -1, 214, -1, 215, 216, -1, 217, + -1, -1, 218, -1, -1, -1, 219, + -1, 220, -1, 221, 222, 223, -1, + -1, -1, 224, -1, 225, -1, -1, + -1, -1, 226, -1, 227, -1, -1, + -1, 228, 229, -1, -1, -1, -1, + -1, 230, -1, 231, 232, -1, -1, + -1, -1, 233, -1, 234, 235, 236, + 237, -1, 238, -1, 239, 240, 241, + 242, -1, -1, 243, -1, 244, -1, + 245, 246, 247, -1, -1, -1, 248, + -1, -1, -1, -1, 249, 250, -1, + -1, -1, -1, -1, -1, -1, 251, + 252, 253, 254, -1, -1, 255, 256, + 257, -1, 258, 259, -1, -1, -1, + 260, -1, -1, -1, -1, -1, 261, + 262, -1, 263, 264, -1, -1, -1, + -1, -1, -1, -1, -1, 265, -1, + 266, -1, 267, -1, -1, -1, 268, + -1, 269, -1, 270, -1, -1, 271, + -1, 272, -1, -1, -1, -1, 273, + 274, 275, -1, 276, -1, -1, -1, + -1, -1, -1, -1, -1, 277, -1, + -1, -1, -1, -1, 278, 279, 280, + -1224, 283, -205, -2, -1, -1, -1, + -1, 284, -1, -1, -1, -1, 285, + 286, 287, -1, -1, 288, 289, 290, + -1, -1, -1, -1, 291, -1, -1, + -1, -1, 292, -1, -1, 293, -1, + 294, 295, 296, 297, -1, -1, -1, + -1, -1, -1, 298, -1, -1, -1, + -1, -1, -1, 299, 300, 301, -1, + -1, -1, -1, 302, 303, -1, -1, + 304, 305, -1, -1, -1, 306, -1, + -1, -1, -1, -1, 307, -1, -1, + 308, 309, -1, -1, -1, -1, 310, + -1, -1, 311, 312, 313, -1, -1, + -1, 314, 315, -1, 316, -1, 317, + -1, -1, 318, 319, 320, 321, -1, + 322, -1, 323, 324, -1, -1, -1, + 325, 326, -1, 327, 328, -1, 329, + -1, -1, 330, -1, 331, -1, -1, + -1, -1, 332, 333, 334, -1, -1, + -1, 335, -1, -1, 336, 337, -1, + -1, -1, -1, -1366, -148, -2, -1, + 340, -1, -1, -1, -1, -1, -1, + 341, -1, -1, 342, -1, -1, -1, + -1, 343, 344, -1, 345, -1, -1, + -1, 346, -1, -1, 347, 348, -1, + -1, -1, -1, -1, 349, 350, -1, + 351, 352, -1, -1, -1, -1, 353, + -1, 354, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 355, -1, 356, -1, + -1, -1, -1, -1, 357, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 358, -1, + 359, 360, -1, 361, -1, -1, -1, + -1, -1, -1, -1, 362, -1, 363, + -1, 364, -1, 365, -1, -1, -1, + 366, 367, 368, -1, -1, 369, -1, + -1, -1, -1, 370, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, + 371, -1, 372, -1, -1, -1, 373, + -1, -1, -1, -1, 374, -1, 375, + -1, -1, -1, 376, -1, -1, -1, + 377, -1, 378, 379, -1, -1, -1, + 380, -1, 381, -1, 382, 383, -1, + -1, 384, -1, -1, -1, -1, -1, + 385, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 386, 387, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 388, 389, -1, + -1, -1, -1, -1, -1, 390, -1, -1, -1, -1, -1, -1, 391, -1, - -1, -1, -1, -1, -1, 392, -1, - -1, -1, -1, -1, 393, -1, 394, - -1, -1, -1, -1, -1, -1, 395, - 396, 397, -1, -1, 398, 399, -1, - 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, -1, -1, 410, 411, - -1, -1, -1, 412, -1, -1, -1, - -1, 413, -1, 414, -1, -1, 415, + -1, -1, -1, -1, 392, -1, 393, + -1, -1, -1, -1, -1, -1, 394, + 395, 396, -1, -1, 397, 398, -1, + 399, 400, 401, 402, 403, 404, 405, + 406, 407, 408, -1, -1, 409, 410, + -1, -1, -1, 411, -1, -1, -1, + -1, 412, -1, 413, -1, -1, 414, -1, -1, -1, -1, -1, -1, -1, - -1, 416, -1, -1, -1, 417, -1, + -1, 415, -1, -1, -1, 416, -1, -1, -1, -1, -1, -1, -1, -1, - 418, -1, -1, 419, -1, -1, 420, + 417, -1, -1, 418, -1, -1, 419, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 421, 422, -1, -1, + -1, -1, -1, 420, 421, -1, -1, + -1, -1, -1, -1, 422, -1, -1, -1, -1, -1, -1, 423, -1, -1, - -1, -1, -1, -1, 424, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 424, -1, -1, -1, -1, -1, -1, 425, -1, -1, - -1, -1, -1, -1, -1705, -62, -2, - -1, -1, -1, -1, 428, -1, -1, - -1, -1, -1, 429, -1, -1, -1, + -1, -1, -1, -1, 426, -1, -1, + -1, -1, -1, 427, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 430, -1, -1, + -1, -1, -1, -1, 428, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 431, -1, -1, -1, -1, -1, 432, - -1, -1, -1, -1, 433, -1, -1, - -1, -1, -1, -1, -1, 434, -1, - -1, -1, -1, 435, -1, -1, 436, - -1, -1, -1, -1, -1, -1, 437, - 438, -1, -1, 439, -1, -1, -1, - -1, -1, 440, 441, -1, -1, -1, - 442, -1, 443, -1, 444, -1, -1, - 445, -1, -1, -1, 446, -1, -1, + 429, -1, -1, -1, -1, -1, 430, + -1, -1, -1, -1, 431, -1, -1, + -1, -1, -1, -1, -1, 432, -1, + -1, -1, -1, 433, -1, -1, 434, + -1, -1, -1, -1, -1, -1, 435, + 436, -1, -1, 437, -1, -1, -1, + -1, -1, 438, 439, -1, -1, -1, + 440, -1, 441, -1, 442, -1, -1, + 443, -1, -1, -1, 444, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 447, - -1, 448, -1, -1, -1, -1, -1, - 449, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 445, + -1, 446, -1, -1, -1, -1, -1, + 447, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 450, -1, 451, -1, - -1, -1, -1, -1, 452, -1, -1, - -1, -1, -1, 453, -1, -1, -1, - -1, -1, 454, -1, -1, 455, -1, + -1, -1, -1, 448, -1, 449, -1, + -1, -1, -1, -1, 450, -1, -1, + -1, -1, -1, 451, -1, -1, -1, + -1, -1, 452, -1, -1, 453, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 456, -1, -1, -1, 457, -1, + -1, 454, -1, -1, -1, 455, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 458, -1, 459, 460, - -1, -1, -1, -1, -1, -1, 461, + -1, -1, -1, 456, -1, 457, 458, + -1, -1, -1, -1, -1, -1, 459, + -1, -1, -1, -1, 460, -1, -1, + -1, -1, 461, -1, -1, -1, -1, -1, -1, -1, -1, 462, -1, -1, - -1, -1, 463, -1, -1, -1, -1, - -1, -1, -1, -1, 464, -1, -1, - -1, -1, -1, 465, -1, -1, -1, - -1, -1, -1, 466, -1, -1, -1, + -1, -1, -1, 463, -1, -1, -1, + -1, -1, -1, 464, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 467, -1, -1, + -1, -1, -1, -1, 465, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 468, -1, -1, -1, 469, + -1, -1, 466, -1, -1, -1, 467, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 470, + -1, -1, -1, -1, -1, -1, 468, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -1356,22 +1352,22 @@ std_name_hint_lookup::find (const char *str, size_t len) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 471, -1, -1, -1, -1, -1, + -1, 469, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 472, -1, 473, -1, + -1, -1, -1, 470, -1, 471, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 474, -1, -1, -1, -1, + -1, -1, 472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 475, -1, - -1, 476, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 473, -1, + -1, 474, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 477, -1, -1, -1, -1, -1, -1, + 475, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -1382,14 +1378,14 @@ std_name_hint_lookup::find (const char *str, size_t len) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 478, -1, -1, + -1, -1, -1, -1, 476, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 479, 480, 481, -1, + -1, -1, -1, 477, 478, 479, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 482, -1, + -1, -1, -1, -1, -1, 480, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -1404,12 +1400,12 @@ std_name_hint_lookup::find (const char *str, size_t len) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 483, -1, -1, -1, -1, -1, + -1, 481, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 484, -1, -1, -1, + -1, -1, -1, 482, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -1417,12 +1413,12 @@ std_name_hint_lookup::find (const char *str, size_t len) -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 485, -1, - -1, -1, -1, -1, -1, 486, -1, + -1, -1, -1, -1, -1, 483, -1, + -1, -1, -1, -1, -1, 484, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 487 + 485 }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 882c082..30eae4b 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1131,6 +1131,14 @@ such an initializer, as shown here: char **foo = (char *[]) @{ "x", "y", "z" @}; @end smallexample +As a GNU extension, GCC allows compound literals with a variable size. +In this case, only empty initialization is allowed. + +@smallexample +int n = 4; +char (*p)[n] = &(char[n])@{ @}; +@end smallexample + Compound literals for scalar types and union types are also allowed. In the following example the variable @code{i} is initialized to the value @code{2}, the result of incrementing the unnamed object created by @@ -7311,11 +7319,16 @@ the attribute. When the field that represents the number of the elements is assigned a negative integer value, the compiler treats the value as zero. -The @code{counted_by} attribute is not allowed for a pointer to @code{void}, -a pointer to function, or a pointer to a structure or union that includes -a flexible array member. However, it is allowed for a pointer to -non-void incomplete structure or union types, as long as the type could -be completed before the first reference to the pointer. +The @code{counted_by} attribute is not allowed for a pointer to function, +or a pointer to a structure or union that includes a flexible array member. +However, it is allowed for a pointer to non-void incomplete structure +or union types, as long as the type could be completed before the first +reference to the pointer. + +The attribute is allowed for a pointer to @code{void}. However, +warnings will be issued for such cases when @option{-Wpointer-arith} is +specified. When this attribute is applied on a pointer to @code{void}, +the size of each element of this pointer array is treated as 1. An explicit @code{counted_by} annotation defines a relationship between two objects, @code{p->array} and @code{p->count}, and there are the diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index a817c69..ac39cf5 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -13842,14 +13842,14 @@ gen_btf_tag_dies (tree attr, dw_die_ref die) if (die) { - /* Add AT_GNU_annotation referring to the annotation DIE. - It may have already been added, some global declarations are processed - twice, but if so it must be the same or we have a bug. */ - dw_die_ref existing = get_AT_ref (die, DW_AT_GNU_annotation); - if (existing) - gcc_checking_assert (existing == tag_die); - else - add_AT_die_ref (die, DW_AT_GNU_annotation, tag_die); + /* Add (or replace) AT_GNU_annotation referring to the annotation DIE. + Replacement may happen for example when 'die' is a global variable + which has been re-declared multiple times. In any case, the set of + input attributes is the one that ought to be reflected. For global + variable re-declarations which add additional decl tags, they will + have been accumulated in the variable's DECL_ATTRIBUTES for us. */ + remove_AT (die, DW_AT_GNU_annotation); + add_AT_die_ref (die, DW_AT_GNU_annotation, tag_die); } return tag_die; diff --git a/gcc/fold-const-call.cc b/gcc/fold-const-call.cc index 439bf80..89c1c28 100644 --- a/gcc/fold-const-call.cc +++ b/gcc/fold-const-call.cc @@ -1440,6 +1440,25 @@ fold_const_fold_left (tree type, tree arg0, tree arg1, tree_code code) return arg0; } +/* Fold a call to IFN_VEC_SHL_INSERT (ARG0, ARG1), returning a value + of type TYPE. */ + +static tree +fold_const_vec_shl_insert (tree, tree arg0, tree arg1) +{ + if (TREE_CODE (arg0) != VECTOR_CST) + return NULL_TREE; + + /* vec_shl_insert ( dup(CST), CST) -> dup (CST). */ + if (tree elem = uniform_vector_p (arg0)) + { + if (operand_equal_p (elem, arg1)) + return arg0; + } + + return NULL_TREE; +} + /* Try to evaluate: *RESULT = FN (*ARG0, *ARG1) @@ -1843,6 +1862,9 @@ fold_const_call (combined_fn fn, tree type, tree arg0, tree arg1) case CFN_FOLD_LEFT_PLUS: return fold_const_fold_left (type, arg0, arg1, PLUS_EXPR); + case CFN_VEC_SHL_INSERT: + return fold_const_vec_shl_insert (type, arg0, arg1); + case CFN_UBSAN_CHECK_ADD: case CFN_ADD_OVERFLOW: subcode = PLUS_EXPR; diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 1311c6e..861d73c 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -264,22 +264,6 @@ protected_set_expr_location_unshare (tree x, location_t loc) return x; } -/* If ARG2 divides ARG1 with zero remainder, carries out the exact - division and returns the quotient. Otherwise returns - NULL_TREE. */ - -tree -div_if_zero_remainder (const_tree arg1, const_tree arg2) -{ - widest_int quo; - - if (wi::multiple_of_p (wi::to_widest (arg1), wi::to_widest (arg2), - SIGNED, &quo)) - return wide_int_to_tree (TREE_TYPE (arg1), quo); - - return NULL_TREE; -} - /* This is nonzero if we should defer warnings about undefined overflow. This facility exists because these warnings are a special case. The code to estimate loop iterations does not want diff --git a/gcc/fold-const.h b/gcc/fold-const.h index 00975dc..87e7ec1 100644 --- a/gcc/fold-const.h +++ b/gcc/fold-const.h @@ -153,7 +153,6 @@ extern tree build_simple_mem_ref_loc (location_t, tree); extern poly_offset_int mem_ref_offset (const_tree); extern tree build_invariant_address (tree, tree, poly_int64); extern tree constant_boolean_node (bool, tree); -extern tree div_if_zero_remainder (const_tree, const_tree); extern bool tree_swap_operands_p (const_tree, const_tree); extern enum tree_code swap_tree_comparison (enum tree_code); diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index cee5ef4..0d937eb 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,43 @@ +2025-10-31 Yuao Ma <c8ef@outlook.com> + + * intrinsic.texi: Fix typo. + * trans-intrinsic.cc (conv_intrinsic_atomic_cas): Remove unreachable + code. + +2025-10-31 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/122452 + * primary.cc (gfc_match_rvalue): Give priority to specific + procedures in a generic interface with the same name as a + PDT template. If found, use as the procedure instead of the + constructor generated from the PDT template. + +2025-10-30 Mikael Morin <mikael@gcc.gnu.org> + + * trans-array.cc: Cleanup obsolete comment. + +2025-10-29 Yuao Ma <c8ef@outlook.com> + + * trans-expr.cc (gfc_conv_gfc_desc_to_cfi_desc): Remove unreachable + code. + +2025-10-29 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/122165 + * primary.cc (gfc_match_varspec): If the previous component ref + was a type specification parameter, a type inquiry ref cannot + follow. + +2025-10-29 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/122433 + PR fortran/122434 + * decl.cc (gfc_get_pdt_instance): Prevent a PDT component of + the same type as the template from being converted into an + instance. + * resolve.cc (gfc_impure_variable): The result of a pure + function is a valid allocate object since it is pure. + 2025-10-28 Yuao Ma <c8ef@outlook.com> PR fortran/122342 diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi index 9012c2a..b2d1e45 100644 --- a/gcc/fortran/intrinsic.texi +++ b/gcc/fortran/intrinsic.texi @@ -2239,7 +2239,7 @@ is different, the value is converted to the kind of @var{ATOM}. program atomic use iso_fortran_env logical(atomic_logical_kind) :: atom[*], prev - call atomic_cas (atom[1], prev, .false., .true.)) + call atomic_cas (atom[1], prev, .false., .true.) end program atomic @end smallexample diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc index 0722c76d..1dcb1c3 100644 --- a/gcc/fortran/primary.cc +++ b/gcc/fortran/primary.cc @@ -3835,6 +3835,9 @@ gfc_match_rvalue (gfc_expr **result) gfc_typespec *ts; bool implicit_char; gfc_ref *ref; + gfc_symtree *pdt_st; + gfc_symbol *found_specific = NULL; + m = gfc_match ("%%loc"); if (m == MATCH_YES) @@ -4082,22 +4085,36 @@ gfc_match_rvalue (gfc_expr **result) break; } + gfc_gobble_whitespace (); + found_specific = NULL; + + /* Even if 'name' is that of a PDT template, priority has to be given to + possible specific procedures in the generic interface. */ + gfc_find_sym_tree (gfc_dt_upper_string (name), NULL, 1, &pdt_st); + if (sym->generic && sym->generic->next + && gfc_peek_ascii_char() != '(') + { + gfc_actual_arglist *arg = actual_arglist; + for (; arg && pdt_st; arg = arg->next) + gfc_resolve_expr (arg->expr); + found_specific = gfc_search_interface (sym->generic, 0, + &actual_arglist); + } + /* Check to see if this is a PDT constructor. The format of these constructors is rather unusual: name [(type_params)](component_values) where, component_values excludes the type_params. With the present gfortran representation this is rather awkward because the two are not distinguished, other than by their attributes. */ - if (sym->attr.generic) + if (sym->attr.generic && pdt_st != NULL && found_specific == NULL) { - gfc_symtree *pdt_st; gfc_symbol *pdt_sym; gfc_actual_arglist *ctr_arglist = NULL, *tmp; gfc_component *c; - /* Obtain the template. */ - gfc_find_sym_tree (gfc_dt_upper_string (name), NULL, 1, &pdt_st); - if (pdt_st && pdt_st->n.sym && pdt_st->n.sym->attr.pdt_template) + /* Use the template. */ + if (pdt_st->n.sym && pdt_st->n.sym->attr.pdt_template) { bool type_spec_list = false; pdt_sym = pdt_st->n.sym; @@ -4155,8 +4172,12 @@ gfc_match_rvalue (gfc_expr **result) tmp = tmp->next; } - gfc_find_sym_tree (gfc_dt_lower_string (pdt_sym->name), - NULL, 1, &symtree); + if (found_specific) + gfc_find_sym_tree (found_specific->name, + NULL, 1, &symtree); + else + gfc_find_sym_tree (gfc_dt_lower_string (pdt_sym->name), + NULL, 1, &symtree); if (!symtree) { gfc_get_ha_sym_tree (gfc_dt_lower_string (pdt_sym->name) , diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index e2b17a7..cb40816 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -268,13 +268,7 @@ gfc_conv_descriptor_data_get (tree desc) return fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), field); } -/* This provides WRITE access to the data field. - - TUPLES_P is true if we are generating tuples. - - This function gets called through the following macros: - gfc_conv_descriptor_data_set - gfc_conv_descriptor_data_set. */ +/* This provides WRITE access to the data field. */ void gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value) diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 67b60c7..2e88e65 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -6090,9 +6090,6 @@ gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym) se.want_pointer = 1; gfc_conv_expr (&se, e); gfc = se.expr; - /* gfc_conv_constant ignores se.want_poiner, e.g. for string_cst. */ - if (!POINTER_TYPE_P (TREE_TYPE (gfc))) - gfc = gfc_build_addr_expr (NULL, gfc); } else { diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index 89a03d8..5b9111d3 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -12844,14 +12844,6 @@ conv_intrinsic_atomic_cas (gfc_code *code) new_val = gfc_build_addr_expr (NULL_TREE, tmp); } - /* Convert a constant to a pointer. */ - if (!POINTER_TYPE_P (TREE_TYPE (comp))) - { - tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp"); - gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp)); - comp = gfc_build_addr_expr (NULL_TREE, tmp); - } - gfc_init_se (&argse, NULL); gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom, atom_expr); diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index edcc04a..8f72dbb 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -5233,24 +5233,6 @@ gimple_fold_builtin_constant_p (gimple_stmt_iterator *gsi) return true; } -/* Fold __builtin_assume_aligned builtin. */ - -static bool -gimple_fold_builtin_assume_aligned (gimple_stmt_iterator *gsi) -{ - if (!fold_before_rtl_expansion_p ()) - return false; - - gcall *call = as_a<gcall*>(gsi_stmt (*gsi)); - - if (gimple_call_num_args (call) < 2) - return false; - - gimplify_and_update_call_from_tree (gsi, gimple_call_arg (call, 0)); - - return true; -} - /* If va_list type is a simple pointer and nothing special is needed, optimize __builtin_va_start (&ap, 0) into ap = __builtin_next_arg (0), __builtin_va_end (&ap) out as NOP and __builtin_va_copy into a simple @@ -5548,9 +5530,6 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi) case BUILT_IN_CONSTANT_P: return gimple_fold_builtin_constant_p (gsi); - case BUILT_IN_ASSUME_ALIGNED: - return gimple_fold_builtin_assume_aligned (gsi); - default:; } diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc index c9bc5c0..3a22606 100644 --- a/gcc/gimple-range-op.cc +++ b/gcc/gimple-range-op.cc @@ -150,6 +150,10 @@ gimple_range_op_handler::gimple_range_op_handler (gimple *s) if (TREE_CODE (ssa) == SSA_NAME) m_op1 = ssa; } + // VIEW_CONVERT_EXPR needs to descend one level deeper to pick + // up the symbolic operand. + if (TREE_CODE (m_op1) == VIEW_CONVERT_EXPR) + m_op1 = TREE_OPERAND (m_op1, 0); if (gimple_num_ops (m_stmt) >= 3) m_op2 = gimple_assign_rhs2 (m_stmt); // Check that operands are supported types. One check is enough. diff --git a/gcc/ipa-icf.cc b/gcc/ipa-icf.cc index b354fb1..c7596f9 100644 --- a/gcc/ipa-icf.cc +++ b/gcc/ipa-icf.cc @@ -2166,7 +2166,9 @@ sem_item_optimizer::write_summary (void) !lsei_end_p (lsei); lsei_next_in_partition (&lsei)) { - symtab_node *node = lsei_node (lsei); + symtab_node *node = dyn_cast <symtab_node *> (lsei_node (lsei)); + if (!node) + continue; if (m_symtab_node_map.get (node)) count++; @@ -2179,7 +2181,9 @@ sem_item_optimizer::write_summary (void) !lsei_end_p (lsei); lsei_next_in_partition (&lsei)) { - symtab_node *node = lsei_node (lsei); + symtab_node *node = dyn_cast <symtab_node *> (lsei_node (lsei)); + if (!node) + continue; sem_item **item = m_symtab_node_map.get (node); @@ -2233,7 +2237,7 @@ sem_item_optimizer::read_section (lto_file_decl_data *file_data, for (i = 0; i < count; i++) { unsigned int index; - symtab_node *node; + toplevel_node *node; lto_symtab_encoder_t encoder; index = streamer_read_uhwi (&ib_main); @@ -2241,12 +2245,11 @@ sem_item_optimizer::read_section (lto_file_decl_data *file_data, node = lto_symtab_encoder_deref (encoder, index); hashval_t hash = streamer_read_uhwi (&ib_main); - gcc_assert (node->definition); + if (symtab_node *snode = dyn_cast <symtab_node *> (node)) + gcc_assert (snode->definition); - if (is_a<cgraph_node *> (node)) + if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) { - cgraph_node *cnode = dyn_cast <cgraph_node *> (node); - sem_function *fn = new sem_function (cnode, &m_bmstack); unsigned count = streamer_read_uhwi (&ib_main); inchash::hash hstate (0); @@ -2263,10 +2266,8 @@ sem_item_optimizer::read_section (lto_file_decl_data *file_data, fn->set_hash (hash); m_items.safe_push (fn); } - else + else if (varpool_node *vnode = dyn_cast <varpool_node *> (node)) { - varpool_node *vnode = dyn_cast <varpool_node *> (node); - sem_variable *var = new sem_variable (vnode, &m_bmstack); var->set_hash (hash); m_items.safe_push (var); diff --git a/gcc/ipa-modref.cc b/gcc/ipa-modref.cc index d3e5101..a319ee3 100644 --- a/gcc/ipa-modref.cc +++ b/gcc/ipa-modref.cc @@ -3752,8 +3752,8 @@ modref_write () for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node *snode = lto_symtab_encoder_deref (encoder, i); - cgraph_node *cnode = dyn_cast <cgraph_node *> (snode); + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode); modref_summary_lto *r; if (cnode && cnode->definition && !cnode->alias @@ -3765,8 +3765,8 @@ modref_write () for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node *snode = lto_symtab_encoder_deref (encoder, i); - cgraph_node *cnode = dyn_cast <cgraph_node *> (snode); + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode); if (cnode && cnode->definition && !cnode->alias) { diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index c8438d6..1e4b6d4 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -5576,8 +5576,8 @@ ipa_write_return_summaries (output_block *ob) unsigned int count = 0; for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node *snode = lto_symtab_encoder_deref (encoder, i); - cgraph_node *cnode = dyn_cast <cgraph_node *> (snode); + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode); ipa_return_value_summary *v; if (cnode && cnode->definition && !cnode->alias @@ -5589,8 +5589,8 @@ ipa_write_return_summaries (output_block *ob) for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node *snode = lto_symtab_encoder_deref (encoder, i); - cgraph_node *cnode = dyn_cast <cgraph_node *> (snode); + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode); ipa_return_value_summary *v; if (cnode && cnode->definition && !cnode->alias @@ -5865,8 +5865,8 @@ ipcp_write_transformation_summaries (void) for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node *snode = lto_symtab_encoder_deref (encoder, i); - cgraph_node *cnode = dyn_cast <cgraph_node *> (snode); + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode); if (!cnode) continue; ipcp_transformation *ts = ipcp_get_transformation_summary (cnode); @@ -5879,8 +5879,8 @@ ipcp_write_transformation_summaries (void) for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node *snode = lto_symtab_encoder_deref (encoder, i); - cgraph_node *cnode = dyn_cast <cgraph_node *> (snode); + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode); if (!cnode) continue; ipcp_transformation *ts = ipcp_get_transformation_summary (cnode); diff --git a/gcc/ipa-reference.cc b/gcc/ipa-reference.cc index 975341c..173c7a5 100644 --- a/gcc/ipa-reference.cc +++ b/gcc/ipa-reference.cc @@ -1070,8 +1070,8 @@ ipa_reference_write_optimization_summary (void) /* See what variables we are interested in. */ for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node *snode = lto_symtab_encoder_deref (encoder, i); - varpool_node *vnode = dyn_cast <varpool_node *> (snode); + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + varpool_node *vnode = dyn_cast <varpool_node *> (tnode); int id; if (vnode @@ -1089,8 +1089,8 @@ ipa_reference_write_optimization_summary (void) if (ltrans_statics_bitcount) for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node *snode = lto_symtab_encoder_deref (encoder, i); - cgraph_node *cnode = dyn_cast <cgraph_node *> (snode); + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode); if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics)) count++; } @@ -1104,15 +1104,15 @@ ipa_reference_write_optimization_summary (void) if (ltrans_statics_bitcount) for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node *snode = lto_symtab_encoder_deref (encoder, i); - cgraph_node *cnode = dyn_cast <cgraph_node *> (snode); + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode); if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics)) { ipa_reference_optimization_summary_t info; int node_ref; info = get_reference_optimization_summary (cnode); - node_ref = lto_symtab_encoder_encode (encoder, snode); + node_ref = lto_symtab_encoder_encode (encoder, tnode); streamer_write_uhwi_stream (ob->main_stream, node_ref); stream_out_bitmap (ob, info->statics_read, ltrans_statics, diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index b152997..48ce7578 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -2552,7 +2552,10 @@ process_alt_operands (int only_alternative) { int regno = decode_hard_reg_constraint (p); gcc_assert (regno >= 0); - cl = REGNO_REG_CLASS (regno); + cl = NO_REGS; + int nregs = hard_regno_nregs (regno, mode); + for (int i = 0; i < nregs; ++i) + cl = reg_class_superunion[cl][REGNO_REG_CLASS (regno + i)]; CLEAR_HARD_REG_SET (hard_reg_constraint); SET_HARD_REG_BIT (hard_reg_constraint, regno); cl_filter = &hard_reg_constraint; diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc index 5708ba0..4c60bf0 100644 --- a/gcc/lto-cgraph.cc +++ b/gcc/lto-cgraph.cc @@ -45,9 +45,6 @@ along with GCC; see the file COPYING3. If not see #include "symtab-thunks.h" #include "symtab-clones.h" -/* True when asm nodes has been output. */ -bool asm_nodes_output = false; - static void output_cgraph_opt_summary (void); static void input_cgraph_opt_summary (vec<symtab_node *> nodes); @@ -82,7 +79,7 @@ lto_symtab_encoder_new (bool for_input) lto_symtab_encoder_t encoder = XCNEW (struct lto_symtab_encoder_d); if (!for_input) - encoder->map = new hash_map<symtab_node *, size_t>; + encoder->map = new hash_map<toplevel_node *, size_t>; encoder->nodes.create (0); return encoder; } @@ -108,7 +105,7 @@ lto_symtab_encoder_delete (lto_symtab_encoder_t encoder) int lto_symtab_encoder_encode (lto_symtab_encoder_t encoder, - symtab_node *node) + toplevel_node *node) { int ref; @@ -140,7 +137,7 @@ lto_symtab_encoder_encode (lto_symtab_encoder_t encoder, bool lto_symtab_encoder_delete_node (lto_symtab_encoder_t encoder, - symtab_node *node) + toplevel_node *node) { int index; @@ -214,7 +211,7 @@ lto_set_symtab_encoder_encode_initializer (lto_symtab_encoder_t encoder, bool lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t encoder, - symtab_node *node) + toplevel_node *node) { int index = lto_symtab_encoder_lookup (encoder, node); if (index == LCC_NOT_FOUND) @@ -226,11 +223,16 @@ lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t encoder, void lto_set_symtab_encoder_in_partition (lto_symtab_encoder_t encoder, - symtab_node *node) + toplevel_node *node) { int index = lto_symtab_encoder_encode (encoder, node); if (dump_file) - fprintf(dump_file, "Node %s, index %d\n", node->asm_name(), index); + { + if (symtab_node* snode = dyn_cast<symtab_node*> (node)) + fprintf (dump_file, "Node %s, index %d\n", snode->asm_name (), index); + else + fprintf (dump_file, "Asm node, index %d\n", index); + } encoder->nodes[index].in_partition = true; } @@ -770,7 +772,10 @@ output_refs (lto_symtab_encoder_t encoder) for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node *node = lto_symtab_encoder_deref (encoder, i); + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + symtab_node *node = dyn_cast <symtab_node *> (tnode); + if (!node) + continue; /* IPA_REF_ALIAS references are always preserved in the boundary. Alias node can't have other references and @@ -895,7 +900,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) pickle those too. */ for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node *node = lto_symtab_encoder_deref (encoder, i); + toplevel_node *node = lto_symtab_encoder_deref (encoder, i); if (varpool_node *vnode = dyn_cast <varpool_node *> (node)) { if (!lto_symtab_encoder_encode_initializer_p (encoder, @@ -962,7 +967,11 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) to stay to aid local calling conventions. */ for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node *node = lto_symtab_encoder_deref (encoder, i); + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + symtab_node *node = dyn_cast <symtab_node *> (tnode); + if (!node) + continue; + cgraph_node *cnode = dyn_cast <cgraph_node *> (node); if (node->alias && node->analyzed) @@ -980,6 +989,13 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) lto_symtab_encoder_encode (encoder, node); } } + + for (lsei = lsei_start (in_encoder); !lsei_end_p (lsei); lsei_next (&lsei)) + { + toplevel_node *tnode = lsei_node (lsei); + if (asm_node* node = dyn_cast <asm_node*> (tnode)) + lto_set_symtab_encoder_in_partition (encoder, node); + } lto_symtab_encoder_delete (in_encoder); return encoder; } @@ -1012,11 +1028,11 @@ output_symtab (void) n_nodes = lto_symtab_encoder_size (encoder); for (i = 0; i < n_nodes; i++) { - symtab_node *node = lto_symtab_encoder_deref (encoder, i); + toplevel_node *node = lto_symtab_encoder_deref (encoder, i); if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) lto_output_node (ob, cnode, encoder); - else - lto_output_varpool_node (ob, dyn_cast<varpool_node *> (node), encoder); + else if (varpool_node *vnode = dyn_cast <varpool_node *> (node)) + lto_output_varpool_node (ob, vnode, encoder); } /* Go over the nodes in SET again to write edges. */ @@ -1036,15 +1052,9 @@ output_symtab (void) lto_destroy_simple_output_block (ob); - /* Emit toplevel asms. - When doing WPA we must output every asm just once. Since we do not partition asm - nodes at all, output them to first output. This is kind of hack, but should work - well. */ - if (!asm_nodes_output && !lto_stream_offload_p) - { - asm_nodes_output = true; - lto_output_toplevel_asms (); - } + /* Emit toplevel asms. */ + if (!lto_stream_offload_p) + lto_output_toplevel_asms (encoder); output_refs (encoder); } @@ -2111,7 +2121,7 @@ output_cgraph_opt_summary (void) n_nodes = lto_symtab_encoder_size (encoder); for (i = 0; i < n_nodes; i++) { - symtab_node *node = lto_symtab_encoder_deref (encoder, i); + toplevel_node *node = lto_symtab_encoder_deref (encoder, i); cgraph_node *cnode = dyn_cast <cgraph_node *> (node); if (cnode && output_cgraph_opt_summary_p (cnode)) count++; @@ -2119,7 +2129,7 @@ output_cgraph_opt_summary (void) streamer_write_uhwi (ob, count); for (i = 0; i < n_nodes; i++) { - symtab_node *node = lto_symtab_encoder_deref (encoder, i); + toplevel_node *node = lto_symtab_encoder_deref (encoder, i); cgraph_node *cnode = dyn_cast <cgraph_node *> (node); if (cnode && output_cgraph_opt_summary_p (cnode)) { diff --git a/gcc/lto-section-in.cc b/gcc/lto-section-in.cc index 1dd9520..bf86219 100644 --- a/gcc/lto-section-in.cc +++ b/gcc/lto-section-in.cc @@ -448,7 +448,6 @@ lto_free_function_in_decl_state_for_node (symtab_node *node) lto_free_function_in_decl_state (*slot); node->lto_file_data->function_decl_states->clear_slot (slot); } - node->lto_file_data = NULL; } diff --git a/gcc/lto-streamer-in.cc b/gcc/lto-streamer-in.cc index be81826..2efa1f3 100644 --- a/gcc/lto-streamer-in.cc +++ b/gcc/lto-streamer-in.cc @@ -2004,6 +2004,7 @@ lto_input_toplevel_asms (struct lto_file_decl_data *file_data, int order_base) { asm_node *node = symtab->finalize_toplevel_asm (str); node->order = streamer_read_hwi (&ib) + order_base; + node->lto_file_data = file_data; if (node->order >= symtab->order) symtab->order = node->order + 1; } diff --git a/gcc/lto-streamer-out.cc b/gcc/lto-streamer-out.cc index 308ab34..d03c41f 100644 --- a/gcc/lto-streamer-out.cc +++ b/gcc/lto-streamer-out.cc @@ -2554,14 +2554,18 @@ output_constructor (struct varpool_node *node, int output_order) /* Emit toplevel asms. */ void -lto_output_toplevel_asms (void) +lto_output_toplevel_asms (lto_symtab_encoder_t encoder) { struct output_block *ob; - struct asm_node *can; char *section_name; struct lto_simple_header_with_strings header; - if (!symtab->first_asm_symbol ()) + bool any_asm = false; + for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) + if (is_a <asm_node*> (lto_symtab_encoder_deref (encoder, i))) + any_asm = true; + + if (!any_asm) return; ob = create_output_block (LTO_section_asm); @@ -2569,17 +2573,22 @@ lto_output_toplevel_asms (void) /* Make string 0 be a NULL string. */ streamer_write_char_stream (ob->string_stream, 0); - for (can = symtab->first_asm_symbol (); can; can = can->next) + for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) { - if (TREE_CODE (can->asm_str) != STRING_CST) + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + asm_node *anode = dyn_cast <asm_node*> (tnode); + if (!anode) + continue; + + if (TREE_CODE (anode->asm_str) != STRING_CST) { - sorry_at (EXPR_LOCATION (can->asm_str), + sorry_at (EXPR_LOCATION (anode->asm_str), "LTO streaming of toplevel extended %<asm%> " "unimplemented"); continue; } - streamer_write_string_cst (ob, ob->main_stream, can->asm_str); - streamer_write_hwi (ob, can->order); + streamer_write_string_cst (ob, ob->main_stream, anode->asm_str); + streamer_write_hwi (ob, anode->order); } streamer_write_string_cst (ob, ob->main_stream, NULL_TREE); @@ -2783,19 +2792,12 @@ create_order_remap (lto_symtab_encoder_t encoder) { auto_vec<int> orders; unsigned i; - struct asm_node* anode; encoder->order_remap = new hash_map<int_hash<int, -1, -2>, int>; unsigned n_nodes = lto_symtab_encoder_size (encoder); for (i = 0; i < n_nodes; i++) orders.safe_push (lto_symtab_encoder_deref (encoder, i)->order); - if (!asm_nodes_output) - { - for (anode = symtab->first_asm_symbol (); anode; anode = anode->next) - orders.safe_push (anode->order); - } - orders.qsort (cmp_int); int ord = 0; int last_order = -1; @@ -2809,14 +2811,6 @@ create_order_remap (lto_symtab_encoder_t encoder) ord++; } } - - /* Asm nodes are currently always output only into first partition. - We can remap already here. */ - if (!asm_nodes_output) - { - for (anode = symtab->first_asm_symbol (); anode; anode = anode->next) - anode->order = *encoder->order_remap->get (anode->order); - } } /* Main entry point from the pass manager. */ @@ -2831,6 +2825,13 @@ lto_output (void) lto_symtab_encoder_t encoder = lto_get_out_decl_state ()->symtab_node_encoder; auto_vec<symtab_node *> symbols_to_copy; + if (!flag_wpa) + { + asm_node *anode; + for (anode = symtab->first_asm_symbol (); anode; anode = anode->next) + lto_set_symtab_encoder_in_partition (encoder, anode); + } + create_order_remap (encoder); prune_offload_funcs (); @@ -2851,16 +2852,18 @@ lto_output (void) section copying. */ for (i = 0; i < n_nodes; i++) { - symtab_node *snode = lto_symtab_encoder_deref (encoder, i); - if (snode->alias) + toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i); + symtab_node *node = dyn_cast <symtab_node *> (tnode); + if (!node || node->alias) continue; - if (cgraph_node *node = dyn_cast <cgraph_node *> (snode)) + + if (cgraph_node *node = dyn_cast <cgraph_node *> (tnode)) { if (lto_symtab_encoder_encode_body_p (encoder, node) && !node->clone_of) symbols_to_copy.safe_push (node); } - else if (varpool_node *node = dyn_cast <varpool_node *> (snode)) + else if (varpool_node *node = dyn_cast <varpool_node *> (tnode)) { /* Wrap symbol references inside the ctor in a type preserving MEM_REF. */ @@ -3202,7 +3205,10 @@ produce_symtab (struct output_block *ob) for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node *node = lsei_node (lsei); + toplevel_node *tnode = lsei_node (lsei); + symtab_node *node = dyn_cast<symtab_node*> (tnode); + if (!node) + continue; if (DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ()) continue; @@ -3212,7 +3218,10 @@ produce_symtab (struct output_block *ob) for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node *node = lsei_node (lsei); + toplevel_node *tnode = lsei_node (lsei); + symtab_node *node = dyn_cast<symtab_node*> (tnode); + if (!node) + continue; if (!DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ()) continue; @@ -3253,7 +3262,10 @@ produce_symtab_extension (struct output_block *ob, for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node *node = lsei_node (lsei); + toplevel_node *tnode = lsei_node (lsei); + symtab_node *node = dyn_cast<symtab_node*> (tnode); + if (!node) + continue; if (DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ()) continue; @@ -3263,7 +3275,10 @@ produce_symtab_extension (struct output_block *ob, for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node *node = lsei_node (lsei); + toplevel_node *tnode = lsei_node (lsei); + symtab_node *node = dyn_cast<symtab_node*> (tnode); + if (!node) + continue; if (!DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ()) continue; diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 4b7209e3..a398f43 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -444,12 +444,12 @@ struct lto_stats_d struct lto_encoder_entry { /* Constructor. */ - lto_encoder_entry (symtab_node* n) + lto_encoder_entry (toplevel_node* n) : node (n), in_partition (false), body (false), only_for_inlining (true), initializer (false) {} - symtab_node *node; + toplevel_node *node; /* Is the node in this partition (i.e. ltrans of this partition will be responsible for outputting it)? */ unsigned int in_partition:1; @@ -468,7 +468,7 @@ struct lto_encoder_entry struct lto_symtab_encoder_d { vec<lto_encoder_entry> nodes; - hash_map<symtab_node *, size_t> *map; + hash_map<toplevel_node *, size_t> *map; /* Mapping of input order of nodes onto output order. */ hash_map<int_hash<int, -1, -2>, int> *order_remap; @@ -897,7 +897,7 @@ extern void lto_output_fn_decl_ref (struct lto_out_decl_state *, struct lto_output_stream *, tree); extern tree lto_input_var_decl_ref (lto_input_block *, lto_file_decl_data *); extern tree lto_input_fn_decl_ref (lto_input_block *, lto_file_decl_data *); -extern void lto_output_toplevel_asms (void); +extern void lto_output_toplevel_asms (lto_symtab_encoder_t); extern void produce_asm (struct output_block *ob); extern void lto_output (); extern void produce_asm_for_decls (); @@ -916,19 +916,18 @@ void lto_prepare_function_for_streaming (cgraph_node *); /* In lto-cgraph.cc */ -extern bool asm_nodes_output; lto_symtab_encoder_t lto_symtab_encoder_new (bool); -int lto_symtab_encoder_encode (lto_symtab_encoder_t, symtab_node *); +int lto_symtab_encoder_encode (lto_symtab_encoder_t, toplevel_node *); void lto_symtab_encoder_delete (lto_symtab_encoder_t); -bool lto_symtab_encoder_delete_node (lto_symtab_encoder_t, symtab_node *); +bool lto_symtab_encoder_delete_node (lto_symtab_encoder_t, toplevel_node *); bool lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t, struct cgraph_node *); bool lto_symtab_encoder_only_for_inlining_p (lto_symtab_encoder_t, struct cgraph_node *); bool lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t, - symtab_node *); + toplevel_node *); void lto_set_symtab_encoder_in_partition (lto_symtab_encoder_t, - symtab_node *); + toplevel_node *); bool lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t, varpool_node *); @@ -1104,7 +1103,7 @@ lto_symtab_encoder_size (lto_symtab_encoder_t encoder) inline int lto_symtab_encoder_lookup (lto_symtab_encoder_t encoder, - symtab_node *node) + toplevel_node *node) { size_t *slot = encoder->map->get (node); return (slot && *slot ? *(slot) - 1 : LCC_NOT_FOUND); @@ -1125,7 +1124,7 @@ lsei_next (lto_symtab_encoder_iterator *lsei) } /* Return the node pointed to by LSI. */ -inline symtab_node * +inline toplevel_node * lsei_node (lto_symtab_encoder_iterator lsei) { return lsei.encoder->nodes[lsei.index].node; @@ -1147,7 +1146,7 @@ lsei_varpool_node (lto_symtab_encoder_iterator lsei) /* Return the cgraph node corresponding to REF using ENCODER. */ -inline symtab_node * +inline toplevel_node * lto_symtab_encoder_deref (lto_symtab_encoder_t encoder, int ref) { if (ref == LCC_NOT_FOUND) diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index d7b3172..c059e06 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,40 @@ +2025-10-30 Michal Jires <mjires@suse.cz> + + * lto.cc (stream_out_partitions): Remove asm_nodes_out. + +2025-10-30 Michal Jires <mjires@suse.cz> + + * lto-partition.cc (create_partition_if_empty): New. + (node_into_file_partition): Break out from ... + (lto_1_to_1_map): ... here. Partition toplevel assembly. + (create_asm_partition): New. + (lto_max_map): Use create_asm_partition. + (lto_balanced_map): Likewise. + +2025-10-30 Michal Jires <mjires@suse.cz> + + * lto-partition.cc (add_symbol_to_partition): Use toplevel_node. + (undo_partition): Likewise. + (join_partitions): Likewise. + (split_partition_into_nodes): Likewise. + (is_partition_reorder): Likewise. + (lto_balanced_map): Likewise. + (lto_promote_cross_file_statics): Likewise. + * lto.cc (lto_wpa_write_files): Likewise. + +2025-10-30 Michal Jires <mjires@suse.cz> + + * lto-partition.cc (lto_balanced_map): Simplify. + +2025-10-30 Michal Jires <mjires@suse.cz> + + * lto-symtab.cc (lto_symtab_merge_symbols_1): likewise. + +2025-10-30 Michal Jires <mjires@suse.cz> + + * lto-partition.cc (cmp_partitions_order): Reverse sort. + (node_cmp): Reverse sort. + 2025-10-27 Richard Biener <rguenther@suse.de> PR middle-end/122325 diff --git a/gcc/lto/lto-partition.cc b/gcc/lto/lto-partition.cc index c7e69ee..baeafc7 100644 --- a/gcc/lto/lto-partition.cc +++ b/gcc/lto/lto-partition.cc @@ -43,7 +43,8 @@ along with GCC; see the file COPYING3. If not see vec<ltrans_partition> ltrans_partitions; -static void add_symbol_to_partition (ltrans_partition part, symtab_node *node); +static void add_symbol_to_partition (ltrans_partition part, + toplevel_node *node); /* Helper for qsort; compare partitions and return one with smaller order. */ @@ -61,7 +62,7 @@ cmp_partitions_order (const void *a, const void *b) ordera = lto_symtab_encoder_deref (pa->encoder, 0)->order; if (lto_symtab_encoder_size (pb->encoder)) orderb = lto_symtab_encoder_deref (pb->encoder, 0)->order; - return orderb - ordera; + return ordera - orderb; } /* Create new partition with name NAME. @@ -87,6 +88,15 @@ new_partition (const char *name) return part; } +/* If the cgraph is empty, create one cgraph node set so that there is still + an output file for any variables that need to be exported in a DSO. */ +static void +create_partition_if_empty () +{ + if (!ltrans_partitions.length ()) + new_partition ("empty"); +} + /* Free memory used by ltrans partition. Encoder can be kept to be freed after streaming. */ static void @@ -266,9 +276,15 @@ contained_in_symbol (symtab_node *node) of other symbol definition, add the other symbol, too. */ static void -add_symbol_to_partition (ltrans_partition part, symtab_node *node) +add_symbol_to_partition (ltrans_partition part, toplevel_node *tnode) { symtab_node *node1; + symtab_node* node = dyn_cast <symtab_node*> (tnode); + if (!node) + { + lto_set_symtab_encoder_in_partition (part->encoder, tnode); + return; + } /* Verify that we do not try to duplicate something that cannot be. */ gcc_checking_assert (node->get_partitioning_class () == SYMBOL_DUPLICATE @@ -299,22 +315,53 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes) { while (lto_symtab_encoder_size (partition->encoder) > (int)n_nodes) { - symtab_node *node = lto_symtab_encoder_deref (partition->encoder, - n_nodes); - partition->symbols--; - cgraph_node *cnode; + toplevel_node *tnode = lto_symtab_encoder_deref (partition->encoder, + n_nodes); /* After UNDO we no longer know what was visited. */ if (partition->initializers_visited) delete partition->initializers_visited; partition->initializers_visited = NULL; - if (!node->alias && (cnode = dyn_cast <cgraph_node *> (node)) - && node->get_partitioning_class () == SYMBOL_PARTITION) - partition->insns -= ipa_size_summaries->get (cnode)->size; - lto_symtab_encoder_delete_node (partition->encoder, node); - node->aux = (void *)((size_t)node->aux - 1); + lto_symtab_encoder_delete_node (partition->encoder, tnode); + + if (symtab_node* node = dyn_cast <symtab_node *> (tnode)) + { + partition->symbols--; + cgraph_node *cnode; + if (!node->alias && (cnode = dyn_cast <cgraph_node *> (node)) + && node->get_partitioning_class () == SYMBOL_PARTITION) + partition->insns -= ipa_size_summaries->get (cnode)->size; + node->aux = (void *)((size_t)node->aux - 1); + } + } +} + +/* Insert node into its file partition. */ +static void +node_into_file_partition (toplevel_node* node, + hash_map<lto_file_decl_data *, + ltrans_partition>& pmap) +{ + ltrans_partition partition; + + struct lto_file_decl_data *file_data = node->lto_file_data; + + if (file_data) + { + ltrans_partition *slot = &pmap.get_or_insert (file_data); + if (*slot) + partition = *slot; + else + { + partition = new_partition (file_data->file_name); + *slot = partition; + } } + else + partition = new_partition (""); + + add_symbol_to_partition (partition, node); } /* Group cgrah nodes by input files. This is used mainly for testing @@ -324,10 +371,7 @@ void lto_1_to_1_map (void) { symtab_node *node; - struct lto_file_decl_data *file_data; hash_map<lto_file_decl_data *, ltrans_partition> pmap; - ltrans_partition partition; - int npartitions = 0; FOR_EACH_SYMBOL (node) { @@ -335,41 +379,38 @@ lto_1_to_1_map (void) || symbol_partitioned_p (node)) continue; - file_data = node->lto_file_data; - - if (file_data) - { - ltrans_partition *slot = &pmap.get_or_insert (file_data); - if (*slot) - partition = *slot; - else - { - partition = new_partition (file_data->file_name); - *slot = partition; - npartitions++; - } - } - else if (!file_data && ltrans_partitions.length ()) - partition = ltrans_partitions[0]; - else - { - partition = new_partition (""); - npartitions++; - } - - add_symbol_to_partition (partition, node); + node_into_file_partition (node, pmap); } - /* If the cgraph is empty, create one cgraph node set so that there is still - an output file for any variables that need to be exported in a DSO. */ - if (!npartitions) - new_partition ("empty"); + struct asm_node *anode; + for (anode = symtab->first_asm_symbol (); anode; anode = anode->next) + node_into_file_partition (anode, pmap); + + create_partition_if_empty (); /* Order partitions by order of symbols because they are linked into binary that way. */ ltrans_partitions.qsort (cmp_partitions_order); } +/* Creates partition with all toplevel assembly. + + Before toplevel asm could be partitioned, all toplevel asm was inserted + into first partition. + This function achieves similar behavior for partitionings that cannot + easily satisfy requirements of toplevel asm. */ +static void +create_asm_partition (void) +{ + struct asm_node *anode = symtab->first_asm_symbol (); + if (anode) + { + ltrans_partition partition = new_partition ("asm_nodes"); + for (; anode; anode = anode->next) + add_symbol_to_partition (partition, anode); + } +} + /* Maximal partitioning. Put every new symbol into new partition if possible. */ void @@ -377,7 +418,6 @@ lto_max_map (void) { symtab_node *node; ltrans_partition partition; - int npartitions = 0; FOR_EACH_SYMBOL (node) { @@ -386,10 +426,10 @@ lto_max_map (void) continue; partition = new_partition (node->asm_name ()); add_symbol_to_partition (partition, node); - npartitions++; } - if (!npartitions) - new_partition ("empty"); + + create_asm_partition (); + create_partition_if_empty (); } /* Helper function for qsort; sort nodes by order. */ @@ -398,7 +438,7 @@ node_cmp (const void *pa, const void *pb) { const symtab_node *a = *static_cast<const symtab_node * const *> (pa); const symtab_node *b = *static_cast<const symtab_node * const *> (pb); - return b->order - a->order; + return a->order - b->order; } /* Add all symtab nodes from NEXT_NODE to PARTITION in order. */ @@ -467,16 +507,17 @@ join_partitions (ltrans_partition into, ltrans_partition from) before adding any symbols to other partition. */ for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node *node = lsei_node (lsei); - node->aux = (void *)((size_t)node->aux - 1); + if (symtab_node *node = dyn_cast <symtab_node*> (lsei_node (lsei))) + node->aux = (void *)((size_t)node->aux - 1); } for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node *node = lsei_node (lsei); + toplevel_node *node = lsei_node (lsei); - if (symbol_partitioned_p (node)) - continue; + if (symtab_node *snode = dyn_cast <symtab_node*> (node)) + if (symbol_partitioned_p (snode)) + continue; add_symbol_to_partition (into, node); } @@ -498,16 +539,17 @@ split_partition_into_nodes (ltrans_partition part) for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node *node = lsei_node (lsei); - node->aux = (void *)((size_t)node->aux - 1); + if (symtab_node *node = dyn_cast <symtab_node*> (lsei_node (lsei))) + node->aux = (void *)((size_t)node->aux - 1); } for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node *node = lsei_node (lsei); + toplevel_node *node = lsei_node (lsei); - if (node->get_partitioning_class () != SYMBOL_PARTITION - || symbol_partitioned_p (node)) + symtab_node *snode = dyn_cast <symtab_node*> (node); + if (snode->get_partitioning_class () != SYMBOL_PARTITION + || symbol_partitioned_p (snode)) continue; ltrans_partition new_part = new_partition_no_push (part->name); @@ -527,8 +569,8 @@ is_partition_reorder (ltrans_partition part) for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node *node = lsei_node (lsei); - if (node->no_reorder) + symtab_node *node = dyn_cast <symtab_node*> (lsei_node (lsei)); + if (!node || node->no_reorder) return false; } return true; @@ -1167,20 +1209,22 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size) callgraph or IPA reference edge leaving the partition contributes into COST. Every edge inside partition was earlier computed as one leaving it and thus we need to subtract it from COST. */ - while (last_visited_node < lto_symtab_encoder_size (partition->encoder)) + for (; last_visited_node < lto_symtab_encoder_size (partition->encoder); + last_visited_node++) { int j; struct ipa_ref *ref = NULL; - symtab_node *snode = lto_symtab_encoder_deref (partition->encoder, - last_visited_node); + toplevel_node *tnode = lto_symtab_encoder_deref (partition->encoder, + last_visited_node); + + symtab_node* snode = dyn_cast <symtab_node*> (tnode); + if (!snode) + continue; if (cgraph_node *node = dyn_cast <cgraph_node *> (snode)) { struct cgraph_edge *edge; - - last_visited_node++; - gcc_assert (node->definition || node->weakref); /* Compute boundary cost of callgraph edges. */ @@ -1197,8 +1241,7 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size) gcc_assert (edge_cost > 0); index = lto_symtab_encoder_lookup (partition->encoder, edge->callee); - if (index != LCC_NOT_FOUND - && index < last_visited_node - 1) + if (index != LCC_NOT_FOUND && index < last_visited_node) cost -= edge_cost, internal += edge_cost; else cost += edge_cost; @@ -1216,15 +1259,12 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size) gcc_assert (edge_cost > 0); index = lto_symtab_encoder_lookup (partition->encoder, edge->caller); - if (index != LCC_NOT_FOUND - && index < last_visited_node - 1) + if (index != LCC_NOT_FOUND && index < last_visited_node) cost -= edge_cost, internal += edge_cost; else cost += edge_cost; } } - else - last_visited_node++; /* Compute boundary cost of IPA REF edges and at the same time look into variables referenced from current partition and try to add them. */ @@ -1242,8 +1282,7 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size) add_symbol_to_partition (partition, vnode); index = lto_symtab_encoder_lookup (partition->encoder, vnode); - if (index != LCC_NOT_FOUND - && index < last_visited_node - 1) + if (index != LCC_NOT_FOUND && index < last_visited_node) cost--, internal++; else cost++; @@ -1255,8 +1294,7 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size) node = dyn_cast <cgraph_node *> (ref->referred); index = lto_symtab_encoder_lookup (partition->encoder, node); - if (index != LCC_NOT_FOUND - && index < last_visited_node - 1) + if (index != LCC_NOT_FOUND && index < last_visited_node) cost--, internal++; else cost++; @@ -1281,8 +1319,7 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size) add_symbol_to_partition (partition, vnode); index = lto_symtab_encoder_lookup (partition->encoder, vnode); - if (index != LCC_NOT_FOUND - && index < last_visited_node - 1) + if (index != LCC_NOT_FOUND && index < last_visited_node) cost--, internal++; else cost++; @@ -1295,8 +1332,7 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size) gcc_assert (node->definition); index = lto_symtab_encoder_lookup (partition->encoder, node); - if (index != LCC_NOT_FOUND - && index < last_visited_node - 1) + if (index != LCC_NOT_FOUND && index < last_visited_node) cost--, internal++; else cost++; @@ -1401,6 +1437,8 @@ lto_balanced_map (int n_lto_partitions, int max_partition_size) gcc_assert (next_nodes.length () || npartitions != 1 || !best_cost || best_cost == -1); add_sorted_nodes (next_nodes, partition); + create_asm_partition (); + if (dump_file) { fprintf (dump_file, "\nPartition sizes:\n"); @@ -1872,7 +1910,10 @@ lto_promote_cross_file_statics (void) for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node *node = lsei_node (lsei); + toplevel_node *tnode = lsei_node (lsei); + symtab_node *node = dyn_cast <symtab_node*> (tnode); + if (!node) + continue; /* If symbol is static, rename it if its assembler name clashes with anything else in this unit. */ diff --git a/gcc/lto/lto-symtab.cc b/gcc/lto/lto-symtab.cc index 66674a4..8d7fc68 100644 --- a/gcc/lto/lto-symtab.cc +++ b/gcc/lto/lto-symtab.cc @@ -953,11 +953,7 @@ lto_symtab_merge_symbols_1 (symtab_node *prevailing) else { DECL_INITIAL (e->decl) = error_mark_node; - if (e->lto_file_data) - { - lto_free_function_in_decl_state_for_node (e); - e->lto_file_data = NULL; - } + lto_free_function_in_decl_state_for_node (e); symtab->call_varpool_removal_hooks (dyn_cast<varpool_node *> (e)); } e->remove_all_references (); diff --git a/gcc/lto/lto.cc b/gcc/lto/lto.cc index 183634f..a4b1bc2 100644 --- a/gcc/lto/lto.cc +++ b/gcc/lto/lto.cc @@ -267,7 +267,6 @@ stream_out_partitions (char *temp_filename, int blen, int min, int max, { /* There are no free tokens, lets do the job outselves. */ stream_out_partitions_1 (temp_filename, blen, min, max); - asm_nodes_output = true; return; } } @@ -296,7 +295,6 @@ stream_out_partitions (char *temp_filename, int blen, int min, int max, if (jinfo != NULL && jinfo->is_connected) jinfo->disconnect (); } - asm_nodes_output = true; #else stream_out_partitions_1 (temp_filename, blen, min, max); #endif @@ -381,14 +379,17 @@ lto_wpa_write_files (void) !lsei_end_p (lsei); lsei_next_in_partition (&lsei)) { - symtab_node *node = lsei_node (lsei); - fprintf (symtab->dump_file, "%s ", node->dump_asm_name ()); + symtab_node *node = dyn_cast<symtab_node*> (lsei_node (lsei)); + if (node) + fprintf (symtab->dump_file, "%s ", node->dump_asm_name ()); } fprintf (symtab->dump_file, "\n Symbols in boundary: "); for (lsei = lsei_start (part->encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node *node = lsei_node (lsei); + symtab_node *node = dyn_cast<symtab_node*> (lsei_node (lsei)); + if (!node) + continue; if (!lto_symtab_encoder_in_partition_p (part->encoder, node)) { fprintf (symtab->dump_file, "%s ", node->dump_asm_name ()); diff --git a/gcc/m2/ChangeLog b/gcc/m2/ChangeLog index 155c082..bb307bb 100644 --- a/gcc/m2/ChangeLog +++ b/gcc/m2/ChangeLog @@ -1,3 +1,24 @@ +2025-10-30 Gaius Mulley <gaiusmod2@gmail.com> + + PR modula2/122485 + * gm2-compiler/M2Comp.mod (Pass0CheckDef): Add spell check + format specifier filtering on module names. + * gm2-compiler/M2MetaError.mod (errorBlock): New field + filterDef. + (initErrorBlock): Initialize filterDef. + (continuation): Add 'D' filter on definition module specifier. + (SpellHint): Rewrite to check for filterDef and defimp symbols. + (FilterOnDefinitionModule): New procedure. + * gm2-compiler/M2Quads.mod (BuildSizeFunction): Rewrite to + ensure variables are initialized. + * gm2-compiler/M2StackSpell.def (GetDefModuleSpellHint): New + procedure function. + * gm2-compiler/M2StackSpell.mod (GetDefModuleSpellHint): New + procedure function. + (CandidatePushName): New procedure. + (BuildHintStr): New procedure. + (CheckForHintStr): Rewrite. + 2025-10-24 Gaius Mulley <gaiusmod2@gmail.com> PR modula2/122407 diff --git a/gcc/m2/gm2-compiler/M2Comp.mod b/gcc/m2/gm2-compiler/M2Comp.mod index 741daeb..0190e01 100644 --- a/gcc/m2/gm2-compiler/M2Comp.mod +++ b/gcc/m2/gm2-compiler/M2Comp.mod @@ -851,12 +851,11 @@ BEGIN MergeDeps (DepContent, ChildDep, LibName) ELSE (* Unrecoverable error. *) - MetaErrorString1 (Sprintf1 (InitString ('file {%%1EUAF%s} containing module {%%1a} cannot be found'), + MetaErrorString1 (Sprintf1 (InitString ('file {%%1EUAF%s} containing module {%%1a} cannot be found {%%1&Ds}'), FileName), sym) END ELSE - (* Unrecoverable error. *) - MetaError1 ('the file containing the definition module {%1EMAa} cannot be found', sym) + MetaError1 ('the file containing the definition module {%1EMAa} cannot be found {%1&Ds}', sym) END ; ModuleType := Implementation ELSE @@ -928,15 +927,15 @@ BEGIN qprintf0 ('\n') ; CloseSource ELSE - (* It is quite legitimate to implement a module in C (and pretend it was a M2 + (* It is legitimate to implement a module in C (and pretend it was a M2 implementation) providing that it is not the main program module and the definition module does not declare a hidden type when -fextended-opaque is used. *) IF (NOT WholeProgram) OR (sym = Main) OR IsHiddenTypeDeclared (sym) THEN (* Unrecoverable error. *) - MetaErrorString1 (Sprintf1 (InitString ('file {%%1EUAF%s} containing module {%%1a} cannot be found'), - FileName), sym) ; + MetaErrorString1 (Sprintf1 (InitString ('file {%%1EUAF%s} containing module {%%1a} cannot be found {%%1&Ds}'), + FileName), sym) END END END diff --git a/gcc/m2/gm2-compiler/M2MetaError.mod b/gcc/m2/gm2-compiler/M2MetaError.mod index aae0f02..22a1557 100644 --- a/gcc/m2/gm2-compiler/M2MetaError.mod +++ b/gcc/m2/gm2-compiler/M2MetaError.mod @@ -42,7 +42,6 @@ FROM SYSTEM IMPORT ADDRESS ; FROM M2Error IMPORT MoveError ; FROM M2Debug IMPORT Assert ; FROM Storage IMPORT ALLOCATE ; -FROM M2StackSpell IMPORT GetSpellHint ; FROM Indexing IMPORT Index, InitIndex, KillIndex, GetIndice, PutIndice, DeleteIndice, HighIndice ; @@ -74,6 +73,7 @@ IMPORT M2Error ; IMPORT FilterError ; FROM FilterError IMPORT Filter, AddSymError, IsSymError ; +FROM M2StackSpell IMPORT GetDefModuleSpellHint, GetSpellHint ; CONST @@ -100,6 +100,7 @@ TYPE len, ini : INTEGER ; vowel, + filterDef, importHint, exportHint, withStackHint, @@ -533,6 +534,7 @@ BEGIN ini := 0 ; glyph := FALSE ; (* Nothing to output yet. *) vowel := FALSE ; (* Check for a vowel when outputing string? *) + filterDef := FALSE ; (* Filter on definition module list? *) importHint := FALSE; exportHint := FALSE ; withStackHint := FALSE ; @@ -1840,7 +1842,7 @@ END op ; (* - continuation := {':'|'1'|'2'|'3'|'4'|'i'|'s'|'x'|'w'} =: + continuation := {':'|'1'|'2'|'3'|'4'|'i'|'s'|'x'|'w'|'D'} =: *) PROCEDURE continuation (VAR eb: errorBlock; @@ -1860,7 +1862,8 @@ BEGIN 'i': AddImportsHint (eb) | 's': SpellHint (eb, sym, bol) | 'x': AddExportsHint (eb) | - 'w': AddWithStackHint (eb) + 'w': AddWithStackHint (eb) | + 'D': FilterOnDefinitionModule (eb) ELSE InternalFormat (eb, 'expecting one of [:1234isxw]', @@ -1956,9 +1959,15 @@ END JoinSentances ; PROCEDURE SpellHint (VAR eb: errorBlock; sym: ARRAY OF CARDINAL; bol: CARDINAL) ; BEGIN - IF (bol <= HIGH (sym)) AND IsUnknown (sym[bol]) + IF bol <= HIGH (sym) THEN - JoinSentances (eb, GetSpellHint (sym[bol])) + IF eb.filterDef AND IsDefImp (sym[bol]) + THEN + JoinSentances (eb, GetDefModuleSpellHint (sym[bol])) + ELSIF IsUnknown (sym[bol]) + THEN + JoinSentances (eb, GetSpellHint (sym[bol])) + END END END SpellHint ; @@ -1994,6 +2003,16 @@ END AddWithStackHint ; (* + FilterOnDefinitionModule - turn on filtering and include all the definition modules. +*) + +PROCEDURE FilterOnDefinitionModule (VAR eb: errorBlock) ; +BEGIN + eb.filterDef := TRUE +END FilterOnDefinitionModule ; + + +(* changeColor - changes to color, c. *) diff --git a/gcc/m2/gm2-compiler/M2Quads.mod b/gcc/m2/gm2-compiler/M2Quads.mod index 5ceeb4f..a263ce3 100644 --- a/gcc/m2/gm2-compiler/M2Quads.mod +++ b/gcc/m2/gm2-compiler/M2Quads.mod @@ -10697,44 +10697,43 @@ BEGIN NoOfParam) ; resulttok := functok ; ReturnVar := MakeConstLit (resulttok, MakeKey('0'), Cardinal) - ELSIF IsAModula2Type (OperandT (1)) - THEN - paramtok := OperandTok (1) ; - resulttok := MakeVirtualTok (functok, functok, paramtok) ; - BuildSizeCheckEnd (ProcSym) ; (* Quadruple generation now on. *) - ReturnVar := MakeTemporary (resulttok, ImmediateValue) ; - GenQuadO (resulttok, SizeOp, ReturnVar, NulSym, OperandT(1), TRUE) - ELSIF IsVar (OperandT (1)) - THEN - BuildSizeCheckEnd (ProcSym) ; (* Quadruple generation now on. *) - Type := GetSType (OperandT (1)) ; + ELSE paramtok := OperandTok (1) ; resulttok := MakeVirtualTok (functok, functok, paramtok) ; - IF IsUnbounded (Type) + IF IsAModula2Type (OperandT (1)) THEN - (* Eg. SIZE(a) ; where a is unbounded dereference HIGH and multiply by the TYPE. *) - dim := OperandD (1) ; - IF dim = 0 + BuildSizeCheckEnd (ProcSym) ; (* Quadruple generation now on. *) + ReturnVar := MakeTemporary (resulttok, ImmediateValue) ; + GenQuadO (resulttok, SizeOp, ReturnVar, NulSym, OperandT(1), TRUE) + ELSIF IsVar (OperandT (1)) + THEN + BuildSizeCheckEnd (ProcSym) ; (* Quadruple generation now on. *) + Type := GetSType (OperandT (1)) ; + IF IsUnbounded (Type) THEN - ReturnVar := calculateMultipicand (resulttok, OperandT (1), Type, dim) + (* Eg. SIZE(a) ; where a is unbounded dereference HIGH and multiply by the TYPE. *) + dim := OperandD (1) ; + IF dim = 0 + THEN + ReturnVar := calculateMultipicand (resulttok, OperandT (1), Type, dim) + ELSE + ReturnVar := calculateMultipicand (resulttok, OperandA (1), Type, dim) + END ELSE - ReturnVar := calculateMultipicand (resulttok, OperandA (1), Type, dim) + ReturnVar := MakeTemporary (resulttok, ImmediateValue) ; + IF Type = NulSym + THEN + MetaErrorT1 (resulttok, + 'cannot get the type and size of {%1Ead}', OperandT (1)) + END ; + GenQuadO (resulttok, SizeOp, ReturnVar, NulSym, Type, TRUE) END ELSE - ReturnVar := MakeTemporary (resulttok, ImmediateValue) ; - IF Type = NulSym - THEN - MetaErrorT1 (resulttok, - 'cannot get the type and size of {%1Ead}', OperandT (1)) - END ; - GenQuadO (resulttok, SizeOp, ReturnVar, NulSym, Type, TRUE) + MetaErrorT1 (paramtok, + '{%E}SYSTEM procedure {%kSIZE} expects a variable or type as its parameter, seen {%1Ed} {%1&s}', + OperandT (1)) ; + ReturnVar := MakeConstLit (paramtok, MakeKey('0'), Cardinal) END - ELSE - paramtok := OperandTok (1) ; - MetaErrorT1 (paramtok, - '{%E}SYSTEM procedure {%kSIZE} expects a variable or type as its parameter, seen {%1Ed} {%1&s}', - OperandT (1)) ; - ReturnVar := MakeConstLit (resulttok, MakeKey('0'), Cardinal) END ; PopN (NoOfParam+1) ; (* Destroy the arguments and function. *) PushTFtok (ReturnVar, GetSType(ProcSym), resulttok) diff --git a/gcc/m2/gm2-compiler/M2StackSpell.def b/gcc/m2/gm2-compiler/M2StackSpell.def index 7c1d00b..c45074a 100644 --- a/gcc/m2/gm2-compiler/M2StackSpell.def +++ b/gcc/m2/gm2-compiler/M2StackSpell.def @@ -59,4 +59,14 @@ PROCEDURE GetRecordField (tokno: CARDINAL; fieldName: Name) : CARDINAL ; +(* + GetDefModuleSpellHint - return a string describing a spelling + hint for the definition module name + similiar to unknown. NIL is returned + if no hint can be given. +*) + +PROCEDURE GetDefModuleSpellHint (defimp: CARDINAL) : String ; + + END M2StackSpell. diff --git a/gcc/m2/gm2-compiler/M2StackSpell.mod b/gcc/m2/gm2-compiler/M2StackSpell.mod index 7a072ae..ac58c1c 100644 --- a/gcc/m2/gm2-compiler/M2StackSpell.mod +++ b/gcc/m2/gm2-compiler/M2StackSpell.mod @@ -31,7 +31,7 @@ FROM SymbolTable IMPORT NulSym, IsModule, IsDefImp, IsRecord, FROM SymbolKey IMPORT PerformOperation ; FROM DynamicStrings IMPORT InitStringCharStar, InitString, Mark, string, ConCat ; FROM FormatStrings IMPORT Sprintf1, Sprintf2, Sprintf3 ; -FROM NameKey IMPORT KeyToCharStar ; +FROM NameKey IMPORT KeyToCharStar, NulName ; FROM M2MetaError IMPORT MetaErrorStringT0 ; FROM M2StackWord IMPORT StackOfWord, PushWord, PopWord, @@ -39,6 +39,7 @@ FROM M2StackWord IMPORT StackOfWord, PushWord, PopWord, NoOfItemsInStackWord, PeepWord ; FROM CDataTypes IMPORT ConstCharStar ; +FROM M2Batch IMPORT GetModuleNo ; IMPORT m2spellcheck ; FROM m2spellcheck IMPORT Candidates ; @@ -97,6 +98,60 @@ END GetRecordField ; (* + CandidatePushName - push a symbol name to the candidate list. +*) + +PROCEDURE CandidatePushName (cand: Candidates; sym: CARDINAL) ; +VAR + str: String ; +BEGIN + str := InitStringCharStar (KeyToCharStar (GetSymName (sym))) ; + m2spellcheck.Push (cand, string (str)) ; + INC (PushCount) +END CandidatePushName ; + + +(* + GetDefModuleSpellHint - return a string describing a spelling + hint for the definition module name + similiar to defimp. The premise is that + defimp has been misspelt. NIL is returned + if no hint can be given. +*) + +PROCEDURE GetDefModuleSpellHint (defimp: CARDINAL) : String ; +VAR + i : CARDINAL ; + sym : CARDINAL ; + cand : Candidates ; + misspell, + content : ConstCharStar ; + HintStr : String ; +BEGIN + HintStr := NIL ; + IF GetSymName (defimp) # NulName + THEN + misspell := KeyToCharStar (GetSymName (defimp)) ; + i := 1 ; + sym := GetModuleNo (i) ; + cand := m2spellcheck.InitCandidates () ; + WHILE sym # NulSym DO + IF sym # defimp + THEN + CandidatePushName (cand, sym) + END ; + INC (i) ; + sym := GetModuleNo (i) + END ; + content := m2spellcheck.FindClosestCharStar (cand, misspell) ; + HintStr := BuildHintStr (HintStr, content) ; + m2spellcheck.KillCandidates (cand) + END ; + RETURN AddPunctuation (HintStr, '?') +END GetDefModuleSpellHint ; + + +(* Push - push a scope onto the spelling stack. sym might be a ModSym, DefImpSym or a varsym of a record type denoting a with statement. @@ -184,6 +239,30 @@ END PushCandidates ; (* + BuildHintStr - create the did you mean hint and return it + if HintStr is NIL. Otherwise append a hint + to HintStr. If content is NIL then return NIL. +*) + +PROCEDURE BuildHintStr (HintStr: String; content: ConstCharStar) : String ; +VAR + str: String ; +BEGIN + IF content # NIL + THEN + str := InitStringCharStar (content) ; + IF HintStr = NIL + THEN + RETURN Sprintf1 (Mark (InitString (", did you mean %s")), str) + ELSE + RETURN Sprintf2 (Mark (InitString ("%s or %s")), HintStr, str) + END + END ; + RETURN NIL +END BuildHintStr ; + + +(* CheckForHintStr - lookup a spell hint matching misspelt. If one exists then append it to HintStr. Return HintStr. *) @@ -193,7 +272,6 @@ PROCEDURE CheckForHintStr (sym: CARDINAL; VAR cand : Candidates ; content: ConstCharStar ; - str : String ; BEGIN IF IsModule (sym) OR IsDefImp (sym) OR IsProcedure (sym) OR IsRecord (sym) OR IsEnumeration (sym) @@ -206,16 +284,7 @@ BEGIN content := NIL END ; m2spellcheck.KillCandidates (cand) ; - IF content # NIL - THEN - str := InitStringCharStar (content) ; - IF HintStr = NIL - THEN - RETURN Sprintf1 (Mark (InitString (", did you mean %s")), str) - ELSE - RETURN Sprintf2 (Mark (InitString ("%s or %s")), HintStr, str) - END - END + HintStr := BuildHintStr (HintStr, content) END ; RETURN HintStr END CheckForHintStr ; diff --git a/gcc/match.pd b/gcc/match.pd index 00493d6..6aaf80e 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -5658,10 +5658,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* Squash view_converts of BFRs if no precision is lost. */ (simplify - (view_convert (BIT_FIELD_REF @1 @2 @3)) + (view_convert (BIT_FIELD_REF@0 @1 @2 @3)) (if (is_gimple_reg_type (type) && (!INTEGRAL_TYPE_P (type) - || type_has_mode_precision_p (type))) + || !INTEGRAL_TYPE_P (TREE_TYPE (@0)) + || (type_has_mode_precision_p (type) + && type_has_mode_precision_p (TREE_TYPE (@0))))) (BIT_FIELD_REF:type @1 @2 @3))) /* For integral conversions with the same precision or pointer @@ -12021,3 +12023,8 @@ and, && direct_internal_fn_supported_p (IFN_AVG_CEIL, type, OPTIMIZE_FOR_BOTH)) (IFN_AVG_CEIL @0 @2))) #endif + +/* vec shift left insert (dup (A), A) -> dup(A) */ +(simplify + (IFN_VEC_SHL_INSERT (vec_duplicate@1 @0) @0) + @1) diff --git a/gcc/range-op-mixed.h b/gcc/range-op-mixed.h index 567b0cd..db31c2b 100644 --- a/gcc/range-op-mixed.h +++ b/gcc/range-op-mixed.h @@ -527,6 +527,47 @@ private: const irange &outer) const; }; + +class operator_view : public range_operator +{ +public: + using range_operator::fold_range; + using range_operator::op1_range; + using range_operator::update_bitmask; + bool fold_range (irange &r, tree type, + const irange &op1, const irange &op2, + relation_trio rel = TRIO_VARYING) const override; + bool fold_range (prange &r, tree type, + const prange &op1, const prange &op2, + relation_trio rel = TRIO_VARYING) const final override; + bool fold_range (irange &r, tree type, + const prange &op1, const irange &op2, + relation_trio rel = TRIO_VARYING) const final override; + bool fold_range (prange &r, tree type, + const irange &op1, const prange &op2, + relation_trio rel = TRIO_VARYING) const final override; + + bool op1_range (irange &r, tree type, + const irange &lhs, const irange &op2, + relation_trio rel = TRIO_VARYING) const override; + bool op1_range (prange &r, tree type, + const prange &lhs, const prange &op2, + relation_trio rel = TRIO_VARYING) const final override; + bool op1_range (irange &r, tree type, + const prange &lhs, const irange &op2, + relation_trio rel = TRIO_VARYING) const final override; + bool op1_range (prange &r, tree type, + const irange &lhs, const prange &op2, + relation_trio rel = TRIO_VARYING) const final override; + + void update_bitmask (irange &r, const irange &lh, + const irange &) const final override; +private: +// VIEW_CONVERT_EXPR works much like a cast between integral values, so use +// the cast operator. Non-integrals are not handled as yet. + operator_cast m_cast; +}; + class operator_plus : public range_operator { public: diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 6b6bf78..cf5b8fe 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -60,6 +60,7 @@ operator_ge op_ge; operator_identity op_ident; operator_cst op_cst; operator_cast op_cast; +operator_view op_view; operator_plus op_plus; operator_abs op_abs; operator_minus op_minus; @@ -97,6 +98,7 @@ range_op_table::range_op_table () set (INTEGER_CST, op_cst); set (NOP_EXPR, op_cast); set (CONVERT_EXPR, op_cast); + set (VIEW_CONVERT_EXPR, op_view); set (FLOAT_EXPR, op_cast); set (FIX_TRUNC_EXPR, op_cast); set (PLUS_EXPR, op_plus); @@ -3247,6 +3249,80 @@ operator_cast::op1_range (irange &r, tree type, return true; } +// VIEW_CONVERT_EXPR works like a cast between integral values. +// If the number of bits are not the same, behaviour is undefined, +// so cast behaviour still works. + +bool +operator_view::fold_range (irange &r, tree type, + const irange &op1, const irange &op2, + relation_trio rel) const +{ + return m_cast.fold_range (r, type, op1, op2, rel); +} + +bool +operator_view::fold_range (prange &r, tree type, + const prange &op1, const prange &op2, + relation_trio rel) const +{ + return m_cast.fold_range (r, type, op1, op2, rel); +} +bool +operator_view::fold_range (irange &r, tree type, + const prange &op1, const irange &op2, + relation_trio rel) const +{ + return m_cast.fold_range (r, type, op1, op2, rel); +} + +bool +operator_view::fold_range (prange &r, tree type, + const irange &op1, const prange &op2, + relation_trio rel) const +{ + return m_cast.fold_range (r, type, op1, op2, rel); +} + +bool +operator_view::op1_range (irange &r, tree type, + const irange &lhs, const irange &op2, + relation_trio rel) const +{ + return m_cast.op1_range (r, type, lhs, op2, rel); +} + +bool +operator_view::op1_range (prange &r, tree type, + const prange &lhs, const prange &op2, + relation_trio rel) const +{ + return m_cast.op1_range (r, type, lhs, op2, rel); +} + +bool +operator_view::op1_range (irange &r, tree type, + const prange &lhs, const irange &op2, + relation_trio rel) const +{ + return m_cast.op1_range (r, type, lhs, op2, rel); +} + +bool +operator_view::op1_range (prange &r, tree type, + const irange &lhs, const prange &op2, + relation_trio rel) const +{ + return m_cast.op1_range (r, type, lhs, op2, rel); +} + +void +operator_view::update_bitmask (irange &r, const irange &lh, + const irange &rh) const +{ + m_cast.update_bitmask (r, lh, rh); +} + class operator_logical_and : public range_operator { diff --git a/gcc/rust/ChangeLog b/gcc/rust/ChangeLog index f960ef2..556ce28 100644 --- a/gcc/rust/ChangeLog +++ b/gcc/rust/ChangeLog @@ -1,3 +1,1446 @@ +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast-pointer-visitor.cc (PointerVisitor::visit): + Handle the expression contained in an ErrorPropagationExpr. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc (visit(TuplePattern)): Update HAS_REST + case to continue to attempt to resolve pattern items after emitting size error. + +2025-10-30 Ryo Yoshida <low.ryoshida@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): Emit + an error when the path refers to an enum itself rather than its variant. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-base.cc (parse_repr_options): Changed TOKEN_TREE + assert into error, update malformed repr attribute error message to be inline + with other attribute error messages. + +2025-10-30 Lucas Ly Ba <lucas.ly-ba@outlook.fr> + + * ast/rust-ast.cc (Attribute::is_derive): + Change string derive to its definition. + * util/rust-attribute-values.h: + Add attribute definition derive. + * util/rust-attributes.cc (AttributeChecker::visit): + Add method check_inner_attributes. + (AttributeChecker::check_inner_attributes): + Check if there is a bad inner attribute. + * util/rust-attributes.h: + Add method check_inner_attributes in .h. + +2025-10-30 lishin <lishin1008@gmail.com> + + * typecheck/rust-tyty-util.cc (TyVar::TyVar): Add null check to avoid ICE. + (TyVar::get_tyty): Return nullptr when lookup fails. + (TyVar::clone): Handle null base type safely. + (TyVar::monomorphized_clone): Add fallback for error types. + +2025-10-30 Ryo Yoshida <low.ryoshida@gmail.com> + + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): check + and properly emit an error when the tuple index is on a non-tuple-struct. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-expr.cc (CompileExpr::array_copied_expr): refactor to new classes + * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit): likewise + (CompilePatternBindings::visit): likewise + * backend/rust-compile-type.cc (TyTyResolveCompile::visit): likewise + * backend/rust-compile-type.h: likewise + * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): likewise + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): likewise + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise + * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): likewise + * typecheck/rust-substitution-mapper.h: likewise + * typecheck/rust-type-util.cc (unify_site_and): remove bad delete (alpine32) + * typecheck/rust-tyty-call.h: refactor to new classes + * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::clone): likewise + (SubstitutionRef::infer_substitions): likewise + * typecheck/rust-tyty-util.cc (TyVar::get_implicit_const_infer_var): likewise + * typecheck/rust-tyty-util.h: likewise + * typecheck/rust-tyty-variance-analysis-private.h: likewise + * typecheck/rust-tyty-visitor.h: likewise + * typecheck/rust-tyty.cc (BaseType::destructure): likewise + (BaseType::monomorphized_clone): likewise + (BaseType::is_concrete): likewise + (VariantDef::clone): likewise + (VariantDef::monomorphized_clone): likewise + (ArrayType::as_string): likewise + (ArrayType::get_capacity): likewise + (ArrayType::handle_substitions): likewise + (generate_tree_str): likewise + (ConstType::ConstType): likewise + (ConstParamType::ConstParamType): likewise + (ConstType::accept_vis): likewise + (ConstParamType::const_kind): likewise + (ConstParamType::get_symbol): likewise + (ConstParamType::can_resolve): likewise + (ConstParamType::resolve): likewise + (ConstParamType::accept_vis): likewise + (ConstType::set_value): likewise + (ConstType::as_string): likewise + (ConstParamType::as_string): likewise + (ConstType::clone): likewise + (ConstParamType::clone): likewise + (ConstType::get_symbol): likewise + (ConstParamType::get_name): likewise + (ConstType::can_resolve): likewise + (ConstParamType::is_equal): likewise + (ConstType::resolve): likewise + (ConstValueType::ConstValueType): likewise + (ConstValueType::const_kind): likewise + (ConstValueType::accept_vis): likewise + (ConstValueType::as_string): likewise + (ConstValueType::clone): likewise + (ConstValueType::get_name): likewise + (ConstValueType::is_equal): likewise + (ConstValueType::get_value): likewise + (ConstInferType::ConstInferType): likewise + (ConstInferType::const_kind): likewise + (ConstInferType::accept_vis): likewise + (ConstType::get_name): likewise + (ConstInferType::as_string): likewise + (ConstInferType::clone): likewise + (ConstInferType::get_name): likewise + (ConstType::is_equal): likewise + (ConstInferType::is_equal): likewise + (ConstErrorType::ConstErrorType): likewise + (ConstErrorType::const_kind): likewise + (ConstType::handle_substitions): likewise + (ConstErrorType::accept_vis): likewise + (ConstErrorType::as_string): likewise + (ConstErrorType::clone): likewise + (ConstErrorType::get_name): likewise + (ConstErrorType::is_equal): likewise + * typecheck/rust-tyty.h (class BaseConstType): likewise + (class ConstType): likewise + (class ConstParamType): likewise + (class ConstValueType): likewise + (class ConstInferType): likewise + (class ConstErrorType): likewise + * typecheck/rust-unify.cc (UnifyRules::commit): likewise + (UnifyRules::go): likewise + (UnifyRules::expect_array): likewise + (UnifyRules::expect_const): likewise + * typecheck/rust-unify.h: likewise + +2025-10-30 0xllx0 <github+elle@weathered-steel.dev> + + * ast/rust-ast.cc (Module::process_file_path): empty module early return + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * util/rust-attributes.cc (check_doc_attribute): Change message. + (AttributeChecker::visit): Add doc attribute checking on traits. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast.cc (AttrInputMetaItemContainer::separate_cfg_attrs): + Avoid malformed attributes. + * util/rust-attributes.cc (AttributeChecker::visit): Change location. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-expr.h: Force crash when retrieving locus. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast.h: Add missing override modifier. + * ast/rust-path.h: Likewise. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * util/rust-attributes.cc (AttributeChecker::check_attribute): Recurse + within attr input for additional attribute checking. + (AttributeChecker::visit): Remove empty definition in favor of default + ast visitor definition. + * util/rust-attributes.h: Remove now unused prototypes. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc (visit(TupleStructPattern)): + Update error for mismatched number of fields to use rich_location. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-pattern.cc: Add compilation support for TupleStructItemsHasRest + in CompilePatternCheckExpr(TupleStructPattern) & CompilePatternBindings(TupleStructPattern) + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit(TupleStructPattern)): + Implement lowering of AST::TupleStructItemsHasRest to HIR. + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(TupleStructPattern)): + Add the respective type checking for AST::TupleStructItemsHasRest + * checks/errors/rust-hir-pattern-analysis.cc (lower_tuple_pattern): + Add respective pattern for HAS_REST case. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc (visit(StructPattern)): Add type check + support for StructPatterns matching against a TUPLE type ADT. + * backend/rust-compile-pattern.cc(CompilePatternBindings::visit(StructPattern)): + Update assert to allow TUPLE type ADTs. + * hir/tree/rust-hir.cc (StructPatternField::as_string()): Improve info dumped. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * ast/rust-pattern.h (StructPatternElements): Rename has_struct_pattern_etc + to has_rest_pattern, and has_etc to has_rest to signify presense of rest + patterns more clearly. + * ast/rust-pattern.cc (StructPatternElements::as_string): Rename variables + accordingly. + * ast/rust-ast-collector.cc: Rename variables accordingly. + * expand/rust-cfg-strip.cc: Rename variables accordingly. + * parse/rust-parse-impl.h: Rename variable accordingly. + * hir/tree/rust-hir-pattern.h (StructPatternElements): Add a boolean to track + presense of rest pattern. + * hir/rust-ast-lower-pattern.cc (visit(StructPattern)): Add support for + lowering rest pattern to HIR. + * typecheck/rust-hir-type-check-pattern.cc (visit(StructPattern)): Remove + size check when rest pattern is present. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * backend/rust-compile-extern.h: Add includes. + (CompileExternItem::visit): Use get_link_name. + (CompileExternItem::get_link_name): New static member function. + * util/rust-attribute-values.h (Attributes::LINK_NAME): New + static constexpr member variable. + * util/rust-attributes.cc (__definitions): New entry for + LINK_NAME. + * util/rust-ggc.cc: Include "rust-ast.h". + (Ident::Ident): Add overload for Rust::Identifier. + * util/rust-ggc.h (class Identifier): Forward declare. + (Ident::Ident): Add overload for Rust::Identifier. + +2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com> + + * expand/rust-expand-visitor.cc: Remove old visitors. + * expand/rust-expand-visitor.h: Likewise, plus inherit from PointerVisitor. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-expand.cc: Forward invocation tree locus to + substitution context. + * expand/rust-macro-substitute-ctx.cc: Use origin location for expanded + tokens. + * expand/rust-macro-substitute-ctx.h (class SubstituteCtx): Save + invocation location. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-expand.cc (transcribe_expression): Emit error + early. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-substitute-ctx.cc (is_builtin_metavariable): Add + function to check builtin metavars knowledge. + (SubstituteCtx::check_repetition_amount): Do not process missing + fragment. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-resolve-path.cc: add error diag + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): add error diagnostic + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): check for error + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-expr.cc: remove old hack + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): handle fnptr + * typecheck/rust-tyty.cc (FnPtr::handle_substitions): new + * typecheck/rust-tyty.h: likewise + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-fmt.h (class FFIOpt): Adjust internal structure to + match a repr(C) rust enum. + +2025-10-30 Magnus-Mage <romescha123@gmail.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Implement + FormatArgs visitor to reconstruct format_args! macro syntax. + * ast/rust-builtin-ast-nodes.h (FormatArguments): Add get_args(), + size(), and empty() accessor methods. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): check for invalid capacity + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-constexpr.cc (eval_constant_expression): port over missing bits + (eval_store_expression): likewise + (eval_call_expression): likewise + (eval_binary_expression): likewise + (eval_bit_field_ref): likewise + (eval_check_shift_p): likewise + (fold_pointer_plus_expression): likewise + (maybe_fold_addr_pointer_plus): likewise + (fold_expr): likewise + (union_active_member): likewise + (fold_indirect_ref_1): likewise + (rs_fold_indirect_ref): likewise + (rs_eval_indirect_ref): likewise + (eval_logical_expression): likewise + (eval_vector_conditional_expression): likewise + (eval_bare_aggregate): likewise + (cxx_eval_trinary_expression): likewise + (eval_and_check_array_index): likewise + (eval_array_reference): likewise + (eval_component_reference): likewise + (rs_bind_parameters_in_call): likewise + (eval_builtin_function_call): likewise + (constexpr_fn_retval): likewise + (verify_constant): likewise + (get_array_or_vector_nelts): likewise + (eval_conditional_expression): likewise + (eval_switch_expr): likewise + (eval_unary_expression): likewise + (cxx_eval_outermost_constant_expr): likewise + (potential_constant_expression_1): likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-expr.cc (CompileExpr::compile_integer_literal): cleanup + * backend/rust-constexpr.cc (struct constexpr_global_ctx): port over c++ helpers + (decl_really_constant_value): likewise + (eval_constant_expression): likewise + (non_const_var_error): likewise + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h (Parser::parse_pattern): Ignore + inner patterns which fail to parse. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Remove + overload for TraitItemConst. + * ast/rust-ast-collector.h (TokenCollector::visit): Likewise. + * ast/rust-ast-pointer-visitor.cc (PointerVisitor::visit): + Likewise. + * ast/rust-ast-pointer-visitor.h (PointerVisitor::visit): + Likewise. + * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. + * ast/rust-ast-visitor.h (ASTVisitor::visit): Likewise. + (DefaultASTVisitor::visit): Likewise. + * expand/rust-cfg-strip.cc (CfgStrip::visit): Likewise. + * expand/rust-cfg-strip.h (CfgStrip::visit): Likewise. + * expand/rust-derive.h (DeriveVisitor::visit): Likewise. + * expand/rust-expand-visitor.cc (ExpandVisitor::visit): + Likewise. + * expand/rust-expand-visitor.h (ExpandVisitor::visit): Likewise. + * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise. + * hir/rust-ast-lower-base.h (ASTLoweringBase::visit): Likewise. + * util/rust-attributes.cc (AttributeChecker::visit): Likewise. + * util/rust-attributes.h (AttributeChecker::visit): Likewise. + * ast/rust-ast.cc (ConstantItem::as_string): Handle missing + expression. + (TraitItemConst::as_string): Remove function definition. + (TraitItemConst::accept_vis): Remove function definition. + * ast/rust-item.h (ConstantItem::mark_for_strip): Adjust + comment. + (ConstantItem::has_expr): Make const. + (class TraitItemConst): Remove definition. + * ast/rust-ast-full-decls.h (class TraitItemConst): Remove + declaration. + * hir/rust-ast-lower-implitem.cc (ASTLowerTraitItem::visit): + Handle ConstantItem instead of TraitItemConst. + * hir/rust-ast-lower-implitem.h (ASTLowerTraitItem::visit): + Likewise. + * parse/rust-parse-impl.h (Parser::parse_trait_const): Return + pointer to ConstantItem instead of TraitItemConst. + * parse/rust-parse.h (Parser::parse_trait_const): Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * Make-lang.in: Handle source files in checks/errors/feature. + * checks/errors/rust-feature-gate.cc: Move to... + * checks/errors/feature/rust-feature-gate.cc: ...here. + * checks/errors/rust-feature-gate.h: Move to... + * checks/errors/feature/rust-feature-gate.h: ...here. + * checks/errors/rust-feature.cc: Move to... + * checks/errors/feature/rust-feature.cc: ...here. + * checks/errors/rust-feature.h: Move to... + * checks/errors/feature/rust-feature.h: ...here. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * Make-lang.in (GRS_OBJS): Remove rust-early-name-resolver.o. + * expand/rust-macro-builtins-helpers.h: Remove inclusion of + rust-early-name-resolver.h. + * expand/rust-macro-builtins.cc: Likewise. + * expand/rust-macro-expand.cc: Likewise. + * expand/rust-macro-expand.h: Likewise. + * resolve/rust-early-name-resolver.cc: Removed. + * resolve/rust-early-name-resolver.h: Removed. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * hir/tree/rust-hir-item.h: add unsafe helper + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): pass in abi and unsafe + * typecheck/rust-tyty.cc (BaseType::monomorphized_clone): likewise + (FnPtr::as_string): emit more info + (FnPtr::clone): update ctor call + * typecheck/rust-tyty.h: new ctor params + * typecheck/rust-unify.cc (UnifyRules::expect_fnptr): check abi and unsafe + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (UnifyRules::expect_reference): remove clone + (UnifyRules::expect_pointer): likewise + (UnifyRules::expect_slice): likewise + (UnifyRules::expect_tuple): likewise + (UnifyRules::expect_int): likewise + (UnifyRules::expect_uint): likewise + (UnifyRules::expect_float): likewise + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * Make-lang.in (GRS_OBJS): Remove entries. + * rust-lang.cc: Remove inclusion of "rust-ast-resolve-item.h". + (run_rust_tests): Remove call to rust_simple_path_resolve_test. + * resolve/rust-ast-resolve-base.cc: Removed. + * resolve/rust-ast-resolve-base.h: Removed. + * resolve/rust-ast-resolve-expr.cc: Removed. + * resolve/rust-ast-resolve-expr.h: Removed. + * resolve/rust-ast-resolve-implitem.h: Removed. + * resolve/rust-ast-resolve-item.cc: Removed. + * resolve/rust-ast-resolve-item.h: Removed. + * resolve/rust-ast-resolve-path.cc: Removed. + * resolve/rust-ast-resolve-path.h: Removed. + * resolve/rust-ast-resolve-pattern.cc: Removed. + * resolve/rust-ast-resolve-pattern.h: Removed. + * resolve/rust-ast-resolve-stmt.cc: Removed. + * resolve/rust-ast-resolve-stmt.h: Removed. + * resolve/rust-ast-resolve-struct-expr-field.cc: Removed. + * resolve/rust-ast-resolve-struct-expr-field.h: Removed. + * resolve/rust-ast-resolve-toplevel.h: Removed. + * resolve/rust-ast-resolve-type.cc: Removed. + * resolve/rust-ast-resolve-type.h: Removed. + * resolve/rust-ast-resolve.cc: Removed. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Use + resolve_type_path_like in overloads for TypePath, + StructExprStruct, StructExprStructBase, and + StructExprStructFields. + (resolve_type_path_like): New static function based off + Late::visit overload for TypePath. + * util/rust-unwrap-segment.h (unwrap_segment_error_string): New + inline static function definitions. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-expr.cc (CompileExpr::visit): add guard + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-context.h: add assertions for context peeks + * backend/rust-compile-expr.cc (CompileExpr::visit): check for valid loop context + (CompileExpr::array_copied_expr): just reuse array tyty capacity value + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): catch error + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * checks/errors/rust-readonly-check.cc (collect_assignment_tuple): Implement + read-only checker for tuple patterns with rest pattern. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-var-decl.h (CompileVarDecl::visit(TuplePattern)): Implement + variable declaration bindings for tuple patterns with rest pattern (i.e. + TuplePatternItemsHasRest). + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * util/rust-attribute-values.h + (Attributes::RUSTC_ALLOW_CONST_FN_UNSTABLE): New static + constexpr member variable. + * util/rust-attributes.cc (__definitions): Add entry for + RUSTC_ALLOW_CONST_FN_UNSTABLE. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (UnifyRules::commit): commit hook update + (UnifyRules::go): insert implicit infer const types + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (UnifyRules::go): unwrap the const type + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-type-check-base.cc (walk_types_to_constrain): track the ref as well + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty-subst.cc: const generic arguments dont have a value yet + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty.cc (VariantDef::clone): fix formatting + (VariantDef::monomorphized_clone): likewise + * typecheck/rust-tyty.h: likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty.cc (InferType::can_eq): remove + (ErrorType::can_eq): likewise + (ADTType::can_eq): likewise + (TupleType::can_eq): likewise + (FnType::can_eq): likewise + (FnPtr::can_eq): likewise + (ClosureType::can_eq): likewise + (ArrayType::can_eq): likewise + (SliceType::can_eq): likewise + (BoolType::can_eq): likewise + (IntType::can_eq): likewise + (UintType::can_eq): likewise + (FloatType::can_eq): likewise + (USizeType::can_eq): likewise + (ISizeType::can_eq): likewise + (CharType::can_eq): likewise + (ReferenceType::can_eq): likewise + (PointerType::can_eq): likewise + (ParamType::can_eq): likewise + (ConstType::can_eq): likewise + (OpaqueType::can_eq): likewise + (StrType::can_eq): likewise + (NeverType::can_eq): likewise + (PlaceholderType::can_eq): likewise + (ProjectionType::can_eq): likewise + (DynamicObjectType::can_eq): likewise + * typecheck/rust-tyty.h: remove can_eq + * typecheck/rust-tyty-cmp.h: Removed. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty.cc (ParamType::is_equal): uses types_compatable + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (unify_error_type_node): new static node + (UnifyRules::go): likewise + (UnifyRules::expect_inference_variable): likewise + (UnifyRules::expect_adt): likewise + (UnifyRules::expect_str): likewise + (UnifyRules::expect_reference): likewise + (UnifyRules::expect_pointer): likewise + (UnifyRules::expect_param): likewise + (UnifyRules::expect_array): likewise + (UnifyRules::expect_slice): likewise + (UnifyRules::expect_fndef): likewise + (UnifyRules::expect_fnptr): likewise + (UnifyRules::expect_tuple): likewise + (UnifyRules::expect_bool): likewise + (UnifyRules::expect_char): likewise + (UnifyRules::expect_int): likewise + (UnifyRules::expect_uint): likewise + (UnifyRules::expect_float): likewise + (UnifyRules::expect_isize): likewise + (UnifyRules::expect_usize): likewise + (UnifyRules::expect_never): likewise + (UnifyRules::expect_placeholder): likewise + (UnifyRules::expect_projection): likewise + (UnifyRules::expect_dyn): likewise + (UnifyRules::expect_closure): likewise + (UnifyRules::expect_opaque): likewise + (UnifyRules::expect_const): likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (UnifyRules::Resolve): check for success + (UnifyRules::expect_inference_variable): dont clone + (UnifyRules::expect_adt): likewise + (UnifyRules::expect_str): likewise + (UnifyRules::expect_reference): likewise + (UnifyRules::expect_pointer): likewise + (UnifyRules::expect_param): likewise + (UnifyRules::expect_array): likewise + (UnifyRules::expect_slice): likewise + (UnifyRules::expect_fndef): likewise + (UnifyRules::expect_fnptr): likewise + (UnifyRules::expect_tuple): likewise + (UnifyRules::expect_bool): likewise + (UnifyRules::expect_char): likewise + (UnifyRules::expect_int): likewise + (UnifyRules::expect_uint): likewise + (UnifyRules::expect_float): likewise + (UnifyRules::expect_isize): likewise + (UnifyRules::expect_usize): likewise + (UnifyRules::expect_never): likewise + (UnifyRules::expect_placeholder): likewise + (UnifyRules::expect_projection): likewise + (UnifyRules::expect_dyn): likewise + (UnifyRules::expect_closure): likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-tyty.cc (BaseType::satisfies_bound): use types_compatable instead + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-type-util.cc (types_compatable): add check bounds flag + (unify_site_and): likewise + * typecheck/rust-type-util.h (types_compatable): likewise + (unify_site_and): likewise + * typecheck/rust-tyty-bounds.cc: likewise + * typecheck/rust-unify.cc (UnifyRules::UnifyRules): likewise + (UnifyRules::Resolve): likewise + (UnifyRules::resolve_subtype): likewise + (UnifyRules::go): likewise + * typecheck/rust-unify.h: likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-hir-path-probe.cc (PathProbeType::process_impl_item_candidate): + refactor to types_compatable + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-unify.cc (UnifyRules::expect_inference_variable): dont commit + (UnifyRules::expect_adt): likewise + (UnifyRules::expect_bool): likewise + (UnifyRules::expect_char): likewise + (UnifyRules::expect_int): likewise + (UnifyRules::expect_uint): likewise + (UnifyRules::expect_float): likewise + (UnifyRules::expect_isize): likewise + (UnifyRules::expect_usize): likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * backend/rust-compile-base.h: remove const + * backend/rust-compile-expr.cc: likewise + * backend/rust-compile.cc (HIRCompileBase::coerce_to_dyn_object): likewise + * typecheck/rust-hir-type-bounds.h: likewise + * typecheck/rust-type-util.cc (lookup_associated_impl_block): likewise + * typecheck/rust-type-util.h (lookup_associated_impl_block): likewise + * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::TypeBoundsProbe): likewise + (TypeBoundsProbe::Probe): likewise + * typecheck/rust-tyty-cmp.h: likewise + * typecheck/rust-tyty-subst.cc (SubstitutionRef::monomorphize): likewise + * typecheck/rust-tyty.cc (BaseType::satisfies_bound): likewise + (BaseType::bounds_compatible): likewise + (VariantDef::clone): likewise + (VariantDef::monomorphized_clone): likewise + (OpaqueType::is_equal): likewise + (DynamicObjectType::is_equal): likewise + * typecheck/rust-tyty.h: likewise + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * typecheck/rust-coercion.cc (TypeCoercionRules::select): respect try flag + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-early-name-resolver-2.0.cc (Early::finalize_rebind_import): + Replace assert with early break and remove early return. + (Early::visit): Check for unsuffixed lower self list. + * resolve/rust-early-name-resolver-2.0.h: Add visit function prototype. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-early-name-resolver-2.0.cc (Early::visit): Emit an error + on top level rebind self use declaration. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * Make-lang.in (GRS_OBJS): Add "rust-resolve-builtins.o". + * resolve/rust-late-name-resolver-2.0.cc: Include + "rust-resolve-builtins.h". + (next_node_id): Remove function. + (next_hir_id): Likewise. + (Late::setup_builtin_types): Likewise. + (Late::go): Use Builtins::setup_type_ctx instead of + Late::setup_builtin_types. + * resolve/rust-late-name-resolver-2.0.h + (Late::setup_builtin_types): Remove function. + * rust-session-manager.cc: Include "rust-resolve-builtins.h". + (Session::expansion): Call Builtins::setup_lang_prelude. + * resolve/rust-resolve-builtins.cc: New file. + * resolve/rust-resolve-builtins.h: New file. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h (Parser::left_denotation): Remove + usage of parse_tuple_index_expr_float. + (Parser::parse_closure_expr_pratt): Remove function. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust-session-manager.cc (Session::compile_crate): Move the AST dump + after parser error check. + +2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-expression-yeast.cc (ExpressionYeast::dispatch): Rename to... + (ExpressionYeast::reseat): ...this. + (ExpressionYeast::visit): Remove. + * ast/rust-expression-yeast.h: Inherit from PointerVisitor, override reseat instead + of declaring dispatch. + +2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com> + + * Make-lang.in: Compile it. + * ast/rust-builtin-ast-nodes.h: Add missing methods for getting pointers. + * ast/rust-expr.h: Likewise. + * ast/rust-item.h: Likewise. + * ast/rust-path.h: Likewise. + * ast/rust-pattern.h: Likewise. + * ast/rust-type.h: Likewise. + * ast/rust-ast-pointer-visitor.cc: New file. + * ast/rust-ast-pointer-visitor.h: New file. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-expr.h (class TupleIndexExpr): Store strip information. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * checks/errors/borrowck/rust-bir-builder-internal.h: Remove + inclusion of "rust-name-resolver.h". + (BuilderContext::resolver): Change type to nr2.0 resolver. + (BuilderContext::BuilderContext): Change initialization of + resolver reference. + (AbstractBuilder::resolve_label): Assume name resolution 2.0 is + enabled. + (AbstractBuilder::resolve_variable): Likewise. + (AbstractBuilder::resolve_variable_or_fn): Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * checks/errors/rust-hir-pattern-analysis.cc: Remove inclusion + of "options.h". + (PatternChecker::PatternChecker): Change initialization of + resolver reference. + (PatternChecker::visit): Assume name resolution 2.0 is enabled. + * checks/errors/rust-hir-pattern-analysis.h: Include nr2.0 + header instead of nr1.0 header. + (PatternChecker::resolver): Change type to nr2.0 resolver. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust-session-manager.cc: Remove inclusion of name resolution + 1.0 headers. + (Session::compile_crate): Assume name resolution 2.0 is enabled. + (Session::expansion): Likewise. + (Session::load_extern_crate): Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * checks/errors/privacy/rust-privacy-check.cc: Adjust includes. + (Resolver::resolve): Pass 2.0 name resolution context to + VisibilityResolver and PrivacyReporter. + * checks/errors/privacy/rust-privacy-reporter.cc + (PrivacyReporter::PrivacyReporter): Change type of resolver + parameter. + (is_child_module): Remove static function. + (PrivacyReporter::check_for_privacy_violation): Assume nr2.0 is + enabled and handle removal of is_child_module. + * checks/errors/privacy/rust-privacy-reporter.h: Adjust + includes. + (PrivacyReporter::PrivacyReporter): Change type of resolver + parameter. + (PrivacyReporter::resolver): Change member variable type. + * checks/errors/privacy/rust-visibility-resolver.cc: Adjust + includes. + (VisibilityResolver::VisibilityResolver): Change type of + resolver parameter. + (VisibilityResolver::resolve_module_path): Assume nr2.0 is + enabled. + * checks/errors/privacy/rust-visibility-resolver.h: Adjust + includes. + (VisibilityResolver::VisibilityResolver): Change type of + resolver parameter. + (VisibilityResolver::resolver): Change member variable type. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * ast/rust-pattern.h: + - Add a new base abstract class `PatternItems` which are used by pattern items class + class derivatives for `TuplePattern`, `TupleStructPattern` & `SlicePattern`. + - Standardized the derived class names to have `HasRest` or `NoRest` as suffixes. + - Values for the common `ItemType` enum is updated to `HAS_REST` or `NO_REST`. + * ast/rust-pattern.cc: Renamed the classes accordingly. + * ast/rust-ast-collector.cc: Renamed the classes accordingly. + * ast/rust-ast-collector.h: Renamed the classes accordingly. + * ast/rust-ast-full-decls.h: Renamed the classes accordingly. + * ast/rust-ast-visitor.cc: Renamed the classes accordingly. + * ast/rust-ast-visitor.h: Renamed the classes accordingly. + * ast/rust-desugar-for-loops.cc: Renamed the classes accordingly. + * ast/rust-desugar-question-mark.cc: Renamed the classes accordingly. + * expand/rust-cfg-strip.cc: Renamed the classes accordingly. + * expand/rust-cfg-strip.h: Renamed the classes accordingly. + * expand/rust-derive-clone.cc: Renamed the classes accordingly. + * expand/rust-derive-cmp-common.cc: Renamed the classes accordingly. + * expand/rust-derive-hash.cc: Renamed the classes accordingly. + * expand/rust-derive-ord.cc: Renamed the classes accordingly. + * expand/rust-derive-partial-eq.cc: Renamed the classes accordingly. + * expand/rust-derive.h: Renamed the classes accordingly. + * expand/rust-expand-visitor.cc: Renamed the classes accordingly. + * expand/rust-expand-visitor.h: Renamed the classes accordingly. + * hir/rust-ast-lower-base.cc: Renamed the classes accordingly. + * hir/rust-ast-lower-base.h: Renamed the classes accordingly. + * hir/rust-ast-lower-pattern.cc: Renamed the classes accordingly. + * hir/tree/rust-hir-pattern.h: Renamed the classes accordingly. + * parse/rust-parse-impl.h: Renamed the classes accordingly. + * resolve/rust-ast-resolve-base.cc: Renamed the classes accordingly. + * resolve/rust-ast-resolve-base.h: Renamed the classes accordingly. + * resolve/rust-ast-resolve-pattern.cc: Renamed the classes accordingly. + * util/rust-attributes.cc: Renamed the classes accordingly. + * util/rust-attributes.h: Renamed the classes accordingly. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast-collector.cc (TokenCollector::visit): Use + should_have_str instead of has_str. + * ast/rust-ast.cc (Token::as_string): Likewise. + * expand/rust-macro-builtins-offset-of.cc + (MacroBuiltin::offset_of_handler): Likewise. + * lex/rust-lex.cc (Lexer::dump_and_skip): Likewise. + * ast/rust-ast.h (class Token): Remove dead code. + (Token::has_str): Remove function. + (Token::should_have_str): New function. + * lex/rust-token.cc (Token::get_str): Remove function + definition. + * lex/rust-token.h: Include "rust-diagnostics.h". + (Token::str): Change type from std::unique_ptr<std::string> to + std::string. + (Token::Token): Adjust initialization of str member variable and + the type of the parameter used to initialize it. + (Token::make_identifier): Accept std::string instead of rvalue + reference to std::string. + (Token::make_int): Likewise. + (Token::make_float): Likewise. + (Token::make_string): Likewise. + (Token::make_byte_string): Likewise. + (Token::make_raw_string): Likewise. + (Token::make_inner_doc_comment): Likewise. + (Token::make_outer_doc_comment): Likewise. + (Token::make_lifetime): Likewise. + (Token::get_str): Add definition to function declaration. + (Token::has_str): Remove member function. + (Token::should_have_str): Handle INNER_DOC_COMMENT and + OUTER_DOC_COMMENT. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * expand/rust-macro-builtins-format-args.cc + (format_args_parse_arguments): Split format expression parsing + into... + (format_args_parse_expr): ...a new function here, while handling + eager expansion. + (MacroBuiltin::format_args_handler): Use format_args_parse_expr. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h (Parser::parse_expr): Avoid skipping + or splitting tokens. + (Parser::null_denotation): Assume initial token was not skipped + and adjust function signature to match. Use + parse_path_in_expression instead of + parse_path_in_expression_pratt and handle SCOPE_RESOLUTION. + (Parser::parse_path_in_expression_pratt): Remove function. + * parse/rust-parse.h (null_denotation): Remove initial token + parameter. + (parse_path_in_expression_pratt): Remove function. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Use as + member function. + (TypeCoercionRules::coerce_borrowed_pointer): Likewise. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): + Move nevertype coercion from here... + (TypeCoercionRules::coerce_never): ... to here. + * typecheck/rust-coercion.h: Add function prototype. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Adapt + call to new return type. + (TypeCoercionRules::coerce_unsized): Change error handling. + * typecheck/rust-coercion.h: Update function prototype and add new + CoerceUnsizedError error type. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Refactor + common return statement. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Remove + unused assignment. + * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_segments): + Likewise. + * typecheck/rust-tyty.cc (ParamType::handle_substitions): Likewise. + * typecheck/rust-unify.cc (UnifyRules::go): Likewise. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): + Construct value in place. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-ast-resolve-stmt.cc (ResolveStmt::visit): Remove + unused copy. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * backend/rust-compile-expr.cc (CompileExpr::generate_closure_fntype): + Unwrap the optional. + * backend/rust-compile.cc: Change return type container. Adapt code to + new return type. + * typecheck/rust-hir-dot-operator.cc: Likewise. + * typecheck/rust-hir-path-probe.cc: Likewise. + * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItemWithTrait::visit): + Likewise. + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): + Likewise. + * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::contains_item): + Likewise. + (TypeBoundPredicate::lookup_associated_item): Likewise. + (TypeBoundPredicateItem::get_parent): Likewise. + (TypeBoundPredicate::lookup_associated_type): Likewise. + * typecheck/rust-tyty.cc (BaseType::satisfies_bound): Likewise. + * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::visit): Change + return type. + * typecheck/rust-tyty.h: Likewise. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-casts.cc (TypeCastRules::cast_rules): Authorize + cast from function pointer to integer like type. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * typecheck/rust-hir-type-check-base.cc (walk_type_to_constrain): Walk + through all kind of type to collect ty leaves. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-type.h: Prevent reconstruction on null pointers. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * util/rust-attribute-values.h (Attributes::SIMD_TEST): Remove + static constexpr member variable. + * util/rust-attributes.cc (__definitions): Remove entry for + SIMD_TEST. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h (Parser::parse_identifier_pattern): + Use parse_pattern_no_alt to parse identifier pattern + subpatterns. + (Parser::parse_ident_leading_pattern): Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-fmt.cc (Pieces::collect): Handle changes to ffi + interface. + (Pieces::~Pieces): Remove function definition. + (Pieces::Pieces): Likewise. + (Pieces::operator=): Likewise. + * ast/rust-fmt.h: Include "optional.h". + (rust_ffi_alloc): New extern "C" function declaration. + (rust_ffi_dealloc): Likewise. + (class FFIVec): New class. + (class FFIOpt): Likewise. + (RustHamster::RustHamster): New constructor accepting const + std::string reference. + (struct FormatSpec): Use FFIOpt. + (struct PieceSlice): Remove struct. + (struct RustString): Likewise. + (struct FormatArgsHandle): Likewise. + (collect_pieces): Change function signature. + (clone_pieces): Likewise. + (destroy_pieces): Remove extern "C" function declaration. + (Pieces::~Pieces): Remove function declaration. + (Pieces::operator=): Likewise. + (Pieces::get_pieces): Handle changes to class fields. + (Pieces::Pieces): Remove copy and move constructor declarations, + adjust signature of remaining constructor declaration. + (Pieces::pieces_vector): Remove member variable. + (Pieces::handle): Likewise. + (Pieces::data): Add member variable. + * expand/rust-macro-builtins-asm.cc (expand_inline_asm_strings): + Use references to avoid copying. + +2025-10-30 lishin <lishin1008@gmail.com> + + * backend/rust-compile-pattern.cc (CompilePatternLet::visit): + Handle tuple destructuring containing by-ref. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * hir/tree/rust-hir-pattern.h: Add SlicePatternItems base class and + SlicePatternItemsNoRest/SlicePatternItemsHasRest derived classes. + Update SlicePattern to hold patterns using the new classes. + * hir/tree/rust-hir-full-decls.h: Declare new classes. + * hir/tree/rust-hir.cc: Add visits for new classes. + * hir/tree/rust-hir-visitor.h: Add visits for new classes. + * hir/tree/rust-hir-visitor.cc: Implement visits for new classes. + * hir/rust-hir-dump.h: Add visits for new classes. + * hir/rust-hir-dump.cc: Implement Dump::visit for new classes. + * hir/rust-ast-lower-base.h: Declare new lower_slice_pattern_no_rest/has_rest + methods. + * hir/rust-ast-lower-base.cc: Implement lower_slice_pattern_no_rest/has_rest + to lower AST slice pattern items to HIR. + * hir/rust-ast-lower-pattern.cc: Update ASTLoweringPattern::visit for + SlicePattern to use new lowering methods. + * backend/rust-compile-pattern.cc: Update CompilePatternCheckExpr::visit + and CompilePatternBindings::visit for SlicePattern to handle + SlicePatternItemsNoRest/HasRest. + * checks/errors/borrowck/rust-bir-builder-pattern.cc: Update + PatternBindingBuilder::visit for SlicePattern to iterate members correctly. + * checks/errors/borrowck/rust-bir-builder-struct.h: Add visits for new + classes. + * checks/errors/borrowck/rust-function-collector.h: Add visits for new + classes. + * checks/errors/rust-const-checker.h: Add visits for new classes. + * checks/errors/rust-const-checker.cc: Implement empty visits for new classes. + * checks/errors/rust-hir-pattern-analysis.h: Add visits for new classes. + * checks/errors/rust-hir-pattern-analysis.cc: Implement empty visits for new + classes. + * checks/errors/rust-unsafe-checker.h: Add visits for new classes. + * checks/errors/rust-unsafe-checker.cc: Implement empty visits for new + classes. + * typecheck/rust-hir-type-check-pattern.cc: Update TypeCheckPattern::visit + for SlicePattern to handle SlicePatternItemsNoRest/HasRest. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust-session-manager.cc (Session::compile_crate): Collect lang + items after expansion. + +2025-10-30 Ryutaro Okada <1015ryu88@gmail.com> + + * Make-lang.in: Replace old read-only checker with new implementation. + * checks/errors/rust-readonly-check.cc (ReadonlyChecker::ReadonlyChecker): + Replace old read-only checker with new implementation. + * checks/errors/rust-readonly-check.h: + Replace old read-only checker with new implementation. + * rust-session-manager.cc (Session::compile_crate): + Switch to new read-only checker. + * checks/errors/rust-readonly-check2.cc: Removed. + * checks/errors/rust-readonly-check2.h: Removed. + +2025-10-30 Ryutaro Okada <1015ryu88@gmail.com> + + * checks/errors/rust-readonly-check2.cc (ReadonlyChecker::check_variable): + Read-only check if the variable is mutable type. + (ReadonlyChecker::is_mutable_type): Read-only check if the variable is mutable type. + * checks/errors/rust-readonly-check2.h: Read-only check if the variable is mutable type. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * typecheck/rust-hir-type-check-pattern.cc(ClosureParamInfer(IdentifierPattern)): + Resolve subpattern types for IdentifierPattern. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * backend/rust-compile-pattern.cc(CompilePatternLet::visit(IdentifierPattern)): + Add support for subpatterns. + * backend/rust-compile-var-decl.h(CompileVarDecl::visit(IdentifierPattern)): + Implement compilation for subpatterns. + +2025-10-30 lishin <lishin1008@gmail.com> + + * typecheck/rust-hir-dot-operator.cc (MethodResolver::Select): + Skip asserts by checking candidate type and using early-continue. + (MethodResolver::try_select_predicate_candidates): + Skip invalid candidates. + +2025-10-30 lishin <lishin1008@gmail.com> + + * rust-gcc.cc (constructor_expression): + Ensure vec_alloc reserves at least one element. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast.cc (Attribute::check_cfg_predicate): Emit an error with + empty cfg_attr input. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * resolve/rust-forever-stack.hxx + (ForeverStack::resolve_segments): Remove usage of optional + reference, allow non-final path segments to resolve to types + even outside the type namespace, and allow resolution to + progress past non-final path segments which resolve to modules. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * parse/rust-parse-impl.h (Parser::parse_stmt_or_expr): Add null check + on parse_macro_invocation_partial call. + * ast/rust-path.cc (Path::convert_to_simple_path): Do not exclude + capitalized "Self". + +2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast-fragment.cc (Fragment::is_pattern_fragment): New function. + (Fragment::take_pattern_fragment): Likewise. + (Fragment::assert_single_fragment): Likewise. + * ast/rust-ast-fragment.h: Declare them. + * ast/rust-ast.cc (SingleASTNode::SingleASTNode): Add new constructor for pattern + single AST nodes. + (SingleASTNode::operator=): Handle patterns. + (SingleASTNode::accept_vis): Likewise. + (SingleASTNode::is_error): Likewise. + (SingleASTNode::as_string): Likewise. + * ast/rust-ast.h: Add get_pattern_ptr() functions. + * ast/rust-expr.h: Likewise. + * ast/rust-item.h: Likewise. + * ast/rust-pattern.h: Likewise. + * ast/rust-stmt.h: Likewise. + * expand/rust-expand-visitor.cc (derive_item): Use new API enum values. + (expand_item_attribute): Likewise. + (expand_stmt_attribute): Likewise. + (ExpandVisitor::maybe_expand_pattern): New function. + (ExpandVisitor::expand_closure_params): Handle patterns. + (ExpandVisitor::visit): Add new visitors for patterns and missed exprs. + * expand/rust-expand-visitor.h: Declare them. + * expand/rust-macro-expand.cc (transcribe_pattern): New function. + (transcribe_context): Call it. + * expand/rust-macro-expand.h (struct MacroExpander): New Context type. + +2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com> + + * ast/rust-ast.h: Change NodeType to enum class Kind. + * ast/rust-ast-fragment.cc: Use new names. + * ast/rust-ast-fragment.h: Likewise. + * ast/rust-ast.cc (SingleASTNode::SingleASTNode): Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * parse/rust-parse-impl.h + (Parser::parse_identifier_or_keyword_token): Record error on + failure. + +2025-10-30 Ryutaro Okada <1015ryu88@gmail.com> + + * resolve/rust-ast-resolve-stmt.h: + Add name resolution processing for discriminant values. + +2025-10-30 Ryutaro Okada <1015ryu88@gmail.com> + + * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): fix error code + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * expand/rust-cfg-strip.cc: Include "rust-macro-expand.h". + (fails_cfg): Rename to... + (CfgStrip::fails_cfg): ...here and handle test attributes. + (fails_cfg_with_expand): Rename to... + (CfgStrip::fails_cfg_with_expand): ...here and handle test + attributes. + * expand/rust-cfg-strip.h (struct ExpansionCfg): Forward + declare. + (CfgStrip::fails_cfg): New member function. + (CfgStrip::fails_cfg_with_expand): Likewise. + (CfgStrip::CfgStrip): Accept reference to ExpansionCfg. + (CfgStrip::expansion_cfg): New member variable. + * rust-session-manager.cc (Session::expansion): Pass + ExpansionCfg instance to CfgStrip constructor. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * resolve/rust-early-name-resolver-2.0.cc (Early::finalize_rebind_import): + Do not abort on wildcard patterns. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-expr.h: Add const getters to llvm members. + * hir/rust-ast-lower-expr.cc (check_llvm_asm_support): Check llvm_asm + usage validity. + (ASTLoweringExpr::visit): Emit an error message instead of aborting. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-builtins-asm.cc (parse_llvm_clobbers): Expect a + comma between clobbers. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-macro-builtins-asm.cc (parse_asm): Simplify expression. + (parse_llvm_asm): Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * ast/rust-ast.h (Stmt::get_node_id): Make virtual. + (Type::get_node_id): Likewise. + (AssociatedItem::get_node_id): New virtual member function. + * ast/rust-expr.h (TypeCastExpr::get_casted_expr_ptr): New + member function. + (TypeCastExpr::get_type_to_cast_to_ptr): Likewise. + (ClosureExprInner::get_definition_expr_ptr): Likewise. + * ast/rust-item.h (TypeAlias::get_node_id): New member function + to override AssociatedItem::get_node_id. + (ConstantItem::get_node_id): Likewise. + * expand/rust-expand-visitor.cc + (ExpandVisitor::maybe_expand_expr): Adjust + macro_invoc_expect_id. + (ExpandVisitor::maybe_expand_type): Likewise and add an overload + for std::unique_ptr<TypeNoBounds>. + (ExpandVisitor::visit): Check macro_invoc_expect_id and + generally improve visitors so that the testsuite will still + pass. + * expand/rust-expand-visitor.h (ExpandVisitor::ExpandVisitor): + Initialize member variable macro_invoc_expect_id. + (ExpandVisitor::maybe_expand_type): Add an overload for + std::unique_ptr<TypeNoBounds>. + (ExpandVisitor::expand_macro_children): Adjust + macro_invoc_expect_id. + (ExpandVisitor::visit): Add an overload for TypeCastExpr. + (ExpandVisitor::macro_invoc_expect_id): New member variable. + +2025-10-30 lishin <lishin1008@gmail.com> + + * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit): + Check upper compare operator. + * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit): + Handle lowering of exclusive range pattern. + * hir/tree/rust-hir-pattern.h (class RangePattern): + Add support for exclusive ranges in HIR representation. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * expand/rust-macro-expand.cc (transcribe_expression): Parse any + outer attributes before parsing an expression. + * parse/rust-parse.h (Parser::parse_outer_attributes): Make + public. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-expr.h (struct TupleClobber): Add constructor. + * backend/rust-compile-context.h (struct fncontext): Likewise. + * typecheck/rust-hir-dot-operator.h: Likewise. + * typecheck/rust-tyty-variance-analysis-private.h (struct Constraint): + Likewise. + * typecheck/rust-unify.h: Likewise. + * ast/rust-ast-builder.cc (Builder::new_lifetime_param): Add memory + reservation and construct in place. + (Builder::new_generic_args): Likewise. + * ast/rust-ast-collector.cc (TokenCollector::newline): Likewise. + (TokenCollector::indentation): Likewise. + (TokenCollector::comment): Likewise. + * ast/rust-desugar-apit.cc: Likewise. + * ast/rust-path.cc (Path::convert_to_simple_path): Likewise. + (TypePath::as_simple_path): Likewise. + * ast/rust-path.h: Likewise. + * backend/rust-compile-type.cc (TyTyResolveCompile::visit): Likewise. + (TyTyResolveCompile::create_dyn_obj_record): Likewise. + * checks/errors/rust-hir-pattern-analysis.cc (Matrix::specialize): + Likewise. + (WitnessMatrix::apply_constructor): Likewise. + (check_match_usefulness): Likewise. + * expand/rust-derive-clone.cc (DeriveClone::clone_fn): Likewise. + * expand/rust-macro-builtins-asm.cc (parse_clobber_abi): Likewise. + * expand/rust-macro-expand.cc (MacroExpander::parse_proc_macro_output): + Likewise. + * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_generic_args): + Likewise. + (ASTLoweringBase::lower_extern_block): Likewise. + * hir/rust-ast-lower-enumitem.h: Likewise. + * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise. + * hir/rust-ast-lower-extern.h: Likewise. + * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): Likewise. + (ASTLowerTraitItem::visit): Likewise. + * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise. + * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit): Likewise. + * hir/rust-ast-lower.cc (ASTLowering::go): Likewise. + (ASTLoweringBlock::visit): Likewise. + (ASTLoweringIfLetBlock::desugar_iflet): Likewise. + (ASTLoweringExprWithBlock::visit): Likewise. + (ASTLowerPathInExpression::visit): Likewise. + (ASTLowerQualPathInExpression::visit): Likewise. + * hir/tree/rust-hir.cc (PathPattern::convert_to_simple_path): Likewise. + (TypePath::as_simple_path): Likewise. + * metadata/rust-export-metadata.cc (ExportContext::emit_function): + Likewise. + * parse/rust-parse-impl.h (Parser::parse_decl_macro_def): Likewise. + (Parser::parse_lifetime_params): Likewise. + * resolve/rust-ast-resolve-item.cc (ResolveTraitItems::visit): + Likewise. + (ResolveItem::visit): Likewise. + (flatten_list): Likewise. + * resolve/rust-ast-resolve-pattern.cc (PatternDeclaration::visit): + Likewise. + * typecheck/rust-autoderef.cc (AutoderefCycle::try_autoderefed): + Likewise. + * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsized): + Likewise. + * typecheck/rust-hir-dot-operator.cc: Likewise. + * typecheck/rust-hir-path-probe.cc: Likewise. + * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): + Likewise. + * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): + Likewise. + (TypeCheckExpr::resolve_fn_trait_call): Likewise. + * typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelExternItem::visit): + Likewise. + (TypeCheckImplItem::visit): Likewise. + * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): + Likewise. + * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): + Likewise. + * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::resolve): + Likewise. + * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): + Likewise. + * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): + Likewise. + * typecheck/rust-typecheck-context.cc (TypeCheckContext::push_return_type): + Likewise. + (TypeCheckContext::insert_associated_impl_mapping): Likewise. + * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::scan): Likewise. + (TypeBoundsProbe::add_trait_bound): Likewise. + (TypeBoundPredicate::operator=): Likewise. + (TypeBoundPredicateItem::get_tyty_for_receiver): Likewise. + (TypeBoundPredicate::get_associated_type_items): Likewise. + * typecheck/rust-tyty-call.cc (TypeCheckMethodCallExpr::go): Likewise. + * typecheck/rust-tyty-subst.cc (SubstitutionRef::clone_substs): + Likewise. + (SubstitutionRef::infer_substitions): Likewise. + (SubstitutionRef::are_mappings_bound): Likewise. + * typecheck/rust-tyty-variance-analysis.cc (GenericTyPerCrateCtx::query_generic_variance): + Likewise. + (GenericTyVisitorCtx::add_constraint): Likewise. + * typecheck/rust-tyty.cc (FnPtr::clone): Likewise. + (DynamicObjectType::get_object_items): Likewise. + * typecheck/rust-unify.cc (UnifyRules::Resolve): Likewise. + (UnifyRules::go): Likewise. + (UnifyRules::expect_tuple): Likewise. + * util/rust-canonical-path.h: Likewise. + * util/rust-token-converter.cc (convert): Likewise. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * util/bi-map.h: Add include directive for required declarations. + * util/fnv-hash.h: Likewise. + * util/rust-dump.h: Likewise. + * util/rust-inline-visitor.h: Likewise. + * util/rust-unwrap-segment.h: Likewise. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * util/rust-lang-item.h (RUST_LANG_ITEM_H): Add header guards. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * parse/rust-parse.h: Change class to struct for friend qualification. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * checks/lints/rust-lint-marklive-base.h (RUST_HIR_LIVENESS_BASE): + Remove header includes. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-cond-compilation.h: Delete copy constructor for + ConfigurationAll and ConfigurationAny. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-type.h: Update member instead of parameter + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-cond-compilation.h: Move vector instead of passing it by + value. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-pattern.h: Include header directly. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-cond-compilation.h: Copy cfg_attrs + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * ast/rust-ast-formatting.h (RUST_AST_FORMATTING_H): Include required + headers directly. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * util/rust-attributes.cc (Attributes::extract_string_literal): + New function definition. + * util/rust-attributes.h (Attributes::extract_string_literal): + New function declaration. + * ast/rust-collect-lang-items.cc (get_lang_item_attr): Use + extract_string_literal. + * backend/rust-compile-base.cc: Include "rust-attributes.h". + (HIRCompileBase::handle_link_section_attribute_on_fndecl): + Use extract_string_literal. + (HIRCompileBase::handle_must_use_attribute_on_fndecl): Likewise. + * hir/rust-ast-lower-base.cc + (ASTLoweringBase::handle_lang_item_attribute): Likewise. + * rust-session-manager.cc (Session::handle_crate_name): + Likewise. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * hir/tree/rust-hir-pattern.h: + - Rename TupleItems to PatternItems. + - Rename TuplePatternItemsMultiple/Ranged & TupleStructItemsRange/NoRange to + TuplePatternItemsNoRest/HasRest and TupleStructItemsNoRest/HasRest. + - Update enum values to NO_REST/HAS_REST. + - Rename clone_tuple_items_impl to clone_pattern_items_impl. + * hir/tree/rust-hir-full-decls.h: Renamed the classes accordingly. + * hir/tree/rust-hir-visitor.h: Renamed the classes accordingly. + * hir/tree/rust-hir-visitor.cc: Renamed the classes accordingly. + * hir/rust-hir-dump.h: Renamed the classes accordingly. + * hir/rust-hir-dump.cc: Renamed the classes accordingly. + * hir/tree/rust-hir.cc: Renamed the classes accordingly. + * hir/rust-ast-lower-base.cc: Renamed the classes accordingly. + * hir/rust-ast-lower-pattern.cc: Renamed the classes accordingly. + * backend/rust-compile-pattern.cc: Renamed the classes accordingly. + * backend/rust-compile-var-decl.h: Renamed the classes accordingly. + * checks/errors/borrowck/rust-bir-builder-pattern.cc: Renamed the classes accordingly. + * checks/errors/borrowck/rust-bir-builder-struct.h: Renamed the classes accordingly. + * checks/errors/borrowck/rust-function-collector.h: Renamed the classes accordingly. + * checks/errors/rust-const-checker.cc: Renamed the classes accordingly. + * checks/errors/rust-const-checker.h: Renamed the classes accordingly. + * checks/errors/rust-hir-pattern-analysis.cc: Renamed the classes accordingly. + * checks/errors/rust-hir-pattern-analysis.h: Renamed the classes accordingly. + * checks/errors/rust-unsafe-checker.cc: Renamed the classes accordingly. + * checks/errors/rust-unsafe-checker.h: Renamed the classes accordingly. + * checks/errors/rust-readonly-check2.cc: Renamed the classes accordingly. + * typecheck/rust-hir-type-check-pattern.cc: Update references to renamed classes and enum + values. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * expand/rust-derive-eq.cc: Use empty vector explicitly. + 2025-08-05 Ryutaro Okada <1015ryu88@gmail.com> * Make-lang.in (rust-readonly-check2.cc): @@ -5197,7 +6640,7 @@ 2025-03-21 Owen Avery <powerboat9.gamer@gmail.com> - * resolve/rust-name-resolver.cc: Include options.txt. + * resolve/rust-name-resolver.cc: Include options.h. (Resolver::insert_resolved_name): Assert that name resolution 2.0 is disabled. (Resolver::lookup_resolved_name): Likewise. diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 8cdf6c9..e5a8a5e 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -84,6 +84,7 @@ GRS_OBJS = \ rust/rust-ast-dump.o \ rust/rust-ast-collector.o \ rust/rust-ast-visitor.o \ + rust/rust-ast-pointer-visitor.o \ rust/rust-hir-visitor.o \ rust/rust-hir-dump.o \ rust/rust-session-manager.o \ @@ -147,17 +148,8 @@ GRS_OBJS = \ rust/rust-ice-finalizer.o \ rust/rust-late-name-resolver-2.0.o \ rust/rust-immutable-name-resolution-context.o \ - rust/rust-early-name-resolver.o \ rust/rust-name-resolver.o \ - rust/rust-ast-resolve.o \ - rust/rust-ast-resolve-base.o \ - rust/rust-ast-resolve-item.o \ - rust/rust-ast-resolve-pattern.o \ - rust/rust-ast-resolve-expr.o \ - rust/rust-ast-resolve-type.o \ - rust/rust-ast-resolve-path.o \ - rust/rust-ast-resolve-stmt.o \ - rust/rust-ast-resolve-struct-expr-field.o \ + rust/rust-resolve-builtins.o \ rust/rust-forever-stack.o \ rust/rust-hir-type-check.o \ rust/rust-privacy-check.o \ @@ -209,7 +201,6 @@ GRS_OBJS = \ rust/rust-lint-marklive.o \ rust/rust-lint-unused-var.o \ rust/rust-readonly-check.o \ - rust/rust-readonly-check2.o \ rust/rust-hir-type-check-path.o \ rust/rust-unsafe-checker.o \ rust/rust-hir-pattern-analysis.o \ @@ -443,6 +434,7 @@ RUST_INCLUDES = -I $(srcdir)/rust \ -I $(srcdir)/rust/checks/errors \ -I $(srcdir)/rust/checks/errors/privacy \ -I $(srcdir)/rust/checks/errors/borrowck \ + -I $(srcdir)/rust/checks/errors/feature \ -I $(srcdir)/rust/util \ -I $(srcdir)/rust/metadata \ -I $(srcdir)/../libgrust @@ -515,6 +507,11 @@ rust/%.o: rust/checks/errors/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) +# build feature related files in rust folder +rust/%.o: rust/checks/errors/feature/%.cc + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< + $(POSTCOMPILE) + # build privacy pass files in rust folder rust/%.o: rust/checks/errors/privacy/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index ed10ce7..632f945 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -554,12 +554,12 @@ std::unique_ptr<GenericParam> Builder::new_lifetime_param (LifetimeParam ¶m) { Lifetime l = new_lifetime (param.get_lifetime ()); + std::vector<Lifetime> lifetime_bounds; + lifetime_bounds.reserve (param.get_lifetime_bounds ().size ()); + for (auto b : param.get_lifetime_bounds ()) - { - Lifetime bl = new_lifetime (b); - lifetime_bounds.push_back (bl); - } + lifetime_bounds.emplace_back (new_lifetime (b)); auto p = new LifetimeParam (l, std::move (lifetime_bounds), param.get_outer_attrs (), param.get_locus ()); @@ -605,11 +605,11 @@ Builder::new_type_param ( for (const auto &lifetime : tb.get_for_lifetimes ()) { std::vector<Lifetime> lifetime_bounds; + lifetime_bounds.reserve ( + lifetime.get_lifetime_bounds ().size ()); + for (const auto &b : lifetime.get_lifetime_bounds ()) - { - Lifetime bl = new_lifetime (b); - lifetime_bounds.push_back (std::move (bl)); - } + lifetime_bounds.emplace_back (new_lifetime (b)); Lifetime nl = new_lifetime (lifetime.get_lifetime ()); LifetimeParam p (std::move (nl), std::move (lifetime_bounds), @@ -626,12 +626,11 @@ Builder::new_type_param ( { const TypePathSegment &segment = (const TypePathSegment &) (*seg.get ()); - TypePathSegment *s = new TypePathSegment ( + + segments.emplace_back (new TypePathSegment ( segment.get_ident_segment (), segment.get_separating_scope_resolution (), - segment.get_locus ()); - std::unique_ptr<TypePathSegment> sg (s); - segments.push_back (std::move (sg)); + segment.get_locus ())); } break; @@ -642,11 +641,10 @@ Builder::new_type_param ( GenericArgs args = new_generic_args (generic.get_generic_args ()); - TypePathSegmentGeneric *s = new TypePathSegmentGeneric ( + + segments.emplace_back (new TypePathSegmentGeneric ( generic.get_ident_segment (), false, std::move (args), - generic.get_locus ()); - std::unique_ptr<TypePathSegment> sg (s); - segments.push_back (std::move (sg)); + generic.get_locus ())); } break; @@ -664,12 +662,9 @@ Builder::new_type_param ( TypePath p (std::move (segments), path.get_locus (), path.has_opening_scope_resolution_op ()); - TraitBound *b = new TraitBound (std::move (p), tb.get_locus (), - tb.is_in_parens (), - tb.has_opening_question_mark (), - std::move (for_lifetimes)); - std::unique_ptr<TypeParamBound> bound (b); - type_param_bounds.push_back (std::move (bound)); + type_param_bounds.emplace_back (new TraitBound ( + std::move (p), tb.get_locus (), tb.is_in_parens (), + tb.has_opening_question_mark (), std::move (for_lifetimes))); } break; @@ -677,10 +672,9 @@ Builder::new_type_param ( { const Lifetime &l = (const Lifetime &) *b.get (); - auto bl = new Lifetime (l.get_lifetime_type (), - l.get_lifetime_name (), l.get_locus ()); - std::unique_ptr<TypeParamBound> bound (bl); - type_param_bounds.push_back (std::move (bound)); + type_param_bounds.emplace_back ( + new Lifetime (l.get_lifetime_type (), l.get_lifetime_name (), + l.get_locus ())); } break; } @@ -709,18 +703,14 @@ Builder::new_generic_args (GenericArgs &args) location_t locus = args.get_locus (); for (const auto &lifetime : args.get_lifetime_args ()) - { - Lifetime l = new_lifetime (lifetime); - lifetime_args.push_back (std::move (l)); - } + lifetime_args.push_back (new_lifetime (lifetime)); for (auto &binding : args.get_binding_args ()) { Type &t = *binding.get_type_ptr ().get (); std::unique_ptr<Type> ty = t.reconstruct (); - GenericArgsBinding b (binding.get_identifier (), std::move (ty), - binding.get_locus ()); - binding_args.push_back (std::move (b)); + binding_args.emplace_back (binding.get_identifier (), std::move (ty), + binding.get_locus ()); } for (auto &arg : args.get_generic_args ()) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 3d9ea78..721d274 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -76,13 +76,13 @@ TokenCollector::trailing_comma () void TokenCollector::newline () { - tokens.push_back ({CollectItem::Kind::Newline}); + tokens.emplace_back (CollectItem::Kind::Newline); } void TokenCollector::indentation () { - tokens.push_back ({indent_level}); + tokens.emplace_back (indent_level); } void @@ -101,7 +101,7 @@ TokenCollector::decrement_indentation () void TokenCollector::comment (std::string comment) { - tokens.push_back ({comment}); + tokens.emplace_back (comment); } void @@ -355,7 +355,8 @@ TokenCollector::visit (MaybeNamedParam ¶m) void TokenCollector::visit (Token &tok) { - std::string data = tok.get_tok_ptr ()->has_str () ? tok.get_str () : ""; + std::string data + = tok.get_tok_ptr ()->should_have_str () ? tok.get_str () : ""; switch (tok.get_id ()) { case IDENTIFIER: @@ -2171,19 +2172,6 @@ TokenCollector::visit (SelfParam ¶m) } void -TokenCollector::visit (TraitItemConst &item) -{ - auto id = item.get_identifier ().as_string (); - indentation (); - push (Rust::Token::make (CONST, item.get_locus ())); - push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); - push (Rust::Token::make (COLON, UNDEF_LOCATION)); - visit (item.get_type ()); - push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); - newline (); -} - -void TokenCollector::visit (TraitItemType &item) { visit_items_as_lines (item.get_outer_attrs ()); @@ -2632,7 +2620,7 @@ TokenCollector::visit (StructPattern &pattern) if (elems.has_struct_pattern_fields ()) { visit_items_joined_by_separator (elems.get_struct_pattern_fields ()); - if (elems.has_etc ()) + if (elems.has_rest ()) { push (Rust::Token::make (COMMA, UNDEF_LOCATION)); visit_items_as_lines (elems.get_etc_outer_attrs ()); @@ -2649,13 +2637,13 @@ TokenCollector::visit (StructPattern &pattern) // void TokenCollector::visit(TupleStructItems& ){} void -TokenCollector::visit (TupleStructItemsNoRange &pattern) +TokenCollector::visit (TupleStructItemsNoRest &pattern) { visit_items_joined_by_separator (pattern.get_patterns ()); } void -TokenCollector::visit (TupleStructItemsRange &pattern) +TokenCollector::visit (TupleStructItemsHasRest &pattern) { for (auto &lower : pattern.get_lower_patterns ()) { @@ -2682,13 +2670,13 @@ TokenCollector::visit (TupleStructPattern &pattern) // {} void -TokenCollector::visit (TuplePatternItemsMultiple &pattern) +TokenCollector::visit (TuplePatternItemsNoRest &pattern) { visit_items_joined_by_separator (pattern.get_patterns (), COMMA); } void -TokenCollector::visit (TuplePatternItemsRanged &pattern) +TokenCollector::visit (TuplePatternItemsHasRest &pattern) { for (auto &lower : pattern.get_lower_patterns ()) { @@ -3009,8 +2997,216 @@ TokenCollector::visit (BareFunctionType &type) void TokenCollector::visit (AST::FormatArgs &fmt) { - rust_sorry_at (fmt.get_locus (), "%s:%u: unimplemented FormatArgs visitor", - __FILE__, __LINE__); + push (Rust::Token::make_identifier (fmt.get_locus (), "format_args")); + push (Rust::Token::make (EXCLAM, fmt.get_locus ())); + push (Rust::Token::make (LEFT_PAREN, fmt.get_locus ())); + + std::string reconstructed_template = "\""; + const auto &template_pieces = fmt.get_template (); + + for (const auto &piece : template_pieces.get_pieces ()) + { + if (piece.tag == Fmt::ffi::Piece::Tag::String) + { + std::string literal = piece.string._0.to_string (); + for (char c : literal) + { + if (c == '"' || c == '\\') + { + reconstructed_template += '\\'; + } + else if (c == '\n') + { + reconstructed_template += "\\n"; + continue; + } + else if (c == '\r') + { + reconstructed_template += "\\r"; + continue; + } + else if (c == '\t') + { + reconstructed_template += "\\t"; + continue; + } + reconstructed_template += c; + } + } + else if (piece.tag == Fmt::ffi::Piece::Tag::NextArgument) + { + reconstructed_template += "{"; + + const auto &argument = piece.next_argument._0; + const auto &position = argument.position; + + switch (position.tag) + { + case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs: + break; + case Fmt::ffi::Position::Tag::ArgumentIs: + reconstructed_template + += std::to_string (position.argument_is._0); + break; + case Fmt::ffi::Position::Tag::ArgumentNamed: + reconstructed_template += position.argument_named._0.to_string (); + break; + } + + // Add format specifiers if any (like :?, :x, etc.) + const auto &format_spec = argument.format; + + bool has_format_spec = false; + std::string format_part; + + // For now, skipping the complex format specifications that use FFIOpt + // since FFIOpt::get_opt() has a bug. + + // Alignment + if (format_spec.align != Fmt::ffi::Alignment::AlignUnknown) + { + has_format_spec = true; + switch (format_spec.align) + { + case Fmt::ffi::Alignment::AlignLeft: + format_part += "<"; + break; + case Fmt::ffi::Alignment::AlignRight: + format_part += ">"; + break; + case Fmt::ffi::Alignment::AlignCenter: + format_part += "^"; + break; + case Fmt::ffi::Alignment::AlignUnknown: + break; + } + } + + // Alternate flag + if (format_spec.alternate) + { + has_format_spec = true; + format_part += "#"; + } + + // Zero pad flag + if (format_spec.zero_pad) + { + has_format_spec = true; + format_part += "0"; + } + + // Width + if (format_spec.width.tag != Fmt::ffi::Count::Tag::CountImplied) + { + has_format_spec = true; + switch (format_spec.width.tag) + { + case Fmt::ffi::Count::Tag::CountIs: + format_part += std::to_string (format_spec.width.count_is._0); + break; + case Fmt::ffi::Count::Tag::CountIsParam: + format_part + += std::to_string (format_spec.width.count_is_param._0) + + "$"; + break; + case Fmt::ffi::Count::Tag::CountIsName: + format_part + += format_spec.width.count_is_name._0.to_string () + "$"; + break; + case Fmt::ffi::Count::Tag::CountIsStar: + format_part += "*"; + break; + case Fmt::ffi::Count::Tag::CountImplied: + break; + } + } + + // Precision + if (format_spec.precision.tag != Fmt::ffi::Count::Tag::CountImplied) + { + has_format_spec = true; + format_part += "."; + switch (format_spec.precision.tag) + { + case Fmt::ffi::Count::Tag::CountIs: + format_part + += std::to_string (format_spec.precision.count_is._0); + break; + case Fmt::ffi::Count::Tag::CountIsParam: + format_part + += std::to_string (format_spec.precision.count_is_param._0) + + "$"; + break; + case Fmt::ffi::Count::Tag::CountIsName: + format_part + += format_spec.precision.count_is_name._0.to_string () + + "$"; + break; + case Fmt::ffi::Count::Tag::CountIsStar: + format_part += "*"; + break; + case Fmt::ffi::Count::Tag::CountImplied: + break; + } + } + + // Type/trait (like ?, x, X, etc.) + std::string type_str = format_spec.ty.to_string (); + if (!type_str.empty ()) + { + has_format_spec = true; + format_part += type_str; + } + + // Add the format specification if any + if (has_format_spec) + { + reconstructed_template += ":"; + reconstructed_template += format_part; + } + + reconstructed_template += "}"; + } + } + reconstructed_template += "\""; + + push (Rust::Token::make_string (fmt.get_locus (), reconstructed_template)); + + // Visit format arguments if any exist + auto &arguments = fmt.get_arguments (); + if (!arguments.empty ()) + { + push (Rust::Token::make (COMMA, fmt.get_locus ())); + + auto &args = arguments.get_args (); + for (size_t i = 0; i < args.size (); ++i) + { + if (i > 0) + { + push (Rust::Token::make (COMMA, fmt.get_locus ())); + } + + auto kind = args[i].get_kind (); + + // Handle named arguments: name = expr + if (kind.kind == FormatArgumentKind::Kind::Named) + { + auto ident = kind.get_ident ().as_string (); + push (Rust::Token::make_identifier (fmt.get_locus (), + std::move (ident))); + push (Rust::Token::make (EQUAL, fmt.get_locus ())); + } + // Note: Captured arguments are handled implicitly in the template + // reconstruction They don't need explicit "name =" syntax in the + // reconstructed macro call + + auto &expr = args[i].get_expr (); + expr.accept_vis (*this); + } + } + + push (Rust::Token::make (RIGHT_PAREN, fmt.get_locus ())); } void diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index d3ab18a..3e33476 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -330,7 +330,6 @@ public: void visit (ConstantItem &const_item); void visit (StaticItem &static_item); void visit (SelfParam ¶m); - void visit (TraitItemConst &item); void visit (TraitItemType &item); void visit (Trait &trait); void visit (InherentImpl &impl); @@ -370,12 +369,12 @@ public: void visit (StructPatternFieldIdent &field); void visit (StructPattern &pattern); // void visit(TupleStructItems& tuple_items); - void visit (TupleStructItemsNoRange &tuple_items); - void visit (TupleStructItemsRange &tuple_items); + void visit (TupleStructItemsNoRest &tuple_items); + void visit (TupleStructItemsHasRest &tuple_items); void visit (TupleStructPattern &pattern); // void visit(TuplePatternItems& tuple_items); - void visit (TuplePatternItemsMultiple &tuple_items); - void visit (TuplePatternItemsRanged &tuple_items); + void visit (TuplePatternItemsNoRest &tuple_items); + void visit (TuplePatternItemsHasRest &tuple_items); void visit (TuplePattern &pattern); void visit (GroupedPattern &pattern); void visit (SlicePatternItemsNoRest &items); diff --git a/gcc/rust/ast/rust-ast-formatting.h b/gcc/rust/ast/rust-ast-formatting.h index aace93f..075c51c 100644 --- a/gcc/rust/ast/rust-ast-formatting.h +++ b/gcc/rust/ast/rust-ast-formatting.h @@ -19,6 +19,9 @@ #ifndef RUST_AST_FORMATTING_H #define RUST_AST_FORMATTING_H +#include "rust-ast.h" +#include "rust-system.h" + namespace Rust { namespace AST { diff --git a/gcc/rust/ast/rust-ast-fragment.cc b/gcc/rust/ast/rust-ast-fragment.cc index 076cab3..8a547b4 100644 --- a/gcc/rust/ast/rust-ast-fragment.cc +++ b/gcc/rust/ast/rust-ast-fragment.cc @@ -107,29 +107,42 @@ Fragment::should_expand () const bool Fragment::is_expression_fragment () const { - return is_single_fragment_of_kind (SingleASTNode::NodeType::EXPRESSION); + return is_single_fragment_of_kind (SingleASTNode::Kind::Expr); } bool Fragment::is_type_fragment () const { - return is_single_fragment_of_kind (SingleASTNode::NodeType::TYPE); + return is_single_fragment_of_kind (SingleASTNode::Kind::Type); +} + +bool +Fragment::is_pattern_fragment () const +{ + return is_single_fragment_of_kind (SingleASTNode::Kind::Pattern); } std::unique_ptr<Expr> Fragment::take_expression_fragment () { - assert_single_fragment (SingleASTNode::NodeType::EXPRESSION); + assert_single_fragment (SingleASTNode::Kind::Expr); return nodes[0].take_expr (); } std::unique_ptr<Type> Fragment::take_type_fragment () { - assert_single_fragment (SingleASTNode::NodeType::TYPE); + assert_single_fragment (SingleASTNode::Kind::Type); return nodes[0].take_type (); } +std::unique_ptr<Pattern> +Fragment::take_pattern_fragment () +{ + assert_single_fragment (SingleASTNode::Kind::Pattern); + return nodes[0].take_pattern (); +} + void Fragment::accept_vis (ASTVisitor &vis) { @@ -144,21 +157,22 @@ Fragment::is_single_fragment () const } bool -Fragment::is_single_fragment_of_kind (SingleASTNode::NodeType expected) const +Fragment::is_single_fragment_of_kind (SingleASTNode::Kind expected) const { return is_single_fragment () && nodes[0].get_kind () == expected; } void -Fragment::assert_single_fragment (SingleASTNode::NodeType expected) const -{ - static const std::map<SingleASTNode::NodeType, const char *> str_map = { - {SingleASTNode::NodeType::ASSOC_ITEM, "associated item"}, - {SingleASTNode::NodeType::ITEM, "item"}, - {SingleASTNode::NodeType::TYPE, "type"}, - {SingleASTNode::NodeType::EXPRESSION, "expr"}, - {SingleASTNode::NodeType::STMT, "stmt"}, - {SingleASTNode::NodeType::EXTERN, "extern"}, +Fragment::assert_single_fragment (SingleASTNode::Kind expected) const +{ + static const std::map<SingleASTNode::Kind, const char *> str_map = { + {SingleASTNode::Kind::Assoc, "associated item"}, + {SingleASTNode::Kind::Item, "item"}, + {SingleASTNode::Kind::Type, "type"}, + {SingleASTNode::Kind::Expr, "expr"}, + {SingleASTNode::Kind::Stmt, "stmt"}, + {SingleASTNode::Kind::Extern, "extern"}, + {SingleASTNode::Kind::Pattern, "pattern"}, }; auto actual = nodes[0].get_kind (); diff --git a/gcc/rust/ast/rust-ast-fragment.h b/gcc/rust/ast/rust-ast-fragment.h index 7d01fd7..23f26d3 100644 --- a/gcc/rust/ast/rust-ast-fragment.h +++ b/gcc/rust/ast/rust-ast-fragment.h @@ -86,9 +86,11 @@ public: bool is_expression_fragment () const; bool is_type_fragment () const; + bool is_pattern_fragment () const; std::unique_ptr<Expr> take_expression_fragment (); std::unique_ptr<Type> take_type_fragment (); + std::unique_ptr<Pattern> take_pattern_fragment (); void accept_vis (ASTVisitor &vis); @@ -119,8 +121,8 @@ private: * one Node will be extracted from the `nodes` vector */ bool is_single_fragment () const; - bool is_single_fragment_of_kind (SingleASTNode::NodeType expected) const; - void assert_single_fragment (SingleASTNode::NodeType expected) const; + bool is_single_fragment_of_kind (SingleASTNode::Kind expected) const; + void assert_single_fragment (SingleASTNode::Kind expected) const; }; enum class InvocKind diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 09706ce..2903ba7 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -195,7 +195,6 @@ class Enum; class Union; class ConstantItem; class StaticItem; -class TraitItemConst; class TraitItemType; class Trait; class Impl; @@ -240,12 +239,12 @@ class StructPatternFieldIdent; class StructPatternElements; class StructPattern; class TupleStructItems; -class TupleStructItemsNoRange; -class TupleStructItemsRange; +class TupleStructItemsNoRest; +class TupleStructItemsHasRest; class TupleStructPattern; class TuplePatternItems; -class TuplePatternItemsMultiple; -class TuplePatternItemsRanged; +class TuplePatternItemsNoRest; +class TuplePatternItemsHasRest; class TuplePattern; class GroupedPattern; class SlicePatternItemsNoRest; diff --git a/gcc/rust/ast/rust-ast-pointer-visitor.cc b/gcc/rust/ast/rust-ast-pointer-visitor.cc new file mode 100644 index 0000000..ee1f001 --- /dev/null +++ b/gcc/rust/ast/rust-ast-pointer-visitor.cc @@ -0,0 +1,1475 @@ +// 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-ast-pointer-visitor.h" +#include "rust-ast-visitor.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace AST { + +void +PointerVisitor::visit (AST::Crate &crate) +{ + visit_inner_attrs (crate); + for (auto &item : crate.items) + reseat (item); +} + +void +PointerVisitor::visit (AST::AttrInputMetaItemContainer &input) +{ + // FIXME: I think we might actually have to reseat sub-items for macro + // invocations within attributes correct? + + for (auto &item : input.get_items ()) + visit (item); +} + +void +PointerVisitor::visit (AST::IdentifierExpr &ident_expr) +{ + visit_outer_attrs (ident_expr); +} + +void +PointerVisitor::visit (AST::LifetimeParam &lifetime_param) +{ + visit_outer_attrs (lifetime_param); + + // Nothing to do for lifetimes right? +} + +void +PointerVisitor::visit (AST::ConstGenericParam &const_param) +{ + visit_outer_attrs (const_param); + if (const_param.has_type ()) + reseat (const_param.get_type_ptr ()); + + if (const_param.has_default_value ()) + visit (const_param.get_default_value_unchecked ()); +} + +void +PointerVisitor::visit (AST::PathInExpression &path) +{ + visit_outer_attrs (path); + + if (!path.is_lang_item ()) + for (auto &segment : path.get_segments ()) + visit (segment); +} + +void +PointerVisitor::visit (GenericArgsBinding &binding) +{ + reseat (binding.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::TypePathSegmentGeneric &segment) +{ + if (segment.has_generic_args ()) + visit (segment.get_generic_args ()); +} + +void +PointerVisitor::visit (AST::TypePathFunction &tpf) +{ + for (auto &input : tpf.get_params ()) + reseat (input); + if (tpf.has_return_type ()) + reseat (tpf.get_return_type_ptr ()); +} + +void +PointerVisitor::visit (AST::TypePathSegmentFunction &segment) +{ + // FIXME: No reseating here correct? No macros possible or desugar? + visit (segment.get_type_path_function ()); + visit (segment.get_ident_segment ()); +} + +void +PointerVisitor::visit (AST::GenericArgs &args) +{ + // Nothing to do for lifetimes? + // for (auto &lifetime : args.get_lifetime_args ()) + // reseat (lifetime); + + // FIXME: Actually this can probably be a macro invocation, so we need to + // reseat them? + for (auto &generic : args.get_generic_args ()) + visit (generic); + + for (auto &binding : args.get_binding_args ()) + visit (binding); +} + +void +PointerVisitor::visit (AST::PathExprSegment &segment) +{ + visit (segment.get_ident_segment ()); + if (segment.has_generic_args ()) + visit (segment.get_generic_args ()); +} +void +PointerVisitor::visit (AST::TypePath &path) +{ + for (auto &segment : path.get_segments ()) + visit (segment); +} + +void +PointerVisitor::visit (AST::QualifiedPathInExpression &path) +{ + visit_outer_attrs (path); + visit (path.get_qualified_path_type ()); + + for (auto &segment : path.get_segments ()) + visit (segment); +} + +void +PointerVisitor::visit (AST::QualifiedPathType &path) +{ + reseat (path.get_type_ptr ()); + if (path.has_as_clause ()) + visit (path.get_as_type_path ()); +} + +void +PointerVisitor::visit (AST::QualifiedPathInType &path) +{ + visit (path.get_qualified_path_type ()); + visit (path.get_associated_segment ()); + + for (auto &segment : path.get_segments ()) + visit (segment); +} + +void +PointerVisitor::visit (AST::LiteralExpr &expr) +{ + visit_outer_attrs (expr); +} + +void +PointerVisitor::visit (AST::AttrInputLiteral &attr_input) +{ + visit (attr_input.get_literal ()); +} + +void +PointerVisitor::visit (AST::AttrInputMacro &attr_input) +{ + visit (attr_input.get_macro ()); +} + +void +PointerVisitor::visit (AST::MetaItemLitExpr &meta_item) +{ + visit (meta_item.get_literal ()); +} + +void +PointerVisitor::visit (AST::SimplePath &path) +{ + for (auto &segment : path.get_segments ()) + visit (segment); +} + +void +PointerVisitor::visit (AST::MetaItemPathExpr &meta_item) +{ + visit (meta_item.get_path ()); + reseat (meta_item.get_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::BorrowExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_borrowed_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::DereferenceExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_dereferenced_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ErrorPropagationExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_propagating_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::NegationExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_negated_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ArithmeticOrLogicalExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_left_expr_ptr ()); + reseat (expr.get_right_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ComparisonExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_left_expr_ptr ()); + reseat (expr.get_right_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::LazyBooleanExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_left_expr_ptr ()); + reseat (expr.get_right_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::TypeCastExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_casted_expr_ptr ()); + reseat (expr.get_type_to_cast_to_ptr ()); +} + +void +PointerVisitor::visit (AST::AssignmentExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_left_expr_ptr ()); + reseat (expr.get_right_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::CompoundAssignmentExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_left_expr_ptr ()); + reseat (expr.get_right_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::GroupedExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + reseat (expr.get_expr_in_parens_ptr ()); +} + +void +PointerVisitor::visit (AST::ArrayElemsValues &elems) +{ + for (auto &value : elems.get_values ()) + reseat (value); +} + +void +PointerVisitor::visit (AST::ArrayElemsCopied &elems) +{ + reseat (elems.get_elem_to_copy_ptr ()); + reseat (elems.get_num_copies_ptr ()); +} + +void +PointerVisitor::visit (AST::ArrayExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + visit (expr.get_array_elems ()); +} + +void +PointerVisitor::visit (AST::ArrayIndexExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_array_expr_ptr ()); + reseat (expr.get_index_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::TupleExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + for (auto &elem : expr.get_tuple_elems ()) + reseat (elem); +} + +void +PointerVisitor::visit (AST::TupleIndexExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_tuple_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::StructExprStruct &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + visit (expr.get_struct_name ()); +} + +void +PointerVisitor::visit (AST::StructExprFieldIdentifier &field) +{} + +void +PointerVisitor::visit (AST::StructExprFieldIdentifierValue &field) +{ + reseat (field.get_value_ptr ()); +} + +void +PointerVisitor::visit (AST::StructExprFieldIndexValue &field) +{ + reseat (field.get_value_ptr ()); +} + +void +PointerVisitor::visit (AST::StructBase &base) +{ + reseat (base.get_base_struct_ptr ()); +} + +void +PointerVisitor::visit (AST::StructExprStructFields &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + visit (expr.get_struct_name ()); + if (expr.has_struct_base ()) + visit (expr.get_struct_base ()); + for (auto &field : expr.get_fields ()) + visit (field); +} + +void +PointerVisitor::visit (AST::StructExprStructBase &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + visit (expr.get_struct_name ()); + visit (expr.get_struct_base ()); +} + +void +PointerVisitor::visit (AST::CallExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_function_expr_ptr ()); + for (auto ¶m : expr.get_params ()) + reseat (param); +} + +void +PointerVisitor::visit (AST::MethodCallExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_receiver_expr_ptr ()); + visit (expr.get_method_name ()); + for (auto ¶m : expr.get_params ()) + reseat (param); +} + +void +PointerVisitor::visit (AST::FieldAccessExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_receiver_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ClosureExprInner &expr) +{ + visit_outer_attrs (expr); + + // TODO: Actually we need to handle macro invocations as closure parameters so + // this needs to be a reseat + for (auto ¶m : expr.get_params ()) + visit (param); + + reseat (expr.get_definition_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::BlockExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + + if (expr.has_label ()) + visit (expr.get_label ()); + + for (auto &stmt : expr.get_statements ()) + reseat (stmt); + + if (expr.has_tail_expr ()) + reseat (expr.get_tail_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ConstBlock &expr) +{ + visit (expr.get_const_expr ()); +} + +void +PointerVisitor::visit (AST::AnonConst &expr) +{ + if (!expr.is_deferred ()) + reseat (expr.get_inner_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ClosureExprInnerTyped &expr) +{ + visit_outer_attrs (expr); + + // TODO: Same as ClosureExprInner + for (auto ¶m : expr.get_params ()) + visit (param); + + reseat (expr.get_return_type_ptr ()); + + reseat (expr.get_definition_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ClosureParam ¶m) +{ + visit_outer_attrs (param); + reseat (param.get_pattern_ptr ()); + if (param.has_type_given ()) + reseat (param.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::ContinueExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_label ()) + visit (expr.get_label_unchecked ()); +} + +void +PointerVisitor::visit (AST::BreakExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_label ()) + visit (expr.get_label_unchecked ()); + + if (expr.has_break_expr ()) + reseat (expr.get_break_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::RangeFromToExpr &expr) +{ + reseat (expr.get_from_expr_ptr ()); + reseat (expr.get_to_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::RangeFromExpr &expr) +{ + reseat (expr.get_from_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::RangeToExpr &expr) +{ + reseat (expr.get_to_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::RangeFullExpr &expr) +{} + +void +PointerVisitor::visit (AST::RangeFromToInclExpr &expr) +{ + reseat (expr.get_from_expr_ptr ()); + reseat (expr.get_to_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::RangeToInclExpr &expr) +{ + reseat (expr.get_to_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ReturnExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_returned_expr ()) + reseat (expr.get_returned_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::TryExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_block_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::BoxExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_boxed_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::UnsafeBlockExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_block_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::LoopLabel &label) +{ + visit (label.get_lifetime ()); +} + +void +PointerVisitor::visit (AST::LoopExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + reseat (expr.get_loop_block_ptr ()); +} + +void +PointerVisitor::visit (AST::WhileLoopExpr &expr) +{ + visit_outer_attrs (expr); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + reseat (expr.get_predicate_expr_ptr ()); + reseat (expr.get_loop_block_ptr ()); +} + +void +PointerVisitor::visit (AST::WhileLetLoopExpr &expr) +{ + visit_outer_attrs (expr); + for (auto &pattern : expr.get_patterns ()) + reseat (pattern); + + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + + reseat (expr.get_scrutinee_expr_ptr ()); + reseat (expr.get_loop_block_ptr ()); +} + +void +PointerVisitor::visit (AST::ForLoopExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_pattern_ptr ()); + reseat (expr.get_iterator_expr_ptr ()); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); + reseat (expr.get_loop_block_ptr ()); +} + +void +PointerVisitor::visit (AST::IfExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_condition_expr_ptr ()); + visit (expr.get_if_block ()); +} + +void +PointerVisitor::visit (AST::IfExprConseqElse &expr) +{ + visit (reinterpret_cast<AST::IfExpr &> (expr)); + visit (expr.get_else_block ()); +} + +void +PointerVisitor::visit (AST::IfLetExpr &expr) +{ + visit_outer_attrs (expr); + for (auto &pattern : expr.get_patterns ()) + reseat (pattern); + reseat (expr.get_value_expr_ptr ()); + visit (expr.get_if_block ()); +} + +void +PointerVisitor::visit (AST::IfLetExprConseqElse &expr) +{ + visit (reinterpret_cast<AST::IfLetExpr &> (expr)); + visit (expr.get_else_block ()); +} + +void +PointerVisitor::visit (AST::MatchArm &arm) +{ + visit_outer_attrs (arm); + for (auto &pattern : arm.get_patterns ()) + reseat (pattern); + if (arm.has_match_arm_guard ()) + reseat (arm.get_guard_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::MatchCase &arm) +{ + visit (arm.get_arm ()); + reseat (arm.get_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::MatchExpr &expr) +{ + visit_outer_attrs (expr); + visit_inner_attrs (expr); + reseat (expr.get_scrutinee_expr_ptr ()); + for (auto &arm : expr.get_match_cases ()) + visit (arm); +} + +void +PointerVisitor::visit (AST::AwaitExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_awaited_expr ()); +} + +void +PointerVisitor::visit (AST::AsyncBlockExpr &expr) +{ + visit_outer_attrs (expr); + reseat (expr.get_block_expr ()); +} + +void +PointerVisitor::visit (AST::InlineAsm &expr) +{ + visit_outer_attrs (expr); + using RegisterType = AST::InlineAsmOperand::RegisterType; + for (auto &operand : expr.get_operands ()) + { + switch (operand.get_register_type ()) + { + case RegisterType::In: + { + reseat (operand.get_in ().expr); + break; + } + case RegisterType::Out: + { + reseat (operand.get_out ().expr); + break; + } + case RegisterType::InOut: + { + reseat (operand.get_in_out ().expr); + break; + } + case RegisterType::SplitInOut: + { + auto split = operand.get_split_in_out (); + reseat (split.in_expr); + reseat (split.out_expr); + break; + } + case RegisterType::Const: + { + reseat (operand.get_const ().anon_const.get_inner_expr_ptr ()); + break; + } + case RegisterType::Sym: + { + reseat (operand.get_sym ().expr); + break; + } + case RegisterType::Label: + { + reseat (operand.get_label ().expr); + break; + } + } + } +} + +void +PointerVisitor::visit (AST::LlvmInlineAsm &expr) +{ + for (auto &output : expr.get_outputs ()) + reseat (output.expr); + + for (auto &input : expr.get_inputs ()) + reseat (input.expr); +} + +void +PointerVisitor::visit (AST::TypeParam ¶m) +{ + visit_outer_attrs (param); + // FIXME: Can we do macro expansion here? + for (auto &bound : param.get_type_param_bounds ()) + visit (bound); + if (param.has_type ()) + reseat (param.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::LifetimeWhereClauseItem &item) +{ + visit (item.get_lifetime ()); + for (auto &bound : item.get_lifetime_bounds ()) + visit (bound); +} + +void +PointerVisitor::visit (AST::TypeBoundWhereClauseItem &item) +{ + for (auto &lifetime : item.get_for_lifetimes ()) + visit (lifetime); + reseat (item.get_type_ptr ()); + // FIXME: Likewise? + for (auto ¶m : item.get_type_param_bounds ()) + visit (param); +} + +void +PointerVisitor::visit (AST::Visibility &vis) +{ + if (vis.has_path ()) + visit (vis.get_path ()); +} + +void +PointerVisitor::visit (AST::WhereClause &where) +{ + for (auto &item : where.get_items ()) + visit (item); +} + +void +PointerVisitor::visit (AST::FunctionParam ¶m) +{ + visit_outer_attrs (param); + if (param.has_name ()) + reseat (param.get_pattern_ptr ()); + + reseat (param.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::SelfParam ¶m) +{ + visit_outer_attrs (param); + + if (param.has_lifetime ()) + visit (param.get_lifetime ()); + + if (param.has_type ()) + reseat (param.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::Module &module) +{ + visit_outer_attrs (module); + visit (module.get_visibility ()); + visit_inner_attrs (module); + for (auto &item : module.get_items ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::ExternCrate &crate) +{ + visit_outer_attrs (crate); + visit (crate.get_visibility ()); +} + +void +PointerVisitor::visit (AST::UseTreeGlob &use_tree) +{ + visit (use_tree.get_path ()); +} + +void +PointerVisitor::visit (AST::UseTreeList &use_tree) +{ + visit (use_tree.get_path ()); +} + +void +PointerVisitor::visit (AST::UseTreeRebind &use_tree) +{ + visit (use_tree.get_path ()); +} + +void +PointerVisitor::visit (AST::UseDeclaration &use_decl) +{ + visit (use_decl.get_visibility ()); + visit (use_decl.get_tree ()); +} + +void +PointerVisitor::visit_function_params (AST::Function &function) +{ + for (auto ¶m : function.get_function_params ()) + visit (param); +} + +void +PointerVisitor::visit (AST::Function &function) +{ + visit_outer_attrs (function); + visit (function.get_visibility ()); + visit (function.get_qualifiers ()); + for (auto &generic : function.get_generic_params ()) + visit (generic); + + visit_function_params (function); + + if (function.has_return_type ()) + reseat (function.get_return_type_ptr ()); + if (function.has_where_clause ()) + visit (function.get_where_clause ()); + if (function.has_body ()) + reseat (*function.get_definition ()); +} + +void +PointerVisitor::visit (AST::TypeAlias &type_alias) +{ + visit_outer_attrs (type_alias); + visit (type_alias.get_visibility ()); + for (auto &generic : type_alias.get_generic_params ()) + visit (generic); + if (type_alias.has_where_clause ()) + visit (type_alias.get_where_clause ()); + reseat (type_alias.get_type_aliased_ptr ()); +} + +void +PointerVisitor::visit (AST::StructField &field) +{ + visit_outer_attrs (field); + visit (field.get_visibility ()); + reseat (field.get_field_type_ptr ()); +} + +void +PointerVisitor::visit (AST::StructStruct &struct_item) +{ + visit_outer_attrs (struct_item); + visit (struct_item.get_visibility ()); + for (auto &generic : struct_item.get_generic_params ()) + visit (generic); + if (struct_item.has_where_clause ()) + visit (struct_item.get_where_clause ()); + for (auto &field : struct_item.get_fields ()) + visit (field); +} + +void +PointerVisitor::visit (AST::TupleField &field) +{ + visit_outer_attrs (field); + visit (field.get_visibility ()); + reseat (field.get_field_type_ptr ()); +} + +void +PointerVisitor::visit (AST::TupleStruct &tuple_struct) +{ + visit_outer_attrs (tuple_struct); + visit (tuple_struct.get_visibility ()); + for (auto &generic : tuple_struct.get_generic_params ()) + visit (generic); + if (tuple_struct.has_where_clause ()) + visit (tuple_struct.get_where_clause ()); + for (auto &field : tuple_struct.get_fields ()) + visit (field); +} + +void +PointerVisitor::visit (AST::EnumItem &item) +{ + visit_outer_attrs (item); + visit (item.get_visibility ()); +} + +void +PointerVisitor::visit (AST::EnumItemTuple &item) +{ + PointerVisitor::visit (static_cast<EnumItem &> (item)); + for (auto &field : item.get_tuple_fields ()) + visit (field); +} + +void +PointerVisitor::visit (AST::EnumItemStruct &item) +{ + PointerVisitor::visit (static_cast<EnumItem &> (item)); + for (auto &field : item.get_struct_fields ()) + visit (field); +} + +void +PointerVisitor::visit (AST::EnumItemDiscriminant &item) +{ + PointerVisitor::visit (static_cast<EnumItem &> (item)); + reseat (item.get_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::Enum &enum_item) +{ + visit_outer_attrs (enum_item); + visit (enum_item.get_visibility ()); + for (auto &generic : enum_item.get_generic_params ()) + visit (generic); + if (enum_item.has_where_clause ()) + visit (enum_item.get_where_clause ()); + for (auto &item : enum_item.get_variants ()) + visit (item); +} + +void +PointerVisitor::visit (AST::Union &union_item) +{ + visit_outer_attrs (union_item); + visit (union_item.get_visibility ()); + for (auto &generic : union_item.get_generic_params ()) + visit (generic); + if (union_item.has_where_clause ()) + visit (union_item.get_where_clause ()); + for (auto &variant : union_item.get_variants ()) + visit (variant); +} + +void +PointerVisitor::visit (AST::ConstantItem &const_item) +{ + visit_outer_attrs (const_item); + visit (const_item.get_visibility ()); + reseat (const_item.get_type_ptr ()); + if (const_item.has_expr ()) + reseat (const_item.get_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::StaticItem &static_item) +{ + visit_outer_attrs (static_item); + visit (static_item.get_visibility ()); + reseat (static_item.get_type_ptr ()); + reseat (static_item.get_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::TraitItemType &item) +{ + visit_outer_attrs (item); + for (auto &bound : item.get_type_param_bounds ()) + visit (bound); +} + +void +PointerVisitor::visit (AST::Trait &trait) +{ + visit_outer_attrs (trait); + visit (trait.get_visibility ()); + + visit_inner_attrs (trait); + + visit (trait.get_implicit_self ()); + + for (auto &generic : trait.get_generic_params ()) + visit (generic); + + if (trait.has_where_clause ()) + visit (trait.get_where_clause ()); + + for (auto &bound : trait.get_type_param_bounds ()) + visit (bound); + + for (auto &item : trait.get_trait_items ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::InherentImpl &impl) +{ + visit_outer_attrs (impl); + visit (impl.get_visibility ()); + + for (auto &generic : impl.get_generic_params ()) + visit (generic); + if (impl.has_where_clause ()) + visit (impl.get_where_clause ()); + reseat (impl.get_type_ptr ()); + visit_inner_attrs (impl); + for (auto &item : impl.get_impl_items ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::TraitImpl &impl) +{ + visit_outer_attrs (impl); + visit (impl.get_visibility ()); + + for (auto &generic : impl.get_generic_params ()) + visit (generic); + if (impl.has_where_clause ()) + visit (impl.get_where_clause ()); + reseat (impl.get_type_ptr ()); + visit (impl.get_trait_path ()); + visit_inner_attrs (impl); + for (auto &item : impl.get_impl_items ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::ExternalTypeItem &item) +{ + visit_outer_attrs (item); + visit (item.get_visibility ()); +} + +void +PointerVisitor::visit (AST::ExternalStaticItem &item) +{ + visit_outer_attrs (item); + visit (item.get_visibility ()); + reseat (item.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::ExternBlock &block) +{ + visit_outer_attrs (block); + visit (block.get_visibility ()); + visit_inner_attrs (block); + for (auto &item : block.get_extern_items ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::MacroMatchFragment &match) +{} + +void +PointerVisitor::visit (AST::MacroMatchRepetition &match) +{ + for (auto &m : match.get_matches ()) + visit (m); +} + +void +PointerVisitor::visit (AST::MacroMatcher &matcher) +{ + for (auto &m : matcher.get_matches ()) + visit (m); +} + +void +PointerVisitor::visit (AST::MacroTranscriber &transcriber) +{ + visit (transcriber.get_token_tree ()); +} + +void +PointerVisitor::visit (AST::MacroRule &rule) +{ + visit (rule.get_matcher ()); + visit (rule.get_transcriber ()); +} + +void +PointerVisitor::visit (AST::MacroRulesDefinition &rules_def) +{ + visit_outer_attrs (rules_def); + for (auto &rule : rules_def.get_macro_rules ()) + visit (rule); +} + +void +PointerVisitor::visit (AST::MacroInvocData &data) +{ + visit (data.get_path ()); + visit (data.get_delim_tok_tree ()); +} + +void +PointerVisitor::visit (AST::MacroInvocation ¯o_invoc) +{ + visit_outer_attrs (macro_invoc); + visit (macro_invoc.get_invoc_data ()); +} + +void +PointerVisitor::visit (AST::MetaItemPath &meta_item) +{ + visit (meta_item.get_path ()); +} + +void +PointerVisitor::visit (AST::MetaItemSeq &meta_item) +{ + visit (meta_item.get_path ()); + for (auto &inner : meta_item.get_seq ()) + visit (inner); +} + +void +PointerVisitor::visit (AST::MetaListPaths &meta_item) +{ + for (auto &path : meta_item.get_paths ()) + visit (path); +} + +void +PointerVisitor::visit (AST::MetaListNameValueStr &meta_item) +{ + for (auto &str : meta_item.get_values ()) + visit (str); +} + +void +PointerVisitor::visit (AST::IdentifierPattern &pattern) +{ + if (pattern.has_subpattern ()) + reseat (pattern.get_subpattern_ptr ()); +} + +void +PointerVisitor::visit (AST::RangePatternBoundPath &bound) +{ + visit (bound.get_path ()); +} + +void +PointerVisitor::visit (AST::RangePatternBoundQualPath &bound) +{ + visit (bound.get_qualified_path ()); +} + +void +PointerVisitor::visit (AST::RangePattern &pattern) +{ + // FIXME: So should this be reseat() instead? Can we have macro invocations as + // patterns in range patterns? + if (pattern.get_has_lower_bound ()) + visit (pattern.get_lower_bound ()); + if (pattern.get_has_upper_bound ()) + visit (pattern.get_upper_bound ()); +} + +void +PointerVisitor::visit (AST::ReferencePattern &pattern) +{ + reseat (pattern.get_referenced_pattern_ptr ()); +} + +void +PointerVisitor::visit (AST::StructPatternFieldTuplePat &field) +{ + visit_outer_attrs (field); + reseat (field.get_index_pattern_ptr ()); +} + +void +PointerVisitor::visit (AST::StructPatternFieldIdentPat &field) +{ + visit_outer_attrs (field); + reseat (field.get_ident_pattern_ptr ()); +} + +void +PointerVisitor::visit (AST::StructPatternFieldIdent &field) +{ + visit_outer_attrs (field); +} + +void +PointerVisitor::visit (AST::StructPatternElements &spe) +{ + for (auto &field : spe.get_struct_pattern_fields ()) + visit (field); + for (auto &attribute : spe.get_etc_outer_attrs ()) + visit (attribute); +} + +void +PointerVisitor::visit (AST::StructPattern &pattern) +{ + visit (pattern.get_path ()); + visit (pattern.get_struct_pattern_elems ()); +} + +void +PointerVisitor::visit (AST::TupleStructItemsNoRest &tuple_items) +{ + for (auto &pattern : tuple_items.get_patterns ()) + reseat (pattern); +} + +void +PointerVisitor::visit (AST::TupleStructItemsHasRest &tuple_items) +{ + for (auto &lower : tuple_items.get_lower_patterns ()) + reseat (lower); + for (auto &upper : tuple_items.get_upper_patterns ()) + reseat (upper); +} + +void +PointerVisitor::visit (AST::TupleStructPattern &pattern) +{ + visit (pattern.get_path ()); + visit (pattern.get_items ()); +} + +void +PointerVisitor::visit (AST::TuplePatternItemsNoRest &tuple_items) +{ + for (auto &pattern : tuple_items.get_patterns ()) + reseat (pattern); +} + +void +PointerVisitor::visit (AST::TuplePatternItemsHasRest &tuple_items) +{ + for (auto &lower : tuple_items.get_lower_patterns ()) + reseat (lower); + for (auto &upper : tuple_items.get_upper_patterns ()) + reseat (upper); +} + +void +PointerVisitor::visit (AST::TuplePattern &pattern) +{ + visit (pattern.get_items ()); +} + +void +PointerVisitor::visit (AST::GroupedPattern &pattern) +{ + reseat (pattern.get_pattern_in_parens_ptr ()); +} + +void +PointerVisitor::visit (AST::SlicePatternItemsNoRest &items) +{ + for (auto &item : items.get_patterns ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::SlicePatternItemsHasRest &items) +{ + for (auto &item : items.get_lower_patterns ()) + reseat (item); + for (auto &item : items.get_upper_patterns ()) + reseat (item); +} + +void +PointerVisitor::visit (AST::SlicePattern &pattern) +{ + visit (pattern.get_items ()); +} + +void +PointerVisitor::visit (AST::AltPattern &pattern) +{ + for (auto &alt : pattern.get_alts ()) + reseat (alt); +} + +void +PointerVisitor::visit (AST::EmptyStmt &stmt) +{} + +void +PointerVisitor::visit (AST::LetStmt &stmt) +{ + visit_outer_attrs (stmt); + reseat (stmt.get_pattern_ptr ()); + if (stmt.has_type ()) + reseat (stmt.get_type_ptr ()); + if (stmt.has_init_expr ()) + reseat (stmt.get_init_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::ExprStmt &stmt) +{ + reseat (stmt.get_expr_ptr ()); +} + +void +PointerVisitor::visit (AST::TraitBound &bound) +{ + for (auto &lifetime : bound.get_for_lifetimes ()) + visit (lifetime); + visit (bound.get_type_path ()); +} + +void +PointerVisitor::visit (AST::ImplTraitType &type) +{ + for (auto &bound : type.get_type_param_bounds ()) + visit (bound); +} + +void +PointerVisitor::visit (AST::TraitObjectType &type) +{ + for (auto &bound : type.get_type_param_bounds ()) + visit (bound); +} + +void +PointerVisitor::visit (AST::ParenthesisedType &type) +{ + reseat (type.get_type_in_parens ()); +} + +void +PointerVisitor::visit (AST::ImplTraitTypeOneBound &type) +{ + // FIXME: Do we need to reseat here? + visit (type.get_trait_bound ()); +} + +void +PointerVisitor::visit (AST::TraitObjectTypeOneBound &type) +{ + // FIXME: Do we need to reseat here? + visit (type.get_trait_bound ()); +} + +void +PointerVisitor::visit (AST::TupleType &type) +{ + for (auto &elem : type.get_elems ()) + reseat (elem); +} + +void +PointerVisitor::visit (AST::NeverType &type) +{} + +void +PointerVisitor::visit (AST::RawPointerType &type) +{ + reseat (type.get_type_pointed_to_ptr ()); +} + +void +PointerVisitor::visit (AST::ReferenceType &type) +{ + visit (type.get_lifetime ()); + reseat (type.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::ArrayType &type) +{ + reseat (type.get_elem_type_ptr ()); + visit (type.get_size_expr ()); +} + +void +PointerVisitor::visit (AST::SliceType &type) +{ + reseat (type.get_elem_type_ptr ()); +} + +void +PointerVisitor::visit (AST::InferredType &type) +{} + +void +PointerVisitor::visit (AST::MaybeNamedParam ¶m) +{ + visit_outer_attrs (param); + reseat (param.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::BareFunctionType &type) +{ + for (auto &lifetime : type.get_for_lifetimes ()) + visit (lifetime); + visit (type.get_function_qualifiers ()); + for (auto ¶m : type.get_function_params ()) + visit (param); + if (type.is_variadic ()) + for (auto attr : type.get_variadic_attr ()) + visit (attr); + if (type.has_return_type ()) + reseat (type.get_return_type_ptr ()); +} + +void +PointerVisitor::visit (AST::FormatArgs &) +{ + // FIXME: Do we have anything to do? any subnodes to visit? Probably, right? +} + +void +PointerVisitor::visit (AST::OffsetOf &offset_of) +{ + reseat (offset_of.get_type_ptr ()); +} + +void +PointerVisitor::visit (AST::VariadicParam ¶m) +{ + if (param.has_pattern ()) + reseat (param.get_pattern_ptr ()); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-ast-pointer-visitor.h b/gcc/rust/ast/rust-ast-pointer-visitor.h new file mode 100644 index 0000000..8c12b4e --- /dev/null +++ b/gcc/rust/ast/rust-ast-pointer-visitor.h @@ -0,0 +1,234 @@ +// 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_AST_POINTER_VISITOR_H +#define RUST_AST_POINTER_VISITOR_H + +#include "rust-ast-visitor.h" +#include "rust-ast.h" +#include "rust-item.h" + +namespace Rust { +namespace AST { + +/** + * Regular AST visitor which may reseat pointers when necessary. + */ +class PointerVisitor : public DefaultASTVisitor +{ +public: + using DefaultASTVisitor::visit; + + virtual void reseat (std::unique_ptr<AST::Expr> &ptr) { visit (ptr); } + virtual void reseat (std::unique_ptr<AST::BlockExpr> &ptr) { visit (ptr); } + + virtual void reseat (std::unique_ptr<AST::Stmt> &ptr) { visit (ptr); } + + virtual void reseat (std::unique_ptr<AST::Item> &ptr) { visit (ptr); } + + virtual void reseat (std::unique_ptr<AST::AssociatedItem> &ptr) + { + visit (ptr); + } + + virtual void reseat (std::unique_ptr<AST::ExternalItem> &ptr) { visit (ptr); } + + virtual void reseat (std::unique_ptr<AST::Type> &ptr) { visit (ptr); } + + virtual void reseat (std::unique_ptr<AST::TypeNoBounds> &ptr) { visit (ptr); } + + virtual void reseat (std::unique_ptr<AST::Pattern> &ptr) { visit (ptr); } + + void visit (AST::Crate &crate) override; + void visit (AST::AttrInputMetaItemContainer &input) override; + void visit (AST::IdentifierExpr &ident_expr) override; + void visit (AST::LifetimeParam &lifetime_param) override; + void visit (AST::ConstGenericParam &const_param) override; + void visit (AST::PathInExpression &path) override; + void visit (GenericArgsBinding &binding) override; + void visit (AST::TypePathSegmentGeneric &segment) override; + void visit (AST::TypePathFunction &tpf) override; + void visit (AST::TypePathSegmentFunction &segment) override; + void visit (AST::GenericArgs &args) override; + void visit (AST::PathExprSegment &segment) override; + void visit (AST::TypePath &path) override; + void visit (AST::QualifiedPathInExpression &path) override; + void visit (AST::QualifiedPathType &path) override; + void visit (AST::QualifiedPathInType &path) override; + void visit (AST::LiteralExpr &expr) override; + void visit (AST::AttrInputLiteral &attr_input) override; + void visit (AST::AttrInputMacro &attr_input) override; + void visit (AST::MetaItemLitExpr &meta_item) override; + void visit (AST::SimplePath &path) override; + void visit (AST::MetaItemPathExpr &meta_item) override; + void visit (AST::BorrowExpr &expr) override; + void visit (AST::DereferenceExpr &expr) override; + void visit (AST::ErrorPropagationExpr &expr) override; + void visit (AST::NegationExpr &expr) override; + void visit (AST::ArithmeticOrLogicalExpr &expr) override; + void visit (AST::ComparisonExpr &expr) override; + void visit (AST::LazyBooleanExpr &expr) override; + void visit (AST::TypeCastExpr &expr) override; + void visit (AST::AssignmentExpr &expr) override; + void visit (AST::CompoundAssignmentExpr &expr) override; + void visit (AST::GroupedExpr &expr) override; + void visit (AST::ArrayElemsValues &elems) override; + void visit (AST::ArrayElemsCopied &elems) override; + void visit (AST::ArrayExpr &expr) override; + void visit (AST::ArrayIndexExpr &expr) override; + void visit (AST::TupleExpr &expr) override; + void visit (AST::TupleIndexExpr &expr) override; + void visit (AST::StructExprStruct &expr) override; + void visit (AST::StructExprFieldIdentifier &field) override; + void visit (AST::StructExprFieldIdentifierValue &field) override; + void visit (AST::StructExprFieldIndexValue &field) override; + void visit (AST::StructBase &base) override; + void visit (AST::StructExprStructFields &expr) override; + void visit (AST::StructExprStructBase &expr) override; + void visit (AST::CallExpr &expr) override; + void visit (AST::MethodCallExpr &expr) override; + void visit (AST::FieldAccessExpr &expr) override; + void visit (AST::ClosureExprInner &expr) override; + void visit (AST::BlockExpr &expr) override; + void visit (AST::ConstBlock &expr) override; + void visit (AST::AnonConst &expr) override; + void visit (AST::ClosureExprInnerTyped &expr) override; + void visit (AST::ClosureParam ¶m) override; + void visit (AST::ContinueExpr &expr) override; + void visit (AST::BreakExpr &expr) override; + void visit (AST::RangeFromToExpr &expr) override; + void visit (AST::RangeFromExpr &expr) override; + void visit (AST::RangeToExpr &expr) override; + void visit (AST::RangeFullExpr &expr) override; + void visit (AST::RangeFromToInclExpr &expr) override; + void visit (AST::RangeToInclExpr &expr) override; + void visit (AST::ReturnExpr &expr) override; + void visit (AST::TryExpr &expr) override; + void visit (AST::BoxExpr &expr) override; + void visit (AST::UnsafeBlockExpr &expr) override; + void visit (AST::LoopLabel &label) override; + void visit (AST::LoopExpr &expr) override; + void visit (AST::WhileLoopExpr &expr) override; + void visit (AST::WhileLetLoopExpr &expr) override; + void visit (AST::ForLoopExpr &expr) override; + void visit (AST::IfExpr &expr) override; + void visit (AST::IfExprConseqElse &expr) override; + void visit (AST::IfLetExpr &expr) override; + void visit (AST::IfLetExprConseqElse &expr) override; + void visit (AST::MatchArm &arm) override; + void visit (AST::MatchCase &arm) override; + void visit (AST::MatchExpr &expr) override; + void visit (AST::AwaitExpr &expr) override; + void visit (AST::AsyncBlockExpr &expr) override; + void visit (AST::InlineAsm &expr) override; + void visit (AST::LlvmInlineAsm &expr) override; + void visit (AST::TypeParam ¶m) override; + void visit (AST::LifetimeWhereClauseItem &item) override; + void visit (AST::TypeBoundWhereClauseItem &item) override; + void visit (AST::Visibility &vis) override; + void visit (AST::WhereClause &where) override; + void visit (AST::FunctionParam ¶m) override; + void visit (AST::SelfParam ¶m) override; + void visit (AST::Module &module) override; + void visit (AST::ExternCrate &crate) override; + void visit (AST::UseTreeGlob &use_tree) override; + void visit (AST::UseTreeList &use_tree) override; + void visit (AST::UseTreeRebind &use_tree) override; + void visit (AST::UseDeclaration &use_decl) override; + void visit_function_params (AST::Function &function) override; + void visit (AST::Function &function) override; + void visit (AST::TypeAlias &type_alias) override; + void visit (AST::StructField &field) override; + void visit (AST::StructStruct &struct_item) override; + void visit (AST::TupleField &field) override; + void visit (AST::TupleStruct &tuple_struct) 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; + void visit (AST::Enum &enum_item) override; + void visit (AST::Union &union_item) override; + void visit (AST::ConstantItem &const_item) override; + void visit (AST::StaticItem &static_item) override; + void visit (AST::TraitItemType &item) override; + void visit (AST::Trait &trait) override; + void visit (AST::InherentImpl &impl) override; + void visit (AST::TraitImpl &impl) override; + void visit (AST::ExternalTypeItem &item) override; + void visit (AST::ExternalStaticItem &item) override; + void visit (AST::ExternBlock &block) override; + void visit (AST::MacroMatchFragment &match) override; + void visit (AST::MacroMatchRepetition &match) override; + void visit (AST::MacroMatcher &matcher) override; + void visit (AST::MacroTranscriber &transcriber) override; + void visit (AST::MacroRule &rule) override; + void visit (AST::MacroRulesDefinition &rules_def) override; + void visit (AST::MacroInvocData &data) override; + void visit (AST::MacroInvocation ¯o_invoc) override; + void visit (AST::MetaItemPath &meta_item) override; + void visit (AST::MetaItemSeq &meta_item) override; + void visit (AST::MetaListPaths &meta_item) override; + void visit (AST::MetaListNameValueStr &meta_item) override; + void visit (AST::IdentifierPattern &pattern) override; + void visit (AST::RangePatternBoundPath &bound) override; + void visit (AST::RangePatternBoundQualPath &bound) override; + void visit (AST::RangePattern &pattern) override; + void visit (AST::ReferencePattern &pattern) override; + void visit (AST::StructPatternFieldTuplePat &field) override; + void visit (AST::StructPatternFieldIdentPat &field) override; + void visit (AST::StructPatternFieldIdent &field) override; + void visit (AST::StructPatternElements &spe) override; + void visit (AST::StructPattern &pattern) override; + void visit (AST::TupleStructItemsNoRest &tuple_items) override; + void visit (AST::TupleStructItemsHasRest &tuple_items) override; + void visit (AST::TupleStructPattern &pattern) override; + void visit (AST::TuplePatternItemsNoRest &tuple_items) override; + void visit (AST::TuplePatternItemsHasRest &tuple_items) override; + void visit (AST::TuplePattern &pattern) override; + void visit (AST::GroupedPattern &pattern) override; + void visit (AST::SlicePatternItemsNoRest &items) override; + void visit (AST::SlicePatternItemsHasRest &items) override; + void visit (AST::SlicePattern &pattern) override; + void visit (AST::AltPattern &pattern) override; + void visit (AST::EmptyStmt &stmt) override; + void visit (AST::LetStmt &stmt) override; + void visit (AST::ExprStmt &stmt) override; + void visit (AST::TraitBound &bound) override; + void visit (AST::ImplTraitType &type) override; + void visit (AST::TraitObjectType &type) override; + void visit (AST::ParenthesisedType &type) override; + void visit (AST::ImplTraitTypeOneBound &type) override; + void visit (AST::TraitObjectTypeOneBound &type) override; + void visit (AST::TupleType &type) override; + void visit (AST::NeverType &type) override; + void visit (AST::RawPointerType &type) override; + void visit (AST::ReferenceType &type) override; + void visit (AST::ArrayType &type) override; + void visit (AST::SliceType &type) override; + void visit (AST::InferredType &type) override; + void visit (AST::MaybeNamedParam ¶m) override; + void visit (AST::BareFunctionType &type) override; + void visit (AST::FormatArgs &) override; + void visit (AST::OffsetOf &offset_of) override; + void visit (AST::VariadicParam ¶m) override; +}; + +} // namespace AST +} // namespace Rust + +#endif diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index ab8cdbe..afdd2b1 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -248,6 +248,7 @@ void DefaultASTVisitor::visit (AST::ErrorPropagationExpr &expr) { visit_outer_attrs (expr); + visit (expr.get_propagating_expr ()); } void @@ -1025,15 +1026,6 @@ DefaultASTVisitor::visit (AST::StaticItem &static_item) } void -DefaultASTVisitor::visit (AST::TraitItemConst &item) -{ - visit_outer_attrs (item); - visit (item.get_type ()); - if (item.has_expr ()) - visit (item.get_expr ()); -} - -void DefaultASTVisitor::visit (AST::TraitItemType &item) { visit_outer_attrs (item); @@ -1296,14 +1288,14 @@ DefaultASTVisitor::visit (AST::StructPattern &pattern) } void -DefaultASTVisitor::visit (AST::TupleStructItemsNoRange &tuple_items) +DefaultASTVisitor::visit (AST::TupleStructItemsNoRest &tuple_items) { for (auto &pattern : tuple_items.get_patterns ()) visit (pattern); } void -DefaultASTVisitor::visit (AST::TupleStructItemsRange &tuple_items) +DefaultASTVisitor::visit (AST::TupleStructItemsHasRest &tuple_items) { for (auto &lower : tuple_items.get_lower_patterns ()) visit (lower); @@ -1319,14 +1311,14 @@ DefaultASTVisitor::visit (AST::TupleStructPattern &pattern) } void -DefaultASTVisitor::visit (AST::TuplePatternItemsMultiple &tuple_items) +DefaultASTVisitor::visit (AST::TuplePatternItemsNoRest &tuple_items) { for (auto &pattern : tuple_items.get_patterns ()) visit (pattern); } void -DefaultASTVisitor::visit (AST::TuplePatternItemsRanged &tuple_items) +DefaultASTVisitor::visit (AST::TuplePatternItemsHasRest &tuple_items) { for (auto &lower : tuple_items.get_lower_patterns ()) visit (lower); diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index 2d81aa1..a7a2ac4 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -164,7 +164,6 @@ public: virtual void visit (Union &union_item) = 0; virtual void visit (ConstantItem &const_item) = 0; virtual void visit (StaticItem &static_item) = 0; - virtual void visit (TraitItemConst &item) = 0; virtual void visit (TraitItemType &item) = 0; virtual void visit (Trait &trait) = 0; virtual void visit (InherentImpl &impl) = 0; @@ -204,12 +203,12 @@ public: virtual void visit (StructPatternFieldIdent &field) = 0; virtual void visit (StructPattern &pattern) = 0; // virtual void visit(TupleStructItems& tuple_items) = 0; - virtual void visit (TupleStructItemsNoRange &tuple_items) = 0; - virtual void visit (TupleStructItemsRange &tuple_items) = 0; + virtual void visit (TupleStructItemsNoRest &tuple_items) = 0; + virtual void visit (TupleStructItemsHasRest &tuple_items) = 0; virtual void visit (TupleStructPattern &pattern) = 0; // virtual void visit(TuplePatternItems& tuple_items) = 0; - virtual void visit (TuplePatternItemsMultiple &tuple_items) = 0; - virtual void visit (TuplePatternItemsRanged &tuple_items) = 0; + virtual void visit (TuplePatternItemsNoRest &tuple_items) = 0; + virtual void visit (TuplePatternItemsHasRest &tuple_items) = 0; virtual void visit (TuplePattern &pattern) = 0; virtual void visit (GroupedPattern &pattern) = 0; virtual void visit (SlicePatternItemsNoRest &items) = 0; @@ -349,7 +348,6 @@ public: virtual void visit (AST::Union &union_item) override; virtual void visit (AST::ConstantItem &const_item) override; virtual void visit (AST::StaticItem &static_item) override; - virtual void visit (AST::TraitItemConst &item) override; virtual void visit (AST::TraitItemType &item) override; virtual void visit (AST::Trait &trait) override; virtual void visit (AST::InherentImpl &impl) override; @@ -381,11 +379,11 @@ public: virtual void visit (AST::StructPatternFieldIdentPat &field) override; virtual void visit (AST::StructPatternFieldIdent &field) override; virtual void visit (AST::StructPattern &pattern) override; - virtual void visit (AST::TupleStructItemsNoRange &tuple_items) override; - virtual void visit (AST::TupleStructItemsRange &tuple_items) override; + virtual void visit (AST::TupleStructItemsNoRest &tuple_items) override; + virtual void visit (AST::TupleStructItemsHasRest &tuple_items) override; virtual void visit (AST::TupleStructPattern &pattern) override; - virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override; + virtual void visit (AST::TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (AST::TuplePatternItemsHasRest &tuple_items) override; virtual void visit (AST::TuplePattern &pattern) override; virtual void visit (AST::GroupedPattern &pattern) override; virtual void visit (AST::SlicePatternItemsNoRest &items) override; diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 8e856fb..337a338 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -48,29 +48,33 @@ SingleASTNode::SingleASTNode (SingleASTNode const &other) kind = other.kind; switch (kind) { - case EXPRESSION: + case Kind::Expr: expr = other.expr->clone_expr (); break; - case ITEM: + case Kind::Item: item = other.item->clone_item (); break; - case STMT: + case Kind::Stmt: stmt = other.stmt->clone_stmt (); break; - case EXTERN: + case Kind::Extern: external_item = other.external_item->clone_external_item (); break; - case ASSOC_ITEM: + case Kind::Assoc: assoc_item = other.assoc_item->clone_associated_item (); break; - case TYPE: + case Kind::Type: type = other.type->clone_type (); break; + + case Kind::Pattern: + pattern = other.pattern->clone_pattern (); + break; } } @@ -80,29 +84,33 @@ SingleASTNode::operator= (SingleASTNode const &other) kind = other.kind; switch (kind) { - case EXPRESSION: + case Kind::Expr: expr = other.expr->clone_expr (); break; - case ITEM: + case Kind::Item: item = other.item->clone_item (); break; - case STMT: + case Kind::Stmt: stmt = other.stmt->clone_stmt (); break; - case EXTERN: + case Kind::Extern: external_item = other.external_item->clone_external_item (); break; - case ASSOC_ITEM: + case Kind::Assoc: assoc_item = other.assoc_item->clone_associated_item (); break; - case TYPE: + case Kind::Type: type = other.type->clone_type (); break; + + case Kind::Pattern: + pattern = other.pattern->clone_pattern (); + break; } return *this; } @@ -112,29 +120,33 @@ SingleASTNode::accept_vis (ASTVisitor &vis) { switch (kind) { - case EXPRESSION: + case Kind::Expr: expr->accept_vis (vis); break; - case ITEM: + case Kind::Item: item->accept_vis (vis); break; - case STMT: + case Kind::Stmt: stmt->accept_vis (vis); break; - case EXTERN: + case Kind::Extern: external_item->accept_vis (vis); break; - case ASSOC_ITEM: + case Kind::Assoc: assoc_item->accept_vis (vis); break; - case TYPE: + case Kind::Type: type->accept_vis (vis); break; + + case Kind::Pattern: + pattern->accept_vis (vis); + break; } } @@ -143,18 +155,20 @@ SingleASTNode::is_error () { switch (kind) { - case EXPRESSION: + case Kind::Expr: return expr == nullptr; - case ITEM: + case Kind::Item: return item == nullptr; - case STMT: + case Kind::Stmt: return stmt == nullptr; - case EXTERN: + case Kind::Extern: return external_item == nullptr; - case ASSOC_ITEM: + case Kind::Assoc: return assoc_item == nullptr; - case TYPE: + case Kind::Type: return type == nullptr; + case Kind::Pattern: + return pattern == nullptr; } rust_unreachable (); @@ -166,18 +180,20 @@ SingleASTNode::as_string () const { switch (kind) { - case EXPRESSION: + case Kind::Expr: return "Expr: " + expr->as_string (); - case ITEM: + case Kind::Item: return "Item: " + item->as_string (); - case STMT: + case Kind::Stmt: return "Stmt: " + stmt->as_string (); - case EXTERN: + case Kind::Extern: return "External Item: " + external_item->as_string (); - case ASSOC_ITEM: + case Kind::Assoc: return "Associated Item: " + assoc_item->as_string (); - case TYPE: + case Kind::Type: return "Type: " + type->as_string (); + case Kind::Pattern: + return "Pattern: " + pattern->as_string (); } rust_unreachable (); @@ -232,7 +248,7 @@ Attribute::as_string () const bool Attribute::is_derive () const { - return has_attr_input () && get_path () == "derive"; + return has_attr_input () && get_path () == Values::Attributes::DERIVE; } /** @@ -389,7 +405,7 @@ DelimTokenTree::as_string () const std::string Token::as_string () const { - if (tok_ref->has_str ()) + if (tok_ref->should_have_str ()) { std::string str = tok_ref->get_str (); @@ -636,14 +652,8 @@ ConstantItem::as_string () const } str += "\n Type: " + type->as_string (); - // DEBUG: null pointer check - if (const_expr == nullptr) - { - rust_debug ("something really terrible has gone wrong - null " - "pointer expr in const item."); - return "NULL_POINTER_MARK"; - } - str += "\n Expression: " + const_expr->as_string (); + if (has_expr ()) + str += "\n Expression: " + const_expr->as_string (); return str + "\n"; } @@ -3034,20 +3044,6 @@ ExternalStaticItem::as_string () const } std::string -TraitItemConst::as_string () const -{ - // TODO: rewrite to work with non-linearisable exprs - std::string str = append_attributes (outer_attrs, OUTER); - - str += "\nconst " + name.as_string () + " : " + type->as_string (); - - if (has_expression ()) - str += " = " + expr->as_string (); - - return str; -} - -std::string TraitItemType::as_string () const { std::string str = append_attributes (outer_attrs, OUTER); @@ -3367,7 +3363,13 @@ void Module::process_file_path () { rust_assert (kind == Module::ModuleKind::UNLOADED); - rust_assert (module_file.empty ()); + + if (!module_file.empty ()) + { + rust_error_at (locus, "error handling module file for %qs", + module_name.as_string ().c_str ()); + return; + } // This corresponds to the path of the file 'including' the module. So the // file that contains the 'mod <file>;' directive @@ -4132,6 +4134,12 @@ AttrInputMetaItemContainer::separate_cfg_attrs () const for (auto it = items.begin () + 1; it != items.end (); ++it) { + if ((*it)->get_kind () == MetaItemInner::Kind::MetaItem + && static_cast<MetaItem &> (**it).get_item_kind () + == MetaItem::ItemKind::PathExpr + && !static_cast<MetaItemPathExpr &> (**it).get_expr ().is_literal ()) + continue; + Attribute attr = (*it)->to_attribute (); if (attr.is_empty ()) { @@ -4149,11 +4157,12 @@ AttrInputMetaItemContainer::separate_cfg_attrs () const bool Attribute::check_cfg_predicate (const Session &session) const { + auto string_path = path.as_string (); /* assume that cfg predicate actually can exist, i.e. attribute has cfg or * cfg_attr path */ if (!has_attr_input () - || (path.as_string () != Values::Attributes::CFG - && path.as_string () != Values::Attributes::CFG_ATTR)) + || (string_path != Values::Attributes::CFG + && string_path != Values::Attributes::CFG_ATTR)) { // DEBUG message rust_debug ( @@ -4169,6 +4178,13 @@ Attribute::check_cfg_predicate (const Session &session) const return false; auto &meta_item = static_cast<AttrInputMetaItemContainer &> (*attr_input); + if (meta_item.get_items ().empty () + && string_path == Values::Attributes::CFG_ATTR) + { + rust_error_at (path.get_locus (), + "malformed %<cfg_attr%> attribute input"); + return false; + } return meta_item.get_items ().front ()->check_cfg_predicate (session); } @@ -4740,12 +4756,6 @@ StaticItem::accept_vis (ASTVisitor &vis) } void -TraitItemConst::accept_vis (ASTVisitor &vis) -{ - vis.visit (*this); -} - -void TraitItemType::accept_vis (ASTVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 2d2c5d0..8a7e618 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -184,17 +184,6 @@ class Token : public TokenTree, public MacroMatch { // A token is a kind of token tree (except delimiter tokens) // A token is a kind of MacroMatch (except $ and delimiter tokens) -#if 0 - // TODO: improve member variables - current ones are the same as lexer token - // Token kind. - TokenId token_id; - // Token location. - location_t locus; - // Associated text (if any) of token. - std::string str; - // Token type hint (if any). - PrimitiveCoreType type_hint; -#endif const_TokenPtr tok_ref; @@ -209,53 +198,7 @@ public: return std::unique_ptr<Token> (clone_token_impl ()); } -#if 0 - /* constructor from general text - avoid using if lexer const_TokenPtr is - * available */ - Token (TokenId token_id, location_t locus, std::string str, - PrimitiveCoreType type_hint) - : token_id (token_id), locus (locus), str (std::move (str)), - type_hint (type_hint) - {} -#endif - // not doable with new implementation - will have to make a const_TokenPtr - // Constructor from lexer const_TokenPtr -#if 0 - /* TODO: find workaround for std::string being nullptr - probably have to - * introduce new method in lexer Token, or maybe make conversion method - * there */ - Token (const_TokenPtr lexer_token_ptr) - : token_id (lexer_token_ptr->get_id ()), - locus (lexer_token_ptr->get_locus ()), str (""), - type_hint (lexer_token_ptr->get_type_hint ()) - { - // FIXME: change to "should have str" later? - if (lexer_token_ptr->has_str ()) - { - str = lexer_token_ptr->get_str (); - - // DEBUG - rust_debug ("ast token created with str '%s'", str.c_str ()); - } - else - { - // FIXME: is this returning correct thing? - str = lexer_token_ptr->get_token_description (); - - // DEBUG - rust_debug ("ast token created with string '%s'", str.c_str ()); - } - - // DEBUG - if (lexer_token_ptr->should_have_str () && !lexer_token_ptr->has_str ()) - { - rust_debug ( - "BAD: for token '%s', should have string but does not!", - lexer_token_ptr->get_token_description ()); - } - } -#endif Token (const_TokenPtr lexer_tok_ptr) : tok_ref (std::move (lexer_tok_ptr)) {} bool is_string_lit () const @@ -283,7 +226,7 @@ public: std::vector<std::unique_ptr<Token>> to_token_stream () const override; TokenId get_id () const { return tok_ref->get_id (); } - bool has_str () const { return tok_ref->has_str (); } + bool should_have_str () const { return tok_ref->should_have_str (); } const std::string &get_str () const { return tok_ref->get_str (); } location_t get_locus () const { return tok_ref->get_locus (); } @@ -1137,7 +1080,9 @@ public: virtual void mark_for_strip () = 0; virtual bool is_marked_for_strip () const = 0; - NodeId get_node_id () const { return node_id; } + + // TODO: put this in a virtual base class? + virtual NodeId get_node_id () const { return node_id; } virtual Kind get_stmt_kind () = 0; @@ -1536,7 +1481,8 @@ public: virtual location_t get_locus () const = 0; - NodeId get_node_id () const { return node_id; } + // TODO: put this in a virtual base class? + virtual NodeId get_node_id () const { return node_id; } virtual Type *reconstruct_impl () const = 0; protected: @@ -1799,6 +1745,8 @@ public: virtual bool is_marked_for_strip () const = 0; virtual location_t get_locus () const = 0; + + virtual NodeId get_node_id () const = 0; }; // Item used in trait declarations - abstract base class @@ -1829,7 +1777,7 @@ public: return std::unique_ptr<TraitItem> (clone_associated_item_impl ()); } - NodeId get_node_id () const { return node_id; } + NodeId get_node_id () const override { return node_id; } location_t get_locus () const override { return locus; } }; @@ -1957,18 +1905,19 @@ public: class SingleASTNode : public Visitable { public: - enum NodeType - { - EXPRESSION, - ITEM, - STMT, - EXTERN, - ASSOC_ITEM, - TYPE, + enum class Kind + { + Expr, + Item, + Stmt, + Extern, + Assoc, + Type, + Pattern, }; private: - NodeType kind; + Kind kind; // FIXME make this a union std::unique_ptr<Expr> expr; @@ -1977,30 +1926,35 @@ private: std::unique_ptr<ExternalItem> external_item; std::unique_ptr<AssociatedItem> assoc_item; std::unique_ptr<Type> type; + std::unique_ptr<Pattern> pattern; public: SingleASTNode (std::unique_ptr<Expr> expr) - : kind (EXPRESSION), expr (std::move (expr)) + : kind (Kind::Expr), expr (std::move (expr)) {} SingleASTNode (std::unique_ptr<Item> item) - : kind (ITEM), item (std::move (item)) + : kind (Kind::Item), item (std::move (item)) {} SingleASTNode (std::unique_ptr<Stmt> stmt) - : kind (STMT), stmt (std::move (stmt)) + : kind (Kind::Stmt), stmt (std::move (stmt)) {} SingleASTNode (std::unique_ptr<ExternalItem> item) - : kind (EXTERN), external_item (std::move (item)) + : kind (Kind::Extern), external_item (std::move (item)) {} SingleASTNode (std::unique_ptr<AssociatedItem> item) - : kind (ASSOC_ITEM), assoc_item (std::move (item)) + : kind (Kind::Assoc), assoc_item (std::move (item)) {} SingleASTNode (std::unique_ptr<Type> type) - : kind (TYPE), type (std::move (type)) + : kind (Kind::Type), type (std::move (type)) + {} + + SingleASTNode (std::unique_ptr<Pattern> pattern) + : kind (Kind::Pattern), pattern (std::move (pattern)) {} SingleASTNode (SingleASTNode const &other); @@ -2010,23 +1964,23 @@ public: SingleASTNode (SingleASTNode &&other) = default; SingleASTNode &operator= (SingleASTNode &&other) = default; - NodeType get_kind () const { return kind; } + Kind get_kind () const { return kind; } std::unique_ptr<Expr> &get_expr () { - rust_assert (kind == EXPRESSION); + rust_assert (kind == Kind::Expr); return expr; } std::unique_ptr<Item> &get_item () { - rust_assert (kind == ITEM); + rust_assert (kind == Kind::Item); return item; } std::unique_ptr<Stmt> &get_stmt () { - rust_assert (kind == STMT); + rust_assert (kind == Kind::Stmt); return stmt; } @@ -2071,6 +2025,12 @@ public: return std::move (type); } + std::unique_ptr<Pattern> take_pattern () + { + rust_assert (!is_error ()); + return std::move (pattern); + } + void accept_vis (ASTVisitor &vis) override; bool is_error (); diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h index 2893e7b..c784ad6 100644 --- a/gcc/rust/ast/rust-builtin-ast-nodes.h +++ b/gcc/rust/ast/rust-builtin-ast-nodes.h @@ -134,6 +134,7 @@ public: FormatArgumentKind get_kind () const { return kind; } const Expr &get_expr () const { return *expr; } + Expr &get_expr () { return *expr; } private: FormatArgument (FormatArgumentKind::Kind kind, tl::optional<Identifier> ident, @@ -164,6 +165,11 @@ public: void push (FormatArgument &&elt) { args.emplace_back (std::move (elt)); } const FormatArgument at (size_t idx) const { return args.at (idx); } + const std::vector<FormatArgument> &get_args () const { return args; } + std::vector<FormatArgument> &get_args () { return args; } + size_t size () const { return args.size (); } + bool empty () const { return args.empty (); } + private: std::vector<FormatArgument> args; }; @@ -200,6 +206,7 @@ public: const Fmt::Pieces &get_template () const { return template_pieces; } const FormatArguments &get_arguments () const { return arguments; } + FormatArguments &get_arguments () { return arguments; } virtual location_t get_locus () const override; Expr::Kind get_expr_kind () const override { return Expr::Kind::FormatArgs; } @@ -255,6 +262,7 @@ public: virtual location_t get_locus () const override { return loc; } const Type &get_type () const { return *type; } Type &get_type () { return *type; } + std::unique_ptr<Type> &get_type_ptr () { return type; } const Identifier &get_field () const { return field; } bool is_expr_without_block () const override { return false; } diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc index 306c6f7..1efe26f 100644 --- a/gcc/rust/ast/rust-collect-lang-items.cc +++ b/gcc/rust/ast/rust-collect-lang-items.cc @@ -43,18 +43,16 @@ get_lang_item_attr (const T &maybe_lang_item) continue; } - bool is_lang_item = str_path == Values::Attributes::LANG - && attr.has_attr_input () - && attr.get_attr_input ().get_attr_input_type () - == AST::AttrInput::AttrInputType::LITERAL; + bool is_lang_item = str_path == Values::Attributes::LANG; if (is_lang_item) { - auto &literal - = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ()); - const auto &lang_item_type_str = literal.get_literal ().as_string (); + auto lang_item_type_str + = Analysis::Attributes::extract_string_literal (attr); - return LangItem::Parse (lang_item_type_str); + rust_assert (lang_item_type_str.has_value ()); + + return LangItem::Parse (*lang_item_type_str); } } diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h index 56a5646..5d5fba5 100644 --- a/gcc/rust/ast/rust-cond-compilation.h +++ b/gcc/rust/ast/rust-cond-compilation.h @@ -91,9 +91,13 @@ class ConfigurationAll : public ConfigurationPredicate predicate_list; // inlined form public: + ConfigurationAll (const ConfigurationAll &) = delete; + + ConfigurationAll (ConfigurationAll &&) = default; + ConfigurationAll ( std::vector<std::unique_ptr<ConfigurationPredicate>> predicate_list) - : predicate_list (predicate_list) + : predicate_list (std::move (predicate_list)) {} void accept_vis (ASTVisitor &vis) override; @@ -103,7 +107,14 @@ protected: * than base */ ConfigurationAll *clone_configuration_predicate_impl () const override { - return new ConfigurationAll (*this); + decltype (predicate_list) predicate_list_clone = {}; + predicate_list_clone.reserve (predicate_list.size ()); + + for (const auto &predicate : predicate_list) + predicate_list_clone.push_back ( + predicate->clone_configuration_predicate ()); + + return new ConfigurationAll (std::move (predicate_list_clone)); } }; @@ -114,9 +125,13 @@ class ConfigurationAny : public ConfigurationPredicate predicate_list; // inlined form public: + ConfigurationAny (const ConfigurationAny &) = delete; + + ConfigurationAny (ConfigurationAny &&) = default; + ConfigurationAny ( std::vector<std::unique_ptr<ConfigurationPredicate>> predicate_list) - : predicate_list (predicate_list) + : predicate_list (std::move (predicate_list)) {} void accept_vis (ASTVisitor &vis) override; @@ -126,7 +141,14 @@ protected: * than base */ ConfigurationAny *clone_configuration_predicate_impl () const override { - return new ConfigurationAny (*this); + decltype (predicate_list) predicate_list_clone = {}; + predicate_list_clone.reserve (predicate_list.size ()); + + for (const auto &predicate : predicate_list) + predicate_list_clone.push_back ( + predicate->clone_configuration_predicate ()); + + return new ConfigurationAny (std::move (predicate_list_clone)); } }; @@ -226,7 +248,7 @@ public: CfgAttrAttribute (CfgAttrAttribute const &other) : config_to_include ( other.config_to_include->clone_configuration_predicate ()), - cfg_attrs (cfg_attrs) + cfg_attrs (other.cfg_attrs) {} // Overloaded assignment operator to clone diff --git a/gcc/rust/ast/rust-desugar-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc index bca14ee..de34e15 100644 --- a/gcc/rust/ast/rust-desugar-apit.cc +++ b/gcc/rust/ast/rust-desugar-apit.cc @@ -188,9 +188,10 @@ public: // 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 ()))); + segments.emplace_back ( + new TypePathSegment (PathIdentSegment (ident.as_string (), + type.get_locus ()), + false, type.get_locus ())); // Create TypePath from segments auto type_path @@ -198,6 +199,8 @@ public: // Convert bounds from impl trait to generic parameter bounds std::vector<std::unique_ptr<TypeParamBound>> bounds; + bounds.reserve (type.get_type_param_bounds ().size ()); + for (auto &bound : type.get_type_param_bounds ()) bounds.push_back (bound->clone_type_param_bound ()); @@ -228,9 +231,10 @@ public: // 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 ()))); + segments.emplace_back ( + new TypePathSegment (PathIdentSegment (ident.as_string (), + type.get_locus ()), + false, type.get_locus ())); // Create TypePath from segments auto type_path @@ -407,6 +411,9 @@ private: std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; + type_param_bounds.reserve ( + tp.get_type_param_bounds ().size ()); + for (auto &b : tp.get_type_param_bounds ()) type_param_bounds.push_back (std::move (b)); tp.get_type_param_bounds ().clear (); @@ -459,9 +466,10 @@ private: 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 ()))); + segments.emplace_back ( + 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); } diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc index 5cc1c19..9a12423 100644 --- a/gcc/rust/ast/rust-desugar-for-loops.cc +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -51,7 +51,7 @@ DesugarForLoops::DesugarCtx::make_continue_arm () patterns.emplace_back (std::move (val)); auto pattern_item = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (patterns))); + new TupleStructItemsNoRest (std::move (patterns))); auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern ( builder.path_in_expression (LangItem::Kind::OPTION_SOME), std::move (pattern_item))); diff --git a/gcc/rust/ast/rust-desugar-question-mark.cc b/gcc/rust/ast/rust-desugar-question-mark.cc index 01400d8..20a4903 100644 --- a/gcc/rust/ast/rust-desugar-question-mark.cc +++ b/gcc/rust/ast/rust-desugar-question-mark.cc @@ -55,7 +55,7 @@ ok_case (Builder &builder) patterns.emplace_back (std::move (val)); auto pattern_item = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (patterns))); + new TupleStructItemsNoRest (std::move (patterns))); auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern ( builder.path_in_expression (LangItem::Kind::RESULT_OK), std::move (pattern_item))); @@ -82,7 +82,7 @@ err_case (Builder &builder) patterns.emplace_back (std::move (val)); auto pattern_item = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (patterns))); + new TupleStructItemsNoRest (std::move (patterns))); auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern ( builder.path_in_expression (LangItem::Kind::RESULT_ERR), std::move (pattern_item))); diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 7b0df25..3c36238 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -282,6 +282,8 @@ public: Expr &get_expr () { return *expr; } + std::unique_ptr<Expr> &get_expr_ptr () { return expr; } + std::string as_string () const override { return path.as_string () + " = " + expr->as_string (); @@ -296,7 +298,11 @@ public: // we have no idea use which of them, just simply return UNKNOWN_LOCATION // now. // Maybe we will figure out when we really need the location in the future. - location_t get_locus () const override { return UNKNOWN_LOCATION; } + location_t get_locus () const override + { + rust_unreachable (); + return UNKNOWN_LOCATION; + } void accept_vis (ASTVisitor &vis) override; @@ -414,6 +420,12 @@ public: return *main_or_left_expr; } + std::unique_ptr<Expr> &get_borrowed_expr_ptr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + bool has_borrow_expr () const { return main_or_left_expr != nullptr; } bool get_is_mut () const { return mutability == Mutability::Mut; } @@ -455,6 +467,12 @@ public: return *main_or_left_expr; } + std::unique_ptr<Expr> &get_dereferenced_expr_ptr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Dereference; } protected: @@ -488,6 +506,12 @@ public: return *main_or_left_expr; } + std::unique_ptr<Expr> &get_propagating_expr_ptr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + Expr::Kind get_expr_kind () const override { return Expr::Kind::ErrorPropagation; @@ -536,6 +560,12 @@ public: return *main_or_left_expr; } + std::unique_ptr<Expr> &get_negated_expr_ptr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Negation; } protected: @@ -865,6 +895,12 @@ public: return *main_or_left_expr; } + std::unique_ptr<Expr> &get_casted_expr_ptr () + { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + // TODO: is this better? Or is a "vis_block" better? TypeNoBounds &get_type_to_cast_to () { @@ -872,6 +908,12 @@ public: return *type_to_convert_to; } + std::unique_ptr<TypeNoBounds> &get_type_to_cast_to_ptr () + { + rust_assert (type_to_convert_to != nullptr); + return type_to_convert_to; + } + Expr::Kind get_expr_kind () const override { return Expr::Kind::TypeCast; } protected: @@ -1282,6 +1324,12 @@ public: return *elem_to_copy; } + std::unique_ptr<Expr> &get_elem_to_copy_ptr () + { + rust_assert (elem_to_copy != nullptr); + return elem_to_copy; + } + // TODO: is this better? Or is a "vis_block" better? Expr &get_num_copies () { @@ -1289,6 +1337,12 @@ public: return *num_copies; } + std::unique_ptr<Expr> &get_num_copies_ptr () + { + rust_assert (num_copies != nullptr); + return num_copies; + } + protected: ArrayElemsCopied *clone_array_elems_impl () const override { @@ -1468,6 +1522,12 @@ public: return *array_expr; } + std::unique_ptr<Expr> &get_array_expr_ptr () + { + rust_assert (array_expr != nullptr); + return array_expr; + } + // TODO: is this better? Or is a "vis_block" better? Expr &get_index_expr () { @@ -1475,6 +1535,12 @@ public: return *index_expr; } + std::unique_ptr<Expr> &get_index_expr_ptr () + { + rust_assert (index_expr != nullptr); + return index_expr; + } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -1599,6 +1665,7 @@ class TupleIndexExpr : public ExprWithoutBlock TupleIndex tuple_index; location_t locus; + bool to_strip; // i.e. pair.0 @@ -1610,13 +1677,15 @@ public: TupleIndexExpr (std::unique_ptr<Expr> tuple_expr, TupleIndex index, std::vector<Attribute> outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), - tuple_expr (std::move (tuple_expr)), tuple_index (index), locus (locus) + tuple_expr (std::move (tuple_expr)), tuple_index (index), locus (locus), + to_strip (false) {} // Copy constructor requires a clone for tuple_expr TupleIndexExpr (TupleIndexExpr const &other) : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), - tuple_index (other.tuple_index), locus (other.locus) + tuple_index (other.tuple_index), locus (other.locus), + to_strip (other.to_strip) { // guard to prevent null dereference (only required if error state) if (other.tuple_expr != nullptr) @@ -1630,6 +1699,7 @@ public: tuple_index = other.tuple_index; locus = other.locus; outer_attrs = other.outer_attrs; + to_strip = other.to_strip; // guard to prevent null dereference (only required if error state) if (other.tuple_expr != nullptr) @@ -1649,8 +1719,8 @@ public: void accept_vis (ASTVisitor &vis) override; // Invalid if tuple expr is null, so base stripping on that. - void mark_for_strip () override { tuple_expr = nullptr; } - bool is_marked_for_strip () const override { return tuple_expr == nullptr; } + void mark_for_strip () override { to_strip = true; } + bool is_marked_for_strip () const override { return to_strip; } // TODO: is this better? Or is a "vis_block" better? Expr &get_tuple_expr () @@ -1659,6 +1729,12 @@ public: return *tuple_expr; } + std::unique_ptr<Expr> &get_tuple_expr_ptr () + { + rust_assert (tuple_expr != nullptr); + return tuple_expr; + } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -1807,6 +1883,12 @@ public: rust_assert (base_struct != nullptr); return *base_struct; } + + std::unique_ptr<Expr> &get_base_struct_ptr () + { + rust_assert (base_struct != nullptr); + return base_struct; + } }; /* Base AST node for a single struct expression field (in struct instance @@ -1923,6 +2005,12 @@ public: rust_assert (value != nullptr); return *value; } + + std::unique_ptr<Expr> &get_value_ptr () + { + rust_assert (value != nullptr); + return value; + } }; // Identifier and value variant of StructExprField AST node @@ -2293,6 +2381,12 @@ public: return *receiver; } + std::unique_ptr<Expr> &get_receiver_expr_ptr () + { + rust_assert (receiver != nullptr); + return receiver; + } + const PathExprSegment &get_method_name () const { return method_name; } PathExprSegment &get_method_name () { return method_name; } @@ -2381,6 +2475,12 @@ public: return *receiver; } + std::unique_ptr<Expr> &get_receiver_expr_ptr () + { + rust_assert (receiver != nullptr); + return receiver; + } + Identifier get_field_name () const { return field; } const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } @@ -2480,6 +2580,12 @@ public: return *pattern; } + std::unique_ptr<Pattern> &get_pattern_ptr () + { + rust_assert (pattern != nullptr); + return pattern; + } + Type &get_type () { rust_assert (has_type_given ()); @@ -2532,6 +2638,7 @@ public: Expr::Kind get_expr_kind () const override { return Expr::Kind::Closure; } virtual Expr &get_definition_expr () = 0; + virtual std::unique_ptr<Expr> &get_definition_expr_ptr () = 0; }; // Represents a non-type-specified closure expression AST node @@ -2597,6 +2704,12 @@ public: return *closure_inner; } + std::unique_ptr<Expr> &get_definition_expr_ptr () override + { + rust_assert (closure_inner != nullptr); + return closure_inner; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2827,6 +2940,12 @@ public: return *expr.value (); } + std::unique_ptr<Expr> &get_inner_expr_ptr () + { + rust_assert (expr.has_value ()); + return expr.value (); + } + NodeId get_node_id () const override { return node_id; } /* FIXME: AnonConst are always "internal" and should not have outer attributes @@ -2922,8 +3041,7 @@ class ClosureExprInnerTyped : public ClosureExpr { // TODO: spec says typenobounds std::unique_ptr<Type> return_type; - std::unique_ptr<BlockExpr> - expr; // only used because may be polymorphic in future + std::unique_ptr<Expr> expr; // only used because may be polymorphic in future public: std::string as_string () const override; @@ -2947,7 +3065,7 @@ public: { // guard to prevent null dereference (only required if error state) if (other.expr != nullptr) - expr = other.expr->clone_block_expr (); + expr = other.expr->clone_expr (); if (other.return_type != nullptr) return_type = other.return_type->clone_type (); } @@ -2962,7 +3080,7 @@ public: // guard to prevent null dereference (only required if error state) if (other.expr != nullptr) - expr = other.expr->clone_block_expr (); + expr = other.expr->clone_expr (); else expr = nullptr; if (other.return_type != nullptr) @@ -2985,12 +3103,19 @@ public: bool is_marked_for_strip () const override { return expr == nullptr; } // TODO: is this better? Or is a "vis_block" better? - BlockExpr &get_definition_expr () override + Expr &get_definition_expr () override { rust_assert (expr != nullptr); return *expr; } + std::unique_ptr<Expr> &get_definition_expr_ptr () override + { + rust_assert (expr != nullptr); + + return expr; + } + // TODO: is this better? Or is a "vis_block" better? Type &get_return_type () { @@ -3147,6 +3272,12 @@ public: return *break_expr; } + std::unique_ptr<Expr> &get_break_expr_ptr () + { + rust_assert (has_break_expr ()); + return break_expr; + } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -3274,6 +3405,18 @@ public: return *to; } + std::unique_ptr<Expr> &get_from_expr_ptr () + { + rust_assert (from != nullptr); + return from; + } + + std::unique_ptr<Expr> &get_to_expr_ptr () + { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3335,6 +3478,12 @@ public: return *from; } + std::unique_ptr<Expr> &get_from_expr_ptr () + { + rust_assert (from != nullptr); + return from; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3397,6 +3546,12 @@ public: return *to; } + std::unique_ptr<Expr> &get_to_expr_ptr () + { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3510,6 +3665,18 @@ public: return *to; } + std::unique_ptr<Expr> &get_from_expr_ptr () + { + rust_assert (from != nullptr); + return from; + } + + std::unique_ptr<Expr> &get_to_expr_ptr () + { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3572,6 +3739,12 @@ public: return *to; } + std::unique_ptr<Expr> &get_to_expr_ptr () + { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3645,6 +3818,12 @@ public: return *expr; } + std::unique_ptr<Expr> &get_boxed_expr_ptr () + { + rust_assert (expr != nullptr); + return expr; + } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Box; } protected: @@ -3726,6 +3905,12 @@ public: return *return_expr; } + std::unique_ptr<Expr> &get_returned_expr_ptr () + { + rust_assert (return_expr != nullptr); + return return_expr; + } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -3801,6 +3986,7 @@ public: // TODO: is this better? Or is a "vis_block" better? BlockExpr &get_block_expr () { return *block_expr; } + std::unique_ptr<BlockExpr> &get_block_expr_ptr () { return block_expr; } const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -3886,6 +4072,12 @@ public: return *expr; } + std::unique_ptr<BlockExpr> &get_block_expr_ptr () + { + rust_assert (expr != nullptr); + return expr; + } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -3978,6 +4170,12 @@ public: return *loop_block; } + std::unique_ptr<BlockExpr> &get_loop_block_ptr () + { + rust_assert (loop_block != nullptr); + return loop_block; + } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } @@ -4078,6 +4276,12 @@ public: return *condition; } + std::unique_ptr<Expr> &get_predicate_expr_ptr () + { + rust_assert (condition != nullptr); + return condition; + } + BaseLoopExpr::Kind get_loop_kind () const override { return BaseLoopExpr::Kind::While; @@ -4156,6 +4360,12 @@ public: return *scrutinee; } + std::unique_ptr<Expr> &get_scrutinee_expr_ptr () + { + rust_assert (scrutinee != nullptr); + return scrutinee; + } + // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector<std::unique_ptr<Pattern>> &get_patterns () const { @@ -4233,6 +4443,12 @@ public: return *iterator_expr; } + std::unique_ptr<Expr> &get_iterator_expr_ptr () + { + rust_assert (iterator_expr != nullptr); + return iterator_expr; + } + // TODO: is this better? Or is a "vis_block" better? Pattern &get_pattern () { @@ -4240,6 +4456,12 @@ public: return *pattern; } + std::unique_ptr<Pattern> &get_pattern_ptr () + { + rust_assert (pattern != nullptr); + return pattern; + } + BaseLoopExpr::Kind get_loop_kind () const override { return BaseLoopExpr::Kind::For; @@ -4892,6 +5114,12 @@ public: return *branch_value; } + std::unique_ptr<Expr> &get_scrutinee_expr_ptr () + { + rust_assert (branch_value != nullptr); + return branch_value; + } + const std::vector<MatchCase> &get_match_cases () const { return match_arms; } std::vector<MatchCase> &get_match_cases () { return match_arms; } @@ -5494,6 +5722,8 @@ struct InlineAsmTemplatePiece struct TupleClobber { + TupleClobber (std::string symbol, location_t loc) : symbol (symbol), loc (loc) + {} // as gccrs still doesn't contain a symbol class I have put them as strings std::string symbol; location_t loc; @@ -5667,6 +5897,10 @@ public: } std::vector<TupleTemplateStr> &get_templates () { return templates; } + const std::vector<TupleTemplateStr> &get_templates () const + { + return templates; + } Expr::Kind get_expr_kind () const override { @@ -5685,9 +5919,12 @@ public: void set_outputs (std::vector<LlvmOperand> operands) { outputs = operands; } std::vector<LlvmOperand> &get_inputs () { return inputs; } + const std::vector<LlvmOperand> &get_inputs () const { return inputs; } std::vector<LlvmOperand> &get_outputs () { return outputs; } + const std::vector<LlvmOperand> &get_outputs () const { return outputs; } std::vector<TupleClobber> &get_clobbers () { return clobbers; } + const std::vector<TupleClobber> &get_clobbers () const { return clobbers; } }; } // namespace AST diff --git a/gcc/rust/ast/rust-expression-yeast.cc b/gcc/rust/ast/rust-expression-yeast.cc index 9f6a62f..7626abc 100644 --- a/gcc/rust/ast/rust-expression-yeast.cc +++ b/gcc/rust/ast/rust-expression-yeast.cc @@ -21,10 +21,8 @@ #include "rust-desugar-question-mark.h" #include "rust-desugar-try-block.h" #include "rust-desugar-for-loops.h" -#include "rust-ast-full.h" #include "rust-desugar-while-let.h" #include "rust-expr.h" -#include "rust-stmt.h" namespace Rust { namespace AST { @@ -32,7 +30,7 @@ namespace AST { void ExpressionYeast::go (AST::Crate &crate) { - DefaultASTVisitor::visit (crate); + PointerVisitor::visit (crate); } void @@ -54,7 +52,7 @@ ExpressionYeast::dispatch_loops (std::unique_ptr<Expr> &loop_expr) } void -ExpressionYeast::dispatch (std::unique_ptr<Expr> &expr) +ExpressionYeast::reseat (std::unique_ptr<Expr> &expr) { switch (expr->get_expr_kind ()) { @@ -71,47 +69,8 @@ ExpressionYeast::dispatch (std::unique_ptr<Expr> &expr) default: break; } -} - -void -ExpressionYeast::visit (ExprStmt &stmt) -{ - dispatch (stmt.get_expr_ptr ()); - - DefaultASTVisitor::visit (stmt); -} - -void -ExpressionYeast::visit (CallExpr &call) -{ - dispatch (call.get_function_expr_ptr ()); - - for (auto &arg : call.get_params ()) - dispatch (arg); - - DefaultASTVisitor::visit (call); -} - -void -ExpressionYeast::visit (BlockExpr &block) -{ - for (auto &stmt : block.get_statements ()) - if (stmt->get_stmt_kind () == Stmt::Kind::Expr) - dispatch (static_cast<ExprStmt &> (*stmt).get_expr_ptr ()); - - if (block.has_tail_expr ()) - dispatch (block.get_tail_expr_ptr ()); - - DefaultASTVisitor::visit (block); -} - -void -ExpressionYeast::visit (LetStmt &stmt) -{ - if (stmt.has_init_expr ()) - dispatch (stmt.get_init_expr_ptr ()); - DefaultASTVisitor::visit (stmt); + visit (expr); } } // namespace AST diff --git a/gcc/rust/ast/rust-expression-yeast.h b/gcc/rust/ast/rust-expression-yeast.h index 855918f..3f64b1d 100644 --- a/gcc/rust/ast/rust-expression-yeast.h +++ b/gcc/rust/ast/rust-expression-yeast.h @@ -19,7 +19,7 @@ #ifndef RUST_EXPRESSION_YEAST #define RUST_EXPRESSION_YEAST -#include "rust-ast-visitor.h" +#include "rust-ast-pointer-visitor.h" #include "rust-ast.h" #include "rust-desugar-question-mark.h" @@ -28,22 +28,19 @@ namespace AST { // This visitor takes care of all the expression desugars: try-blocks, // error-propagation, etc. -class ExpressionYeast : public AST::DefaultASTVisitor +class ExpressionYeast : public AST::PointerVisitor { - using AST::DefaultASTVisitor::visit; + using AST::PointerVisitor::reseat; + using AST::PointerVisitor::visit; public: void go (AST::Crate &); private: // Dispatch to the proper desugar - void dispatch (std::unique_ptr<Expr> &expr); - void dispatch_loops (std::unique_ptr<Expr> &loop_expr); + void reseat (std::unique_ptr<Expr> &expr) override; - void visit (AST::ExprStmt &) override; - void visit (AST::CallExpr &) override; - void visit (AST::LetStmt &) override; - void visit (AST::BlockExpr &) override; + void dispatch_loops (std::unique_ptr<Expr> &loop_expr); }; } // namespace AST diff --git a/gcc/rust/ast/rust-fmt.cc b/gcc/rust/ast/rust-fmt.cc index a29c820..21f4f03 100644 --- a/gcc/rust/ast/rust-fmt.cc +++ b/gcc/rust/ast/rust-fmt.cc @@ -32,41 +32,11 @@ Pieces Pieces::collect (const std::string &to_parse, bool append_newline, ffi::ParseMode parse_mode) { - auto handle - = ffi::collect_pieces (to_parse.c_str (), append_newline, parse_mode); - - // this performs multiple copies, can we avoid them maybe? - // TODO: Instead of just creating a vec of, basically, `ffi::Piece`s, we - // should transform them into the proper C++ type which we can work with. so - // transform all the strings into C++ strings? all the Option<T> into - // tl::optional<T>? - auto pieces_vector = std::vector<ffi::Piece> (handle.piece_slice.base_ptr, - handle.piece_slice.base_ptr - + handle.piece_slice.len); - - return Pieces (handle, std::move (pieces_vector)); -} - -Pieces::~Pieces () { ffi::destroy_pieces (handle); } - -Pieces::Pieces (const Pieces &other) : pieces_vector (other.pieces_vector) -{ - handle = ffi::clone_pieces (other.handle); + Pieces ret (to_parse, ffi::FFIVec<ffi::Piece> ()); + ret.data->second = ffi::collect_pieces (ffi::RustHamster (ret.data->first), + append_newline, parse_mode); + return ret; } -Pieces & -Pieces::operator= (const Pieces &other) -{ - handle = ffi::clone_pieces (other.handle); - pieces_vector = other.pieces_vector; - - return *this; -} - -Pieces::Pieces (Pieces &&other) - : pieces_vector (std::move (other.pieces_vector)), - handle (clone_pieces (other.handle)) -{} - } // namespace Fmt } // namespace Rust diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h index 3722db2..e59bed3 100644 --- a/gcc/rust/ast/rust-fmt.h +++ b/gcc/rust/ast/rust-fmt.h @@ -20,20 +20,171 @@ #define RUST_FMT_H #include "rust-system.h" - -// FIXME: How to encode Option? +#include "optional.h" namespace Rust { namespace Fmt { namespace ffi { +extern "C" { + +unsigned char *rust_ffi_alloc (size_t count, size_t elem_size, size_t align); + +void rust_ffi_dealloc (unsigned char *data, size_t count, size_t elem_size, + size_t align); + +} // extern "C" + +template <typename T> class FFIVec +{ + T *data; + size_t len; + size_t cap; + +public: + FFIVec () : data ((T *) alignof (T)), len (0), cap (0) {} + + FFIVec (const FFIVec &) = delete; + FFIVec &operator= (const FFIVec &) = delete; + + FFIVec (FFIVec &&other) : data (other.data), len (other.len), cap (other.cap) + { + other.data = (T *) alignof (T); + other.len = 0; + other.cap = 0; + } + + FFIVec &operator= (FFIVec &&other) + { + this->~FFIVec (); + new (this) FFIVec (std::move (other)); + return *this; + } + + ~FFIVec () + { + // T can't be zero-sized + if (cap) + rust_ffi_dealloc ((unsigned char *) data, cap, sizeof (T), alignof (T)); + } + + size_t size () const { return len; } + + const T &operator[] (size_t idx) const + { + rust_assert (idx <= len); + return data[idx]; + } + + T *begin () { return data; } + const T *begin () const { return data; } + T *end () { return data + len; } + const T *end () const { return data + len; } +}; + +// https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md +template <typename T, + typename = + typename std::enable_if<std::is_standard_layout<T>::value>::type> +class FFIOpt +{ +public: + template <typename U> + FFIOpt (U &&val) : some{Some::KIND, std::forward<U> (val)} + {} + + FFIOpt () : none{None::KIND} {} + + FFIOpt (const FFIOpt &other) + { + if (other.has_value ()) + new (&some) Some{Some::KIND, other.some.val}; + else + new (&none) None{None::KIND}; + } + + FFIOpt (FFIOpt &&other) + { + if (other.has_value ()) + new (&some) Some{Some::KIND, std::move (other.some.val)}; + else + new (&none) None{None::KIND}; + } + + ~FFIOpt () + { + if (has_value ()) + some.~Some (); + else + none.~None (); + } + + FFIOpt &operator= (const FFIOpt &other) + { + this->~FFIOpt (); + new (this) FFIOpt (other); + return *this; + } + + FFIOpt &operator= (FFIOpt &&other) + { + this->~FFIOpt (); + new (this) FFIOpt (std::move (other)); + return *this; + } + + tl::optional<std::reference_wrapper<T>> get_opt () + { + if (has_value ()) + return std::ref (some.val); + else + return tl::nullopt; + } + + tl::optional<std::reference_wrapper<const T>> get_opt () const + { + if (has_value ()) + return std::ref (some.val); + else + return tl::nullopt; + } + + bool has_value () const { return some.kind == Some::KIND; } + + operator bool () const { return has_value (); } + +private: + struct Some + { + static constexpr uint8_t KIND = 0; + uint8_t kind; + T val; + }; + + struct None + { + static constexpr uint8_t KIND = 1; + uint8_t kind; + }; + + union + { + Some some; + None none; + }; +}; + struct RustHamster { const char *ptr; size_t len; std::string to_string () const; + + explicit RustHamster (const std::string &str) + : ptr (str.data ()), len (str.size ()) + {} }; /// Enum of alignments which are supported. @@ -166,33 +317,33 @@ struct Count struct FormatSpec { /// Optionally specified character to fill alignment with. - const uint32_t *fill; + FFIOpt<uint32_t> fill; /// Span of the optionally specified fill character. - const InnerSpan *fill_span; + FFIOpt<InnerSpan> fill_span; /// Optionally specified alignment. Alignment align; /// The `+` or `-` flag. - const Sign *sign; + FFIOpt<Sign> sign; /// The `#` flag. bool alternate; /// The `0` flag. bool zero_pad; /// The `x` or `X` flag. (Only for `Debug`.) - const DebugHex *debug_hex; + FFIOpt<DebugHex> debug_hex; /// The integer precision to use. Count precision; /// The span of the precision formatting flag (for diagnostics). - const InnerSpan *precision_span; + FFIOpt<InnerSpan> precision_span; /// The string width requested for the resulting format. Count width; /// The span of the width formatting flag (for diagnostics). - const InnerSpan *width_span; + FFIOpt<InnerSpan> width_span; /// The descriptor string representing the name of the format desired for /// this argument, this can be empty or any number of characters, although /// it is required to be one word. RustHamster ty; /// The span of the descriptor string (for diagnostics). - const InnerSpan *ty_span; + FFIOpt<InnerSpan> ty_span; }; /// Representation of an argument specification. @@ -238,26 +389,6 @@ struct Piece }; }; -struct PieceSlice -{ - const Piece *base_ptr; - size_t len; - size_t cap; -}; - -struct RustString -{ - const unsigned char *ptr; - size_t len; - size_t cap; -}; - -struct FormatArgsHandle -{ - PieceSlice piece_slice; - RustString rust_string; -}; - enum ParseMode { Format = 0, @@ -266,12 +397,10 @@ enum ParseMode extern "C" { -FormatArgsHandle collect_pieces (const char *input, bool append_newline, - ParseMode parse_mode); +FFIVec<Piece> collect_pieces (RustHamster input, bool append_newline, + ParseMode parse_mode); -FormatArgsHandle clone_pieces (const FormatArgsHandle &); - -void destroy_pieces (FormatArgsHandle); +FFIVec<Piece> clone_pieces (const FFIVec<Piece> &); } // extern "C" @@ -281,33 +410,20 @@ struct Pieces { static Pieces collect (const std::string &to_parse, bool append_newline, ffi::ParseMode parse_mode); - ~Pieces (); - - Pieces (const Pieces &other); - Pieces &operator= (const Pieces &other); - Pieces (Pieces &&other); - - const std::vector<ffi::Piece> &get_pieces () const { return pieces_vector; } - - // { - // slice = clone_pieces (&other.slice); - // to_parse = other.to_parse; - - // return *this; - // } + const ffi::FFIVec<ffi::Piece> &get_pieces () const { return data->second; } private: - Pieces (ffi::FormatArgsHandle handle, std::vector<ffi::Piece> &&pieces_vector) - : pieces_vector (std::move (pieces_vector)), handle (handle) + Pieces (std::string str, ffi::FFIVec<ffi::Piece> pieces) + : data ( + std::make_shared<decltype (data)::element_type> (std::move (str), + std::move (pieces))) {} - std::vector<ffi::Piece> pieces_vector; - - // this memory is held for FFI reasons - it needs to be released and cloned - // precisely, so try to not access it/modify it if possible. you should - // instead work with `pieces_vector` - ffi::FormatArgsHandle handle; + // makes copying simpler + // also, we'd need to keep the parsed string in a shared_ptr anyways + // since we store pointers into the parsed string + std::shared_ptr<std::pair<std::string, ffi::FFIVec<ffi::Piece>>> data; }; } // namespace Fmt diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index d11eed7..7aea763 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -631,6 +631,12 @@ public: return *param_name; } + std::unique_ptr<Pattern> &get_pattern_ptr () + { + rust_assert (param_name != nullptr); + return param_name; + } + const Pattern &get_pattern () const { rust_assert (param_name != nullptr); @@ -714,6 +720,12 @@ public: return *param_name; } + std::unique_ptr<Pattern> &get_pattern_ptr () + { + rust_assert (param_name != nullptr); + return param_name; + } + bool has_name () const { return param_name != nullptr; } // TODO: is this better? Or is a "vis_block" better? @@ -1567,6 +1579,9 @@ public: location_t get_locus () const override final { return locus; } + // needed to override AssociatedItem::get_node_id + NodeId get_node_id () const override final { return VisItem::get_node_id (); } + void accept_vis (ASTVisitor &vis) override; // Invalid if existing type is null, so base stripping on that. @@ -1595,6 +1610,12 @@ public: return *existing_type; } + std::unique_ptr<Type> &get_type_aliased_ptr () + { + rust_assert (existing_type != nullptr); + return existing_type; + } + Identifier get_new_type_name () const { return new_type_name; } Item::Kind get_item_kind () const override { return Item::Kind::TypeAlias; } @@ -2515,9 +2536,12 @@ public: location_t get_locus () const override final { return locus; } + // needed to override AssociatedItem::get_node_id + NodeId get_node_id () const override final { return VisItem::get_node_id (); } + void accept_vis (ASTVisitor &vis) override; - // Invalid if type or expression are null, so base stripping on that. + // Invalid if type and expression are null, so base stripping on that. void mark_for_strip () override { type = nullptr; @@ -2528,7 +2552,7 @@ public: return type == nullptr && const_expr == nullptr; } - bool has_expr () { return const_expr != nullptr; } + bool has_expr () const { return const_expr != nullptr; } // TODO: is this better? Or is a "vis_block" better? Expr &get_expr () @@ -2695,123 +2719,6 @@ protected: } }; -// Constant item within traits -class TraitItemConst : public TraitItem -{ - std::vector<Attribute> outer_attrs; - Identifier name; - std::unique_ptr<Type> type; - - // bool has_expression; - std::unique_ptr<Expr> expr; - -public: - // Whether the constant item has an associated expression. - bool has_expression () const { return expr != nullptr; } - - TraitItemConst (Identifier name, std::unique_ptr<Type> type, - std::unique_ptr<Expr> expr, - std::vector<Attribute> outer_attrs, location_t locus) - : TraitItem (locus), outer_attrs (std::move (outer_attrs)), - name (std::move (name)), type (std::move (type)), expr (std::move (expr)) - {} - - // Copy constructor with clones - TraitItemConst (TraitItemConst const &other) - : TraitItem (other.locus), outer_attrs (other.outer_attrs), - name (other.name) - { - node_id = other.node_id; - - // guard to prevent null dereference - if (other.expr != nullptr) - expr = other.expr->clone_expr (); - - // guard to prevent null dereference (only for error state) - if (other.type != nullptr) - type = other.type->clone_type (); - } - - // Overloaded assignment operator to clone - TraitItemConst &operator= (TraitItemConst const &other) - { - TraitItem::operator= (other); - outer_attrs = other.outer_attrs; - name = other.name; - locus = other.locus; - node_id = other.node_id; - - // guard to prevent null dereference - if (other.expr != nullptr) - expr = other.expr->clone_expr (); - else - expr = nullptr; - - // guard to prevent null dereference (only for error state) - if (other.type != nullptr) - type = other.type->clone_type (); - else - type = nullptr; - - return *this; - } - - // move constructors - TraitItemConst (TraitItemConst &&other) = default; - TraitItemConst &operator= (TraitItemConst &&other) = default; - - std::string as_string () const override; - - location_t get_locus () const override { return locus; } - - void accept_vis (ASTVisitor &vis) override; - - // Invalid if type is null, so base stripping on that. - void mark_for_strip () override { type = nullptr; } - bool is_marked_for_strip () const override { return type == nullptr; } - - // TODO: this mutable getter seems really dodgy. Think up better way. - std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } - - bool has_expr () const { return expr != nullptr; } - - // TODO: is this better? Or is a "vis_block" better? - Expr &get_expr () - { - rust_assert (has_expr ()); - return *expr; - } - - std::unique_ptr<Expr> &get_expr_ptr () - { - rust_assert (has_expr ()); - return expr; - } - - // TODO: is this better? Or is a "vis_block" better? - Type &get_type () - { - rust_assert (type != nullptr); - return *type; - } - - std::unique_ptr<Type> &get_type_ptr () - { - rust_assert (type != nullptr); - return type; - } - - Identifier get_identifier () const { return name; } - -protected: - // Clone function implementation as (not pure) virtual method - TraitItemConst *clone_associated_item_impl () const override - { - return new TraitItemConst (*this); - } -}; - // Type items within traits class TraitItemType : public TraitItem { diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc index 793423a..068e364 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -167,14 +167,13 @@ Path::convert_to_simple_path (bool with_opening_scope_resolution) const for (const auto &segment : segments) { // return empty path if doesn't meet simple path segment requirements - if (segment.is_error () || segment.has_generic_args () - || segment.as_string () == "Self") + if (segment.is_error () || segment.has_generic_args ()) return SimplePath::create_empty (); // create segment and add to vector std::string segment_str = segment.as_string (); - simple_segments.push_back ( - SimplePathSegment (std::move (segment_str), segment.get_locus ())); + simple_segments.emplace_back (std::move (segment_str), + segment.get_locus ()); } // kind of a HACK to get locus depending on opening scope resolution @@ -258,8 +257,8 @@ TypePath::as_simple_path () const // create segment and add to vector std::string segment_str = segment->as_string (); - simple_segments.push_back ( - SimplePathSegment (std::move (segment_str), segment->get_locus ())); + simple_segments.emplace_back (std::move (segment_str), + segment->get_locus ()); } return SimplePath (std::move (simple_segments), has_opening_scope_resolution, diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index a1b19d5..be04882 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -377,6 +377,13 @@ public: return *type; } + std::unique_ptr<AST::Type> &get_type_ptr () + { + rust_assert (has_type ()); + + return type; + } + GenericArg &get_default_value_unchecked () { rust_assert (has_default_value ()); @@ -448,9 +455,7 @@ public: generic_args.clear (); generic_args.reserve (other.generic_args.size ()); for (const auto &arg : other.generic_args) - { - generic_args.push_back (GenericArg (arg)); - } + generic_args.emplace_back (arg); } ~GenericArgs () = default; @@ -465,9 +470,7 @@ public: generic_args.clear (); generic_args.reserve (other.generic_args.size ()); for (const auto &arg : other.generic_args) - { - generic_args.push_back (GenericArg (arg)); - } + generic_args.emplace_back (arg); return *this; } @@ -1252,7 +1255,7 @@ public: TraitBound *to_trait_bound (bool in_parens) const override; location_t get_locus () const override final { return locus; } - NodeId get_node_id () const { return node_id; } + NodeId get_node_id () const override { return node_id; } void mark_for_strip () override {} bool is_marked_for_strip () const override { return false; } diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc index 15ab0b7..a2fe5d5 100644 --- a/gcc/rust/ast/rust-pattern.cc +++ b/gcc/rust/ast/rust-pattern.cc @@ -186,8 +186,8 @@ StructPatternElements::as_string () const str += "\n " + field->as_string (); } - str += "\n Etc: "; - if (has_struct_pattern_etc) + str += "\n Has rest: "; + if (has_rest_pattern) str += "true"; else str += "false"; @@ -212,7 +212,7 @@ StructPattern::as_string () const } std::string -TupleStructItemsNoRange::as_string () const +TupleStructItemsNoRest::as_string () const { std::string str; @@ -223,7 +223,7 @@ TupleStructItemsNoRange::as_string () const } std::string -TupleStructItemsRange::as_string () const +TupleStructItemsHasRest::as_string () const { std::string str ("\n Lower patterns: "); @@ -264,7 +264,7 @@ TupleStructPattern::as_string () const } std::string -TuplePatternItemsMultiple::as_string () const +TuplePatternItemsNoRest::as_string () const { std::string str; @@ -275,7 +275,7 @@ TuplePatternItemsMultiple::as_string () const } std::string -TuplePatternItemsRanged::as_string () const +TuplePatternItemsHasRest::as_string () const { std::string str; @@ -421,7 +421,7 @@ SlicePattern::accept_vis (ASTVisitor &vis) } void -TuplePatternItemsRanged::accept_vis (ASTVisitor &vis) +TuplePatternItemsHasRest::accept_vis (ASTVisitor &vis) { vis.visit (*this); } @@ -433,7 +433,7 @@ TuplePattern::accept_vis (ASTVisitor &vis) } void -TuplePatternItemsMultiple::accept_vis (ASTVisitor &vis) +TuplePatternItemsNoRest::accept_vis (ASTVisitor &vis) { vis.visit (*this); } @@ -517,13 +517,13 @@ StructPattern::accept_vis (ASTVisitor &vis) } void -TupleStructItemsNoRange::accept_vis (ASTVisitor &vis) +TupleStructItemsNoRest::accept_vis (ASTVisitor &vis) { vis.visit (*this); } void -TupleStructItemsRange::accept_vis (ASTVisitor &vis) +TupleStructItemsHasRest::accept_vis (ASTVisitor &vis) { vis.visit (*this); } diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 4945ec4..0da1981 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -20,6 +20,7 @@ #define RUST_AST_PATTERN_H #include "rust-ast.h" +#include "rust-path.h" namespace Rust { namespace AST { @@ -143,6 +144,12 @@ public: return *subpattern; } + std::unique_ptr<Pattern> &get_subpattern_ptr () + { + rust_assert (has_subpattern ()); + return subpattern; + } + Identifier get_ident () const { return variable_ident; } bool get_is_mut () const { return is_mut; } @@ -518,6 +525,12 @@ public: return *pattern; } + std::unique_ptr<Pattern> &get_referenced_pattern_ptr () + { + rust_assert (pattern != nullptr); + return pattern; + } + bool is_double_reference () const { return has_two_amps; } bool get_is_mut () const { return is_mut; } @@ -681,6 +694,12 @@ public: return *tuple_pattern; } + std::unique_ptr<Pattern> &get_index_pattern_ptr () + { + rust_assert (tuple_pattern != nullptr); + return tuple_pattern; + } + ItemType get_item_type () const override final { return ItemType::TUPLE_PAT; } protected: @@ -761,6 +780,12 @@ public: return *ident_pattern; } + std::unique_ptr<Pattern> &get_ident_pattern_ptr () + { + rust_assert (ident_pattern != nullptr); + return ident_pattern; + } + ItemType get_item_type () const override final { return ItemType::IDENT_PAT; } protected: @@ -818,7 +843,7 @@ class StructPatternElements // bool has_struct_pattern_fields; std::vector<std::unique_ptr<StructPatternField>> fields; - bool has_struct_pattern_etc; + bool has_rest_pattern; std::vector<Attribute> struct_pattern_etc_attrs; // StructPatternEtc etc; @@ -834,29 +859,29 @@ public: * no etc). */ bool is_empty () const { - return !has_struct_pattern_fields () && !has_struct_pattern_etc; + return !has_struct_pattern_fields () && !has_rest_pattern; } - bool has_etc () const { return has_struct_pattern_etc; } + bool has_rest () const { return has_rest_pattern; } // Constructor for StructPatternElements with both (potentially) StructPatternElements ( std::vector<std::unique_ptr<StructPatternField>> fields, std::vector<Attribute> etc_attrs) - : fields (std::move (fields)), has_struct_pattern_etc (true), + : fields (std::move (fields)), has_rest_pattern (true), struct_pattern_etc_attrs (std::move (etc_attrs)) {} // Constructor for StructPatternElements with no StructPatternEtc StructPatternElements ( std::vector<std::unique_ptr<StructPatternField>> fields) - : fields (std::move (fields)), has_struct_pattern_etc (false), + : fields (std::move (fields)), has_rest_pattern (false), struct_pattern_etc_attrs () {} // Copy constructor with vector clone StructPatternElements (StructPatternElements const &other) - : has_struct_pattern_etc (other.has_struct_pattern_etc), + : has_rest_pattern (other.has_rest_pattern), struct_pattern_etc_attrs (other.struct_pattern_etc_attrs) { fields.reserve (other.fields.size ()); @@ -868,7 +893,7 @@ public: StructPatternElements &operator= (StructPatternElements const &other) { struct_pattern_etc_attrs = other.struct_pattern_etc_attrs; - has_struct_pattern_etc = other.has_struct_pattern_etc; + has_rest_pattern = other.has_rest_pattern; fields.clear (); fields.reserve (other.fields.size ()); @@ -913,7 +938,7 @@ public: void strip_etc () { - has_struct_pattern_etc = false; + has_rest_pattern = false; struct_pattern_etc_attrs.clear (); struct_pattern_etc_attrs.shrink_to_fit (); } @@ -975,49 +1000,62 @@ protected: } }; -// Base abstract class for patterns used in TupleStructPattern -class TupleStructItems +// Base abstract class for TupleStructItems, TuplePatternItems & +// SlicePatternItems +class PatternItems { public: enum ItemType { - RANGE, - NO_RANGE + NO_REST, + HAS_REST, }; - virtual ~TupleStructItems () {} + virtual ~PatternItems () {} // TODO: should this store location data? // Unique pointer custom clone function - std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const + std::unique_ptr<PatternItems> clone_pattern_items () const { - return std::unique_ptr<TupleStructItems> (clone_tuple_struct_items_impl ()); + return std::unique_ptr<PatternItems> (clone_pattern_items_impl ()); } virtual std::string as_string () const = 0; - + virtual ItemType get_item_type () const = 0; virtual void accept_vis (ASTVisitor &vis) = 0; - virtual ItemType get_item_type () const = 0; +protected: + virtual PatternItems *clone_pattern_items_impl () const = 0; +}; + +// Base abstract class for patterns used in TupleStructPattern +class TupleStructItems : public PatternItems +{ +public: + // Unique pointer custom clone function + std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const + { + return std::unique_ptr<TupleStructItems> (clone_pattern_items_impl ()); + } protected: // pure virtual clone implementation - virtual TupleStructItems *clone_tuple_struct_items_impl () const = 0; + virtual TupleStructItems *clone_pattern_items_impl () const = 0; }; // Class for non-ranged tuple struct pattern patterns -class TupleStructItemsNoRange : public TupleStructItems +class TupleStructItemsNoRest : public TupleStructItems { std::vector<std::unique_ptr<Pattern>> patterns; public: - TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern>> patterns) + TupleStructItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) : patterns (std::move (patterns)) {} // Copy constructor with vector clone - TupleStructItemsNoRange (TupleStructItemsNoRange const &other) + TupleStructItemsNoRest (TupleStructItemsNoRest const &other) { patterns.reserve (other.patterns.size ()); for (const auto &e : other.patterns) @@ -1025,7 +1063,7 @@ public: } // Overloaded assignment operator with vector clone - TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other) + TupleStructItemsNoRest &operator= (TupleStructItemsNoRest const &other) { patterns.clear (); patterns.reserve (other.patterns.size ()); @@ -1036,9 +1074,8 @@ public: } // move constructors - TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default; - TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other) - = default; + TupleStructItemsNoRest (TupleStructItemsNoRest &&other) = default; + TupleStructItemsNoRest &operator= (TupleStructItemsNoRest &&other) = default; std::string as_string () const override; @@ -1051,32 +1088,32 @@ public: return patterns; } - ItemType get_item_type () const override final { return ItemType::NO_RANGE; } + ItemType get_item_type () const override final { return ItemType::NO_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TupleStructItemsNoRange *clone_tuple_struct_items_impl () const override + TupleStructItemsNoRest *clone_pattern_items_impl () const override { - return new TupleStructItemsNoRange (*this); + return new TupleStructItemsNoRest (*this); } }; // Class for ranged tuple struct pattern patterns -class TupleStructItemsRange : public TupleStructItems +class TupleStructItemsHasRest : public TupleStructItems { std::vector<std::unique_ptr<Pattern>> lower_patterns; std::vector<std::unique_ptr<Pattern>> upper_patterns; public: - TupleStructItemsRange (std::vector<std::unique_ptr<Pattern>> lower_patterns, - std::vector<std::unique_ptr<Pattern>> upper_patterns) + TupleStructItemsHasRest (std::vector<std::unique_ptr<Pattern>> lower_patterns, + std::vector<std::unique_ptr<Pattern>> upper_patterns) : lower_patterns (std::move (lower_patterns)), upper_patterns (std::move (upper_patterns)) {} // Copy constructor with vector clone - TupleStructItemsRange (TupleStructItemsRange const &other) + TupleStructItemsHasRest (TupleStructItemsHasRest const &other) { lower_patterns.reserve (other.lower_patterns.size ()); for (const auto &e : other.lower_patterns) @@ -1088,7 +1125,7 @@ public: } // Overloaded assignment operator to clone - TupleStructItemsRange &operator= (TupleStructItemsRange const &other) + TupleStructItemsHasRest &operator= (TupleStructItemsHasRest const &other) { lower_patterns.clear (); lower_patterns.reserve (other.lower_patterns.size ()); @@ -1104,8 +1141,9 @@ public: } // move constructors - TupleStructItemsRange (TupleStructItemsRange &&other) = default; - TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default; + TupleStructItemsHasRest (TupleStructItemsHasRest &&other) = default; + TupleStructItemsHasRest &operator= (TupleStructItemsHasRest &&other) + = default; std::string as_string () const override; @@ -1131,14 +1169,14 @@ public: return upper_patterns; } - ItemType get_item_type () const override final { return ItemType::RANGE; } + ItemType get_item_type () const override final { return ItemType::HAS_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TupleStructItemsRange *clone_tuple_struct_items_impl () const override + TupleStructItemsHasRest *clone_pattern_items_impl () const override { - return new TupleStructItemsRange (*this); + return new TupleStructItemsHasRest (*this); } }; @@ -1221,49 +1259,32 @@ protected: }; // Base abstract class representing TuplePattern patterns -class TuplePatternItems +class TuplePatternItems : public PatternItems { public: - enum TuplePatternItemType - { - MULTIPLE, - RANGED, - }; - - virtual ~TuplePatternItems () {} - - // TODO: should this store location data? - // Unique pointer custom clone function std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const { - return std::unique_ptr<TuplePatternItems> ( - clone_tuple_pattern_items_impl ()); + return std::unique_ptr<TuplePatternItems> (clone_pattern_items_impl ()); } - virtual std::string as_string () const = 0; - - virtual void accept_vis (ASTVisitor &vis) = 0; - - virtual TuplePatternItemType get_pattern_type () const = 0; - protected: // pure virtual clone implementation - virtual TuplePatternItems *clone_tuple_pattern_items_impl () const = 0; + virtual TuplePatternItems *clone_pattern_items_impl () const = 0; }; -// Class representing TuplePattern patterns where there are multiple patterns -class TuplePatternItemsMultiple : public TuplePatternItems +// Class representing TuplePattern patterns which contains no rest pattern +class TuplePatternItemsNoRest : public TuplePatternItems { std::vector<std::unique_ptr<Pattern>> patterns; public: - TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern>> patterns) + TuplePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) : patterns (std::move (patterns)) {} // Copy constructor with vector clone - TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other) + TuplePatternItemsNoRest (TuplePatternItemsNoRest const &other) { patterns.reserve (other.patterns.size ()); for (const auto &e : other.patterns) @@ -1271,7 +1292,7 @@ public: } // Overloaded assignment operator to vector clone - TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other) + TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest const &other) { patterns.clear (); patterns.reserve (other.patterns.size ()); @@ -1282,8 +1303,8 @@ public: } // move constructors - TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default; - TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other) + TuplePatternItemsNoRest (TuplePatternItemsNoRest &&other) = default; + TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest &&other) = default; std::string as_string () const override; @@ -1297,35 +1318,33 @@ public: return patterns; } - TuplePatternItemType get_pattern_type () const override - { - return TuplePatternItemType::MULTIPLE; - } + ItemType get_item_type () const override { return ItemType::NO_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TuplePatternItemsMultiple *clone_tuple_pattern_items_impl () const override + TuplePatternItemsNoRest *clone_pattern_items_impl () const override { - return new TuplePatternItemsMultiple (*this); + return new TuplePatternItemsNoRest (*this); } }; -// Class representing TuplePattern patterns where there are a range of patterns -class TuplePatternItemsRanged : public TuplePatternItems +// Class representing TuplePattern patterns which contains a rest pattern +class TuplePatternItemsHasRest : public TuplePatternItems { std::vector<std::unique_ptr<Pattern>> lower_patterns; std::vector<std::unique_ptr<Pattern>> upper_patterns; public: - TuplePatternItemsRanged (std::vector<std::unique_ptr<Pattern>> lower_patterns, - std::vector<std::unique_ptr<Pattern>> upper_patterns) + TuplePatternItemsHasRest ( + std::vector<std::unique_ptr<Pattern>> lower_patterns, + std::vector<std::unique_ptr<Pattern>> upper_patterns) : lower_patterns (std::move (lower_patterns)), upper_patterns (std::move (upper_patterns)) {} // Copy constructor with vector clone - TuplePatternItemsRanged (TuplePatternItemsRanged const &other) + TuplePatternItemsHasRest (TuplePatternItemsHasRest const &other) { lower_patterns.reserve (other.lower_patterns.size ()); for (const auto &e : other.lower_patterns) @@ -1337,7 +1356,7 @@ public: } // Overloaded assignment operator to clone - TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other) + TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest const &other) { lower_patterns.clear (); lower_patterns.reserve (other.lower_patterns.size ()); @@ -1353,8 +1372,8 @@ public: } // move constructors - TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default; - TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other) + TuplePatternItemsHasRest (TuplePatternItemsHasRest &&other) = default; + TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest &&other) = default; std::string as_string () const override; @@ -1381,17 +1400,14 @@ public: return upper_patterns; } - TuplePatternItemType get_pattern_type () const override - { - return TuplePatternItemType::RANGED; - } + ItemType get_item_type () const override { return ItemType::HAS_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TuplePatternItemsRanged *clone_tuple_pattern_items_impl () const override + TuplePatternItemsHasRest *clone_pattern_items_impl () const override { - return new TuplePatternItemsRanged (*this); + return new TuplePatternItemsHasRest (*this); } }; @@ -1508,6 +1524,12 @@ public: return *pattern_in_parens; } + std::unique_ptr<Pattern> &get_pattern_in_parens_ptr () + { + rust_assert (pattern_in_parens != nullptr); + return pattern_in_parens; + } + NodeId get_node_id () const override { return node_id; } Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Grouped; } @@ -1522,35 +1544,18 @@ protected: }; // Base abstract class representing patterns in a SlicePattern -class SlicePatternItems +class SlicePatternItems : public PatternItems { public: - enum SlicePatternItemType - { - NO_REST, - HAS_REST, - }; - - virtual ~SlicePatternItems () {} - - // TODO: should this store location data? - // Unique pointer custom clone function std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const { - return std::unique_ptr<SlicePatternItems> ( - clone_slice_pattern_items_impl ()); + return std::unique_ptr<SlicePatternItems> (clone_pattern_items_impl ()); } - virtual std::string as_string () const = 0; - - virtual void accept_vis (ASTVisitor &vis) = 0; - - virtual SlicePatternItemType get_pattern_type () const = 0; - protected: // pure virtual clone implementation - virtual SlicePatternItems *clone_slice_pattern_items_impl () const = 0; + virtual SlicePatternItems *clone_pattern_items_impl () const = 0; }; // Class representing the patterns in a SlicePattern without `..` @@ -1598,15 +1603,12 @@ public: return patterns; } - SlicePatternItemType get_pattern_type () const override - { - return SlicePatternItemType::NO_REST; - } + ItemType get_item_type () const override { return ItemType::NO_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - SlicePatternItemsNoRest *clone_slice_pattern_items_impl () const override + SlicePatternItemsNoRest *clone_pattern_items_impl () const override { return new SlicePatternItemsNoRest (*this); } @@ -1683,15 +1685,12 @@ public: return upper_patterns; } - SlicePatternItemType get_pattern_type () const override - { - return SlicePatternItemType::HAS_REST; - } + ItemType get_item_type () const override { return ItemType::HAS_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - SlicePatternItemsHasRest *clone_slice_pattern_items_impl () const override + SlicePatternItemsHasRest *clone_pattern_items_impl () const override { return new SlicePatternItemsHasRest (*this); } diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index f843a79..5fb00ef 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -201,6 +201,12 @@ public: return *variables_pattern; } + std::unique_ptr<Pattern> &get_pattern_ptr () + { + rust_assert (variables_pattern != nullptr); + return variables_pattern; + } + Type &get_type () { rust_assert (has_type ()); diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 2a3496b..014963f 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -571,6 +571,12 @@ public: return *type; } + std::unique_ptr<TypeNoBounds> &get_type_pointed_to_ptr () + { + rust_assert (type != nullptr); + return type; + } + // Getter for direct access to the type unique_ptr std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; } @@ -646,6 +652,12 @@ public: return *type; } + std::unique_ptr<TypeNoBounds> &get_type_referenced_ptr () + { + rust_assert (type != nullptr); + return type; + } + bool get_has_mut () const { return has_mut; } Lifetime &get_lifetime () { return lifetime.value (); } @@ -720,6 +732,12 @@ public: return *elem_type; } + std::unique_ptr<Type> &get_elem_type_ptr () + { + rust_assert (elem_type != nullptr); + return elem_type; + } + // TODO: would a "vis_expr" be better? AnonConst &get_size_expr () { @@ -986,7 +1004,7 @@ public: return_type (std::move (type)), locus (locus) { if (!variadic_attrs.empty ()) - is_variadic = true; + _is_variadic = true; } // Copy constructor with clone @@ -1044,14 +1062,24 @@ public: return *return_type; } + std::unique_ptr<TypeNoBounds> &get_return_type_ptr () + { + rust_assert (has_return_type ()); + return return_type; + } + FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; } BareFunctionType *reconstruct_impl () const override { + std::unique_ptr<TypeNoBounds> ret_type = nullptr; + if (return_type != nullptr) + ret_type = return_type->reconstruct (); + return new BareFunctionType ( for_lifetimes, function_qualifiers, params, /* FIXME: Should params be reconstruct() as well? */ - _is_variadic, variadic_attrs, return_type->reconstruct (), locus); + _is_variadic, variadic_attrs, std::move (ret_type), locus); } protected: diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index 73c34b2..d1db58e 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -32,6 +32,7 @@ #include "rust-type-util.h" #include "rust-compile-implitem.h" #include "rust-attribute-values.h" +#include "rust-attributes.h" #include "rust-immutable-name-resolution-context.h" #include "fold-const.h" @@ -251,25 +252,21 @@ void HIRCompileBase::handle_link_section_attribute_on_fndecl ( tree fndecl, const AST::Attribute &attr) { - if (!attr.has_attr_input ()) + auto msg_str = Analysis::Attributes::extract_string_literal (attr); + + if (!msg_str.has_value ()) { rust_error_at (attr.get_locus (), - "%<link_section%> expects exactly one argment"); + "malformed %<link_section%> attribute input"); return; } - rust_assert (attr.get_attr_input ().get_attr_input_type () - == AST::AttrInput::AttrInputType::LITERAL); - - auto &literal = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ()); - const auto &msg_str = literal.get_literal ().as_string (); - if (decl_section_name (fndecl)) { rust_warning_at (attr.get_locus (), 0, "section name redefined"); } - set_decl_section_name (fndecl, msg_str.c_str ()); + set_decl_section_name (fndecl, msg_str->c_str ()); } void @@ -416,13 +413,10 @@ HIRCompileBase::handle_must_use_attribute_on_fndecl (tree fndecl, if (attr.has_attr_input ()) { - rust_assert (attr.get_attr_input ().get_attr_input_type () - == AST::AttrInput::AttrInputType::LITERAL); + auto msg_str = Analysis::Attributes::extract_string_literal (attr); + rust_assert (msg_str.has_value ()); - auto &literal - = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ()); - const auto &msg_str = literal.get_literal ().as_string (); - tree message = build_string (msg_str.size (), msg_str.c_str ()); + tree message = build_string (msg_str->size (), msg_str->c_str ()); value = tree_cons (nodiscard, message, NULL_TREE); } diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index e9b8596..3bf26af 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -56,7 +56,7 @@ protected: TyTy::BaseType *expected, location_t lvalue_locus, location_t rvalue_locus); - tree coerce_to_dyn_object (tree compiled_ref, const TyTy::BaseType *actual, + tree coerce_to_dyn_object (tree compiled_ref, TyTy::BaseType *actual, const TyTy::DynamicObjectType *ty, location_t locus); diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index d4a642b..e98bbc2 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -34,6 +34,10 @@ namespace Compile { struct fncontext { + fncontext (tree fndecl, ::Bvariable *ret_addr, TyTy::BaseType *retty) + : fndecl (fndecl), ret_addr (ret_addr), retty (retty) + {} + tree fndecl; ::Bvariable *ret_addr; TyTy::BaseType *retty; @@ -154,7 +158,7 @@ public: if (it == mono_fns.end ()) mono_fns[dId] = {}; - mono_fns[dId].push_back ({ref, fn}); + mono_fns[dId].emplace_back (ref, fn); } void insert_closure_decl (const TyTy::ClosureType *ref, tree fn) @@ -164,7 +168,7 @@ public: if (it == mono_closure_fns.end ()) mono_closure_fns[dId] = {}; - mono_closure_fns[dId].push_back ({ref, fn}); + mono_closure_fns[dId].emplace_back (ref, fn); } tree lookup_closure_decl (const TyTy::ClosureType *ref) @@ -279,7 +283,7 @@ public: void push_fn (tree fn, ::Bvariable *ret_addr, TyTy::BaseType *retty) { - fn_stack.push_back (fncontext{fn, ret_addr, retty}); + fn_stack.emplace_back (fn, ret_addr, retty); } void pop_fn () { fn_stack.pop_back (); } @@ -318,7 +322,13 @@ public: void push_loop_context (Bvariable *var) { loop_value_stack.push_back (var); } - Bvariable *peek_loop_context () { return loop_value_stack.back (); } + bool have_loop_context () const { return !loop_value_stack.empty (); } + + Bvariable *peek_loop_context () + { + rust_assert (!loop_value_stack.empty ()); + return loop_value_stack.back (); + } Bvariable *pop_loop_context () { @@ -332,7 +342,11 @@ public: loop_begin_labels.push_back (label); } - tree peek_loop_begin_label () { return loop_begin_labels.back (); } + tree peek_loop_begin_label () + { + rust_assert (!loop_begin_labels.empty ()); + return loop_begin_labels.back (); + } tree pop_loop_begin_label () { diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 6433923..0a627f3 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -828,6 +828,10 @@ CompileExpr::visit (HIR::BreakExpr &expr) { tree compiled_expr = CompileExpr::Compile (expr.get_expr (), ctx); + translated = error_mark_node; + if (!ctx->have_loop_context ()) + return; + Bvariable *loop_result_holder = ctx->peek_loop_context (); tree result_reference = Backend::var_expression (loop_result_holder, @@ -891,6 +895,10 @@ CompileExpr::visit (HIR::BreakExpr &expr) void CompileExpr::visit (HIR::ContinueExpr &expr) { + translated = error_mark_node; + if (!ctx->have_loop_context ()) + return; + tree label = ctx->peek_loop_begin_label (); if (expr.has_label ()) { @@ -1647,37 +1655,39 @@ CompileExpr::compile_integer_literal (const HIR::LiteralExpr &expr, const TyTy::BaseType *tyty) { rust_assert (expr.get_lit_type () == HIR::Literal::INT); - const auto literal_value = expr.get_literal (); - + const auto &literal_value = expr.get_literal (); tree type = TyTyResolveCompile::compile (ctx, tyty); + std::string s = literal_value.as_string (); + s.erase (std::remove (s.begin (), s.end (), '_'), s.end ()); + + int base = 0; mpz_t ival; - if (mpz_init_set_str (ival, literal_value.as_string ().c_str (), 10) != 0) + if (mpz_init_set_str (ival, s.c_str (), base) != 0) { - rust_error_at (expr.get_locus (), "bad number in literal"); + rust_error_at (expr.get_locus (), "failed to load number literal"); return error_mark_node; } + if (expr.is_negative ()) + mpz_neg (ival, ival); - mpz_t type_min; - mpz_t type_max; + mpz_t type_min, type_max; mpz_init (type_min); mpz_init (type_max); get_type_static_bounds (type, type_min, type_max); - if (expr.is_negative ()) - { - mpz_neg (ival, ival); - } if (mpz_cmp (ival, type_min) < 0 || mpz_cmp (ival, type_max) > 0) { rust_error_at (expr.get_locus (), "integer overflows the respective type %qs", tyty->get_name ().c_str ()); + mpz_clear (type_min); + mpz_clear (type_max); + mpz_clear (ival); return error_mark_node; } tree result = wide_int_to_tree (type, wi::from_mpz (type, ival, true)); - mpz_clear (type_min); mpz_clear (type_max); mpz_clear (ival); @@ -2000,13 +2010,25 @@ CompileExpr::array_copied_expr (location_t expr_locus, return error_mark_node; } - ctx->push_const_context (); - tree capacity_expr = CompileExpr::Compile (elems.get_num_copies_expr (), ctx); - ctx->pop_const_context (); + auto capacity_ty = array_tyty.get_capacity (); + + // Check if capacity is a const type + if (capacity_ty->get_kind () != TyTy::TypeKind::CONST) + { + rust_error_at (array_tyty.get_locus (), + "array capacity is not a const type"); + return error_mark_node; + } + + auto *capacity_const = capacity_ty->as_const_type (); - if (!TREE_CONSTANT (capacity_expr)) + rust_assert (capacity_const->const_kind () + == TyTy::BaseConstType::ConstKind::Value); + auto &capacity_value = *static_cast<TyTy::ConstValueType *> (capacity_const); + auto cap_tree = capacity_value.get_value (); + if (error_operand_p (cap_tree) || !TREE_CONSTANT (cap_tree)) { - rust_error_at (expr_locus, "non const num copies %qT", array_type); + rust_error_at (expr_locus, "non const num copies %qT", cap_tree); return error_mark_node; } @@ -2059,9 +2081,9 @@ CompileExpr::array_copied_expr (location_t expr_locus, ctx->push_block (init_block); tree tmp; - tree stmts = Backend::array_initializer (fndecl, init_block, array_type, - capacity_expr, translated_expr, - &tmp, expr_locus); + tree stmts + = Backend::array_initializer (fndecl, init_block, array_type, cap_tree, + translated_expr, &tmp, expr_locus); ctx->add_statement (stmts); tree block = ctx->pop_block (); @@ -2209,11 +2231,10 @@ HIRCompileBase::resolve_unsized_dyn_adjustment ( tree rvalue = expression; location_t rvalue_locus = locus; - const TyTy::BaseType *actual = adjustment.get_actual (); - const TyTy::BaseType *expected = adjustment.get_expected (); + auto actual = adjustment.get_actual (); + auto expected = adjustment.get_expected (); - const TyTy::DynamicObjectType *dyn - = static_cast<const TyTy::DynamicObjectType *> (expected); + const auto dyn = static_cast<const TyTy::DynamicObjectType *> (expected); rust_debug ("resolve_unsized_dyn_adjustment actual={%s} dyn={%s}", actual->debug_str ().c_str (), dyn->debug_str ().c_str ()); @@ -2617,15 +2638,15 @@ CompileExpr::generate_closure_fntype (HIR::ClosureExpr &expr, TyTy::TypeBoundPredicateItem item = TyTy::TypeBoundPredicateItem::error (); if (predicate.get_name ().compare ("FnOnce") == 0) { - item = predicate.lookup_associated_item ("call_once"); + item = predicate.lookup_associated_item ("call_once").value (); } else if (predicate.get_name ().compare ("FnMut") == 0) { - item = predicate.lookup_associated_item ("call_mut"); + item = predicate.lookup_associated_item ("call_mut").value (); } else if (predicate.get_name ().compare ("Fn") == 0) { - item = predicate.lookup_associated_item ("call"); + item = predicate.lookup_associated_item ("call").value (); } else { diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h index d6aa589..a78f9ee 100644 --- a/gcc/rust/backend/rust-compile-extern.h +++ b/gcc/rust/backend/rust-compile-extern.h @@ -24,6 +24,8 @@ #include "rust-compile-type.h" #include "rust-diagnostics.h" #include "rust-hir-full-decls.h" +#include "rust-attributes.h" +#include "rust-attribute-values.h" namespace Rust { namespace Compile { @@ -57,8 +59,7 @@ public: rust_assert (ok); std::string name = item.get_item_name ().as_string (); - // FIXME this is assuming C ABI - std::string asm_name = name; + GGC::Ident asm_name = get_link_name (item); tree type = TyTyResolveCompile::compile (ctx, resolved_type); bool is_external = true; @@ -124,16 +125,7 @@ public: tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); std::string ir_symbol_name = function.get_item_name ().as_string (); - std::string asm_name = function.get_item_name ().as_string (); - if (fntype->get_abi () == ABI::RUST) - { - // then we need to get the canonical path of it and mangle it - auto canonical_path = ctx->get_mappings ().lookup_canonical_path ( - function.get_mappings ().get_nodeid ()); - - ir_symbol_name = canonical_path->get () + fntype->subst_as_string (); - asm_name = ctx->mangle_item (fntype, *canonical_path); - } + GGC::Ident asm_name = get_link_name (function); const unsigned int flags = Backend::function_is_declaration; tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, asm_name, @@ -158,6 +150,36 @@ private: ref_locus (ref_locus) {} + template <typename T> static GGC::Ident get_link_name (T &obj) + { + AST::Attribute *use_attr = nullptr; + + for (auto &attr : obj.get_outer_attrs ()) + { + if (attr.get_path ().as_string () == Values::Attributes::LINK_NAME) + { + // later attributes override earlier ones + // TODO: add warning -- should duplicate + // attributes be folded elsewhere? + use_attr = &attr; + } + } + + if (use_attr) + { + auto link_name + = Analysis::Attributes::extract_string_literal (*use_attr); + + if (!link_name.has_value ()) + rust_error_at (use_attr->get_locus (), + "malformed %<link_name%> attribute input"); + else + return *link_name; + } + + return obj.get_item_name (); + } + TyTy::BaseType *concrete; tree reference; location_t ref_locus; diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index fe65921..82333dc 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -27,6 +27,7 @@ #include "rust-hir-pattern.h" #include "rust-system.h" #include "rust-tyty.h" +#include "tree.h" namespace Rust { namespace Compile { @@ -158,13 +159,15 @@ CompilePatternCheckExpr::visit (HIR::RangePattern &pattern) pattern.get_mappings (), pattern.get_locus (), ctx); + ComparisonOperator upper_cmp = pattern.is_inclusive_range () + ? ComparisonOperator::LESS_OR_EQUAL + : ComparisonOperator::LESS_THAN; tree check_lower = Backend::comparison_expression (ComparisonOperator::GREATER_OR_EQUAL, match_scrutinee_expr, lower, pattern.get_locus ()); tree check_upper - = Backend::comparison_expression (ComparisonOperator::LESS_OR_EQUAL, - match_scrutinee_expr, upper, + = Backend::comparison_expression (upper_cmp, match_scrutinee_expr, upper, pattern.get_locus ()); check_expr = Backend::arithmetic_or_logical_expression ( ArithmeticOrLogicalOperator::BITWISE_AND, check_lower, check_upper, @@ -354,17 +357,51 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern) HIR::TupleStructItems &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: + case HIR::TupleStructItems::HAS_REST: { - // TODO - rust_unreachable (); + HIR::TupleStructItemsHasRest &items_has_rest + = static_cast<HIR::TupleStructItemsHasRest &> (items); + size_t num_patterns = items_has_rest.get_lower_patterns ().size () + + items_has_rest.get_upper_patterns ().size (); + + // enums cases shouldn't reach here + rust_assert (num_patterns <= variant->num_fields () + && (!adt->is_enum ())); + + size_t tuple_field_index = 0; + for (auto &pattern : items_has_rest.get_lower_patterns ()) + { + tree field_expr + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, + pattern->get_locus ()); + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern->get_locus ()); + } + tuple_field_index = variant->num_fields () + - items_has_rest.get_upper_patterns ().size (); + for (auto &pattern : items_has_rest.get_upper_patterns ()) + { + tree field_expr + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, + pattern->get_locus ()); + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern->get_locus ()); + } } break; - case HIR::TupleStructItems::MULTIPLE: + case HIR::TupleStructItems::NO_REST: { - HIR::TupleStructItemsNoRange &items_no_range - = static_cast<HIR::TupleStructItemsNoRange &> (items); + HIR::TupleStructItemsNoRest &items_no_range + = static_cast<HIR::TupleStructItemsNoRest &> (items); rust_assert (items_no_range.get_patterns ().size () == variant->num_fields ()); @@ -428,10 +465,10 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::RANGED: + case HIR::TuplePatternItems::HAS_REST: { auto &items - = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); size_t tuple_field_index = 0; // lookup the type to find out number of fields @@ -477,10 +514,10 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) } break; - case HIR::TuplePatternItems::MULTIPLE: + case HIR::TuplePatternItems::NO_REST: { - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); size_t tuple_field_index = 0; for (auto &pat : items.get_patterns ()) @@ -532,25 +569,14 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern) || lookup->get_kind () == TyTy::TypeKind::SLICE || lookup->get_kind () == TyTy::REF); - size_t array_element_index = 0; + // function ptr that points to either array_index_expression or + // slice_index_expression depending on the scrutinee's type + tree (*scrutinee_index_expr_func) (tree, tree, location_t) = nullptr; + switch (lookup->get_kind ()) { case TyTy::TypeKind::ARRAY: - for (auto &pattern_member : pattern.get_items ()) - { - tree array_index_tree - = Backend::size_constant_expression (array_element_index++); - tree element_expr - = Backend::array_index_expression (match_scrutinee_expr, - array_index_tree, - pattern.get_locus ()); - tree check_expr_sub - = CompilePatternCheckExpr::Compile (*pattern_member, element_expr, - ctx); - check_expr = Backend::arithmetic_or_logical_expression ( - ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, - check_expr_sub, pattern.get_locus ()); - } + scrutinee_index_expr_func = Backend::array_index_expression; break; case TyTy::TypeKind::SLICE: rust_sorry_at ( @@ -560,25 +586,81 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern) case TyTy::TypeKind::REF: { rust_assert (RS_DST_FLAG_P (TREE_TYPE (match_scrutinee_expr))); + scrutinee_index_expr_func = Backend::slice_index_expression; tree size_field = Backend::struct_field_expression (match_scrutinee_expr, 1, pattern.get_locus ()); - // First compare the size - check_expr = Backend::comparison_expression ( - ComparisonOperator::EQUAL, size_field, - build_int_cst (size_type_node, pattern.get_items ().size ()), - pattern.get_locus ()); + // for slices, generate a dynamic size comparison expression tree + // because size checking is done at runtime. + switch (pattern.get_items ().get_item_type ()) + { + case HIR::SlicePatternItems::ItemType::NO_REST: + { + auto &items = static_cast<HIR::SlicePatternItemsNoRest &> ( + pattern.get_items ()); + check_expr = Backend::comparison_expression ( + ComparisonOperator::EQUAL, size_field, + build_int_cst (size_type_node, items.get_patterns ().size ()), + pattern.get_locus ()); + } + break; + case HIR::SlicePatternItems::ItemType::HAS_REST: + { + auto &items = static_cast<HIR::SlicePatternItemsHasRest &> ( + pattern.get_items ()); + auto pattern_min_cap = items.get_lower_patterns ().size () + + items.get_upper_patterns ().size (); + check_expr = Backend::comparison_expression ( + ComparisonOperator::GREATER_OR_EQUAL, size_field, + build_int_cst (size_type_node, pattern_min_cap), + pattern.get_locus ()); + } + break; + } + } + break; + default: + rust_unreachable (); + } + + rust_assert (scrutinee_index_expr_func != nullptr); - // Then compare each element in the slice pattern - for (auto &pattern_member : pattern.get_items ()) + // Generate tree to compare every element within array/slice + size_t element_index = 0; + switch (pattern.get_items ().get_item_type ()) + { + case HIR::SlicePatternItems::ItemType::NO_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ()); + for (auto &pattern_member : items.get_patterns ()) { - tree slice_index_tree - = Backend::size_constant_expression (array_element_index++); + tree index_tree + = Backend::size_constant_expression (element_index++); tree element_expr - = Backend::slice_index_expression (match_scrutinee_expr, - slice_index_tree, - pattern.get_locus ()); + = scrutinee_index_expr_func (match_scrutinee_expr, index_tree, + pattern.get_locus ()); + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern_member, element_expr, + ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern.get_locus ()); + } + break; + } + case HIR::SlicePatternItems::ItemType::HAS_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ()); + for (auto &pattern_member : items.get_lower_patterns ()) + { + tree index_tree + = Backend::size_constant_expression (element_index++); + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, index_tree, + pattern.get_locus ()); tree check_expr_sub = CompilePatternCheckExpr::Compile (*pattern_member, element_expr, ctx); @@ -586,10 +668,82 @@ CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern) ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, check_expr_sub, pattern.get_locus ()); } + + // handle codegen for upper patterns differently for both types + switch (lookup->get_kind ()) + { + case TyTy::TypeKind::ARRAY: + { + // for array type scrutinee, we can simply get the capacity as a + // const and calculate how many elements to skip + auto array_ty = static_cast<TyTy::ArrayType *> (lookup); + auto capacity_ty = array_ty->get_capacity (); + + rust_assert (capacity_ty->get_kind () == TyTy::TypeKind::CONST); + auto *capacity_const = capacity_ty->as_const_type (); + rust_assert (capacity_const->const_kind () + == TyTy::BaseConstType::ConstKind::Value); + auto &capacity_value + = *static_cast<TyTy::ConstValueType *> (capacity_const); + auto cap_tree = capacity_value.get_value (); + + rust_assert (!error_operand_p (cap_tree)); + + size_t cap_wi = (size_t) wi::to_wide (cap_tree).to_uhwi (); + element_index = cap_wi - items.get_upper_patterns ().size (); + for (auto &pattern_member : items.get_upper_patterns ()) + { + tree index_tree + = Backend::size_constant_expression (element_index++); + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, + index_tree, + pattern.get_locus ()); + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern_member, + element_expr, ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern.get_locus ()); + } + } + break; + case TyTy::TypeKind::REF: + { + // for slice type scrutinee, size is dyanamic, so number of + // elements to skip is calculated during runtime + tree slice_size + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern.get_locus ()); + tree upper_patterns_size = Backend::size_constant_expression ( + items.get_upper_patterns ().size ()); + tree index_tree = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::SUBTRACT, slice_size, + upper_patterns_size, pattern.get_locus ()); + for (auto &pattern_member : items.get_upper_patterns ()) + { + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, + index_tree, + pattern.get_locus ()); + tree check_expr_sub + = CompilePatternCheckExpr::Compile (*pattern_member, + element_expr, ctx); + check_expr = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, + check_expr_sub, pattern.get_locus ()); + index_tree = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::ADD, index_tree, + Backend::size_constant_expression (1), + pattern.get_locus ()); + } + } + break; + default: + rust_unreachable (); + } } break; - default: - rust_unreachable (); } } @@ -628,25 +782,54 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) HIR::TupleStructItems &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: + case HIR::TupleStructItems::HAS_REST: { - // TODO - rust_unreachable (); + HIR::TupleStructItemsHasRest &items_has_rest + = static_cast<HIR::TupleStructItemsHasRest &> (items); + size_t num_patterns = items_has_rest.get_lower_patterns ().size () + + items_has_rest.get_upper_patterns ().size (); + + // enums cases shouldn't reach here + rust_assert (num_patterns <= variant->num_fields () + && (!adt->is_enum ())); + + size_t tuple_field_index = 0; + for (auto &pattern : items_has_rest.get_lower_patterns ()) + { + tree binding + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, + pattern->get_locus ()); + + CompilePatternBindings::Compile (*pattern, binding, ctx); + } + + tuple_field_index = variant->num_fields () + - items_has_rest.get_upper_patterns ().size (); + + for (auto &pattern : items_has_rest.get_upper_patterns ()) + { + tree binding + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_field_index++, + pattern->get_locus ()); + + CompilePatternBindings::Compile (*pattern, binding, ctx); + } } break; - case HIR::TupleStructItems::MULTIPLE: + case HIR::TupleStructItems::NO_REST: { - HIR::TupleStructItemsNoRange &items_no_range - = static_cast<HIR::TupleStructItemsNoRange &> (items); - - rust_assert (items_no_range.get_patterns ().size () + HIR::TupleStructItemsNoRest &items_no_rest + = static_cast<HIR::TupleStructItemsNoRest &> (items); + rust_assert (items_no_rest.get_patterns ().size () == variant->num_fields ()); if (adt->is_enum ()) { size_t tuple_field_index = 0; - for (auto &pattern : items_no_range.get_patterns ()) + for (auto &pattern : items_no_rest.get_patterns ()) { tree payload_accessor_union = Backend::struct_field_expression (match_scrutinee_expr, 1, @@ -668,12 +851,10 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) else { size_t tuple_field_index = 0; - for (auto &pattern : items_no_range.get_patterns ()) + for (auto &pattern : items_no_rest.get_patterns ()) { - tree variant_accessor = match_scrutinee_expr; - tree binding - = Backend::struct_field_expression (variant_accessor, + = Backend::struct_field_expression (match_scrutinee_expr, tuple_field_index++, pattern->get_locus ()); @@ -777,8 +958,9 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern) rust_assert (ok); } - rust_assert (variant->get_variant_type () - == TyTy::VariantDef::VariantType::STRUCT); + rust_assert ( + variant->get_variant_type () == TyTy::VariantDef::VariantType::STRUCT + || variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE); auto &struct_pattern_elems = pattern.get_struct_pattern_elems (); for (auto &field : struct_pattern_elems.get_struct_pattern_fields ()) @@ -843,11 +1025,11 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::RANGED: + case HIR::TuplePatternItems::ItemType::HAS_REST: { size_t tuple_idx = 0; auto &items - = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); auto &items_lower = items.get_lower_patterns (); auto &items_upper = items.get_upper_patterns (); @@ -887,11 +1069,11 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern) return; } - case HIR::TuplePatternItems::ItemType::MULTIPLE: + case HIR::TuplePatternItems::ItemType::NO_REST: { size_t tuple_idx = 0; - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); for (auto &sub : items.get_patterns ()) { @@ -930,43 +1112,132 @@ CompilePatternBindings::visit (HIR::SlicePattern &pattern) || lookup->get_kind () == TyTy::TypeKind::SLICE || lookup->get_kind () == TyTy::REF); - size_t array_element_index = 0; + // function ptr that points to either array_index_expression or + // slice_index_expression depending on the scrutinee's type + tree (*scrutinee_index_expr_func) (tree, tree, location_t) = nullptr; + switch (lookup->get_kind ()) { case TyTy::TypeKind::ARRAY: - for (auto &pattern_member : pattern.get_items ()) - { - tree array_index_tree - = Backend::size_constant_expression (array_element_index++); - tree element_expr - = Backend::array_index_expression (match_scrutinee_expr, - array_index_tree, - pattern.get_locus ()); - CompilePatternBindings::Compile (*pattern_member, element_expr, ctx); - } + scrutinee_index_expr_func = Backend::array_index_expression; break; case TyTy::TypeKind::SLICE: - rust_sorry_at ( - pattern.get_locus (), - "SlicePattern matching against non-ref slices are not yet supported"); + rust_sorry_at (pattern.get_locus (), + "SlicePattern matching against non-ref slices are " + "not yet supported"); break; case TyTy::TypeKind::REF: + scrutinee_index_expr_func = Backend::slice_index_expression; + break; + default: + rust_unreachable (); + } + + rust_assert (scrutinee_index_expr_func != nullptr); + + size_t element_index = 0; + + switch (pattern.get_items ().get_item_type ()) + { + case HIR::SlicePatternItems::ItemType::NO_REST: { - for (auto &pattern_member : pattern.get_items ()) + auto &items + = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ()); + for (auto &pattern_member : items.get_patterns ()) { - tree slice_index_tree - = Backend::size_constant_expression (array_element_index++); + tree index_tree + = Backend::size_constant_expression (element_index++); tree element_expr - = Backend::slice_index_expression (match_scrutinee_expr, - slice_index_tree, - pattern.get_locus ()); + = scrutinee_index_expr_func (match_scrutinee_expr, index_tree, + pattern.get_locus ()); CompilePatternBindings::Compile (*pattern_member, element_expr, ctx); } - break; } - default: - rust_unreachable (); + break; + case HIR::SlicePatternItems::ItemType::HAS_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ()); + for (auto &pattern_member : items.get_lower_patterns ()) + { + tree index_tree + = Backend::size_constant_expression (element_index++); + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, index_tree, + pattern.get_locus ()); + CompilePatternBindings::Compile (*pattern_member, element_expr, + ctx); + } + + // handle codegen for upper patterns differently for both types + switch (lookup->get_kind ()) + { + case TyTy::TypeKind::ARRAY: + { + auto array_ty = static_cast<TyTy::ArrayType *> (lookup); + auto capacity_ty = array_ty->get_capacity (); + + rust_assert (capacity_ty->get_kind () == TyTy::TypeKind::CONST); + auto *capacity_const = capacity_ty->as_const_type (); + rust_assert (capacity_const->const_kind () + == TyTy::BaseConstType::ConstKind::Value); + auto &capacity_value + = *static_cast<TyTy::ConstValueType *> (capacity_const); + auto cap_tree = capacity_value.get_value (); + + rust_assert (!error_operand_p (cap_tree)); + + size_t cap_wi = (size_t) wi::to_wide (cap_tree).to_uhwi (); + element_index = cap_wi - items.get_upper_patterns ().size (); + for (auto &pattern_member : items.get_upper_patterns ()) + { + tree index_tree + = Backend::size_constant_expression (element_index++); + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, + index_tree, + pattern.get_locus ()); + CompilePatternBindings::Compile (*pattern_member, + element_expr, ctx); + } + } + break; + case TyTy::TypeKind::SLICE: + rust_sorry_at (pattern.get_locus (), + "SlicePattern matching against non-ref slices are " + "not yet supported"); + break; + case TyTy::TypeKind::REF: + { + tree slice_size + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern.get_locus ()); + tree upper_patterns_size = Backend::size_constant_expression ( + items.get_upper_patterns ().size ()); + tree index_tree = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::SUBTRACT, slice_size, + upper_patterns_size, pattern.get_locus ()); + for (auto &pattern_member : items.get_upper_patterns ()) + { + tree element_expr + = scrutinee_index_expr_func (match_scrutinee_expr, + index_tree, + pattern.get_locus ()); + CompilePatternBindings::Compile (*pattern_member, + element_expr, ctx); + index_tree = Backend::arithmetic_or_logical_expression ( + ArithmeticOrLogicalOperator::ADD, index_tree, + Backend::size_constant_expression (1), + pattern.get_locus ()); + } + } + break; + default: + rust_unreachable (); + } + } + break; } } @@ -979,6 +1250,11 @@ CompilePatternLet::visit (HIR::IdentifierPattern &pattern) rust_assert ( ctx->lookup_var_decl (pattern.get_mappings ().get_hirid (), &var)); + if (pattern.get_is_ref ()) + { + init_expr = address_expression (init_expr, EXPR_LOCATION (init_expr)); + } + auto fnctx = ctx->peek_fn (); if (ty->is_unit ()) { @@ -990,6 +1266,11 @@ CompilePatternLet::visit (HIR::IdentifierPattern &pattern) } else { + if (pattern.has_subpattern ()) + { + CompilePatternLet::Compile (&pattern.get_subpattern (), init_expr, ty, + rval_locus, ctx); + } auto s = Backend::init_statement (fnctx.fndecl, var, init_expr); ctx->add_statement (s); } @@ -1013,22 +1294,65 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) { rust_assert (pattern.has_tuple_pattern_items ()); - tree tuple_type = TyTyResolveCompile::compile (ctx, ty); + bool has_by_ref = false; + auto check_refs + = [] (const std::vector<std::unique_ptr<HIR::Pattern>> &patterns) { + for (const auto &sub : patterns) + { + switch (sub->get_pattern_type ()) + { + case HIR::Pattern::PatternType::IDENTIFIER: + { + auto id = static_cast<HIR::IdentifierPattern *> (sub.get ()); + if (id->get_is_ref ()) + return true; + break; + } + case HIR::Pattern::PatternType::REFERENCE: + return true; + default: + break; + } + } + return false; + }; + switch (pattern.get_items ().get_item_type ()) + { + case HIR::TuplePatternItems::ItemType::NO_REST: + { + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); + has_by_ref = check_refs (items.get_patterns ()); + break; + } + case HIR::TuplePatternItems::ItemType::HAS_REST: + { + auto &items + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); + has_by_ref = check_refs (items.get_lower_patterns ()) + || check_refs (items.get_upper_patterns ()); + break; + } + default: + break; + } + + tree rhs_tuple_type = TYPE_MAIN_VARIANT (TREE_TYPE (init_expr)); tree init_stmt; Bvariable *tmp_var = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE, - tuple_type, init_expr, false, + rhs_tuple_type, init_expr, has_by_ref, pattern.get_locus (), &init_stmt); tree access_expr = Backend::var_expression (tmp_var, pattern.get_locus ()); ctx->add_statement (init_stmt); switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::RANGED: + case HIR::TuplePatternItems::ItemType::HAS_REST: { size_t tuple_idx = 0; auto &items - = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); auto &items_lower = items.get_lower_patterns (); auto &items_upper = items.get_upper_patterns (); @@ -1069,11 +1393,11 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) return; } - case HIR::TuplePatternItems::ItemType::MULTIPLE: + case HIR::TuplePatternItems::ItemType::NO_REST: { size_t tuple_idx = 0; - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); for (auto &sub : items.get_patterns ()) { diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index f3b9dc2..c33d0b0 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -97,8 +97,11 @@ ResolvePathRef::attempt_constructor_expression_lookup ( // this can only be for discriminant variants the others are built up // using call-expr or struct-init - rust_assert (variant->get_variant_type () - == TyTy::VariantDef::VariantType::NUM); + if (variant->get_variant_type () != TyTy::VariantDef::VariantType::NUM) + { + rust_error_at (expr_locus, "variant expected constructor call"); + return error_mark_node; + } // we need the actual gcc type tree compiled_adt_type = TyTyResolveCompile::compile (ctx, adt); diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index 0622954..5b00afa 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -136,13 +136,31 @@ TyTyResolveCompile::visit (const TyTy::InferType &type) } void -TyTyResolveCompile::visit (const TyTy::ParamType &) +TyTyResolveCompile::visit (const TyTy::ParamType &type) { translated = error_mark_node; } void -TyTyResolveCompile::visit (const TyTy::ConstType &) +TyTyResolveCompile::visit (const TyTy::ConstParamType &type) +{ + translated = error_mark_node; +} + +void +TyTyResolveCompile::visit (const TyTy::ConstValueType &type) +{ + translated = error_mark_node; +} + +void +TyTyResolveCompile::visit (const TyTy::ConstInferType &type) +{ + translated = error_mark_node; +} + +void +TyTyResolveCompile::visit (const TyTy::ConstErrorType &type) { translated = error_mark_node; } @@ -186,8 +204,8 @@ TyTyResolveCompile::visit (const TyTy::ClosureType &type) // this should be based on the closure move-ability tree decl_type = TyTyResolveCompile::compile (ctx, lookup); tree capture_type = build_reference_type (decl_type); - fields.push_back (Backend::typed_identifier (mappings_name, capture_type, - type.get_ident ().locus)); + fields.emplace_back (mappings_name, capture_type, + type.get_ident ().locus); } tree type_record = Backend::struct_type (fields); @@ -217,8 +235,7 @@ TyTyResolveCompile::visit (const TyTy::FnType &type) auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode); location_t return_type_locus = ctx->get_mappings ().lookup_location (hir_type->get_ref ()); - results.push_back ( - Backend::typed_identifier ("_", ret, return_type_locus)); + results.emplace_back ("_", ret, return_type_locus); } for (auto ¶m_pair : type.get_params ()) @@ -227,11 +244,10 @@ TyTyResolveCompile::visit (const TyTy::FnType &type) auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode); - auto compiled_param = Backend::typed_identifier ( - param_pair.get_pattern ().as_string (), compiled_param_type, - ctx->get_mappings ().lookup_location (param_tyty->get_ref ())); - - parameters.push_back (compiled_param); + parameters.emplace_back (param_pair.get_pattern ().as_string (), + compiled_param_type, + ctx->get_mappings ().lookup_location ( + param_tyty->get_ref ())); } if (!type.is_variadic ()) @@ -277,10 +293,9 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type) tree compiled_field_ty = TyTyResolveCompile::compile (ctx, field->get_field_type ()); - Backend::typed_identifier f (field->get_name (), compiled_field_ty, - ctx->get_mappings ().lookup_location ( - type.get_ty_ref ())); - fields.push_back (std::move (f)); + fields.emplace_back (field->get_name (), compiled_field_ty, + ctx->get_mappings ().lookup_location ( + type.get_ty_ref ())); } type_record = type.is_union () ? Backend::union_type (fields, false) @@ -357,10 +372,9 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type) == TyTy::VariantDef::VariantType::TUPLE) field_name = "__" + field->get_name (); - Backend::typed_identifier f ( - field_name, compiled_field_ty, - ctx->get_mappings ().lookup_location (type.get_ty_ref ())); - fields.push_back (std::move (f)); + fields.emplace_back (field_name, compiled_field_ty, + ctx->get_mappings ().lookup_location ( + type.get_ty_ref ())); } tree variant_record = Backend::struct_type (fields); @@ -382,10 +396,9 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type) TyTy::VariantDef *variant = type.get_variants ().at (i++); std::string implicit_variant_name = variant->get_identifier (); - Backend::typed_identifier f (implicit_variant_name, variant_record, - ctx->get_mappings ().lookup_location ( - type.get_ty_ref ())); - enum_fields.push_back (std::move (f)); + enum_fields.emplace_back (implicit_variant_name, variant_record, + ctx->get_mappings ().lookup_location ( + type.get_ty_ref ())); } // @@ -460,10 +473,9 @@ TyTyResolveCompile::visit (const TyTy::TupleType &type) // this, rather than simply emitting the integer, is that this // approach makes it simpler to use a C-only debugger, or // GDB's C mode, when debugging Rust. - Backend::typed_identifier f ("__" + std::to_string (i), compiled_field_ty, - ctx->get_mappings ().lookup_location ( - type.get_ty_ref ())); - fields.push_back (std::move (f)); + fields.emplace_back ("__" + std::to_string (i), compiled_field_ty, + ctx->get_mappings ().lookup_location ( + type.get_ty_ref ())); } tree struct_type_record = Backend::struct_type (fields); @@ -476,8 +488,22 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type) { tree element_type = TyTyResolveCompile::compile (ctx, type.get_element_type ()); - TyTy::ConstType *const_capacity = type.get_capacity (); - tree folded_capacity_expr = const_capacity->get_value (); + auto const_capacity = type.get_capacity (); + + // Check if capacity is a const type + if (const_capacity->get_kind () != TyTy::TypeKind::CONST) + { + rust_error_at (type.get_locus (), "array capacity is not a const type"); + translated = error_mark_node; + return; + } + + auto *capacity_const = const_capacity->as_const_type (); + + rust_assert (capacity_const->const_kind () + == TyTy::BaseConstType::ConstKind::Value); + auto &capacity_value = *static_cast<TyTy::ConstValueType *> (capacity_const); + auto folded_capacity_expr = capacity_value.get_value (); // build_index_type takes the maximum index, which is one less than // the length. @@ -772,17 +798,15 @@ TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type) tree uint = Backend::integer_type (true, Backend::get_pointer_size ()); tree uintptr_ty = build_pointer_type (uint); - Backend::typed_identifier f ("pointer", uintptr_ty, - ctx->get_mappings ().lookup_location ( - type.get_ty_ref ())); - fields.push_back (std::move (f)); + fields.emplace_back ("pointer", uintptr_ty, + ctx->get_mappings ().lookup_location ( + type.get_ty_ref ())); tree vtable_size = build_int_cst (size_type_node, items.size ()); tree vtable_type = Backend::array_type (uintptr_ty, vtable_size); - Backend::typed_identifier vtf ("vtable", vtable_type, - ctx->get_mappings ().lookup_location ( - type.get_ty_ref ())); - fields.push_back (std::move (vtf)); + fields.emplace_back ("vtable", vtable_type, + ctx->get_mappings ().lookup_location ( + type.get_ty_ref ())); tree record = Backend::struct_type (fields); RS_DST_FLAG (record) = 1; diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h index 0675343..d6c3259 100644 --- a/gcc/rust/backend/rust-compile-type.h +++ b/gcc/rust/backend/rust-compile-type.h @@ -50,7 +50,10 @@ public: void visit (const TyTy::ReferenceType &) override; void visit (const TyTy::PointerType &) override; void visit (const TyTy::ParamType &) override; - void visit (const TyTy::ConstType &) override; + void visit (const TyTy::ConstParamType &) override; + void visit (const TyTy::ConstValueType &) override; + void visit (const TyTy::ConstInferType &) override; + void visit (const TyTy::ConstErrorType &) override; void visit (const TyTy::StrType &) override; void visit (const TyTy::NeverType &) override; void visit (const TyTy::PlaceholderType &) override; diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index 5c6d145..1f306ad 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -64,31 +64,79 @@ public: ctx->insert_var_decl (stmt_id, var); vars.push_back (var); + + if (pattern.has_subpattern ()) + { + auto subpattern_vars + = CompileVarDecl::compile (fndecl, translated_type, + &pattern.get_subpattern (), ctx); + vars.insert (vars.end (), subpattern_vars.begin (), + subpattern_vars.end ()); + } } void visit (HIR::TuplePattern &pattern) override { + rust_assert (TREE_CODE (translated_type) == RECORD_TYPE); switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::MULTIPLE: + case HIR::TuplePatternItems::ItemType::NO_REST: { - rust_assert (TREE_CODE (translated_type) == RECORD_TYPE); - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( + auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> ( pattern.get_items ()); - size_t offs = 0; - for (auto &sub : items.get_patterns ()) + tree field = TYPE_FIELDS (translated_type); + for (auto &sub : items_no_rest.get_patterns ()) { - tree sub_ty = error_mark_node; - tree field = TYPE_FIELDS (translated_type); - for (size_t i = 0; i < offs; i++) + gcc_assert (field != NULL_TREE); + tree sub_ty = TREE_TYPE (field); + CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx); + field = DECL_CHAIN (field); + } + } + break; + + case HIR::TuplePatternItems::ItemType::HAS_REST: + { + auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> ( + pattern.get_items ()); + + // count total fields in translated_type + size_t total_fields = 0; + for (tree t = TYPE_FIELDS (translated_type); t; t = DECL_CHAIN (t)) + { + total_fields++; + } + + // process lower patterns + tree field = TYPE_FIELDS (translated_type); + for (auto &sub : items_has_rest.get_lower_patterns ()) + { + gcc_assert (field != NULL_TREE); + tree sub_ty = TREE_TYPE (field); + CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx); + field = DECL_CHAIN (field); + } + + // process upper patterns + if (!items_has_rest.get_upper_patterns ().empty ()) + { + size_t upper_start + = total_fields - items_has_rest.get_upper_patterns ().size (); + field = TYPE_FIELDS (translated_type); + for (size_t i = 0; i < upper_start; i++) { field = DECL_CHAIN (field); gcc_assert (field != NULL_TREE); } - sub_ty = TREE_TYPE (field); - CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx); - offs++; + + for (auto &sub : items_has_rest.get_upper_patterns ()) + { + gcc_assert (field != NULL_TREE); + tree sub_ty = TREE_TYPE (field); + CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx); + field = DECL_CHAIN (field); + } } } break; diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index dbd8515..40f16e4 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -183,8 +183,7 @@ HIRCompileBase::coercion_site1 (tree rvalue, TyTy::BaseType *rval, } tree -HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, - const TyTy::BaseType *actual, +HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, TyTy::BaseType *actual, const TyTy::DynamicObjectType *ty, location_t locus) { @@ -201,9 +200,7 @@ HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, // __trait_object_ptr // [list of function ptrs] - std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>> - probed_bounds_for_receiver = Resolver::TypeBoundsProbe::Probe (actual); - + auto probed_bounds_for_receiver = Resolver::TypeBoundsProbe::Probe (actual); tree address_of_compiled_ref = null_pointer_node; if (!actual->is_unit ()) address_of_compiled_ref = address_expression (compiled_ref, locus); @@ -241,12 +238,13 @@ HIRCompileBase::compute_address_for_trait_item ( &receiver_bounds, const TyTy::BaseType *receiver, const TyTy::BaseType *root, location_t locus) { - TyTy::TypeBoundPredicateItem predicate_item + tl::optional<TyTy::TypeBoundPredicateItem> predicate_item = predicate->lookup_associated_item (ref->get_identifier ()); - rust_assert (!predicate_item.is_error ()); + rust_assert (predicate_item.has_value ()); // This is the expected end type - TyTy::BaseType *trait_item_type = predicate_item.get_tyty_for_receiver (root); + TyTy::BaseType *trait_item_type + = predicate_item->get_tyty_for_receiver (root); rust_assert (trait_item_type->get_kind () == TyTy::TypeKind::FNDEF); TyTy::FnType *trait_item_fntype = static_cast<TyTy::FnType *> (trait_item_type); diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index d524d09..d04f864 100644 --- a/gcc/rust/backend/rust-constexpr.cc +++ b/gcc/rust/backend/rust-constexpr.cc @@ -101,12 +101,54 @@ struct constexpr_global_ctx auto_vec<tree, 16> heap_vars; /* Cleanups that need to be evaluated at the end of CLEANUP_POINT_EXPR. */ vec<tree> *cleanups; + /* If non-null, only allow modification of existing values of the variables + in this set. Set by modifiable_tracker, below. */ + hash_set<tree> *modifiable; /* Number of heap VAR_DECL deallocations. */ unsigned heap_dealloc_count; /* Constructor. */ constexpr_global_ctx () : constexpr_ops_count (0), cleanups (NULL), heap_dealloc_count (0) {} + + tree get_value (tree t) + { + if (tree *p = values.get (t)) + if (*p != void_node) + return *p; + return NULL_TREE; + } + tree *get_value_ptr (tree t, bool initializing) + { + if (modifiable && !modifiable->contains (t)) + return nullptr; + if (tree *p = values.get (t)) + { + if (*p != void_node) + return p; + else if (initializing) + { + *p = NULL_TREE; + return p; + } + } + return nullptr; + } + void put_value (tree t, tree v) + { + bool already_in_map = values.put (t, v); + if (!already_in_map && modifiable) + modifiable->add (t); + } + void destroy_value (tree t) + { + if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL + || TREE_CODE (t) == RESULT_DECL) + values.put (t, void_node); + else + values.remove (t); + } + void clear_value (tree t) { values.remove (t); } }; /* In constexpr.cc */ @@ -457,23 +499,24 @@ save_fundef_copy (tree fun, tree copy) static tree constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p, bool unshare_p); +static tree decl_really_constant_value (tree decl, bool unshare_p /*= true*/); tree decl_constant_value (tree decl, bool unshare_p); 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); + bool *, bool *, tree *jump_target); 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 *); + bool *, bool *, tree *jump_target); static tree eval_call_expression (const constexpr_ctx *ctx, tree r, bool, - bool *, bool *); + bool *, bool *, tree *); static tree eval_binary_expression (const constexpr_ctx *ctx, tree r, bool, - bool *, bool *); + bool *, bool *, tree *jump_target); static tree get_function_named_in_call (tree t); @@ -488,7 +531,8 @@ static tree eval_conditional_expression (const constexpr_ctx *ctx, tree t, 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); + 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, @@ -500,7 +544,15 @@ static tree eval_switch_expr (const constexpr_ctx *ctx, tree t, static tree eval_unary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/, bool *non_constant_p, - bool *overflow_p); + bool *overflow_p, tree *jump_target); +static bool eval_check_shift_p (location_t loc, const constexpr_ctx *ctx, + enum tree_code code, tree type, tree lhs, + tree rhs); +static tree fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t, + tree lhs, tree rhs, + bool *non_constant_p, + bool *overflow_p, tree *jump_target); +static tree maybe_fold_addr_pointer_plus (tree t); /* Variables and functions to manage constexpr call expansion context. These do not need to be marked for PCH or GC. */ @@ -562,8 +614,9 @@ fold_expr (tree expr) bool non_constant_p = false; bool overflow_p = false; + tree jump_target = NULL_TREE; tree folded = eval_constant_expression (&ctx, expr, false, &non_constant_p, - &overflow_p); + &overflow_p, &jump_target); rust_assert (folded != NULL_TREE); // more logic here to possibly port @@ -589,13 +642,13 @@ same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2) otherwise return NULL_TREE. */ static tree -union_active_member (const constexpr_ctx *ctx, tree t) +union_active_member (const constexpr_ctx *ctx, tree t, tree *jump_target) { constexpr_ctx new_ctx = *ctx; new_ctx.quiet = true; bool non_constant_p = false, overflow_p = false; tree ctor = eval_constant_expression (&new_ctx, t, false, &non_constant_p, - &overflow_p); + &overflow_p, jump_target); if (TREE_CODE (ctor) == CONSTRUCTOR && CONSTRUCTOR_NELTS (ctor) == 1 && CONSTRUCTOR_ELT (ctor, 0)->index && TREE_CODE (CONSTRUCTOR_ELT (ctor, 0)->index) == FIELD_DECL) @@ -607,7 +660,8 @@ union_active_member (const constexpr_ctx *ctx, tree t) static tree fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, - tree op, unsigned HOST_WIDE_INT off, bool *empty_base) + tree op, unsigned HOST_WIDE_INT off, bool *empty_base, + tree *jump_target) { tree optype = TREE_TYPE (op); unsigned HOST_WIDE_INT const_nunits; @@ -654,7 +708,8 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, tree index = size_int (idx + tree_to_uhwi (min_val)); op = build4_loc (loc, ARRAY_REF, TREE_TYPE (optype), op, index, NULL_TREE, NULL_TREE); - return fold_indirect_ref_1 (ctx, loc, type, op, rem, empty_base); + return fold_indirect_ref_1 (ctx, loc, type, op, rem, empty_base, + jump_target); } } /* ((foo *)&struct_with_foo_field)[x] => COMPONENT_REF */ @@ -663,7 +718,7 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, { if (TREE_CODE (optype) == UNION_TYPE) /* For unions prefer the currently active member. */ - if (tree field = union_active_member (ctx, op)) + if (tree field = union_active_member (ctx, op, jump_target)) { unsigned HOST_WIDE_INT el_sz = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (field))); @@ -672,7 +727,7 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, tree cop = build3 (COMPONENT_REF, TREE_TYPE (field), op, field, NULL_TREE); if (tree ret = fold_indirect_ref_1 (ctx, loc, type, cop, off, - empty_base)) + empty_base, jump_target)) return ret; } } @@ -691,8 +746,9 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, { tree cop = build3 (COMPONENT_REF, TREE_TYPE (field), op, field, NULL_TREE); - if (tree ret = fold_indirect_ref_1 (ctx, loc, type, cop, - off - upos, empty_base)) + if (tree ret + = fold_indirect_ref_1 (ctx, loc, type, cop, off - upos, + empty_base, jump_target)) return ret; } } @@ -721,7 +777,7 @@ fold_indirect_ref_1 (const constexpr_ctx *ctx, location_t loc, tree type, static tree rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, - tree op0, bool *empty_base) + tree op0, bool *empty_base, tree *jump_target) { tree sub = op0; tree subtype; @@ -780,7 +836,8 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, tree off = integer_zero_node; canonicalize_obj_off (op, off); gcc_assert (integer_zerop (off)); - return fold_indirect_ref_1 (ctx, loc, type, op, 0, empty_base); + return fold_indirect_ref_1 (ctx, loc, type, op, 0, empty_base, + jump_target); } } else if (TREE_CODE (sub) == POINTER_PLUS_EXPR @@ -795,7 +852,7 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, tree obj = TREE_OPERAND (op00, 0); canonicalize_obj_off (obj, off); return fold_indirect_ref_1 (ctx, loc, type, obj, tree_to_uhwi (off), - empty_base); + empty_base, jump_target); } } /* *(foo *)fooarrptr => (*fooarrptr)[0] */ @@ -804,8 +861,8 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, { tree type_domain; tree min_val = size_zero_node; - tree newsub - = rs_fold_indirect_ref (ctx, loc, TREE_TYPE (subtype), sub, NULL); + tree newsub = rs_fold_indirect_ref (ctx, loc, TREE_TYPE (subtype), sub, + NULL, jump_target); if (newsub) sub = newsub; else @@ -824,7 +881,7 @@ rs_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, static tree rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree orig_op0 = TREE_OPERAND (t, 0); bool empty_base = false; @@ -842,13 +899,13 @@ rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval, /* First try to simplify it directly. */ tree r = rs_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t), - orig_op0, &empty_base); + orig_op0, &empty_base, jump_target); if (!r) { /* If that didn't work, evaluate the operand first. */ - tree op0 - = eval_constant_expression (ctx, orig_op0, - /*lval*/ false, non_constant_p, overflow_p); + tree op0 = eval_constant_expression (ctx, orig_op0, + /*lval*/ false, non_constant_p, + overflow_p, jump_target); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) return t; @@ -862,7 +919,7 @@ rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval, } r = rs_fold_indirect_ref (ctx, EXPR_LOCATION (t), TREE_TYPE (t), op0, - &empty_base); + &empty_base, jump_target); if (r == NULL_TREE) { /* We couldn't fold to a constant value. Make sure it's not @@ -891,7 +948,8 @@ rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval, } } - r = eval_constant_expression (ctx, r, lval, non_constant_p, overflow_p); + r = eval_constant_expression (ctx, r, lval, non_constant_p, overflow_p, + jump_target); if (*non_constant_p) return t; @@ -917,17 +975,17 @@ rs_eval_indirect_ref (const constexpr_ctx *ctx, tree t, bool lval, static tree eval_logical_expression (const constexpr_ctx *ctx, tree t, tree bailout_value, tree continue_value, bool lval, bool *non_constant_p, - bool *overflow_p) + bool *overflow_p, tree *jump_target) { tree r; tree lhs = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); VERIFY_CONSTANT (lhs); if (tree_int_cst_equal (lhs, bailout_value)) return lhs; gcc_assert (tree_int_cst_equal (lhs, continue_value)); r = eval_constant_expression (ctx, TREE_OPERAND (t, 1), lval, non_constant_p, - overflow_p); + overflow_p, jump_target); VERIFY_CONSTANT (r); return r; } @@ -1243,19 +1301,20 @@ get_or_insert_ctor_field (tree ctor, tree index, int pos_hint = -1) static tree eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { - tree arg1 - = eval_constant_expression (ctx, TREE_OPERAND (t, 0), - /*lval*/ false, non_constant_p, overflow_p); + tree arg1 = eval_constant_expression (ctx, TREE_OPERAND (t, 0), + /*lval*/ false, non_constant_p, + overflow_p, jump_target); VERIFY_CONSTANT (arg1); - tree arg2 - = eval_constant_expression (ctx, TREE_OPERAND (t, 1), - /*lval*/ false, non_constant_p, overflow_p); + tree arg2 = eval_constant_expression (ctx, TREE_OPERAND (t, 1), + /*lval*/ false, non_constant_p, + overflow_p, jump_target); VERIFY_CONSTANT (arg2); - tree arg3 - = eval_constant_expression (ctx, TREE_OPERAND (t, 2), - /*lval*/ false, non_constant_p, overflow_p); + tree arg3 = eval_constant_expression (ctx, TREE_OPERAND (t, 2), + /*lval*/ false, non_constant_p, + overflow_p, jump_target); VERIFY_CONSTANT (arg3); location_t loc = EXPR_LOCATION (t); tree type = TREE_TYPE (t); @@ -1280,7 +1339,7 @@ eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t, static tree eval_bare_aggregate (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, tree *jump_target) { vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t); bool changed = false; @@ -1331,8 +1390,9 @@ eval_bare_aggregate (const constexpr_ctx *ctx, tree t, bool lval, the active union member now so that we can later detect and diagnose if its initializer attempts to activate another member. */ get_or_insert_ctor_field (ctx->ctor, index); - tree elt = eval_constant_expression (&new_ctx, value, lval, - non_constant_p, overflow_p); + tree elt + = eval_constant_expression (&new_ctx, value, lval, non_constant_p, + overflow_p, jump_target); /* Don't VERIFY_CONSTANT here. */ if (ctx->quiet && *non_constant_p) break; @@ -1401,7 +1461,8 @@ eval_bare_aggregate (const constexpr_ctx *ctx, tree t, bool lval, static tree cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { int i; tree args[3]; @@ -1409,8 +1470,9 @@ cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t, bool lval, for (i = 0; i < 3; i++) { - args[i] = eval_constant_expression (ctx, TREE_OPERAND (t, i), lval, - non_constant_p, overflow_p); + args[i] + = eval_constant_expression (ctx, TREE_OPERAND (t, i), lval, + non_constant_p, overflow_p, jump_target); VERIFY_CONSTANT (args[i]); } @@ -1555,7 +1617,8 @@ 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); + bool *non_constant_p, bool *overflow_p, + tree *jump_target); // forked from gcc/cp/constexpr.cc cxx_eval_array_reference @@ -1564,11 +1627,11 @@ static tree eval_and_check_array_index (const constexpr_ctx *ctx, tree t, static tree eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree oldary = TREE_OPERAND (t, 0); - tree ary - = eval_constant_expression (ctx, oldary, lval, non_constant_p, overflow_p); + tree ary = eval_constant_expression (ctx, oldary, lval, non_constant_p, + overflow_p, jump_target); if (*non_constant_p) return t; if (!lval && TREE_CODE (ary) == VIEW_CONVERT_EXPR @@ -1577,8 +1640,8 @@ eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval, ary = TREE_OPERAND (ary, 0); tree oldidx = TREE_OPERAND (t, 1); - tree index - = eval_and_check_array_index (ctx, t, lval, non_constant_p, overflow_p); + tree index = eval_and_check_array_index (ctx, t, lval, non_constant_p, + overflow_p, jump_target); if (*non_constant_p) return t; @@ -1680,7 +1743,8 @@ eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval, new_ctx.ctor = build_constructor (elem_type, NULL); ctx = &new_ctx; } - t = eval_constant_expression (ctx, val, lval, non_constant_p, overflow_p); + t = eval_constant_expression (ctx, val, lval, non_constant_p, overflow_p, + jump_target); if (!SCALAR_TYPE_P (elem_type) && t != ctx->ctor) free_constructor (ctx->ctor); return t; @@ -1693,7 +1757,8 @@ eval_array_reference (const constexpr_ctx *ctx, tree t, bool lval, static tree eval_component_reference (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { unsigned HOST_WIDE_INT i; tree field; @@ -1701,7 +1766,7 @@ eval_component_reference (const constexpr_ctx *ctx, tree t, bool lval, tree part = TREE_OPERAND (t, 1); tree orig_whole = TREE_OPERAND (t, 0); tree whole = eval_constant_expression (ctx, orig_whole, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); if (INDIRECT_REF_P (whole) && integer_zerop (TREE_OPERAND (whole, 0))) { if (!ctx->quiet) @@ -1790,8 +1855,8 @@ eval_component_reference (const constexpr_ctx *ctx, tree t, bool lval, // back to handle this to assign suitable value to value before sending it in // eval_constant_expression below // value = build_value_init (TREE_TYPE (t), tf_warning_or_error); - return eval_constant_expression (ctx, value, lval, non_constant_p, - overflow_p); + return eval_constant_expression (ctx, value, lval, non_constant_p, overflow_p, + jump_target); } /* Subroutine of cxx_eval_statement_list. Determine whether the statement @@ -1850,7 +1915,7 @@ label_matches (const constexpr_ctx *ctx, tree *jump_target, tree stmt) static tree eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, bool *non_constant_p, bool *overflow_p, - tree *jump_target /* = NULL */) + tree *jump_target) { if (jump_target && *jump_target) { @@ -1921,34 +1986,44 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, { r = DECL_VALUE_EXPR (t); return eval_constant_expression (ctx, r, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); } /* 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) - return t; - else if (t == ctx->object) - return ctx->ctor; - if (VAR_P (t)) - if (tree *p = ctx->global->values.get (t)) - if (*p != NULL_TREE) - { - r = *p; - break; - } + /* We used to not check lval for CONST_DECL, but darwin.cc uses + CONST_DECL for aggregate constants. */ + if (lval) + return t; + else if (t == ctx->object) + return ctx->ctor; + if (VAR_P (t)) + { + if (tree v = ctx->global->get_value (t)) + { + r = v; + break; + } + } + if (COMPLETE_TYPE_P (TREE_TYPE (t)) + && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/ false)) + { + /* If the class is empty, we aren't actually loading anything. */ + r = build_constructor (TREE_TYPE (t), NULL); + TREE_CONSTANT (r) = true; + } + else if (ctx->strict) + r = decl_really_constant_value (t, /*unshare_p=*/false); + else r = decl_constant_value (t, /*unshare_p=*/false); - if (TREE_CODE (r) == TARGET_EXPR - && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR) - r = TARGET_EXPR_INITIAL (r); - if (DECL_P (r)) - { + if (TREE_CODE (r) == TARGET_EXPR + && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR) + r = TARGET_EXPR_INITIAL (r); + if (DECL_P (r) && !(VAR_P (t) && TYPE_REF_P (TREE_TYPE (t)))) + { + if (!ctx->quiet) non_const_var_error (loc, r); - return r; - } - } + *non_constant_p = true; + } break; case PARM_DECL: @@ -2014,7 +2089,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, case LTGT_EXPR: case RANGE_EXPR: case COMPLEX_EXPR: - r = eval_binary_expression (ctx, t, lval, non_constant_p, overflow_p); + r = eval_binary_expression (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; /* fold can introduce non-IF versions of these; still treat them as @@ -2023,14 +2099,14 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, case TRUTH_ANDIF_EXPR: r = eval_logical_expression (ctx, t, boolean_false_node, boolean_true_node, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); break; case TRUTH_OR_EXPR: case TRUTH_ORIF_EXPR: r = eval_logical_expression (ctx, t, boolean_true_node, boolean_false_node, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); break; case TARGET_EXPR: @@ -2079,7 +2155,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, /* Pass false for 'lval' because this indicates initialization of a temporary. */ r = eval_constant_expression (ctx, TREE_OPERAND (t, 1), false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); if (*non_constant_p) break; /* Adjust the type of the result to the type of the temporary. */ @@ -2096,13 +2172,14 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, break; case CALL_EXPR: - r = eval_call_expression (ctx, t, lval, non_constant_p, overflow_p); + r = eval_call_expression (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case RETURN_EXPR: if (TREE_OPERAND (t, 0) != NULL_TREE) r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); /* FALLTHRU */ case BREAK_STMT: case CONTINUE_STMT: @@ -2135,7 +2212,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, if (tree init = DECL_INITIAL (r)) { init = eval_constant_expression (ctx, init, false, non_constant_p, - overflow_p); + overflow_p, jump_target); /* Don't share a CONSTRUCTOR that might be changed. */ init = unshare_constructor (init); /* Remember that a constant object's constructor has already @@ -2156,12 +2233,13 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, constant without its operand being, and vice versa. */ case MEM_REF: case INDIRECT_REF: - r = rs_eval_indirect_ref (ctx, t, lval, non_constant_p, overflow_p); + r = rs_eval_indirect_ref (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case VEC_PERM_EXPR: - r = cxx_eval_trinary_expression (ctx, t, lval, non_constant_p, - overflow_p); + r = cxx_eval_trinary_expression (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case PAREN_EXPR: @@ -2169,11 +2247,12 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, /* A PAREN_EXPR resulting from __builtin_assoc_barrier has no effect in constant expressions since it's unaffected by -fassociative-math. */ r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); break; case MODIFY_EXPR: - r = eval_store_expression (ctx, t, false, non_constant_p, overflow_p); + r = eval_store_expression (ctx, t, false, non_constant_p, overflow_p, + jump_target); break; case STATEMENT_LIST: @@ -2189,13 +2268,14 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, case OBJ_TYPE_REF: /* Virtual function lookup. We don't need to do anything fancy. */ return eval_constant_expression (ctx, OBJ_TYPE_REF_EXPR (t), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); case EXIT_EXPR: { tree cond = TREE_OPERAND (t, 0); - cond = eval_constant_expression (ctx, cond, /*lval*/ false, - non_constant_p, overflow_p); + cond + = eval_constant_expression (ctx, cond, /*lval*/ false, non_constant_p, + overflow_p, jump_target); VERIFY_CONSTANT (cond); if (integer_nonzerop (cond)) *jump_target = t; @@ -2225,7 +2305,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, else { r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) break; ctx->global->values.put (t, r); @@ -2239,7 +2320,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, tree oldop = TREE_OPERAND (t, 0); tree op = eval_constant_expression (ctx, oldop, /*lval*/ true, non_constant_p, - overflow_p); + overflow_p, jump_target); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) return t; @@ -2284,7 +2365,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, if (lval) { r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (r == error_mark_node) ; else if (r == TREE_OPERAND (t, 0)) @@ -2303,7 +2385,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, case BIT_NOT_EXPR: case TRUTH_NOT_EXPR: case FIXED_CONVERT_EXPR: - r = eval_unary_expression (ctx, t, lval, non_constant_p, overflow_p); + r = eval_unary_expression (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case LOOP_EXPR: @@ -2318,7 +2401,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, break; case ARRAY_REF: - r = eval_array_reference (ctx, t, lval, non_constant_p, overflow_p); + r = eval_array_reference (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case COMPONENT_REF: @@ -2332,11 +2416,13 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, *non_constant_p = true; return t; } - r = eval_component_reference (ctx, t, lval, non_constant_p, overflow_p); + r = eval_component_reference (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case BIT_FIELD_REF: - r = eval_bit_field_ref (ctx, t, lval, non_constant_p, overflow_p); + r = eval_bit_field_ref (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; case COND_EXPR: @@ -2381,7 +2467,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, case VEC_COND_EXPR: r = eval_vector_conditional_expression (ctx, t, non_constant_p, - overflow_p); + overflow_p, jump_target); break; case TRY_CATCH_EXPR: @@ -2407,7 +2493,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, /* Evaluate the cleanups. */ FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup) eval_constant_expression (ctx, cleanup, false, non_constant_p, - overflow_p); + overflow_p, jump_target); } break; @@ -2417,7 +2503,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, if (!*non_constant_p) /* Also evaluate the cleanup. */ eval_constant_expression (ctx, TREE_OPERAND (t, 1), true, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); break; case CONSTRUCTOR: @@ -2429,7 +2515,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, if (TREE_CONSTANT (t)) return fold (t); } - r = eval_bare_aggregate (ctx, t, lval, non_constant_p, overflow_p); + r = eval_bare_aggregate (ctx, t, lval, non_constant_p, overflow_p, + jump_target); break; /* FALLTHROUGH. */ @@ -2440,7 +2527,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, tree oldop = TREE_OPERAND (t, 0); tree op = eval_constant_expression (ctx, oldop, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); if (*non_constant_p) return t; tree type = TREE_TYPE (t); @@ -2571,7 +2658,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, return ctor; else return eval_constant_expression (ctx, ctor, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); } /* A placeholder without a referent. We can get here when checking whether NSDMIs are noexcept, or in massage_init_elt; @@ -2632,7 +2719,8 @@ is_empty_field (tree decl) static tree eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { constexpr_ctx new_ctx = *ctx; @@ -2653,7 +2741,7 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, if (!SCALAR_TYPE_P (type)) new_ctx.ctor = new_ctx.object = NULL_TREE; init = eval_constant_expression (&new_ctx, init, false, non_constant_p, - overflow_p); + overflow_p, jump_target); if (*non_constant_p) return t; } @@ -2665,7 +2753,7 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, as a whole; otherwise, only evaluate the innermost piece to avoid building up unnecessary *_REFs. */ target = eval_constant_expression (ctx, target, true, non_constant_p, - overflow_p); + overflow_p, jump_target); evaluated = true; if (*non_constant_p) return t; @@ -2694,7 +2782,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, if (TREE_CODE (probe) == ARRAY_REF) { elt = eval_and_check_array_index (ctx, probe, false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) return t; } @@ -2718,8 +2807,9 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, object = probe; else { - probe = eval_constant_expression (ctx, probe, true, - non_constant_p, overflow_p); + probe + = eval_constant_expression (ctx, probe, true, non_constant_p, + overflow_p, jump_target); evaluated = true; if (*non_constant_p) return t; @@ -2910,7 +3000,7 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, if (tree tinit = TARGET_EXPR_INITIAL (init)) init = tinit; init = eval_constant_expression (&new_ctx, init, false, non_constant_p, - overflow_p); + overflow_p, jump_target); /* The hash table might have moved since the get earlier, and the initializer might have mutated the underlying CONSTRUCTORs, so we must recompute VALP. */ @@ -3012,22 +3102,115 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, Like cxx_eval_unary_expression, except for binary expressions. */ static tree eval_binary_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { + tree r = NULL_TREE; tree orig_lhs = TREE_OPERAND (t, 0); tree orig_rhs = TREE_OPERAND (t, 1); tree lhs, rhs; - lhs = eval_constant_expression (ctx, orig_lhs, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); + /* Don't VERIFY_CONSTANT here, it's unnecessary and will break pointer + subtraction. */ + if (*non_constant_p) + return t; + if (*jump_target) + return NULL_TREE; + rhs = eval_constant_expression (ctx, orig_rhs, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); + if (*non_constant_p) + return t; + if (*jump_target) + return NULL_TREE; location_t loc = EXPR_LOCATION (t); enum tree_code code = TREE_CODE (t); tree type = TREE_TYPE (t); - return fold_binary_loc (loc, code, type, lhs, rhs); + if (code == EQ_EXPR || code == NE_EXPR) + { + bool is_code_eq = (code == EQ_EXPR); + + if (TREE_CODE (lhs) == PTRMEM_CST && TREE_CODE (rhs) == PTRMEM_CST) + { + tree lmem = PTRMEM_CST_MEMBER (lhs); + tree rmem = PTRMEM_CST_MEMBER (rhs); + bool eq; + if (TREE_CODE (lmem) == TREE_CODE (rmem) + && TREE_CODE (lmem) == FIELD_DECL + && TREE_CODE (DECL_CONTEXT (lmem)) == UNION_TYPE + && same_type_p (DECL_CONTEXT (lmem), DECL_CONTEXT (rmem))) + /* If both refer to (possibly different) members of the same union + (12.3), they compare equal. */ + eq = true; + // else + // eq = cp_tree_equal (lhs, rhs); + r = constant_boolean_node (eq == is_code_eq, type); + } + else if ((TREE_CODE (lhs) == PTRMEM_CST || TREE_CODE (rhs) == PTRMEM_CST) + && (null_member_pointer_value_p (lhs) + || null_member_pointer_value_p (rhs))) + r = constant_boolean_node (!is_code_eq, type); + } + if (r == NULL_TREE && TREE_CODE_CLASS (code) == tcc_comparison + && POINTER_TYPE_P (TREE_TYPE (lhs))) + { + if (tree lhso = maybe_fold_addr_pointer_plus (lhs)) + lhs = fold_convert (TREE_TYPE (lhs), lhso); + if (tree rhso = maybe_fold_addr_pointer_plus (rhs)) + rhs = fold_convert (TREE_TYPE (rhs), rhso); + } + if (code == POINTER_PLUS_EXPR && !*non_constant_p && integer_zerop (lhs) + && !integer_zerop (rhs)) + { + if (!ctx->quiet) + error ("arithmetic involving a null pointer in %qE", lhs); + *non_constant_p = true; + return t; + } + else if (code == POINTER_PLUS_EXPR) + { + r = fold_pointer_plus_expression (ctx, t, lhs, rhs, non_constant_p, + overflow_p, jump_target); + if (*jump_target) + return NULL_TREE; + } + + if (r == NULL_TREE) + { + r = fold_binary_loc (loc, code, type, lhs, rhs); + } + + if (r == NULL_TREE && (code == LSHIFT_EXPR || code == RSHIFT_EXPR) + && TREE_CODE (lhs) == INTEGER_CST && TREE_CODE (rhs) == INTEGER_CST + && wi::neg_p (wi::to_wide (rhs))) + { + /* For diagnostics and -fpermissive emulate previous behavior of + handling shifts by negative amount. */ + tree nrhs = const_unop (NEGATE_EXPR, TREE_TYPE (rhs), rhs); + if (nrhs) + r = fold_binary_loc (loc, + code == LSHIFT_EXPR ? RSHIFT_EXPR : LSHIFT_EXPR, + type, lhs, nrhs); + } + + if (r == NULL_TREE) + { + if (lhs == orig_lhs && rhs == orig_rhs) + r = t; + else + r = build2_loc (loc, code, type, lhs, rhs); + } + else if (eval_check_shift_p (loc, ctx, code, type, lhs, rhs)) + *non_constant_p = true; + /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to + a local array in a constexpr function. */ + bool ptr = INDIRECT_TYPE_P (TREE_TYPE (lhs)); + if (!ptr) + VERIFY_CONSTANT (r); + return r; } /* Helper function of cxx_bind_parameters_in_call. Return non-NULL @@ -3065,7 +3248,7 @@ addr_of_non_const_var (tree *tp, int *walk_subtrees, void *data) static tree rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, bool *non_constant_p, bool *overflow_p, - bool *non_constant_args) + bool *non_constant_args, tree *jump_target) { const int nargs = call_expr_nargs (t); tree parms = DECL_ARGUMENTS (fun); @@ -3089,7 +3272,7 @@ rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, such as this, but here we do the elision differently: we keep the TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm. */ arg = eval_constant_expression (ctx, x, /*lval=*/false, non_constant_p, - overflow_p); + overflow_p, jump_target); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p && ctx->quiet) break; @@ -3155,7 +3338,8 @@ rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, static tree eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, - bool lval, bool *non_constant_p, bool *overflow_p) + bool lval, bool *non_constant_p, bool *overflow_p, + tree *jump_target) { const int nargs = call_expr_nargs (t); tree *args = (tree *) alloca (nargs * sizeof (tree)); @@ -3258,8 +3442,9 @@ eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, || potential_constant_expression (arg)) { bool dummy1 = false, dummy2 = false; - arg - = eval_constant_expression (&new_ctx, arg, false, &dummy1, &dummy2); + tree dummy_jump_target = NULL_TREE; + arg = eval_constant_expression (&new_ctx, arg, false, &dummy1, + &dummy2, &dummy_jump_target); } if (bi_const_p) @@ -3355,7 +3540,7 @@ eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, } return eval_constant_expression (&new_ctx, new_call, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); } // Subroutine of cxx_eval_constant_expression. @@ -3363,7 +3548,7 @@ eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, // evaluation. static tree eval_call_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, tree *jump_target) { location_t loc = EXPR_LOCATION (t); tree fun = get_function_named_in_call (t); @@ -3392,12 +3577,12 @@ eval_call_expression (const constexpr_ctx *ctx, tree t, bool lval, if (fndecl_built_in_p (fun)) return eval_builtin_function_call (ctx, t, fun, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); bool non_constant_args = false; new_call.bindings = rs_bind_parameters_in_call (ctx, t, fun, non_constant_p, overflow_p, - &non_constant_args); + &non_constant_args, jump_target); /* We build up the bindings list before we know whether we already have this call cached. If we don't end up saving these bindings, ggc_free them when @@ -3960,7 +4145,7 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body) bool non_constant_p = false; bool overflow_p = false; return eval_constant_expression (ctx, body, false, &non_constant_p, - &overflow_p); + &overflow_p, NULL); } case DECL_EXPR: { @@ -4024,6 +4209,17 @@ constant_value_1 (tree decl, bool, bool, bool unshare_p) return unshare_p ? unshare_expr (decl) : decl; } +/* Like scalar_constant_value, but can also return aggregate initializers. + If UNSHARE_P, return an unshared copy of the initializer. */ + +tree +decl_really_constant_value (tree decl, bool unshare_p /*= true*/) +{ + return constant_value_1 (decl, /*strict_p=*/true, + /*return_aggregate_cst_ok_p=*/true, + /*unshare_p=*/unshare_p); +} + // A more relaxed version of decl_really_constant_value, used by the // common C/C++ code. tree @@ -4037,15 +4233,38 @@ decl_constant_value (tree decl, bool unshare_p) static void non_const_var_error (location_t loc, tree r) { - error_at (loc, - "the value of %qD is not usable in a constant " - "expression", - r); + tree type = TREE_TYPE (r); + /* Avoid error cascade. */ if (DECL_INITIAL (r) == error_mark_node) return; - - // more in cp/constexpr.cc + if (DECL_DECLARED_CONSTEXPR_P (r)) + inform (DECL_SOURCE_LOCATION (r), "%qD used in its own initializer", r); + else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type)) + { + if (!DECL_INITIAL (r) || !TREE_CONSTANT (DECL_INITIAL (r)) + || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)) + inform (DECL_SOURCE_LOCATION (r), + "%qD was not initialized with a constant " + "expression", + r); + else + gcc_unreachable (); + } + else if (TYPE_REF_P (type)) + inform (DECL_SOURCE_LOCATION (r), + "%qD was not initialized with a constant " + "expression", + r); + else + { + if (!DECL_DECLARED_CONSTEXPR_P (r)) + inform (DECL_SOURCE_LOCATION (r), "%qD was not declared %<constexpr%>", + r); + else + inform (DECL_SOURCE_LOCATION (r), + "%qD does not have integral or enumeration type", r); + } } static tree @@ -4322,7 +4541,7 @@ verify_constant (tree t, bool allow_non_constant, bool *non_constant_p, if (!*non_constant_p && !reduced_constant_expression_p (t) && t != void_node) { if (!allow_non_constant) - error ("%q+E is not a constant expression", t); + error_at (EXPR_LOCATION (t), "is not a constant expression"); *non_constant_p = true; } if (TREE_OVERFLOW_P (t)) @@ -4427,7 +4646,8 @@ diag_array_subscript (location_t loc, const constexpr_ctx *ctx, tree array, static tree get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree nelts; if (TREE_CODE (type) == ARRAY_TYPE) @@ -4443,8 +4663,8 @@ get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type, rust_unreachable (); /* For VLAs, the number of elements won't be an integer constant. */ - nelts - = eval_constant_expression (ctx, nelts, false, non_constant_p, overflow_p); + nelts = eval_constant_expression (ctx, nelts, false, non_constant_p, + overflow_p, jump_target); return nelts; } @@ -4456,13 +4676,13 @@ get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type, static tree eval_and_check_array_index (const constexpr_ctx *ctx, tree t, bool allow_one_past, bool *non_constant_p, - bool *overflow_p) + bool *overflow_p, tree *jump_target) { location_t loc = rs_expr_loc_or_input_loc (t); tree ary = TREE_OPERAND (t, 0); t = TREE_OPERAND (t, 1); tree index = eval_constant_expression (ctx, t, allow_one_past, non_constant_p, - overflow_p); + overflow_p, jump_target); VERIFY_CONSTANT (index); if (!tree_fits_shwi_p (index) || tree_int_cst_sgn (index) < 0) @@ -4473,7 +4693,7 @@ eval_and_check_array_index (const constexpr_ctx *ctx, tree t, } tree nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary), non_constant_p, - overflow_p); + overflow_p, jump_target); VERIFY_CONSTANT (nelts); if (allow_one_past ? !tree_int_cst_le (index, nelts) : !tree_int_cst_lt (index, nelts)) @@ -4683,9 +4903,9 @@ eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval, bool *non_constant_p, bool *overflow_p, tree *jump_target) { - tree val - = eval_constant_expression (ctx, TREE_OPERAND (t, 0), - /*lval*/ false, non_constant_p, overflow_p); + tree val = eval_constant_expression (ctx, TREE_OPERAND (t, 0), + /*lval*/ false, non_constant_p, + overflow_p, jump_target); VERIFY_CONSTANT (val); if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_P (t)) { @@ -4722,14 +4942,14 @@ eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval, static tree eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree orig_whole = TREE_OPERAND (t, 0); tree retval, fldval, utype, mask; bool fld_seen = false; HOST_WIDE_INT istart, isize; tree whole = eval_constant_expression (ctx, orig_whole, lval, non_constant_p, - overflow_p); + overflow_p, jump_target); tree start, field, value; unsigned HOST_WIDE_INT i; @@ -4960,8 +5180,8 @@ eval_switch_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, { tree cond = TREE_CODE (t) == SWITCH_STMT ? SWITCH_STMT_COND (t) : SWITCH_COND (t); - cond - = eval_constant_expression (ctx, cond, false, non_constant_p, overflow_p); + cond = eval_constant_expression (ctx, cond, false, non_constant_p, overflow_p, + jump_target); VERIFY_CONSTANT (cond); *jump_target = cond; @@ -4995,12 +5215,13 @@ eval_switch_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p, static tree eval_unary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/, - bool *non_constant_p, bool *overflow_p) + bool *non_constant_p, bool *overflow_p, + tree *jump_target) { tree r; tree orig_arg = TREE_OPERAND (t, 0); tree arg = eval_constant_expression (ctx, orig_arg, /*lval*/ false, - non_constant_p, overflow_p); + non_constant_p, overflow_p, jump_target); VERIFY_CONSTANT (arg); location_t loc = EXPR_LOCATION (t); enum tree_code code = TREE_CODE (t); @@ -5136,7 +5357,9 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, if (manifestly_const_eval) instantiate_constexpr_fns (r); - r = eval_constant_expression (&ctx, r, false, &non_constant_p, &overflow_p); + tree jump_target = NULL_TREE; + r = eval_constant_expression (&ctx, r, false, &non_constant_p, &overflow_p, + &jump_target); if (!constexpr_dtor) verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p); @@ -5148,7 +5371,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, /* Evaluate the cleanups. */ FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup) eval_constant_expression (&ctx, cleanup, false, &non_constant_p, - &overflow_p); + &overflow_p, NULL); /* Mutable logic is a bit tricky: we want to allow initialization of constexpr variables with mutable members, but we can't copy those @@ -5908,7 +6131,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, /* A pointer-to-member constant. */ return true; - // handle_addr_expr: #if 0 /* FIXME adjust when issue 1197 is fully resolved. For now don't do any checking here, as we might dereference the pointer later. If @@ -6484,6 +6706,170 @@ fold_non_dependent_init (tree t, tsubst_flags_t /*=tf_warning_or_error*/, return maybe_constant_init (t, object, manifestly_const_eval); } +/* Check whether the shift operation with code CODE and type TYPE on LHS + and RHS is undefined. If it is, give an error with an explanation, + and return true; return false otherwise. */ + +static bool +eval_check_shift_p (location_t loc, const constexpr_ctx *ctx, + enum tree_code code, tree type, tree lhs, tree rhs) +{ + if ((code != LSHIFT_EXPR && code != RSHIFT_EXPR) + || TREE_CODE (lhs) != INTEGER_CST || TREE_CODE (rhs) != INTEGER_CST) + return false; + + tree lhstype = TREE_TYPE (lhs); + unsigned HOST_WIDE_INT uprec = TYPE_PRECISION (TREE_TYPE (lhs)); + + /* [expr.shift] The behavior is undefined if the right operand + is negative, or greater than or equal to the length in bits + of the promoted left operand. */ + if (tree_int_cst_sgn (rhs) == -1) + { + if (!ctx->quiet) + permerror (loc, "right operand of shift expression %q+E is negative", + build2_loc (loc, code, type, lhs, rhs)); + return (!flag_permissive || ctx->quiet); + } + if (compare_tree_int (rhs, uprec) >= 0) + { + if (!ctx->quiet) + permerror (loc, + "right operand of shift expression %q+E is greater " + "than or equal to the precision %wu of the left operand", + build2_loc (loc, code, type, lhs, rhs), uprec); + return (!flag_permissive || ctx->quiet); + } + + /* The value of E1 << E2 is E1 left-shifted E2 bit positions; [...] + if E1 has a signed type and non-negative value, and E1x2^E2 is + representable in the corresponding unsigned type of the result type, + then that value, converted to the result type, is the resulting value; + otherwise, the behavior is undefined. + For C++20: + The value of E1 << E2 is the unique value congruent to E1 x 2^E2 modulo + 2^N, where N is the range exponent of the type of the result. */ + if (code == LSHIFT_EXPR && !TYPE_OVERFLOW_WRAPS (lhstype)) + { + if (tree_int_cst_sgn (lhs) == -1) + { + if (!ctx->quiet) + permerror (loc, "left operand of shift expression %q+E is negative", + build2_loc (loc, code, type, lhs, rhs)); + return (!flag_permissive || ctx->quiet); + } + /* For signed x << y the following: + (unsigned) x >> ((prec (lhs) - 1) - y) + if > 1, is undefined. The right-hand side of this formula + is the highest bit of the LHS that can be set (starting from 0), + so that the shift doesn't overflow. We then right-shift the LHS + to see whether any other bit is set making the original shift + undefined -- the result is not representable in the corresponding + unsigned type. */ + tree t = build_int_cst (unsigned_type_node, uprec - 1); + t = fold_build2 (MINUS_EXPR, unsigned_type_node, t, rhs); + tree ulhs = fold_convert (unsigned_type_for (lhstype), lhs); + t = fold_build2 (RSHIFT_EXPR, TREE_TYPE (ulhs), ulhs, t); + if (tree_int_cst_lt (integer_one_node, t)) + { + if (!ctx->quiet) + permerror (loc, "shift expression %q+E overflows", + build2_loc (loc, code, type, lhs, rhs)); + return (!flag_permissive || ctx->quiet); + } + } + return false; +} + +/* Helper function for cxx_eval_binary_expression. Try to optimize + original POINTER_PLUS_EXPR T, LHS p+ RHS, return NULL_TREE if the + generic folding should be used. */ + +static tree +fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t, tree lhs, + tree rhs, bool *non_constant_p, bool *overflow_p, + tree *jump_target) +{ + STRIP_NOPS (lhs); + if (TREE_CODE (lhs) != ADDR_EXPR) + return NULL_TREE; + + lhs = TREE_OPERAND (lhs, 0); + + /* &A[i] p+ j => &A[i + j] */ + if (TREE_CODE (lhs) == ARRAY_REF + && TREE_CODE (TREE_OPERAND (lhs, 1)) == INTEGER_CST + && TREE_CODE (rhs) == INTEGER_CST && TYPE_SIZE_UNIT (TREE_TYPE (lhs)) + && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (lhs))) == INTEGER_CST) + { + tree orig_type = TREE_TYPE (t); + location_t loc = EXPR_LOCATION (t); + tree type = TREE_TYPE (lhs); + + t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (lhs, 1)); + tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (lhs, 0))); + nelts = eval_constant_expression (ctx, nelts, true, non_constant_p, + overflow_p, jump_target); + if (*non_constant_p) + return NULL_TREE; + if (*jump_target) + return NULL_TREE; + /* Don't fold an out-of-bound access. */ + if (!tree_int_cst_le (t, nelts)) + return NULL_TREE; + rhs = fold_convert (ssizetype, rhs); + /* Don't fold if rhs can't be divided exactly by TYPE_SIZE_UNIT. + constexpr int A[1]; ... (char *)&A[0] + 1 */ + if (!integer_zerop (fold_build2_loc (loc, TRUNC_MOD_EXPR, sizetype, rhs, + TYPE_SIZE_UNIT (type)))) + return NULL_TREE; + /* Make sure to treat the second operand of POINTER_PLUS_EXPR + as signed. */ + rhs = fold_build2_loc (loc, EXACT_DIV_EXPR, ssizetype, rhs, + TYPE_SIZE_UNIT (type)); + t = size_binop_loc (loc, PLUS_EXPR, rhs, t); + t = build4_loc (loc, ARRAY_REF, type, TREE_OPERAND (lhs, 0), t, NULL_TREE, + NULL_TREE); + t = build_fold_addr_expr (t); + t = fold_convert (orig_type, t); + return eval_constant_expression (ctx, t, true, non_constant_p, overflow_p, + jump_target); + } + + return NULL_TREE; +} + +/* Try to fold expressions like + (struct S *) (&a[0].D.2378 + 12) + into + &MEM <struct T> [(void *)&a + 12B] + This is something normally done by gimple_fold_stmt_to_constant_1 + on GIMPLE, but is undesirable on GENERIC if we are e.g. going to + dereference the address because some details are lost. + For pointer comparisons we want such folding though so that + match.pd address_compare optimization works. */ + +static tree +maybe_fold_addr_pointer_plus (tree t) +{ + while (CONVERT_EXPR_P (t) && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0)))) + t = TREE_OPERAND (t, 0); + if (TREE_CODE (t) != POINTER_PLUS_EXPR) + return NULL_TREE; + tree op0 = TREE_OPERAND (t, 0); + tree op1 = TREE_OPERAND (t, 1); + if (TREE_CODE (op1) != INTEGER_CST) + return NULL_TREE; + while (CONVERT_EXPR_P (op0) + && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0)))) + op0 = TREE_OPERAND (op0, 0); + if (TREE_CODE (op0) != ADDR_EXPR) + return NULL_TREE; + op1 = fold_convert (ptr_type_node, op1); + tree r = fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (op0)), op0, op1); + return build1_loc (EXPR_LOCATION (t), ADDR_EXPR, TREE_TYPE (op0), r); +} + } // namespace Compile } // namespace Rust 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 e2cc2dd..de8a830 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h @@ -24,7 +24,6 @@ #include "rust-hir-item.h" #include "rust-hir-type-check.h" #include "rust-hir-visitor.h" -#include "rust-name-resolver.h" #include "rust-bir.h" #include "rust-bir-free-region.h" #include "rust-immutable-name-resolution-context.h" @@ -75,7 +74,7 @@ struct BuilderContext // External context. Resolver::TypeCheckContext &tyctx; - Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; // BIR output BasicBlocks basic_blocks; @@ -104,7 +103,7 @@ struct BuilderContext public: BuilderContext () : tyctx (*Resolver::TypeCheckContext::get ()), - resolver (*Resolver::Resolver::get ()) + resolver (Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()) { basic_blocks.emplace_back (); // StartBB } @@ -403,69 +402,31 @@ protected: // HIR resolution helpers template <typename T> NodeId resolve_label (T &expr) { - NodeId resolved_label; - 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; + auto res = ctx.resolver.lookup (expr.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + return res.value (); } template <typename T> PlaceId resolve_variable (T &variable) { - NodeId variable_id; - 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); + auto res = ctx.resolver.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + return ctx.place_db.lookup_variable (res.value ()); } template <typename T> PlaceId resolve_variable_or_fn (T &variable, TyTy::BaseType *ty) { ty = (ty) ? ty : lookup_type (variable); + // Unlike variables, // functions do not have to be declared in PlaceDB before use. - NodeId variable_id; - 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 - return ctx.place_db.lookup_or_add_variable (variable_id, ty); + + auto res = ctx.resolver.lookup (variable.get_mappings ().get_nodeid ()); + rust_assert (res.has_value ()); + return ctx.place_db.lookup_or_add_variable (res.value (), ty); } protected: // Implicit conversions. 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 2d655f9..e78d750 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc @@ -70,11 +70,34 @@ PatternBindingBuilder::visit (HIR::SlicePattern &pattern) return ty->as<TyTy::SliceType> ()->get_element_type (); }); - // Regions are unchnaged. + // Regions are unchanged. - for (auto &item : pattern.get_items ()) + switch (pattern.get_items ().get_item_type ()) { - item->accept_vis (*this); + case HIR::SlicePatternItems::NO_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ()); + for (auto &member : items.get_patterns ()) + { + member->accept_vis (*this); + } + break; + } + case HIR::SlicePatternItems::HAS_REST: + { + auto &items + = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ()); + for (auto &member : items.get_lower_patterns ()) + { + member->accept_vis (*this); + } + for (auto &member : items.get_upper_patterns ()) + { + member->accept_vis (*this); + } + break; + } } } @@ -202,17 +225,17 @@ PatternBindingBuilder::visit (HIR::TuplePattern &pattern) size_t index = 0; switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::MULTIPLE: + case HIR::TuplePatternItems::NO_REST: { - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + auto &items + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); visit_tuple_fields (items.get_patterns (), saved, index); break; } - case HIR::TuplePatternItems::RANGED: + case HIR::TuplePatternItems::HAS_REST: { auto &items - = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); auto tyty = ctx.place_db[init.value ()].tyty; rust_assert (tyty->get_kind () == TyTy::TUPLE); @@ -249,10 +272,10 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern) size_t index = 0; switch (pattern.get_items ().get_item_type ()) { - case HIR::TupleStructItems::RANGED: + case HIR::TupleStructItems::HAS_REST: { auto &items - = static_cast<HIR::TupleStructItemsRange &> (pattern.get_items ()); + = static_cast<HIR::TupleStructItemsHasRest &> (pattern.get_items ()); rust_assert (type->get_kind () == TyTy::ADT); auto adt_ty = static_cast<TyTy::ADTType *> (type); @@ -267,10 +290,10 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern) visit_tuple_fields (items.get_upper_patterns (), saved, index); break; } - case HIR::TupleStructItems::MULTIPLE: + case HIR::TupleStructItems::NO_REST: { auto &items - = static_cast<HIR::TupleStructItemsNoRange &> (pattern.get_items ()); + = static_cast<HIR::TupleStructItemsNoRest &> (pattern.get_items ()); visit_tuple_fields (items.get_patterns (), saved, index); break; } 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 d87ff8c..6cb87c7 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h @@ -225,11 +225,11 @@ protected: rust_unreachable (); } void visit (HIR::StructPattern &pattern) override { rust_unreachable (); } - void visit (HIR::TupleStructItemsNoRange &tuple_items) override + void visit (HIR::TupleStructItemsNoRest &tuple_items) override { rust_unreachable (); } - void visit (HIR::TupleStructItemsRange &tuple_items) override + void visit (HIR::TupleStructItemsHasRest &tuple_items) override { rust_unreachable (); } @@ -237,15 +237,23 @@ protected: { rust_unreachable (); } - void visit (HIR::TuplePatternItemsMultiple &tuple_items) override + void visit (HIR::TuplePatternItemsNoRest &tuple_items) override { rust_unreachable (); } - void visit (HIR::TuplePatternItemsRanged &tuple_items) override + void visit (HIR::TuplePatternItemsHasRest &tuple_items) override { rust_unreachable (); } void visit (HIR::TuplePattern &pattern) override { rust_unreachable (); } + void visit (HIR::SlicePatternItemsNoRest &tuple_items) override + { + rust_unreachable (); + } + void visit (HIR::SlicePatternItemsHasRest &tuple_items) override + { + rust_unreachable (); + } void visit (HIR::SlicePattern &pattern) override { rust_unreachable (); } void visit (HIR::AltPattern &pattern) override { rust_unreachable (); } void visit (HIR::EmptyStmt &stmt) override { rust_unreachable (); } diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h b/gcc/rust/checks/errors/borrowck/rust-function-collector.h index 86f96c1..63f2a95 100644 --- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h +++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h @@ -170,12 +170,14 @@ public: void visit (HIR::StructPatternFieldIdentPat &field) override {} void visit (HIR::StructPatternFieldIdent &field) override {} void visit (HIR::StructPattern &pattern) override {} - void visit (HIR::TupleStructItemsNoRange &tuple_items) override {} - void visit (HIR::TupleStructItemsRange &tuple_items) override {} + void visit (HIR::TupleStructItemsNoRest &tuple_items) override {} + void visit (HIR::TupleStructItemsHasRest &tuple_items) override {} void visit (HIR::TupleStructPattern &pattern) override {} - void visit (HIR::TuplePatternItemsMultiple &tuple_items) override {} - void visit (HIR::TuplePatternItemsRanged &tuple_items) override {} + void visit (HIR::TuplePatternItemsNoRest &tuple_items) override {} + void visit (HIR::TuplePatternItemsHasRest &tuple_items) override {} void visit (HIR::TuplePattern &pattern) override {} + void visit (HIR::SlicePatternItemsNoRest &tuple_items) override {} + void visit (HIR::SlicePatternItemsHasRest &tuple_items) override {} void visit (HIR::SlicePattern &pattern) override {} void visit (HIR::AltPattern &pattern) override {} void visit (HIR::EmptyStmt &stmt) override {} diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc b/gcc/rust/checks/errors/feature/rust-feature-gate.cc index 44007f9..44007f9 100644 --- a/gcc/rust/checks/errors/rust-feature-gate.cc +++ b/gcc/rust/checks/errors/feature/rust-feature-gate.cc diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/feature/rust-feature-gate.h index f1011e5..f1011e5 100644 --- a/gcc/rust/checks/errors/rust-feature-gate.h +++ b/gcc/rust/checks/errors/feature/rust-feature-gate.h diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/feature/rust-feature.cc index 071d3f8..071d3f8 100644 --- a/gcc/rust/checks/errors/rust-feature.cc +++ b/gcc/rust/checks/errors/feature/rust-feature.cc diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/feature/rust-feature.h index e7cb0af..e7cb0af 100644 --- a/gcc/rust/checks/errors/rust-feature.h +++ b/gcc/rust/checks/errors/feature/rust-feature.h diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc index 5291276..90248d3 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc @@ -20,7 +20,7 @@ #include "rust-reachability.h" #include "rust-hir-type-check.h" #include "rust-hir-map.h" -#include "rust-name-resolver.h" +#include "rust-immutable-name-resolution-context.h" #include "rust-visibility-resolver.h" #include "rust-pub-restricted-visitor.h" #include "rust-privacy-reporter.h" @@ -35,12 +35,13 @@ Resolver::resolve (HIR::Crate &crate) { PrivacyContext ctx; auto &mappings = Analysis::Mappings::get (); - auto resolver = Rust::Resolver::Resolver::get (); + auto &resolver + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); auto ty_ctx = ::Rust::Resolver::TypeCheckContext::get (); - VisibilityResolver (mappings, *resolver).go (crate); + VisibilityResolver (mappings, resolver).go (crate); PubRestrictedVisitor (mappings).go (crate); - PrivacyReporter (mappings, *resolver, *ty_ctx).go (crate); + PrivacyReporter (mappings, resolver, *ty_ctx).go (crate); auto visitor = ReachabilityVisitor (ctx, *ty_ctx); diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc index 4af9639..c1a3d45 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc @@ -28,7 +28,8 @@ namespace Rust { namespace Privacy { PrivacyReporter::PrivacyReporter ( - Analysis::Mappings &mappings, Resolver::Resolver &resolver, + Analysis::Mappings &mappings, + const Resolver2_0::NameResolutionContext &resolver, const Rust::Resolver::TypeCheckContext &ty_ctx) : mappings (mappings), resolver (resolver), ty_ctx (ty_ctx), current_module (tl::nullopt) @@ -90,59 +91,18 @@ PrivacyReporter::go (HIR::Crate &crate) } } -static bool -is_child_module (Analysis::Mappings &mappings, NodeId parent, - NodeId possible_child) -{ - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - return nr_ctx.values.is_module_descendant (parent, possible_child); - } - - auto children = mappings.lookup_module_children (parent); - - if (!children) - return false; - - // Visit all toplevel children - for (auto &child : *children) - if (child == possible_child) - return true; - - // Now descend recursively in the child module tree - for (auto &child : *children) - if (is_child_module (mappings, child, possible_child)) - return true; - - return false; -} - // FIXME: This function needs a lot of refactoring void PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, const location_t locus) { - NodeId ref_node_id = UNKNOWN_NODEID; - - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - if (auto id = nr_ctx.lookup (use_id)) - ref_node_id = *id; - } - // FIXME: Don't assert here - we might be dealing with a type - else if (!resolver.lookup_resolved_name (use_id, &ref_node_id)) - resolver.lookup_resolved_type (use_id, &ref_node_id); + NodeId ref_node_id; // FIXME: Assert here. For now, we return since this causes issues when // checking inferred types (#1260) - // rust_assert (ref_node_id != UNKNOWN_NODEID); - if (ref_node_id == UNKNOWN_NODEID) + if (auto id = resolver.lookup (use_id)) + ref_node_id = *id; + else return; auto vis = mappings.lookup_visibility (ref_node_id); @@ -175,7 +135,9 @@ PrivacyReporter::check_for_privacy_violation (const NodeId &use_id, // FIXME: This needs a LOT of TLC: hinting about the definition, a // string to say if it's a module, function, type, etc... - if (!is_child_module (mappings, mod_node_id, current_module.value ())) + + if (!resolver.values.is_module_descendant (mod_node_id, + current_module.value ())) valid = false; } break; diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h index 72716a6..d64b7a7 100644 --- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h +++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h @@ -22,8 +22,9 @@ #include "rust-hir-expr.h" #include "rust-hir-map.h" #include "rust-hir-visitor.h" +#include "rust-hir-type-check.h" #include "rust-mapping-common.h" -#include "rust-name-resolver.h" +#include "rust-name-resolution-context.h" namespace Rust { namespace Privacy { @@ -38,7 +39,7 @@ class PrivacyReporter : public HIR::HIRExpressionVisitor, { public: PrivacyReporter (Analysis::Mappings &mappings, - Rust::Resolver::Resolver &resolver, + const Resolver2_0::NameResolutionContext &resolver, const Rust::Resolver::TypeCheckContext &ty_ctx); /** @@ -157,7 +158,7 @@ types virtual void visit (HIR::ExprStmt &stmt); Analysis::Mappings &mappings; - Rust::Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; const Rust::Resolver::TypeCheckContext &ty_ctx; // `None` means we're in the root module - the crate diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc index c59763d..4240673 100644 --- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc +++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc @@ -20,16 +20,14 @@ #include "rust-ast.h" #include "rust-hir.h" #include "rust-hir-item.h" -#include "rust-immutable-name-resolution-context.h" - -// for flag_name_resolution_2_0 -#include "options.h" +#include "rust-name-resolution-context.h" namespace Rust { namespace Privacy { -VisibilityResolver::VisibilityResolver (Analysis::Mappings &mappings, - Resolver::Resolver &resolver) +VisibilityResolver::VisibilityResolver ( + Analysis::Mappings &mappings, + const Resolver2_0::NameResolutionContext &resolver) : mappings (mappings), resolver (resolver) {} @@ -64,23 +62,12 @@ VisibilityResolver::resolve_module_path (const HIR::SimplePath &restriction, = Error (restriction.get_locus (), "cannot use non-module path as privacy restrictor"); - NodeId ref_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) + NodeId ref_node_id; + if (auto id = resolver.lookup (ast_node_id)) { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - if (auto id = nr_ctx.lookup (ast_node_id)) - { - ref_node_id = *id; - } - else - { - invalid_path.emit (); - return false; - } + ref_node_id = *id; } - else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) + else { invalid_path.emit (); return false; diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h index 4dfba4c..ddd70a8 100644 --- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h +++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.h @@ -24,7 +24,7 @@ #include "rust-hir-stmt.h" #include "rust-hir-item.h" #include "rust-hir-map.h" -#include "rust-name-resolver.h" +#include "rust-name-resolution-context.h" #include "rust-hir-visitor.h" namespace Rust { @@ -34,7 +34,7 @@ class VisibilityResolver : public HIR::HIRVisItemVisitor { public: VisibilityResolver (Analysis::Mappings &mappings, - Rust::Resolver::Resolver &resolver); + const Resolver2_0::NameResolutionContext &resolver); /** * Perform visibility resolving on an entire crate @@ -93,7 +93,7 @@ public: private: Analysis::Mappings &mappings; - Rust::Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; DefId current_module; }; diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc index c40f9db..782d694 100644 --- a/gcc/rust/checks/errors/rust-const-checker.cc +++ b/gcc/rust/checks/errors/rust-const-checker.cc @@ -813,11 +813,11 @@ ConstChecker::visit (StructPattern &) {} void -ConstChecker::visit (TupleStructItemsNoRange &) +ConstChecker::visit (TupleStructItemsNoRest &) {} void -ConstChecker::visit (TupleStructItemsRange &) +ConstChecker::visit (TupleStructItemsHasRest &) {} void @@ -825,11 +825,11 @@ ConstChecker::visit (TupleStructPattern &) {} void -ConstChecker::visit (TuplePatternItemsMultiple &) +ConstChecker::visit (TuplePatternItemsNoRest &) {} void -ConstChecker::visit (TuplePatternItemsRanged &) +ConstChecker::visit (TuplePatternItemsHasRest &) {} void @@ -837,6 +837,14 @@ ConstChecker::visit (TuplePattern &) {} void +ConstChecker::visit (SlicePatternItemsNoRest &) +{} + +void +ConstChecker::visit (SlicePatternItemsHasRest &) +{} + +void ConstChecker::visit (SlicePattern &) {} diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h index eb63095..d464b7b 100644 --- a/gcc/rust/checks/errors/rust-const-checker.h +++ b/gcc/rust/checks/errors/rust-const-checker.h @@ -180,12 +180,14 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override; virtual void visit (StructPatternFieldIdent &field) override; virtual void visit (StructPattern &pattern) override; - virtual void visit (TupleStructItemsNoRange &tuple_items) override; - virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructItemsNoRest &tuple_items) override; + virtual void visit (TupleStructItemsHasRest &tuple_items) override; virtual void visit (TupleStructPattern &pattern) override; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override; virtual void visit (TuplePattern &pattern) override; + virtual void visit (SlicePatternItemsNoRest &items) override; + virtual void visit (SlicePatternItemsHasRest &items) override; virtual void visit (SlicePattern &pattern) override; virtual void visit (AltPattern &pattern) override; virtual void visit (EmptyStmt &stmt) override; diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc index 2566971..f132e04 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc @@ -28,15 +28,12 @@ #include "rust-tyty.h" #include "rust-immutable-name-resolution-context.h" -// for flag_name_resolution_2_0 -#include "options.h" - namespace Rust { namespace Analysis { PatternChecker::PatternChecker () : tyctx (*Resolver::TypeCheckContext::get ()), - resolver (*Resolver::Resolver::get ()), + resolver (Resolver2_0::ImmutableNameResolutionContext::get ().resolver ()), mappings (Analysis::Mappings::get ()) {} @@ -238,17 +235,9 @@ PatternChecker::visit (CallExpr &expr) NodeId ast_node_id = expr.get_fnexpr ().get_mappings ().get_nodeid (); NodeId ref_node_id; - if (flag_name_resolution_2_0) - { - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - if (auto id = nr_ctx.lookup (ast_node_id)) - ref_node_id = *id; - else - return; - } - else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) + if (auto id = resolver.lookup (ast_node_id)) + ref_node_id = *id; + else return; if (auto definition_id = mappings.lookup_node_to_hir (ref_node_id)) @@ -640,11 +629,11 @@ PatternChecker::visit (StructPattern &) {} void -PatternChecker::visit (TupleStructItemsNoRange &) +PatternChecker::visit (TupleStructItemsNoRest &) {} void -PatternChecker::visit (TupleStructItemsRange &) +PatternChecker::visit (TupleStructItemsHasRest &) {} void @@ -652,11 +641,11 @@ PatternChecker::visit (TupleStructPattern &) {} void -PatternChecker::visit (TuplePatternItemsMultiple &) +PatternChecker::visit (TuplePatternItemsNoRest &) {} void -PatternChecker::visit (TuplePatternItemsRanged &) +PatternChecker::visit (TuplePatternItemsHasRest &) {} void @@ -664,6 +653,14 @@ PatternChecker::visit (TuplePattern &) {} void +PatternChecker::visit (SlicePatternItemsNoRest &) +{} + +void +PatternChecker::visit (SlicePatternItemsHasRest &) +{} + +void PatternChecker::visit (SlicePattern &) {} @@ -980,7 +977,7 @@ Matrix::specialize (const Constructor &ctor) const if (ctor.is_covered_by (hd.ctor ())) { pats.pop_head_constructor (ctor, subfields_place_info.size ()); - new_rows.push_back (MatrixRow (pats, row.is_under_guard ())); + new_rows.emplace_back (pats, row.is_under_guard ()); } } @@ -1186,7 +1183,7 @@ WitnessMatrix::apply_constructor (const Constructor &ctor, } } - stack.push_back (WitnessPat (ctor, subfield, ty)); + stack.emplace_back (ctor, subfield, ty); } } @@ -1213,27 +1210,54 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx, std::vector<DeconstructedPat> fields; switch (elems.get_item_type ()) { - case HIR::TupleStructItems::ItemType::MULTIPLE: + case HIR::TupleStructItems::ItemType::NO_REST: { - HIR::TupleStructItemsNoRange &multiple - = static_cast<HIR::TupleStructItemsNoRange &> (elems); + HIR::TupleStructItemsNoRest &items_no_rest + = static_cast<HIR::TupleStructItemsNoRest &> (elems); rust_assert (variant->get_fields ().size () - == multiple.get_patterns ().size ()); + == items_no_rest.get_patterns ().size ()); - for (size_t i = 0; i < multiple.get_patterns ().size (); i++) + for (size_t i = 0; i < items_no_rest.get_patterns ().size (); i++) { fields.push_back ( - lower_pattern (ctx, *multiple.get_patterns ().at (i), + lower_pattern (ctx, *items_no_rest.get_patterns ().at (i), variant->get_fields ().at (i)->get_field_type ())); } return DeconstructedPat (ctor, arity, fields, pattern.get_locus ()); } break; - case HIR::TupleStructItems::ItemType::RANGED: + case HIR::TupleStructItems::ItemType::HAS_REST: { - // TODO: ranged tuple struct items - rust_unreachable (); + HIR::TupleStructItemsHasRest &items_has_rest + = static_cast<HIR::TupleStructItemsHasRest &> (elems); + + size_t num_patterns = items_has_rest.get_lower_patterns ().size () + + items_has_rest.get_upper_patterns ().size (); + + rust_assert (num_patterns <= variant->num_fields ()); + + size_t i = 0; + for (auto &pattern_member : items_has_rest.get_lower_patterns ()) + { + fields.push_back (lower_pattern ( + ctx, *pattern_member, + variant->get_fields ().at (i++)->get_field_type ())); + } + while (i < variant->num_fields () + - items_has_rest.get_upper_patterns ().size ()) + { + fields.push_back ( + DeconstructedPat::make_wildcard (pattern.get_locus ())); + i++; + } + for (auto &pattern_member : items_has_rest.get_upper_patterns ()) + { + fields.push_back (lower_pattern ( + ctx, *pattern_member, + variant->get_fields ().at (i++)->get_field_type ())); + } + return DeconstructedPat (ctor, arity, fields, pattern.get_locus ()); } break; default: @@ -1597,7 +1621,7 @@ check_match_usefulness (Resolver::TypeCheckContext *ctx, MatchArm lowered = lower_arm (ctx, arm, scrutinee_ty); PatOrWild pat = PatOrWild::make_pattern (lowered.get_pat ()); pats.push (pat); - rows.push_back (MatrixRow (pats, lowered.has_guard ())); + rows.emplace_back (pats, lowered.has_guard ()); } std::vector<PlaceInfo> place_infos = {{PlaceInfo (scrutinee_ty)}}; diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h index dd44abc..645e61d 100644 --- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h +++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h @@ -26,7 +26,7 @@ #include "rust-tyty.h" #include "optional.h" #include "rust-hir-visitor.h" -#include "rust-name-resolver.h" +#include "rust-immutable-name-resolution-context.h" namespace Rust { namespace Analysis { @@ -46,7 +46,7 @@ public: private: Resolver::TypeCheckContext &tyctx; - Resolver::Resolver &resolver; + const Resolver2_0::NameResolutionContext &resolver; Analysis::Mappings &mappings; virtual void visit (Lifetime &lifetime) override; @@ -153,12 +153,14 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override; virtual void visit (StructPatternFieldIdent &field) override; virtual void visit (StructPattern &pattern) override; - virtual void visit (TupleStructItemsNoRange &tuple_items) override; - virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructItemsNoRest &tuple_items) override; + virtual void visit (TupleStructItemsHasRest &tuple_items) override; virtual void visit (TupleStructPattern &pattern) override; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override; virtual void visit (TuplePattern &pattern) override; + virtual void visit (SlicePatternItemsNoRest &items) override; + virtual void visit (SlicePatternItemsHasRest &items) override; virtual void visit (SlicePattern &pattern) override; virtual void visit (AltPattern &pattern) override; virtual void visit (EmptyStmt &stmt) override; diff --git a/gcc/rust/checks/errors/rust-readonly-check.cc b/gcc/rust/checks/errors/rust-readonly-check.cc index c128933..f484047 100644 --- a/gcc/rust/checks/errors/rust-readonly-check.cc +++ b/gcc/rust/checks/errors/rust-readonly-check.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2025 Free Software Foundation, Inc. +// Copyright (C) 2025 Free Software Foundation, Inc. // This file is part of GCC. @@ -17,184 +17,252 @@ // <http://www.gnu.org/licenses/>. #include "rust-readonly-check.h" -#include "rust-tree.h" -#include "rust-gcc.h" -#include "print-tree.h" +#include "rust-hir-expr.h" +#include "rust-hir-node.h" +#include "rust-hir-path.h" +#include "rust-hir-map.h" +#include "rust-hir-pattern.h" +#include "rust-mapping-common.h" +#include "rust-system.h" +#include "rust-immutable-name-resolution-context.h" +#include "rust-tyty.h" namespace Rust { -namespace Analysis { +namespace HIR { -static std::map<tree, int> assignment_map = {}; +static std::set<HirId> already_assigned_variables = {}; + +ReadonlyChecker::ReadonlyChecker () + : resolver (*Resolver::Resolver::get ()), + mappings (Analysis::Mappings::get ()), + context (*Resolver::TypeCheckContext::get ()) +{} + +void +ReadonlyChecker::go (Crate &crate) +{ + for (auto &item : crate.get_items ()) + item->accept_vis (*this); +} -// ported over from c-family/c-warn.cc void -readonly_error (location_t loc, tree arg, enum lvalue_use use) +ReadonlyChecker::visit (AssignmentExpr &expr) { - gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement - || use == lv_asm); - STRIP_ANY_LOCATION_WRAPPER (arg); - /* Using this macro rather than (for example) arrays of messages - ensures that all the format strings are checked at compile - time. */ -#define READONLY_MSG(A, I, D, AS) \ - (use == lv_assign \ - ? (A) \ - : (use == lv_increment ? (I) : (use == lv_decrement ? (D) : (AS)))) - if (TREE_CODE (arg) == COMPONENT_REF) + Expr &lhs = expr.get_lhs (); + mutable_context.enter (expr.get_mappings ().get_hirid ()); + lhs.accept_vis (*this); + mutable_context.exit (); +} + +void +ReadonlyChecker::visit (PathInExpression &expr) +{ + if (!mutable_context.is_in_context ()) + return; + + NodeId ast_node_id = expr.get_mappings ().get_nodeid (); + NodeId def_id; + + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + if (auto id = nr_ctx.lookup (ast_node_id)) + def_id = *id; + else + return; + + auto hir_id = mappings.lookup_node_to_hir (def_id); + if (!hir_id) + return; + + // Check if the local variable is mutable. + auto maybe_pattern = mappings.lookup_hir_pattern (*hir_id); + if (maybe_pattern + && maybe_pattern.value ()->get_pattern_type () + == HIR::Pattern::PatternType::IDENTIFIER) + check_variable (static_cast<IdentifierPattern *> (maybe_pattern.value ()), + expr.get_locus ()); + + // Check if the static item is mutable. + auto maybe_item = mappings.lookup_hir_item (*hir_id); + if (maybe_item + && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Static) { - if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) - error_at (loc, - READONLY_MSG (G_ ("assignment of member " - "%qD in read-only object"), - G_ ("increment of member " - "%qD in read-only object"), - G_ ("decrement of member " - "%qD in read-only object"), - G_ ("member %qD in read-only object " - "used as %<asm%> output")), - TREE_OPERAND (arg, 1)); - else - error_at ( - loc, - READONLY_MSG (G_ ("assignment of read-only member %qD"), - G_ ("increment of read-only member %qD"), - G_ ("decrement of read-only member %qD"), - G_ ("read-only member %qD used as %<asm%> output")), - TREE_OPERAND (arg, 1)); + auto static_item = static_cast<HIR::StaticItem *> (*maybe_item); + if (!static_item->is_mut ()) + rust_error_at (expr.get_locus (), + "assignment of read-only location '%s'", + static_item->get_identifier ().as_string ().c_str ()); } - else if (VAR_P (arg)) - error_at (loc, - READONLY_MSG (G_ ("assignment of read-only variable %qD"), - G_ ("increment of read-only variable %qD"), - G_ ("decrement of read-only variable %qD"), - G_ ( - "read-only variable %qD used as %<asm%> output")), - arg); - else if (TREE_CODE (arg) == PARM_DECL) - error_at (loc, - READONLY_MSG (G_ ("assignment of read-only parameter %qD"), - G_ ("increment of read-only parameter %qD"), - G_ ("decrement of read-only parameter %qD"), - G_ ( - "read-only parameter %qD use as %<asm%> output")), - arg); - else if (TREE_CODE (arg) == RESULT_DECL) + + // Check if the constant item is mutable. + if (maybe_item + && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant) { - error_at (loc, - READONLY_MSG (G_ ("assignment of " - "read-only named return value %qD"), - G_ ("increment of " - "read-only named return value %qD"), - G_ ("decrement of " - "read-only named return value %qD"), - G_ ("read-only named return value %qD " - "used as %<asm%>output")), - arg); + auto const_item = static_cast<HIR::ConstantItem *> (*maybe_item); + rust_error_at (expr.get_locus (), "assignment of read-only location '%s'", + const_item->get_identifier ().as_string ().c_str ()); } - else if (TREE_CODE (arg) == FUNCTION_DECL) - error_at (loc, - READONLY_MSG (G_ ("assignment of function %qD"), - G_ ("increment of function %qD"), - G_ ("decrement of function %qD"), - G_ ("function %qD used as %<asm%> output")), - arg); - else - error_at (loc, - READONLY_MSG (G_ ("assignment of read-only location %qE"), - G_ ("increment of read-only location %qE"), - G_ ("decrement of read-only location %qE"), - G_ ( - "read-only location %qE used as %<asm%> output")), - arg); } -static void -emit_error (tree *t, tree lhs, enum lvalue_use use) +void +ReadonlyChecker::check_variable (IdentifierPattern *pattern, + location_t assigned_loc) { - readonly_error (EXPR_LOCATION (*t), lhs, use); - TREE_OPERAND (*t, 0) = error_mark_node; + if (!mutable_context.is_in_context ()) + return; + + TyTy::BaseType *type; + if (context.lookup_type (pattern->get_mappings ().get_hirid (), &type) + && is_mutable_type (type)) + return; + if (pattern->is_mut ()) + return; + + auto hir_id = pattern->get_mappings ().get_hirid (); + if (already_assigned_variables.count (hir_id) > 0) + rust_error_at (assigned_loc, "assignment of read-only variable '%s'", + pattern->as_string ().c_str ()); + already_assigned_variables.insert (hir_id); } -static void -check_modify_expr (tree *t) +void +ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern, + bool has_init_expr) { - tree lhs = TREE_OPERAND (*t, 0); - if (TREE_CODE (lhs) == ARRAY_REF || TREE_CODE (lhs) == COMPONENT_REF) - lhs = TREE_OPERAND (lhs, 0); - - tree lhs_type = TREE_TYPE (lhs); - if (TYPE_READONLY (lhs_type) || TREE_READONLY (lhs) || TREE_CONSTANT (lhs)) + if (has_init_expr) { - if (TREE_CODE (lhs) != VAR_DECL) - emit_error (t, lhs, lv_assign); - else if (!DECL_ARTIFICIAL (lhs)) - { - if (DECL_INITIAL (lhs) != NULL) - emit_error (t, lhs, lv_assign); - else - { - if (assignment_map.find (lhs) == assignment_map.end ()) - { - assignment_map.insert ({lhs, 0}); - } - assignment_map[lhs]++; - - if (assignment_map[lhs] > 1) - emit_error (t, lhs, lv_assign); - } - } + HirId pattern_id = pattern.get_mappings ().get_hirid (); + already_assigned_variables.insert (pattern_id); } } -static void -check_decl (tree *t) +void +ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern, + bool has_init_expr) { - switch (TREE_CODE (*t)) + switch (tuple_pattern.get_items ().get_item_type ()) { - case MODIFY_EXPR: - check_modify_expr (t); + case HIR::TuplePatternItems::ItemType::NO_REST: + { + auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> ( + tuple_pattern.get_items ()); + for (auto &sub : items_no_rest.get_patterns ()) + { + collect_assignment (*sub, has_init_expr); + } + } + break; + case HIR::TuplePatternItems::ItemType::HAS_REST: + { + auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> ( + tuple_pattern.get_items ()); + for (auto &sub : items_has_rest.get_lower_patterns ()) + collect_assignment (*sub, has_init_expr); + for (auto &sub : items_has_rest.get_upper_patterns ()) + collect_assignment (*sub, has_init_expr); + } + break; + default: break; + } +} +void +ReadonlyChecker::collect_assignment (Pattern &pattern, bool has_init_expr) +{ + switch (pattern.get_pattern_type ()) + { + case HIR::Pattern::PatternType::IDENTIFIER: + { + collect_assignment_identifier (static_cast<IdentifierPattern &> ( + pattern), + has_init_expr); + } + break; + case HIR::Pattern::PatternType::TUPLE: + { + auto &tuple_pattern = static_cast<HIR::TuplePattern &> (pattern); + collect_assignment_tuple (tuple_pattern, has_init_expr); + } + break; default: break; } } -static tree -readonly_walk_fn (tree *t, int *, void *) +void +ReadonlyChecker::visit (LetStmt &stmt) +{ + HIR::Pattern &pattern = stmt.get_pattern (); + collect_assignment (pattern, stmt.has_init_expr ()); +} + +void +ReadonlyChecker::visit (FieldAccessExpr &expr) { - check_decl (t); - return NULL_TREE; + if (mutable_context.is_in_context ()) + { + expr.get_receiver_expr ().accept_vis (*this); + } } void -ReadonlyCheck::Lint (Compile::Context &ctx) +ReadonlyChecker::visit (TupleIndexExpr &expr) { - assignment_map.clear (); - for (auto &fndecl : ctx.get_func_decls ()) + if (mutable_context.is_in_context ()) { - for (tree p = DECL_ARGUMENTS (fndecl); p != NULL_TREE; p = DECL_CHAIN (p)) - { - check_decl (&p); - } + expr.get_tuple_expr ().accept_vis (*this); + } +} - walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl), - &readonly_walk_fn, &ctx); +void +ReadonlyChecker::visit (ArrayIndexExpr &expr) +{ + if (mutable_context.is_in_context ()) + { + expr.get_array_expr ().accept_vis (*this); } +} - assignment_map.clear (); - for (auto &var : ctx.get_var_decls ()) +void +ReadonlyChecker::visit (TupleExpr &expr) +{ + if (mutable_context.is_in_context ()) { - tree decl = var->get_decl (); - check_decl (&decl); + // TODO: Add check for tuple expression } +} - assignment_map.clear (); - for (auto &const_decl : ctx.get_const_decls ()) +void +ReadonlyChecker::visit (LiteralExpr &expr) +{ + if (mutable_context.is_in_context ()) { - check_decl (&const_decl); + rust_error_at (expr.get_locus (), "assignment of read-only location"); } } -} // namespace Analysis +void +ReadonlyChecker::visit (DereferenceExpr &expr) +{ + if (!mutable_context.is_in_context ()) + return; + TyTy::BaseType *to_deref_type; + auto to_deref = expr.get_expr ().get_mappings ().get_hirid (); + if (!context.lookup_type (to_deref, &to_deref_type)) + return; + if (!is_mutable_type (to_deref_type)) + rust_error_at (expr.get_locus (), "assignment of read-only location"); +} + +bool +ReadonlyChecker::is_mutable_type (TyTy::BaseType *type) +{ + if (type->get_kind () == TyTy::TypeKind::REF) + return static_cast<TyTy::ReferenceType *> (type)->is_mutable (); + if (type->get_kind () == TyTy::TypeKind::POINTER) + return static_cast<TyTy::PointerType *> (type)->is_mutable (); + return false; +} +} // namespace HIR } // namespace Rust diff --git a/gcc/rust/checks/errors/rust-readonly-check.h b/gcc/rust/checks/errors/rust-readonly-check.h index b39eee3..3525620 100644 --- a/gcc/rust/checks/errors/rust-readonly-check.h +++ b/gcc/rust/checks/errors/rust-readonly-check.h @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2025 Free Software Foundation, Inc. +// Copyright (C) 2025 Free Software Foundation, Inc. // This file is part of GCC. @@ -16,21 +16,54 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -#ifndef RUST_READONLY_CHECK -#define RUST_READONLY_CHECK - -#include "rust-compile-context.h" +#include "rust-hir-visitor.h" +#include "rust-name-resolver.h" +#include "rust-stacked-contexts.h" +#include "rust-hir-type-check.h" namespace Rust { -namespace Analysis { - -class ReadonlyCheck +namespace HIR { +class ReadonlyChecker : public DefaultHIRVisitor { public: - static void Lint (Compile::Context &ctx); -}; + ReadonlyChecker (); + + void go (HIR::Crate &crate); + +private: + enum class lvalue_use + { + assign, + increment, + decrement, + }; + + Resolver::Resolver &resolver; + Analysis::Mappings &mappings; + Resolver::TypeCheckContext &context; + StackedContexts<HirId> mutable_context; -} // namespace Analysis -} // namespace Rust + using DefaultHIRVisitor::visit; + + virtual void visit (AssignmentExpr &expr) override; + virtual void visit (PathInExpression &expr) override; + virtual void visit (FieldAccessExpr &expr) override; + virtual void visit (ArrayIndexExpr &expr) override; + virtual void visit (TupleExpr &expr) override; + virtual void visit (TupleIndexExpr &expr) override; + virtual void visit (LetStmt &stmt) override; + virtual void visit (LiteralExpr &expr) override; + virtual void visit (DereferenceExpr &expr) override; + + void collect_assignment (Pattern &pattern, bool has_init_expr); + void collect_assignment_identifier (IdentifierPattern &pattern, + bool has_init_expr); + void collect_assignment_tuple (TuplePattern &pattern, bool has_init_expr); + + void check_variable (IdentifierPattern *pattern, location_t assigned_loc); + + bool is_mutable_type (TyTy::BaseType *type); +}; -#endif // RUST_READONLY_CHECK +} // namespace HIR +} // namespace Rust
\ No newline at end of file diff --git a/gcc/rust/checks/errors/rust-readonly-check2.cc b/gcc/rust/checks/errors/rust-readonly-check2.cc deleted file mode 100644 index 2fa92ae..0000000 --- a/gcc/rust/checks/errors/rust-readonly-check2.cc +++ /dev/null @@ -1,253 +0,0 @@ -// 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-readonly-check2.h" -#include "rust-hir-expr.h" -#include "rust-hir-node.h" -#include "rust-hir-path.h" -#include "rust-hir-map.h" -#include "rust-hir-pattern.h" -#include "rust-mapping-common.h" -#include "rust-system.h" -#include "rust-immutable-name-resolution-context.h" -#include "rust-tyty.h" - -namespace Rust { -namespace HIR { - -static std::set<HirId> already_assigned_variables = {}; - -ReadonlyChecker::ReadonlyChecker () - : resolver (*Resolver::Resolver::get ()), - mappings (Analysis::Mappings::get ()), - context (*Resolver::TypeCheckContext::get ()) -{} - -void -ReadonlyChecker::go (Crate &crate) -{ - for (auto &item : crate.get_items ()) - item->accept_vis (*this); -} - -void -ReadonlyChecker::visit (AssignmentExpr &expr) -{ - Expr &lhs = expr.get_lhs (); - mutable_context.enter (expr.get_mappings ().get_hirid ()); - lhs.accept_vis (*this); - mutable_context.exit (); -} - -void -ReadonlyChecker::visit (PathInExpression &expr) -{ - if (!mutable_context.is_in_context ()) - return; - - NodeId ast_node_id = expr.get_mappings ().get_nodeid (); - NodeId def_id; - - auto &nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - if (auto id = nr_ctx.lookup (ast_node_id)) - def_id = *id; - else - return; - - auto hir_id = mappings.lookup_node_to_hir (def_id); - if (!hir_id) - return; - - // Check if the local variable is mutable. - auto maybe_pattern = mappings.lookup_hir_pattern (*hir_id); - if (maybe_pattern - && maybe_pattern.value ()->get_pattern_type () - == HIR::Pattern::PatternType::IDENTIFIER) - check_variable (static_cast<IdentifierPattern *> (maybe_pattern.value ()), - expr.get_locus ()); - - // Check if the static item is mutable. - auto maybe_item = mappings.lookup_hir_item (*hir_id); - if (maybe_item - && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Static) - { - auto static_item = static_cast<HIR::StaticItem *> (*maybe_item); - if (!static_item->is_mut ()) - rust_error_at (expr.get_locus (), - "assignment of read-only location '%s'", - static_item->get_identifier ().as_string ().c_str ()); - } - - // Check if the constant item is mutable. - if (maybe_item - && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant) - { - auto const_item = static_cast<HIR::ConstantItem *> (*maybe_item); - rust_error_at (expr.get_locus (), "assignment of read-only location '%s'", - const_item->get_identifier ().as_string ().c_str ()); - } -} - -void -ReadonlyChecker::check_variable (IdentifierPattern *pattern, - location_t assigned_loc) -{ - if (!mutable_context.is_in_context ()) - return; - if (pattern->is_mut ()) - return; - - auto hir_id = pattern->get_mappings ().get_hirid (); - if (already_assigned_variables.count (hir_id) > 0) - rust_error_at (assigned_loc, "assignment of read-only variable '%s'", - pattern->as_string ().c_str ()); - already_assigned_variables.insert (hir_id); -} - -void -ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern, - bool has_init_expr) -{ - if (has_init_expr) - { - HirId pattern_id = pattern.get_mappings ().get_hirid (); - already_assigned_variables.insert (pattern_id); - } -} - -void -ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern, - bool has_init_expr) -{ - switch (tuple_pattern.get_items ().get_item_type ()) - { - case HIR::TuplePatternItems::ItemType::MULTIPLE: - { - auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - tuple_pattern.get_items ()); - for (auto &sub : items.get_patterns ()) - { - collect_assignment (*sub, has_init_expr); - } - } - break; - default: - break; - } -} - -void -ReadonlyChecker::collect_assignment (Pattern &pattern, bool has_init_expr) -{ - switch (pattern.get_pattern_type ()) - { - case HIR::Pattern::PatternType::IDENTIFIER: - { - collect_assignment_identifier (static_cast<IdentifierPattern &> ( - pattern), - has_init_expr); - } - break; - case HIR::Pattern::PatternType::TUPLE: - { - auto &tuple_pattern = static_cast<HIR::TuplePattern &> (pattern); - collect_assignment_tuple (tuple_pattern, has_init_expr); - } - break; - default: - break; - } -} - -void -ReadonlyChecker::visit (LetStmt &stmt) -{ - HIR::Pattern &pattern = stmt.get_pattern (); - collect_assignment (pattern, stmt.has_init_expr ()); -} - -void -ReadonlyChecker::visit (FieldAccessExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - expr.get_receiver_expr ().accept_vis (*this); - } -} - -void -ReadonlyChecker::visit (TupleIndexExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - expr.get_tuple_expr ().accept_vis (*this); - } -} - -void -ReadonlyChecker::visit (ArrayIndexExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - expr.get_array_expr ().accept_vis (*this); - } -} - -void -ReadonlyChecker::visit (TupleExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - // TODO: Add check for tuple expression - } -} - -void -ReadonlyChecker::visit (LiteralExpr &expr) -{ - if (mutable_context.is_in_context ()) - { - rust_error_at (expr.get_locus (), "assignment of read-only location"); - } -} - -void -ReadonlyChecker::visit (DereferenceExpr &expr) -{ - if (!mutable_context.is_in_context ()) - return; - TyTy::BaseType *to_deref_type; - auto to_deref = expr.get_expr ().get_mappings ().get_hirid (); - if (!context.lookup_type (to_deref, &to_deref_type)) - return; - if (to_deref_type->get_kind () == TyTy::TypeKind::REF) - { - auto ref_type = static_cast<TyTy::ReferenceType *> (to_deref_type); - if (!ref_type->is_mutable ()) - rust_error_at (expr.get_locus (), "assignment of read-only location"); - } - if (to_deref_type->get_kind () == TyTy::TypeKind::POINTER) - { - auto ptr_type = static_cast<TyTy::PointerType *> (to_deref_type); - if (!ptr_type->is_mutable ()) - rust_error_at (expr.get_locus (), "assignment of read-only location"); - } -} -} // namespace HIR -} // namespace Rust diff --git a/gcc/rust/checks/errors/rust-readonly-check2.h b/gcc/rust/checks/errors/rust-readonly-check2.h deleted file mode 100644 index 06af9db..0000000 --- a/gcc/rust/checks/errors/rust-readonly-check2.h +++ /dev/null @@ -1,67 +0,0 @@ -// 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-hir-visitor.h" -#include "rust-name-resolver.h" -#include "rust-stacked-contexts.h" -#include "rust-hir-type-check.h" - -namespace Rust { -namespace HIR { -class ReadonlyChecker : public DefaultHIRVisitor -{ -public: - ReadonlyChecker (); - - void go (HIR::Crate &crate); - -private: - enum class lvalue_use - { - assign, - increment, - decrement, - }; - - Resolver::Resolver &resolver; - Analysis::Mappings &mappings; - Resolver::TypeCheckContext &context; - StackedContexts<HirId> mutable_context; - - using DefaultHIRVisitor::visit; - - virtual void visit (AssignmentExpr &expr) override; - virtual void visit (PathInExpression &expr) override; - virtual void visit (FieldAccessExpr &expr) override; - virtual void visit (ArrayIndexExpr &expr) override; - virtual void visit (TupleExpr &expr) override; - virtual void visit (TupleIndexExpr &expr) override; - virtual void visit (LetStmt &stmt) override; - virtual void visit (LiteralExpr &expr) override; - virtual void visit (DereferenceExpr &expr) override; - - void collect_assignment (Pattern &pattern, bool has_init_expr); - void collect_assignment_identifier (IdentifierPattern &pattern, - bool has_init_expr); - void collect_assignment_tuple (TuplePattern &pattern, bool has_init_expr); - - void check_variable (IdentifierPattern *pattern, location_t assigned_loc); -}; - -} // namespace HIR -} // namespace Rust
\ No newline at end of file diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc index 405c59b..607d20f 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.cc +++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc @@ -926,11 +926,11 @@ UnsafeChecker::visit (StructPattern &) {} void -UnsafeChecker::visit (TupleStructItemsNoRange &) +UnsafeChecker::visit (TupleStructItemsNoRest &) {} void -UnsafeChecker::visit (TupleStructItemsRange &) +UnsafeChecker::visit (TupleStructItemsHasRest &) {} void @@ -938,11 +938,11 @@ UnsafeChecker::visit (TupleStructPattern &) {} void -UnsafeChecker::visit (TuplePatternItemsMultiple &) +UnsafeChecker::visit (TuplePatternItemsNoRest &) {} void -UnsafeChecker::visit (TuplePatternItemsRanged &) +UnsafeChecker::visit (TuplePatternItemsHasRest &) {} void @@ -950,6 +950,14 @@ UnsafeChecker::visit (TuplePattern &) {} void +UnsafeChecker::visit (SlicePatternItemsNoRest &) +{} + +void +UnsafeChecker::visit (SlicePatternItemsHasRest &) +{} + +void UnsafeChecker::visit (SlicePattern &) {} diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h index dc3b482..420668f 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.h +++ b/gcc/rust/checks/errors/rust-unsafe-checker.h @@ -161,12 +161,14 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override; virtual void visit (StructPatternFieldIdent &field) override; virtual void visit (StructPattern &pattern) override; - virtual void visit (TupleStructItemsNoRange &tuple_items) override; - virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructItemsNoRest &tuple_items) override; + virtual void visit (TupleStructItemsHasRest &tuple_items) override; virtual void visit (TupleStructPattern &pattern) override; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override; virtual void visit (TuplePattern &pattern) override; + virtual void visit (SlicePatternItemsNoRest &items) override; + virtual void visit (SlicePatternItemsHasRest &items) override; virtual void visit (SlicePattern &pattern) override; virtual void visit (AltPattern &pattern) override; virtual void visit (EmptyStmt &stmt) override; diff --git a/gcc/rust/checks/lints/rust-lint-marklive-base.h b/gcc/rust/checks/lints/rust-lint-marklive-base.h index 2a97577..dec9396 100644 --- a/gcc/rust/checks/lints/rust-lint-marklive-base.h +++ b/gcc/rust/checks/lints/rust-lint-marklive-base.h @@ -19,9 +19,6 @@ #ifndef RUST_HIR_LIVENESS_BASE #define RUST_HIR_LIVENESS_BASE -#include "rust-diagnostics.h" -#include "rust-lint-marklive.h" -#include "rust-lint-marklive-base.h" #include "rust-hir-visitor.h" #include "rust-hir-map.h" diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index 58d8071..3c5e74e 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -22,6 +22,7 @@ #include "rust-path.h" #include "rust-session-manager.h" #include "rust-attribute-values.h" +#include "rust-macro-expand.h" namespace Rust { @@ -30,7 +31,7 @@ namespace Rust { * should be stripped. Note that attributes must be expanded before calling. */ bool -fails_cfg (const AST::AttrVec &attrs) +CfgStrip::fails_cfg (const AST::AttrVec &attrs) const { auto &session = Session::get_instance (); @@ -39,6 +40,9 @@ fails_cfg (const AST::AttrVec &attrs) if (attr.get_path () == Values::Attributes::CFG && !attr.check_cfg_predicate (session)) return true; + else if (!expansion_cfg.should_test + && attr.get_path () == Values::Attributes::TEST) + return true; } return false; } @@ -48,7 +52,7 @@ fails_cfg (const AST::AttrVec &attrs) * should be stripped. Will expand attributes as well. */ bool -fails_cfg_with_expand (AST::AttrVec &attrs) +CfgStrip::fails_cfg_with_expand (AST::AttrVec &attrs) const { auto &session = Session::get_instance (); @@ -85,6 +89,9 @@ fails_cfg_with_expand (AST::AttrVec &attrs) attr.as_string ().c_str ()); } } + else if (!expansion_cfg.should_test + && attr.get_path () == Values::Attributes::TEST) + return true; } return false; } @@ -2062,38 +2069,6 @@ CfgStrip::visit (AST::StaticItem &static_item) } void -CfgStrip::visit (AST::TraitItemConst &item) -{ - // initial test based on outer attrs - expand_cfg_attrs (item.get_outer_attrs ()); - if (fails_cfg_with_expand (item.get_outer_attrs ())) - { - item.mark_for_strip (); - return; - } - - AST::DefaultASTVisitor::visit (item); - - // strip any sub-types - auto &type = item.get_type (); - - if (type.is_marked_for_strip ()) - rust_error_at (type.get_locus (), "cannot strip type in this position"); - - /* strip any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped */ - if (item.has_expression ()) - { - auto &expr = item.get_expr (); - if (expr.is_marked_for_strip ()) - rust_error_at (expr.get_locus (), - "cannot strip expression in this position - outer " - "attributes not allowed"); - } -} - -void CfgStrip::visit (AST::TraitItemType &item) { // initial test based on outer attrs @@ -2374,7 +2349,7 @@ CfgStrip::visit (AST::StructPattern &pattern) maybe_strip_pointer_allow_strip (elems.get_struct_pattern_fields ()); // assuming you can strip the ".." part - if (elems.has_etc ()) + if (elems.has_rest ()) { expand_cfg_attrs (elems.get_etc_outer_attrs ()); if (fails_cfg_with_expand (elems.get_etc_outer_attrs ())) @@ -2383,7 +2358,7 @@ CfgStrip::visit (AST::StructPattern &pattern) } void -CfgStrip::visit (AST::TupleStructItemsNoRange &tuple_items) +CfgStrip::visit (AST::TupleStructItemsNoRest &tuple_items) { AST::DefaultASTVisitor::visit (tuple_items); // can't strip individual patterns, only sub-patterns @@ -2396,7 +2371,7 @@ CfgStrip::visit (AST::TupleStructItemsNoRange &tuple_items) } } void -CfgStrip::visit (AST::TupleStructItemsRange &tuple_items) +CfgStrip::visit (AST::TupleStructItemsHasRest &tuple_items) { AST::DefaultASTVisitor::visit (tuple_items); // can't strip individual patterns, only sub-patterns @@ -2429,7 +2404,7 @@ CfgStrip::visit (AST::TupleStructPattern &pattern) } void -CfgStrip::visit (AST::TuplePatternItemsMultiple &tuple_items) +CfgStrip::visit (AST::TuplePatternItemsNoRest &tuple_items) { AST::DefaultASTVisitor::visit (tuple_items); @@ -2444,7 +2419,7 @@ CfgStrip::visit (AST::TuplePatternItemsMultiple &tuple_items) } void -CfgStrip::visit (AST::TuplePatternItemsRanged &tuple_items) +CfgStrip::visit (AST::TuplePatternItemsHasRest &tuple_items) { AST::DefaultASTVisitor::visit (tuple_items); diff --git a/gcc/rust/expand/rust-cfg-strip.h b/gcc/rust/expand/rust-cfg-strip.h index 767cf28..42cd266 100644 --- a/gcc/rust/expand/rust-cfg-strip.h +++ b/gcc/rust/expand/rust-cfg-strip.h @@ -23,14 +23,23 @@ #include "rust-item.h" namespace Rust { + +// forward declare +struct ExpansionCfg; + // Visitor used to maybe_strip attributes. class CfgStrip : public AST::DefaultASTVisitor { private: + bool fails_cfg (const AST::AttrVec &attrs) const; + + bool fails_cfg_with_expand (AST::AttrVec &attrs) const; + public: using DefaultASTVisitor::visit; - CfgStrip () {} + CfgStrip (const ExpansionCfg &expansion_cfg) : expansion_cfg (expansion_cfg) + {} /* Run the AttrVisitor on an entire crate */ void go (AST::Crate &crate); @@ -147,7 +156,6 @@ public: void visit (AST::Union &union_item) override; void visit (AST::ConstantItem &const_item) override; void visit (AST::StaticItem &static_item) override; - void visit (AST::TraitItemConst &item) override; void visit (AST::TraitItemType &item) override; void visit (AST::Trait &trait) override; void visit (AST::InherentImpl &impl) override; @@ -166,11 +174,11 @@ public: void visit (AST::StructPatternFieldIdentPat &field) override; void visit (AST::StructPatternFieldIdent &field) override; void visit (AST::StructPattern &pattern) override; - void visit (AST::TupleStructItemsNoRange &tuple_items) override; - void visit (AST::TupleStructItemsRange &tuple_items) override; + void visit (AST::TupleStructItemsNoRest &tuple_items) override; + void visit (AST::TupleStructItemsHasRest &tuple_items) override; void visit (AST::TupleStructPattern &pattern) override; - void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - void visit (AST::TuplePatternItemsRanged &tuple_items) override; + void visit (AST::TuplePatternItemsNoRest &tuple_items) override; + void visit (AST::TuplePatternItemsHasRest &tuple_items) override; void visit (AST::GroupedPattern &pattern) override; void visit (AST::SlicePatternItemsNoRest &items) override; void visit (AST::SlicePatternItemsHasRest &items) override; @@ -194,6 +202,9 @@ public: { DefaultASTVisitor::visit (item); } + +private: + const ExpansionCfg &expansion_cfg; }; } // namespace Rust diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc index 321fa00..27dcc66 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -64,11 +64,10 @@ DeriveClone::clone_fn (std::unique_ptr<Expr> &&clone_expr) new BlockExpr ({}, std::move (clone_expr), {}, {}, tl::nullopt, loc, loc)); auto big_self_type = builder.single_type_path ("Self"); - std::unique_ptr<SelfParam> self (new SelfParam (tl::nullopt, - /* is_mut */ false, loc)); - std::vector<std::unique_ptr<Param>> params; - params.push_back (std::move (self)); + + params.emplace_back (new SelfParam (tl::nullopt, + /* is_mut */ false, loc)); return std::unique_ptr<AssociatedItem> ( new Function ({"clone"}, builder.fn_qualifiers (), /* generics */ {}, @@ -211,7 +210,7 @@ DeriveClone::clone_enum_tuple (PathInExpression variant_path, } auto pattern_items = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (patterns))); + new TupleStructItemsNoRest (std::move (patterns))); auto pattern = std::unique_ptr<Pattern> (new ReferencePattern ( std::unique_ptr<Pattern> (new TupleStructPattern ( diff --git a/gcc/rust/expand/rust-derive-cmp-common.cc b/gcc/rust/expand/rust-derive-cmp-common.cc index 22ca16f..9890bb7 100644 --- a/gcc/rust/expand/rust-derive-cmp-common.cc +++ b/gcc/rust/expand/rust-derive-cmp-common.cc @@ -101,9 +101,9 @@ EnumMatchBuilder::tuple (EnumItem &variant_raw) auto other_variant_path = builder.variant_path (enum_path, variant_path); auto self_pattern_items = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (self_patterns))); + new TupleStructItemsNoRest (std::move (self_patterns))); auto other_pattern_items = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (other_patterns))); + new TupleStructItemsNoRest (std::move (other_patterns))); auto self_pattern = std::unique_ptr<Pattern> ( new ReferencePattern (std::unique_ptr<Pattern> (new TupleStructPattern ( @@ -114,7 +114,7 @@ EnumMatchBuilder::tuple (EnumItem &variant_raw) other_variant_path, std::move (other_pattern_items))), false, false, builder.loc)); - auto tuple_items = std::make_unique<TuplePatternItemsMultiple> ( + auto tuple_items = std::make_unique<TuplePatternItemsNoRest> ( vec (std::move (self_pattern), std::move (other_pattern))); auto pattern @@ -176,7 +176,7 @@ EnumMatchBuilder::strukt (EnumItem &variant_raw) std::move (other_elts))), false, false, builder.loc)); - auto tuple_items = std::make_unique<TuplePatternItemsMultiple> ( + auto tuple_items = std::make_unique<TuplePatternItemsNoRest> ( vec (std::move (self_pattern), std::move (other_pattern))); auto pattern diff --git a/gcc/rust/expand/rust-derive-eq.cc b/gcc/rust/expand/rust-derive-eq.cc index 7da137f..17332a4 100644 --- a/gcc/rust/expand/rust-derive-eq.cc +++ b/gcc/rust/expand/rust-derive-eq.cc @@ -128,9 +128,13 @@ DeriveEq::eq_impls ( auto eq_impl = builder.trait_impl (eq, std::move (eq_generics.self_type), std::move (trait_items), std::move (eq_generics.impl)); + + // StructuralEq is a marker trait + decltype (trait_items) steq_trait_items = {}; + auto steq_impl = builder.trait_impl (steq, std::move (steq_generics.self_type), - std::move (trait_items), + std::move (steq_trait_items), std::move (steq_generics.impl)); return vec (std::move (eq_impl), std::move (steq_impl)); diff --git a/gcc/rust/expand/rust-derive-hash.cc b/gcc/rust/expand/rust-derive-hash.cc index 94aede2..616bfdb 100644 --- a/gcc/rust/expand/rust-derive-hash.cc +++ b/gcc/rust/expand/rust-derive-hash.cc @@ -151,7 +151,7 @@ DeriveHash::match_enum_tuple (PathInExpression variant_path, } auto patterns_elts = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (self_patterns))); + new TupleStructItemsNoRest (std::move (self_patterns))); auto pattern = std::unique_ptr<Pattern> ( new ReferencePattern (std::unique_ptr<Pattern> (new TupleStructPattern ( variant_path, std::move (patterns_elts))), diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc index afc4b71..6f3981f 100644 --- a/gcc/rust/expand/rust-derive-ord.cc +++ b/gcc/rust/expand/rust-derive-ord.cc @@ -120,7 +120,7 @@ DeriveOrd::make_equal () if (ordering == Ordering::Partial) { auto pattern_items = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (vec (std::move (equal)))); + new TupleStructItemsNoRest (vec (std::move (equal)))); equal = std::make_unique<TupleStructPattern> (builder.path_in_expression ( diff --git a/gcc/rust/expand/rust-derive-partial-eq.cc b/gcc/rust/expand/rust-derive-partial-eq.cc index a0bf87a..287d8a7 100644 --- a/gcc/rust/expand/rust-derive-partial-eq.cc +++ b/gcc/rust/expand/rust-derive-partial-eq.cc @@ -146,7 +146,7 @@ DerivePartialEq::match_enum_identifier ( builder.ref_pattern ( std::unique_ptr<Pattern> (new PathInExpression (variant_path)))); - auto tuple_items = std::make_unique<TuplePatternItemsMultiple> ( + auto tuple_items = std::make_unique<TuplePatternItemsNoRest> ( std::move (inner_ref_patterns)); auto pattern = std::make_unique<TuplePattern> (std::move (tuple_items), loc); @@ -186,9 +186,9 @@ DerivePartialEq::match_enum_tuple (PathInExpression variant_path, } auto self_pattern_items = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (self_patterns))); + new TupleStructItemsNoRest (std::move (self_patterns))); auto other_pattern_items = std::unique_ptr<TupleStructItems> ( - new TupleStructItemsNoRange (std::move (other_patterns))); + new TupleStructItemsNoRest (std::move (other_patterns))); auto self_pattern = std::unique_ptr<Pattern> ( new ReferencePattern (std::unique_ptr<Pattern> (new TupleStructPattern ( @@ -199,7 +199,7 @@ DerivePartialEq::match_enum_tuple (PathInExpression variant_path, variant_path, std::move (other_pattern_items))), false, false, loc)); - auto tuple_items = std::make_unique<TuplePatternItemsMultiple> ( + auto tuple_items = std::make_unique<TuplePatternItemsNoRest> ( vec (std::move (self_pattern), std::move (other_pattern))); auto pattern = std::make_unique<TuplePattern> (std::move (tuple_items), loc); @@ -254,7 +254,7 @@ DerivePartialEq::match_enum_struct (PathInExpression variant_path, variant_path, loc, std::move (other_elts))), false, false, loc)); - auto tuple_items = std::make_unique<TuplePatternItemsMultiple> ( + auto tuple_items = std::make_unique<TuplePatternItemsNoRest> ( vec (std::move (self_pattern), std::move (other_pattern))); auto pattern = std::make_unique<TuplePattern> (std::move (tuple_items), loc); diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h index 10c146c..d28bba9 100644 --- a/gcc/rust/expand/rust-derive.h +++ b/gcc/rust/expand/rust-derive.h @@ -192,7 +192,6 @@ private: virtual void visit (EnumItemDiscriminant &item) override final{}; virtual void visit (ConstantItem &const_item) override final{}; virtual void visit (StaticItem &static_item) override final{}; - virtual void visit (TraitItemConst &item) override final{}; virtual void visit (TraitItemType &item) override final{}; virtual void visit (Trait &trait) override final{}; virtual void visit (InherentImpl &impl) override final{}; @@ -224,11 +223,11 @@ private: virtual void visit (StructPatternFieldIdentPat &field) override final{}; virtual void visit (StructPatternFieldIdent &field) override final{}; virtual void visit (StructPattern &pattern) override final{}; - virtual void visit (TupleStructItemsNoRange &tuple_items) override final{}; - virtual void visit (TupleStructItemsRange &tuple_items) override final{}; + virtual void visit (TupleStructItemsNoRest &tuple_items) override final{}; + virtual void visit (TupleStructItemsHasRest &tuple_items) override final{}; virtual void visit (TupleStructPattern &pattern) override final{}; - virtual void visit (TuplePatternItemsMultiple &tuple_items) override final{}; - virtual void visit (TuplePatternItemsRanged &tuple_items) override final{}; + virtual void visit (TuplePatternItemsNoRest &tuple_items) override final{}; + virtual void visit (TuplePatternItemsHasRest &tuple_items) override final{}; virtual void visit (TuplePattern &pattern) override final{}; virtual void visit (GroupedPattern &pattern) override final{}; virtual void visit (SlicePatternItemsNoRest &items) override final{}; @@ -262,4 +261,4 @@ private: } // namespace AST } // namespace Rust -#endif // DERIVE_VISITOR_H +#endif // DERIVE_VISITOR_H
\ No newline at end of file diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index 8f6e7fa..4593cc3 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -18,6 +18,7 @@ #include "rust-expand-visitor.h" #include "rust-ast-fragment.h" +#include "rust-item.h" #include "rust-proc-macro.h" #include "rust-attributes.h" #include "rust-ast.h" @@ -62,7 +63,7 @@ derive_item (AST::Item &item, AST::SimplePath &to_derive, { switch (node.get_kind ()) { - case AST::SingleASTNode::ITEM: + case AST::SingleASTNode::Kind::Item: result.push_back (node.take_item ()); break; default: @@ -85,7 +86,7 @@ expand_item_attribute (AST::Item &item, AST::SimplePath &name, { switch (node.get_kind ()) { - case AST::SingleASTNode::ITEM: + case AST::SingleASTNode::Kind::Item: result.push_back (node.take_item ()); break; default: @@ -114,7 +115,7 @@ expand_stmt_attribute (T &statement, AST::SimplePath &attribute, { switch (node.get_kind ()) { - case AST::SingleASTNode::STMT: + case AST::SingleASTNode::Kind::Stmt: result.push_back (node.take_stmt ()); break; default: @@ -329,10 +330,15 @@ ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr) void ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr) { + NodeId old_expect = expr->get_node_id (); + std::swap (macro_invoc_expect_id, old_expect); + expander.push_context (MacroExpander::ContextType::EXPR); expr->accept_vis (*this); expander.pop_context (); + std::swap (macro_invoc_expect_id, old_expect); + auto final_fragment = expander.take_expanded_fragment (); if (final_fragment.should_expand () && final_fragment.is_expression_fragment ()) @@ -342,14 +348,54 @@ ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr) void ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type) { - expander.push_context (MacroExpander::ContextType::TYPE); + NodeId old_expect = type->get_node_id (); + std::swap (macro_invoc_expect_id, old_expect); + expander.push_context (MacroExpander::ContextType::TYPE); type->accept_vis (*this); + expander.pop_context (); + + std::swap (macro_invoc_expect_id, old_expect); + auto final_fragment = expander.take_expanded_fragment (); if (final_fragment.should_expand () && final_fragment.is_type_fragment ()) type = final_fragment.take_type_fragment (); +} + +// HACK: maybe we shouldn't have TypeNoBounds as a base class +void +ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type) +{ + NodeId old_expect = type->get_node_id (); + std::swap (macro_invoc_expect_id, old_expect); + expander.push_context (MacroExpander::ContextType::TYPE); + type->accept_vis (*this); expander.pop_context (); + + std::swap (macro_invoc_expect_id, old_expect); + + auto final_fragment = expander.take_expanded_fragment (); + if (final_fragment.should_expand () && final_fragment.is_type_fragment ()) + type = std::make_unique<AST::ParenthesisedType> ( + final_fragment.take_type_fragment (), BUILTINS_LOCATION); +} + +void +ExpandVisitor::maybe_expand_pattern (std::unique_ptr<AST::Pattern> &pattern) +{ + NodeId old_expect = pattern->get_node_id (); + std::swap (macro_invoc_expect_id, old_expect); + + expander.push_context (MacroExpander::ContextType::PATTERN); + pattern->accept_vis (*this); + expander.pop_context (); + + std::swap (macro_invoc_expect_id, old_expect); + + auto final_fragment = expander.take_expanded_fragment (); + if (final_fragment.should_expand () && final_fragment.is_pattern_fragment ()) + pattern = final_fragment.take_pattern_fragment (); } // FIXME: Can this be refactored into a `scoped` method? Which takes a @@ -424,6 +470,8 @@ ExpandVisitor::expand_closure_params (std::vector<AST::ClosureParam> ¶ms) { for (auto ¶m : params) { + maybe_expand_pattern (param.get_pattern_ptr ()); + if (param.has_type_given ()) maybe_expand_type (param.get_type_ptr ()); } @@ -465,6 +513,14 @@ ExpandVisitor::visit (AST::ConstGenericParam &) void ExpandVisitor::visit (AST::MacroInvocation ¯o_invoc) { + if (macro_invoc_expect_id != macro_invoc.get_node_id ()) + { + rust_internal_error_at ( + macro_invoc.get_locus (), + "attempting to expand node with id %d into position with node id %d", + (int) macro_invoc.get_node_id (), (int) macro_invoc_expect_id); + } + // TODO: Can we do the AST fragment replacing here? Probably not, right? expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon () ? AST::InvocKind::Semicoloned @@ -542,12 +598,6 @@ ExpandVisitor::visit (AST::MetaItemPathExpr &) {} void -ExpandVisitor::visit (AST::ErrorPropagationExpr &expr) -{ - visit (expr.get_propagating_expr ()); -} - -void ExpandVisitor::visit (AST::ArithmeticOrLogicalExpr &expr) { maybe_expand_expr (expr.get_left_expr_ptr ()); @@ -569,6 +619,13 @@ ExpandVisitor::visit (AST::LazyBooleanExpr &expr) } void +ExpandVisitor::visit (AST::TypeCastExpr &expr) +{ + maybe_expand_expr (expr.get_casted_expr_ptr ()); + maybe_expand_type (expr.get_type_to_cast_to_ptr ()); +} + +void ExpandVisitor::visit (AST::AssignmentExpr &expr) { maybe_expand_expr (expr.get_left_expr_ptr ()); @@ -602,20 +659,11 @@ ExpandVisitor::visit (AST::CallExpr &expr) } void -ExpandVisitor::visit (AST::MethodCallExpr &expr) -{ - visit (expr.get_receiver_expr ()); - - for (auto ¶m : expr.get_params ()) - maybe_expand_expr (param); -} - -void ExpandVisitor::visit (AST::ClosureExprInner &expr) { expand_closure_params (expr.get_params ()); - visit (expr.get_definition_expr ()); + maybe_expand_expr (expr.get_definition_expr_ptr ()); } void @@ -677,22 +725,10 @@ ExpandVisitor::visit (AST::IfLetExprConseqElse &expr) } void -ExpandVisitor::visit (AST::MatchExpr &expr) +ExpandVisitor::visit (AST::TupleExpr &expr) { - visit (expr.get_scrutinee_expr ()); - - for (auto &match_case : expr.get_match_cases ()) - { - auto &arm = match_case.get_arm (); - - for (auto &pattern : arm.get_patterns ()) - visit (pattern); - - if (arm.has_match_arm_guard ()) - maybe_expand_expr (arm.get_guard_expr_ptr ()); - - maybe_expand_expr (match_case.get_expr_ptr ()); - } + for (auto &sub : expr.get_tuple_elems ()) + maybe_expand_expr (sub); } void @@ -838,15 +874,6 @@ ExpandVisitor::visit (AST::StaticItem &static_item) } void -ExpandVisitor::visit (AST::TraitItemConst &const_item) -{ - maybe_expand_type (const_item.get_type_ptr ()); - - if (const_item.has_expr ()) - maybe_expand_expr (const_item.get_expr_ptr ()); -} - -void ExpandVisitor::visit (AST::Trait &trait) { for (auto &generic : trait.get_generic_params ()) @@ -970,13 +997,70 @@ ExpandVisitor::visit (AST::StructPatternFieldIdent &field) void ExpandVisitor::visit (AST::GroupedPattern &pattern) { - visit (pattern.get_pattern_in_parens ()); + maybe_expand_pattern (pattern.get_pattern_in_parens_ptr ()); +} + +void +ExpandVisitor::visit (AST::SlicePatternItemsNoRest &items) +{ + for (auto &sub : items.get_patterns ()) + maybe_expand_pattern (sub); +} + +void +ExpandVisitor::visit (AST::SlicePatternItemsHasRest &items) +{ + for (auto &sub : items.get_lower_patterns ()) + maybe_expand_pattern (sub); + for (auto &sub : items.get_upper_patterns ()) + maybe_expand_pattern (sub); +} + +void +ExpandVisitor::visit (AST::AltPattern &pattern) +{ + for (auto &alt : pattern.get_alts ()) + maybe_expand_pattern (alt); +} + +void +ExpandVisitor::visit (AST::TupleStructItemsNoRest &tuple_items) +{ + for (auto &sub : tuple_items.get_patterns ()) + maybe_expand_pattern (sub); +} + +void +ExpandVisitor::visit (AST::TupleStructItemsHasRest &tuple_items) +{ + for (auto &sub : tuple_items.get_lower_patterns ()) + maybe_expand_pattern (sub); + + for (auto &sub : tuple_items.get_upper_patterns ()) + maybe_expand_pattern (sub); +} + +void +ExpandVisitor::visit (AST::TuplePatternItemsNoRest &tuple_items) +{ + for (auto &sub : tuple_items.get_patterns ()) + maybe_expand_pattern (sub); +} + +void +ExpandVisitor::visit (AST::TuplePatternItemsHasRest &tuple_items) +{ + for (auto &sub : tuple_items.get_lower_patterns ()) + maybe_expand_pattern (sub); + + for (auto &sub : tuple_items.get_upper_patterns ()) + maybe_expand_pattern (sub); } void ExpandVisitor::visit (AST::LetStmt &stmt) { - visit (stmt.get_pattern ()); + maybe_expand_pattern (stmt.get_pattern_ptr ()); if (stmt.has_type ()) maybe_expand_type (stmt.get_type_ptr ()); @@ -1006,10 +1090,18 @@ ExpandVisitor::visit (AST::BareFunctionType &type) void ExpandVisitor::visit (AST::FunctionParam ¶m) { + maybe_expand_pattern (param.get_pattern_ptr ()); maybe_expand_type (param.get_type_ptr ()); } void +ExpandVisitor::visit (AST::VariadicParam ¶m) +{ + if (param.has_pattern ()) + maybe_expand_pattern (param.get_pattern_ptr ()); +} + +void ExpandVisitor::visit (AST::SelfParam ¶m) { /* TODO: maybe check for invariants being violated - e.g. both type and diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h index 845e10c..b79eb66 100644 --- a/gcc/rust/expand/rust-expand-visitor.h +++ b/gcc/rust/expand/rust-expand-visitor.h @@ -19,7 +19,9 @@ #ifndef RUST_EXPAND_VISITOR_H #define RUST_EXPAND_VISITOR_H +#include "rust-ast-pointer-visitor.h" #include "rust-ast-visitor.h" +#include "rust-item.h" #include "rust-macro-expand.h" #include "rust-proc-macro.h" @@ -35,27 +37,48 @@ bool is_derive (AST::Attribute &attr); */ bool is_builtin (AST::Attribute &attr); -class ExpandVisitor : public AST::DefaultASTVisitor +class ExpandVisitor : public AST::PointerVisitor { public: - ExpandVisitor (MacroExpander &expander) : expander (expander) {} + ExpandVisitor (MacroExpander &expander) + : expander (expander), macro_invoc_expect_id (UNKNOWN_NODEID) + {} /* Expand all of the macro invocations currently contained in a crate */ void go (AST::Crate &crate); - using AST::DefaultASTVisitor::visit; + using AST::PointerVisitor::reseat; + using AST::PointerVisitor::visit; - /* - Maybe expand a macro invocation in lieu of an expression - expr : Core guidelines R33, this function reseat the pointer. - */ - void maybe_expand_expr (std::unique_ptr<AST::Expr> &expr); + void reseat (std::unique_ptr<AST::Expr> &ptr) override + { + maybe_expand_expr (ptr); + } - /* - Maybe expand a macro invocation in lieu of a type - type : Core guidelines R33, this function reseat the pointer. + void reseat (std::unique_ptr<AST::Type> &ptr) override + { + maybe_expand_type (ptr); + } + + void reseat (std::unique_ptr<AST::TypeNoBounds> &ptr) override + { + maybe_expand_type (ptr); + } + + void reseat (std::unique_ptr<AST::Pattern> &ptr) override + { + maybe_expand_pattern (ptr); + } + + /** + * Maybe expand a macro invocation in lieu of an expression, type or pattern. + * + * @ptr Core guidelines R33, this function reseats the pointer. */ - void maybe_expand_type (std::unique_ptr<AST::Type> &type); + void maybe_expand_expr (std::unique_ptr<AST::Expr> &ptr); + void maybe_expand_type (std::unique_ptr<AST::Type> &ptr); + void maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type); + void maybe_expand_pattern (std::unique_ptr<AST::Pattern> &ptr); /** * Expand all macro invocations in lieu of types within a vector of struct @@ -128,7 +151,10 @@ public: auto &value = *it; // Perform expansion + NodeId old_expect = value->get_node_id (); + std::swap (macro_invoc_expect_id, old_expect); value->accept_vis (*this); + std::swap (macro_invoc_expect_id, old_expect); auto final_fragment = expander.take_expanded_fragment (); @@ -210,17 +236,16 @@ public: void visit (AST::AttrInputMacro &) override; void visit (AST::MetaItemLitExpr &) override; void visit (AST::MetaItemPathExpr &) override; - void visit (AST::ErrorPropagationExpr &expr) override; void visit (AST::ArithmeticOrLogicalExpr &expr) override; void visit (AST::ComparisonExpr &expr) override; void visit (AST::LazyBooleanExpr &expr) override; + void visit (AST::TypeCastExpr &expr) override; void visit (AST::AssignmentExpr &expr) override; void visit (AST::CompoundAssignmentExpr &expr) override; void visit (AST::GroupedExpr &expr) override; void visit (AST::StructExprStruct &expr) override; void visit (AST::CallExpr &expr) override; - void visit (AST::MethodCallExpr &expr) override; void visit (AST::ClosureExprInner &expr) override; void visit (AST::BlockExpr &expr) override; @@ -231,7 +256,7 @@ public: void visit (AST::IfExprConseqElse &expr) override; void visit (AST::IfLetExpr &expr) override; void visit (AST::IfLetExprConseqElse &expr) override; - void visit (AST::MatchExpr &expr) override; + void visit (AST::TupleExpr &expr) override; void visit (AST::TypeParam ¶m) override; void visit (AST::LifetimeWhereClauseItem &) override; void visit (AST::TypeBoundWhereClauseItem &item) override; @@ -251,7 +276,6 @@ public: void visit (AST::Union &union_item) override; void visit (AST::ConstantItem &const_item) override; void visit (AST::StaticItem &static_item) override; - void visit (AST::TraitItemConst &item) override; void visit (AST::Trait &trait) override; void visit (AST::InherentImpl &impl) override; void visit (AST::TraitImpl &impl) override; @@ -269,12 +293,20 @@ public: void visit (AST::MetaListNameValueStr &) override; void visit (AST::StructPatternFieldIdent &field) override; void visit (AST::GroupedPattern &pattern) override; + void visit (AST::SlicePatternItemsNoRest &items) override; + void visit (AST::SlicePatternItemsHasRest &items) override; + void visit (AST::AltPattern &pattern) override; + void visit (AST::TupleStructItemsNoRest &tuple_items) override; + void visit (AST::TupleStructItemsHasRest &tuple_items) override; + void visit (AST::TuplePatternItemsNoRest &tuple_items) override; + void visit (AST::TuplePatternItemsHasRest &tuple_items) override; void visit (AST::LetStmt &stmt) override; void visit (AST::ExprStmt &stmt) override; void visit (AST::BareFunctionType &type) override; - void visit (AST::FunctionParam &type) override; + void visit (AST::FunctionParam ¶m) override; + void visit (AST::VariadicParam ¶m) override; void visit (AST::SelfParam &type) override; template <typename T> @@ -287,6 +319,7 @@ public: private: MacroExpander &expander; + NodeId macro_invoc_expect_id; }; } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc index 61222db..c991ca7 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.cc +++ b/gcc/rust/expand/rust-macro-builtins-asm.cc @@ -101,7 +101,7 @@ parse_clobber_abi (InlineAsmContext inline_asm_ctx) if (token->get_id () == STRING_LITERAL) { // TODO: Caring for span in here. - new_abis.push_back ({token->as_string (), token->get_locus ()}); + new_abis.emplace_back (token->as_string (), token->get_locus ()); } else { @@ -787,12 +787,12 @@ expand_inline_asm_strings (InlineAsmContext inline_asm_ctx) auto pieces = Fmt::Pieces::collect (template_str.symbol, false, Fmt::ffi::ParseMode::InlineAsm); - auto pieces_vec = pieces.get_pieces (); + auto &pieces_vec = pieces.get_pieces (); std::string transformed_template_str = ""; for (size_t i = 0; i < pieces_vec.size (); i++) { - auto piece = pieces_vec[i]; + auto &piece = pieces_vec[i]; if (piece.tag == Fmt::ffi::Piece::Tag::String) { transformed_template_str += piece.string._0.to_string (); @@ -880,7 +880,8 @@ parse_asm (location_t invoc_locus, AST::MacroInvocData &invoc, // context. if (resulting_context) { - auto node = (*resulting_context).inline_asm.clone_expr_without_block (); + auto resulting_ctx = resulting_context.value (); + auto node = resulting_ctx.inline_asm.clone_expr_without_block (); std::vector<AST::SingleASTNode> single_vec = {}; @@ -1124,8 +1125,11 @@ parse_llvm_clobbers (LlvmAsmContext &ctx) { ctx.llvm_asm.get_clobbers ().push_back ( {strip_double_quotes (token->as_string ()), token->get_locus ()}); + + parser.skip_token (STRING_LITERAL); } - parser.skip_token (STRING_LITERAL); + + parser.maybe_skip_token (COMMA); token = parser.peek_current_token (); } } @@ -1177,12 +1181,13 @@ parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc, auto asm_ctx = LlvmAsmContext (llvm_asm, parser, last_token_id); - auto resulting_context + tl::optional<LlvmAsmContext> resulting_context = parse_llvm_templates (asm_ctx).and_then (parse_llvm_arguments); if (resulting_context) { - auto node = (*resulting_context).llvm_asm.clone_expr_without_block (); + auto resulting_ctx = resulting_context.value (); + auto node = resulting_ctx.llvm_asm.clone_expr_without_block (); std::vector<AST::SingleASTNode> single_vec = {}; @@ -1190,12 +1195,13 @@ parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc, // need to make it a statement. This way, it will be expanded // properly. if (semicolon == AST::InvocKind::Semicoloned) - single_vec.emplace_back (AST::SingleASTNode ( - std::make_unique<AST::ExprStmt> (std::move (node), invoc_locus, - semicolon - == AST::InvocKind::Semicoloned))); + { + single_vec.emplace_back ( + std::make_unique<AST::ExprStmt> (std::move (node), invoc_locus, + true /* has semicolon */)); + } else - single_vec.emplace_back (AST::SingleASTNode (std::move (node))); + single_vec.emplace_back (std::move (node)); AST::Fragment fragment_ast = AST::Fragment (single_vec, diff --git a/gcc/rust/expand/rust-macro-builtins-format-args.cc b/gcc/rust/expand/rust-macro-builtins-format-args.cc index b20c849..eb2a1cc 100644 --- a/gcc/rust/expand/rust-macro-builtins-format-args.cc +++ b/gcc/rust/expand/rust-macro-builtins-format-args.cc @@ -37,39 +37,42 @@ struct FormatArgsParseError } kind; }; -static tl::expected<FormatArgsInput, FormatArgsParseError> -format_args_parse_arguments (AST::MacroInvocData &invoc) +static inline tl::expected<std::string, AST::Fragment> +format_args_parse_expr (location_t invoc_locus, AST::MacroInvocData &invoc, + Parser<MacroInvocLexer> &parser, + BuiltinMacro macro_kind) { - MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ()); - Parser<MacroInvocLexer> parser (lex); - - // TODO: check if EOF - return that format_args!() requires at least one - // argument - - auto args = AST::FormatArguments (); - auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser); - std::unique_ptr<AST::Expr> format_expr = nullptr; + std::unique_ptr<AST::Expr> format_expr = parser.parse_expr (); + rust_assert (format_expr); - // TODO: Handle the case where we're not parsing a string literal (macro - // invocation for e.g.) - switch (parser.peek_current_token ()->get_id ()) + if (format_expr->get_expr_kind () == AST::Expr::Kind::MacroInvocation) { - case STRING_LITERAL: - case RAW_STRING_LITERAL: - format_expr = parser.parse_literal_expr (); - default: - // do nothing - ; + std::vector<std::unique_ptr<AST::MacroInvocation>> pending; + pending.emplace_back ( + static_cast<AST::MacroInvocation *> (format_expr.release ())); + return tl::unexpected<AST::Fragment> ( + make_eager_builtin_invocation (macro_kind, invoc_locus, + invoc.get_delim_tok_tree (), + std::move (pending))); } - rust_assert (format_expr); - // TODO(Arthur): Clean this up - if we haven't parsed a string literal but a // macro invocation, what do we do here? return a tl::unexpected? - auto format_str = static_cast<AST::LiteralExpr &> (*format_expr) - .get_literal () - .as_string (); + rust_assert (format_expr->is_literal ()); + return static_cast<AST::LiteralExpr &> (*format_expr) + .get_literal () + .as_string (); +} + +static inline tl::expected<AST::FormatArguments, FormatArgsParseError> +format_args_parse_arguments (AST::MacroInvocData &invoc, + Parser<MacroInvocLexer> &parser, + TokenId last_token_id) +{ + // TODO: check if EOF - return that format_args!() requires at least one + // argument + auto args = AST::FormatArguments (); // TODO: Allow implicit captures ONLY if the the first arg is a string literal // and not a macro invocation @@ -126,7 +129,7 @@ format_args_parse_arguments (AST::MacroInvocData &invoc) // we need to skip commas, don't we? } - return FormatArgsInput{std::move (format_str), std::move (args)}; + return args; } tl::optional<AST::Fragment> @@ -135,9 +138,24 @@ MacroBuiltin::format_args_handler (location_t invoc_locus, AST::InvocKind semicolon, AST::FormatArgs::Newline nl) { - auto input = format_args_parse_arguments (invoc); + MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ()); + Parser<MacroInvocLexer> parser (lex); + + auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser); + + auto format_str = format_args_parse_expr (invoc_locus, invoc, parser, + nl == AST::FormatArgs::Newline::Yes + ? BuiltinMacro::FormatArgsNl + : BuiltinMacro::FormatArgs); + + if (!format_str) + { + return std::move (format_str.error ()); + } + + auto args = format_args_parse_arguments (invoc, parser, last_token_id); - if (!input) + if (!args) { rust_error_at (invoc_locus, "could not parse arguments to %<format_args!()%>"); @@ -173,7 +191,7 @@ MacroBuiltin::format_args_handler (location_t invoc_locus, bool append_newline = nl == AST::FormatArgs::Newline::Yes; - auto fmt_str = std::move (input->format_str); + auto fmt_str = std::move (format_str.value ()); if (append_newline) fmt_str += '\n'; @@ -189,7 +207,7 @@ MacroBuiltin::format_args_handler (location_t invoc_locus, // for creating the `template` auto fmt_args_node = AST::FormatArgs (invoc_locus, std::move (pieces), - std::move (input->args)); + std::move (args.value ())); auto expanded = Fmt::expand_format_args (fmt_args_node, diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.h b/gcc/rust/expand/rust-macro-builtins-helpers.h index 32cf58f..ce63017 100644 --- a/gcc/rust/expand/rust-macro-builtins-helpers.h +++ b/gcc/rust/expand/rust-macro-builtins-helpers.h @@ -22,7 +22,6 @@ #include "rust-ast.h" #include "rust-cfg-strip.h" #include "rust-diagnostics.h" -#include "rust-early-name-resolver.h" #include "rust-expr.h" #include "rust-lex.h" #include "rust-macro-builtins.h" diff --git a/gcc/rust/expand/rust-macro-builtins-offset-of.cc b/gcc/rust/expand/rust-macro-builtins-offset-of.cc index 53efe74..02c637b 100644 --- a/gcc/rust/expand/rust-macro-builtins-offset-of.cc +++ b/gcc/rust/expand/rust-macro-builtins-offset-of.cc @@ -56,7 +56,7 @@ MacroBuiltin::offset_of_handler (location_t invoc_locus, parser.skip_token (COMMA); auto field_tok = parser.parse_identifier_or_keyword_token (); - auto invalid_field = !field_tok || !field_tok->has_str (); + auto invalid_field = !field_tok || !field_tok->should_have_str (); if (invalid_field) rust_error_at (invoc_locus, "could not parse field argument for %qs", diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc index a7ae220..948f389 100644 --- a/gcc/rust/expand/rust-macro-builtins.cc +++ b/gcc/rust/expand/rust-macro-builtins.cc @@ -29,7 +29,6 @@ #include "rust-ast.h" #include "rust-cfg-strip.h" #include "rust-diagnostics.h" -#include "rust-early-name-resolver.h" #include "rust-expr.h" #include "rust-lex.h" #include "rust-macro-invoc-lexer.h" diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 4c54cef..52f8e2b 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -27,7 +27,6 @@ #include "rust-macro.h" #include "rust-parse.h" #include "rust-cfg-strip.h" -#include "rust-early-name-resolver.h" #include "rust-proc-macro.h" #include "rust-token-tree-desugar.h" @@ -961,9 +960,14 @@ transcribe_expression (Parser<MacroInvocLexer> &parser) auto &lexer = parser.get_token_source (); auto start = lexer.get_offs (); - auto expr = parser.parse_expr (); + auto attrs = parser.parse_outer_attributes (); + auto expr = parser.parse_expr (std::move (attrs)); if (expr == nullptr) - return AST::Fragment::create_error (); + { + for (auto error : parser.get_errors ()) + error.emit (); + return AST::Fragment::create_error (); + } // FIXME: make this an error for some edititons if (parser.peek_current_token ()->get_id () == SEMICOLON) @@ -999,6 +1003,27 @@ transcribe_type (Parser<MacroInvocLexer> &parser) return AST::Fragment ({std::move (type)}, lexer.get_token_slice (start, end)); } +/** + * Transcribe one pattern from a macro invocation + * + * @param parser Parser to extract statements from + */ +static AST::Fragment +transcribe_pattern (Parser<MacroInvocLexer> &parser) +{ + auto &lexer = parser.get_token_source (); + auto start = lexer.get_offs (); + + auto pattern = parser.parse_pattern (); + for (auto err : parser.get_errors ()) + err.emit (); + + auto end = lexer.get_offs (); + + return AST::Fragment ({std::move (pattern)}, + lexer.get_token_slice (start, end)); +} + static AST::Fragment transcribe_context (MacroExpander::ContextType ctx, Parser<MacroInvocLexer> &parser, bool semicolon, @@ -1011,6 +1036,7 @@ transcribe_context (MacroExpander::ContextType ctx, // -- Trait --> parser.parse_trait_item(); // -- Impl --> parser.parse_impl_item(); // -- Extern --> parser.parse_extern_item(); + // -- Pattern --> parser.parse_pattern(); // -- None --> [has semicolon?] // -- Yes --> parser.parse_stmt(); // -- No --> [switch invocation.delimiter()] @@ -1039,6 +1065,8 @@ transcribe_context (MacroExpander::ContextType ctx, break; case MacroExpander::ContextType::TYPE: return transcribe_type (parser); + case MacroExpander::ContextType::PATTERN: + return transcribe_pattern (parser); break; case MacroExpander::ContextType::STMT: return transcribe_many_stmts (parser, last_token_id, semicolon); @@ -1080,8 +1108,9 @@ MacroExpander::transcribe_rule ( auto invoc_stream = invoc_token_tree.to_token_stream (); auto macro_rule_tokens = transcribe_tree.to_token_stream (); - auto substitute_context = SubstituteCtx (invoc_stream, macro_rule_tokens, - matched_fragments, definition); + auto substitute_context + = SubstituteCtx (invoc_stream, macro_rule_tokens, matched_fragments, + definition, invoc_token_tree.get_locus ()); std::vector<std::unique_ptr<AST::Token>> substituted_tokens = substitute_context.substitute_tokens (); @@ -1128,11 +1157,7 @@ MacroExpander::transcribe_rule ( // emit any errors if (parser.has_errors ()) - { - for (auto &err : parser.get_errors ()) - rust_error_at (err.locus, "%s", err.message.c_str ()); - return AST::Fragment::create_error (); - } + return AST::Fragment::create_error (); // are all the tokens used? bool did_delimit = parser.skip_token (last_token_id); @@ -1165,7 +1190,7 @@ MacroExpander::parse_proc_macro_output (ProcMacro::TokenStream ts) auto result = parser.parse_item (false); if (result == nullptr) break; - nodes.push_back ({std::move (result)}); + nodes.emplace_back (std::move (result)); } break; case ContextType::STMT: @@ -1174,7 +1199,7 @@ MacroExpander::parse_proc_macro_output (ProcMacro::TokenStream ts) auto result = parser.parse_stmt (); if (result == nullptr) break; - nodes.push_back ({std::move (result)}); + nodes.emplace_back (std::move (result)); } break; case ContextType::TRAIT: diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index 360294c..c3d5e7d 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -27,7 +27,6 @@ #include "rust-ast.h" #include "rust-macro.h" #include "rust-hir-map.h" -#include "rust-early-name-resolver.h" #include "rust-name-resolver.h" #include "rust-macro-invoc-lexer.h" #include "rust-proc-macro-invoc-lexer.h" @@ -291,6 +290,7 @@ struct MacroExpander TRAIT, IMPL, TRAIT_IMPL, + PATTERN, }; ExpansionCfg cfg; diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc index ac36ed8..36bae5b 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.cc +++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc @@ -40,7 +40,7 @@ SubstituteCtx::substitute_dollar_crate ( if (*def_crate == current_crate) { expanded.push_back (std::make_unique<AST::Token> ( - Rust::Token::make_identifier (UNKNOWN_LOCATION, "crate"))); + Rust::Token::make_identifier (origin, "crate"))); } else { @@ -49,9 +49,9 @@ SubstituteCtx::substitute_dollar_crate ( rust_assert (name); expanded.push_back (std::make_unique<AST::Token> ( - Rust::Token::make (SCOPE_RESOLUTION, UNKNOWN_LOCATION))); + Rust::Token::make (SCOPE_RESOLUTION, origin))); expanded.push_back (std::make_unique<AST::Token> ( - Rust::Token::make_identifier (UNKNOWN_LOCATION, std::string (*name)))); + Rust::Token::make_identifier (origin, std::string (*name)))); } return true; @@ -108,6 +108,12 @@ SubstituteCtx::substitute_metavar ( return true; } +static bool +is_builtin_metavariable (AST::Token &token) +{ + return token.get_id () == CRATE; +} + bool SubstituteCtx::check_repetition_amount (size_t pattern_start, size_t pattern_end, @@ -125,6 +131,10 @@ SubstituteCtx::check_repetition_amount (size_t pattern_start, || frag_token->get_id () == IDENTIFIER) { auto it = fragments.find (frag_token->get_str ()); + + if (is_builtin_metavariable (*frag_token)) + continue; + if (it == fragments.end ()) { // If the repetition is not anything we know (ie no declared @@ -136,6 +146,7 @@ SubstituteCtx::check_repetition_amount (size_t pattern_start, frag_token->get_str ().c_str ()); is_valid = false; + continue; } auto &fragment = *it->second; @@ -226,7 +237,7 @@ SubstituteCtx::substitute_repetition ( } auto substitute_context - = SubstituteCtx (input, new_macro, sub_map, definition); + = SubstituteCtx (input, new_macro, sub_map, definition, origin); auto new_tokens = substitute_context.substitute_tokens (); // Skip the first repetition, but add the separator to the expanded diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.h b/gcc/rust/expand/rust-macro-substitute-ctx.h index c5c4956..3829a5a 100644 --- a/gcc/rust/expand/rust-macro-substitute-ctx.h +++ b/gcc/rust/expand/rust-macro-substitute-ctx.h @@ -27,6 +27,8 @@ class SubstituteCtx std::vector<std::unique_ptr<AST::Token>> ¯o; std::map<std::string, MatchedFragmentContainer *> &fragments; AST::MacroRulesDefinition &definition; + // Macro invocation location + location_t origin; /** * Find the repetition amount to use when expanding a repetition, and @@ -43,9 +45,9 @@ public: SubstituteCtx (std::vector<std::unique_ptr<AST::Token>> &input, std::vector<std::unique_ptr<AST::Token>> ¯o, std::map<std::string, MatchedFragmentContainer *> &fragments, - AST::MacroRulesDefinition &definition) + AST::MacroRulesDefinition &definition, location_t origin) : input (input), macro (macro), fragments (fragments), - definition (definition) + definition (definition), origin (origin) {} /** diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index b723f59..1c8e5b6 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -372,9 +372,6 @@ void ASTLoweringBase::visit (AST::StaticItem &) {} void -ASTLoweringBase::visit (AST::TraitItemConst &) -{} -void ASTLoweringBase::visit (AST::TraitItemType &) {} void @@ -473,20 +470,20 @@ ASTLoweringBase::visit (AST::StructPattern &) {} // void ASTLoweringBase::visit(TupleStructItemstuple_items) {} void -ASTLoweringBase::visit (AST::TupleStructItemsNoRange &) +ASTLoweringBase::visit (AST::TupleStructItemsNoRest &) {} void -ASTLoweringBase::visit (AST::TupleStructItemsRange &) +ASTLoweringBase::visit (AST::TupleStructItemsHasRest &) {} void ASTLoweringBase::visit (AST::TupleStructPattern &) {} // void ASTLoweringBase::visit(TuplePatternItemstuple_items) {} void -ASTLoweringBase::visit (AST::TuplePatternItemsMultiple &) +ASTLoweringBase::visit (AST::TuplePatternItemsNoRest &) {} void -ASTLoweringBase::visit (AST::TuplePatternItemsRanged &) +ASTLoweringBase::visit (AST::TuplePatternItemsHasRest &) {} void ASTLoweringBase::visit (AST::TuplePattern &) @@ -622,11 +619,10 @@ ASTLoweringBase::lower_generic_params ( std::vector<std::unique_ptr<AST::GenericParam>> ¶ms) { std::vector<std::unique_ptr<HIR::GenericParam>> lowered; + lowered.reserve (params.size ()); + for (auto &ast_param : params) - { - auto hir_param = ASTLowerGenericParam::translate (*ast_param); - lowered.push_back (std::unique_ptr<HIR::GenericParam> (hir_param)); - } + lowered.emplace_back (ASTLowerGenericParam::translate (*ast_param)); return lowered; } @@ -659,18 +655,16 @@ HIR::GenericArgs ASTLoweringBase::lower_generic_args (AST::GenericArgs &args) { std::vector<HIR::GenericArgsBinding> binding_args; + binding_args.reserve (args.get_binding_args ().size ()); + for (auto &binding : args.get_binding_args ()) - { - HIR::GenericArgsBinding b = lower_binding (binding); - binding_args.push_back (std::move (b)); - } + binding_args.emplace_back (lower_binding (binding)); std::vector<HIR::Lifetime> lifetime_args; + lifetime_args.reserve (args.get_lifetime_args ().size ()); + for (auto &lifetime : args.get_lifetime_args ()) - { - HIR::Lifetime l = lower_lifetime (lifetime); - lifetime_args.push_back (std::move (l)); - } + lifetime_args.emplace_back (lower_lifetime (lifetime)); std::vector<std::unique_ptr<HIR::Type>> type_args; std::vector<HIR::ConstGenericArg> const_args; @@ -681,16 +675,15 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args) { case AST::GenericArg::Kind::Type: { - auto type = ASTLoweringType::translate (arg.get_type ()); - type_args.emplace_back (std::unique_ptr<HIR::Type> (type)); + type_args.emplace_back ( + ASTLoweringType::translate (arg.get_type ())); break; } case AST::GenericArg::Kind::Const: { auto expr = ASTLoweringExpr::translate (arg.get_expression ()); - const_args.emplace_back ( - HIR::ConstGenericArg (std::unique_ptr<HIR::Expr> (expr), - expr->get_locus ())); + const_args.emplace_back (std::unique_ptr<HIR::Expr> (expr), + expr->get_locus ()); break; } default: @@ -850,9 +843,10 @@ void ASTLoweringBase::handle_lang_item_attribute (const ItemWrapper &item, const AST::Attribute &attr) { - auto &literal = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ()); - const auto &lang_item_type_str = literal.get_literal ().as_string (); - auto lang_item_type = LangItem::Parse (lang_item_type_str); + auto lang_item_type_str = Analysis::Attributes::extract_string_literal (attr); + rust_assert (lang_item_type_str.has_value ()); + + auto lang_item_type = LangItem::Parse (*lang_item_type_str); if (lang_item_type) mappings.insert_lang_item (*lang_item_type, @@ -877,41 +871,71 @@ ASTLoweringBase::attribute_handled_in_another_pass ( std::unique_ptr<HIR::TuplePatternItems> ASTLoweringBase::lower_tuple_pattern_multiple ( - AST::TuplePatternItemsMultiple &pattern) + AST::TuplePatternItemsNoRest &pattern) { std::vector<std::unique_ptr<HIR::Pattern>> patterns; + patterns.reserve (pattern.get_patterns ().size ()); + for (auto &p : pattern.get_patterns ()) - { - HIR::Pattern *translated = ASTLoweringPattern::translate (*p); - patterns.push_back (std::unique_ptr<HIR::Pattern> (translated)); - } + patterns.emplace_back (ASTLoweringPattern::translate (*p)); return std::unique_ptr<HIR::TuplePatternItems> ( - new HIR::TuplePatternItemsMultiple (std::move (patterns))); + new HIR::TuplePatternItemsNoRest (std::move (patterns))); } std::unique_ptr<TuplePatternItems> ASTLoweringBase::lower_tuple_pattern_ranged ( - AST::TuplePatternItemsRanged &pattern) + AST::TuplePatternItemsHasRest &pattern) { std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns; + lower_patterns.reserve (pattern.get_lower_patterns ().size ()); std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns; + upper_patterns.reserve (pattern.get_upper_patterns ().size ()); for (auto &p : pattern.get_lower_patterns ()) - { - HIR::Pattern *translated = ASTLoweringPattern::translate (*p); - lower_patterns.push_back (std::unique_ptr<HIR::Pattern> (translated)); - } + lower_patterns.emplace_back (ASTLoweringPattern::translate (*p)); for (auto &p : pattern.get_upper_patterns ()) - { - HIR::Pattern *translated = ASTLoweringPattern::translate (*p); - upper_patterns.push_back (std::unique_ptr<HIR::Pattern> (translated)); - } + upper_patterns.emplace_back (ASTLoweringPattern::translate (*p)); return std::unique_ptr<HIR::TuplePatternItems> ( - new HIR::TuplePatternItemsRanged (std::move (lower_patterns), - std::move (upper_patterns))); + new HIR::TuplePatternItemsHasRest (std::move (lower_patterns), + std::move (upper_patterns))); +} + +std::unique_ptr<HIR::SlicePatternItems> +ASTLoweringBase::lower_slice_pattern_no_rest ( + AST::SlicePatternItemsNoRest &pattern) +{ + std::vector<std::unique_ptr<HIR::Pattern>> patterns; + patterns.reserve (pattern.get_patterns ().size ()); + for (auto &p : pattern.get_patterns ()) + patterns.emplace_back (ASTLoweringPattern::translate (*p)); + + return std::unique_ptr<HIR::SlicePatternItems> ( + new HIR::SlicePatternItemsNoRest (std::move (patterns))); +} + +std::unique_ptr<HIR::SlicePatternItems> +ASTLoweringBase::lower_slice_pattern_has_rest ( + AST::SlicePatternItemsHasRest &pattern) +{ + std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns; + lower_patterns.reserve (pattern.get_lower_patterns ().size ()); + std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns; + upper_patterns.reserve (pattern.get_upper_patterns ().size ()); + + for (auto &p : pattern.get_lower_patterns ()) + lower_patterns.emplace_back ( + std::unique_ptr<HIR::Pattern> (ASTLoweringPattern::translate (*p))); + + for (auto &p : pattern.get_upper_patterns ()) + upper_patterns.emplace_back ( + std::unique_ptr<HIR::Pattern> (ASTLoweringPattern::translate (*p))); + + return std::unique_ptr<HIR::SlicePatternItems> ( + new HIR::SlicePatternItemsHasRest (std::move (lower_patterns), + std::move (upper_patterns))); } std::unique_ptr<HIR::RangePatternBound> @@ -1008,14 +1032,15 @@ ASTLoweringBase::lower_extern_block (AST::ExternBlock &extern_block) mappings.get_next_localdef_id (crate_num)); std::vector<std::unique_ptr<HIR::ExternalItem>> extern_items; + extern_items.reserve (extern_block.get_extern_items ().size ()); + for (auto &item : extern_block.get_extern_items ()) { if (item->is_marked_for_strip ()) continue; - HIR::ExternalItem *lowered - = ASTLoweringExternItem::translate (item.get (), mapping.get_hirid ()); - extern_items.push_back (std::unique_ptr<HIR::ExternalItem> (lowered)); + extern_items.emplace_back ( + ASTLoweringExternItem::translate (item.get (), mapping.get_hirid ())); } ABI abi = ABI::C; diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index e86aacb..933f77b 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -189,7 +189,6 @@ public: virtual void visit (AST::Union &union_item) override; virtual void visit (AST::ConstantItem &const_item) override; virtual void visit (AST::StaticItem &static_item) override; - virtual void visit (AST::TraitItemConst &item) override; virtual void visit (AST::TraitItemType &item) override; virtual void visit (AST::Trait &trait) override; virtual void visit (AST::InherentImpl &impl) override; @@ -228,12 +227,12 @@ public: virtual void visit (AST::StructPatternFieldIdent &field) override; virtual void visit (AST::StructPattern &pattern) override; // virtual void visit(TupleStructItems& tuple_items) override; - virtual void visit (AST::TupleStructItemsNoRange &tuple_items) override; - virtual void visit (AST::TupleStructItemsRange &tuple_items) override; + virtual void visit (AST::TupleStructItemsNoRest &tuple_items) override; + virtual void visit (AST::TupleStructItemsHasRest &tuple_items) override; virtual void visit (AST::TupleStructPattern &pattern) override; // virtual void visit(TuplePatternItems& tuple_items) override; - virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override; + virtual void visit (AST::TuplePatternItemsNoRest &tuple_items) override; + virtual void visit (AST::TuplePatternItemsHasRest &tuple_items) override; virtual void visit (AST::TuplePattern &pattern) override; virtual void visit (AST::GroupedPattern &pattern) override; virtual void visit (AST::SlicePatternItemsNoRest &items) override; @@ -317,10 +316,16 @@ protected: attribute_handled_in_another_pass (const std::string &attribute_path) const; std::unique_ptr<TuplePatternItems> - lower_tuple_pattern_multiple (AST::TuplePatternItemsMultiple &pattern); + lower_tuple_pattern_multiple (AST::TuplePatternItemsNoRest &pattern); std::unique_ptr<TuplePatternItems> - lower_tuple_pattern_ranged (AST::TuplePatternItemsRanged &pattern); + lower_tuple_pattern_ranged (AST::TuplePatternItemsHasRest &pattern); + + std::unique_ptr<SlicePatternItems> + lower_slice_pattern_no_rest (AST::SlicePatternItemsNoRest &pattern); + + std::unique_ptr<SlicePatternItems> + lower_slice_pattern_has_rest (AST::SlicePatternItemsHasRest &pattern); std::unique_ptr<HIR::RangePatternBound> lower_range_pattern_bound (AST::RangePatternBound &bound); diff --git a/gcc/rust/hir/rust-ast-lower-enumitem.h b/gcc/rust/hir/rust-ast-lower-enumitem.h index 1b95345..8e28c08 100644 --- a/gcc/rust/hir/rust-ast-lower-enumitem.h +++ b/gcc/rust/hir/rust-ast-lower-enumitem.h @@ -80,6 +80,8 @@ public: item.get_visibility ().as_string ().c_str ()); std::vector<HIR::TupleField> fields; + fields.reserve (item.get_tuple_fields ().size ()); + for (auto &field : item.get_tuple_fields ()) { HIR::Visibility vis = translate_visibility (field.get_visibility ()); @@ -90,11 +92,8 @@ public: crate_num, field.get_node_id (), mappings.get_next_hir_id (crate_num), mappings.get_next_localdef_id (crate_num)); - HIR::TupleField translated_field (field_mapping, - std::unique_ptr<HIR::Type> (type), - vis, field.get_locus (), - field.get_outer_attrs ()); - fields.push_back (std::move (translated_field)); + fields.emplace_back (field_mapping, std::unique_ptr<HIR::Type> (type), + vis, field.get_locus (), field.get_outer_attrs ()); } translated diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc index 4ed51d9..a1e24ee 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.cc +++ b/gcc/rust/hir/rust-ast-lower-expr.cc @@ -81,11 +81,10 @@ void ASTLoweringExpr::visit (AST::TupleExpr &expr) { std::vector<std::unique_ptr<HIR::Expr>> tuple_elements; + tuple_elements.reserve (expr.get_tuple_elems ().size ()); + for (auto &e : expr.get_tuple_elems ()) - { - HIR::Expr *t = ASTLoweringExpr::translate (*e); - tuple_elements.push_back (std::unique_ptr<HIR::Expr> (t)); - } + tuple_elements.emplace_back (ASTLoweringExpr::translate (*e)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), @@ -221,12 +220,12 @@ ASTLoweringExpr::visit (AST::CallExpr &expr) HIR::Expr *func = ASTLoweringExpr::translate (expr.get_function_expr ()); auto const &in_params = expr.get_params (); + std::vector<std::unique_ptr<HIR::Expr>> params; + params.reserve (in_params.size ()); + for (auto ¶m : in_params) - { - auto trans = ASTLoweringExpr::translate (*param); - params.push_back (std::unique_ptr<HIR::Expr> (trans)); - } + params.emplace_back (ASTLoweringExpr::translate (*param)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping ( @@ -248,11 +247,10 @@ ASTLoweringExpr::visit (AST::MethodCallExpr &expr) auto const &in_params = expr.get_params (); std::vector<std::unique_ptr<HIR::Expr>> params; + params.reserve (in_params.size ()); + for (auto ¶m : in_params) - { - auto trans = ASTLoweringExpr::translate (*param); - params.push_back (std::unique_ptr<HIR::Expr> (trans)); - } + params.emplace_back (ASTLoweringExpr::translate (*param)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), @@ -338,11 +336,10 @@ void ASTLoweringExpr::visit (AST::ArrayElemsValues &elems) { std::vector<std::unique_ptr<HIR::Expr>> elements; + elements.reserve (elems.get_values ().size ()); + for (auto &elem : elems.get_values ()) - { - HIR::Expr *translated_elem = ASTLoweringExpr::translate (*elem); - elements.push_back (std::unique_ptr<HIR::Expr> (translated_elem)); - } + elements.emplace_back (ASTLoweringExpr::translate (*elem)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (mappings.get_current_crate (), @@ -569,13 +566,12 @@ ASTLoweringExpr::visit (AST::StructExprStructFields &struct_expr) } auto const &in_fields = struct_expr.get_fields (); + std::vector<std::unique_ptr<HIR::StructExprField>> fields; + fields.reserve (in_fields.size ()); + for (auto &field : in_fields) - { - HIR::StructExprField *translated - = ASTLowerStructExprField::translate (*field); - fields.push_back (std::unique_ptr<HIR::StructExprField> (translated)); - } + fields.emplace_back (ASTLowerStructExprField::translate (*field)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, struct_expr.get_node_id (), @@ -814,11 +810,10 @@ ASTLoweringExpr::visit (AST::ClosureExprInner &expr) = ASTLoweringExpr::translate (expr.get_definition_expr ()); std::vector<HIR::ClosureParam> closure_params; + closure_params.reserve (expr.get_params ().size ()); + for (auto ¶m : expr.get_params ()) - { - HIR::ClosureParam p = lower_closure_param (param); - closure_params.push_back (std::move (p)); - } + closure_params.emplace_back (lower_closure_param (param)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), @@ -841,11 +836,10 @@ ASTLoweringExpr::visit (AST::ClosureExprInnerTyped &expr) = ASTLoweringExpr::translate (expr.get_definition_expr ()); std::vector<HIR::ClosureParam> closure_params; + closure_params.reserve (expr.get_params ().size ()); + for (auto ¶m : expr.get_params ()) - { - HIR::ClosureParam p = lower_closure_param (param); - closure_params.push_back (std::move (p)); - } + closure_params.emplace_back (lower_closure_param (param)); auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), @@ -1000,6 +994,23 @@ ASTLoweringExpr::visit (AST::InlineAsm &expr) expr.get_options (), mapping); } +namespace { +// We're not really supporting llvm_asm, only the bare minimum for libcore's +// blackbox +// llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile"); +bool +check_llvm_asm_support (const std::vector<LlvmOperand> &inputs, + const std::vector<LlvmOperand> &outputs, + const AST::LlvmInlineAsm &expr) +{ + return outputs.size () == 0 && inputs.size () <= 1 + && expr.get_clobbers ().size () <= 1 + && expr.get_templates ().size () == 1 + && expr.get_templates ()[0].symbol == ""; +} + +} // namespace + void ASTLoweringExpr::visit (AST::LlvmInlineAsm &expr) { @@ -1009,7 +1020,10 @@ ASTLoweringExpr::visit (AST::LlvmInlineAsm &expr) mappings.get_next_localdef_id (crate_num)); std::vector<LlvmOperand> inputs; + inputs.reserve (expr.get_inputs ().size ()); + std::vector<LlvmOperand> outputs; + outputs.reserve (expr.get_outputs ().size ()); for (auto i : expr.get_inputs ()) { @@ -1029,13 +1043,15 @@ ASTLoweringExpr::visit (AST::LlvmInlineAsm &expr) expr.is_stack_aligned (), expr.get_dialect ()}; - // We're not really supporting llvm_asm, only the bare minimum - // we're quite conservative here as the current code support more usecase. - rust_assert (outputs.size () == 0); - rust_assert (inputs.size () <= 1); - rust_assert (expr.get_clobbers ().size () <= 1); - rust_assert (expr.get_templates ().size () == 1); - rust_assert (expr.get_templates ()[0].symbol == ""); + if (!check_llvm_asm_support (inputs, outputs, expr)) + { + rust_error_at (expr.get_locus (), "unsupported %qs construct", + "llvm_asm"); + rust_inform ( + expr.get_locus (), + "%<llvm_asm%> has been replaced with %<asm%>, gccrs only supports a " + "subset of %<llvm_asm%> to compile libcore"); + } translated = new HIR::LlvmInlineAsm (expr.get_locus (), inputs, outputs, diff --git a/gcc/rust/hir/rust-ast-lower-extern.h b/gcc/rust/hir/rust-ast-lower-extern.h index 3dca1b6..1f3ceda 100644 --- a/gcc/rust/hir/rust-ast-lower-extern.h +++ b/gcc/rust/hir/rust-ast-lower-extern.h @@ -109,9 +109,8 @@ public: mappings.get_next_localdef_id ( crate_num)); - function_params.push_back ( - HIR::NamedFunctionParam (mapping, param_name, - std::unique_ptr<HIR::Type> (param_type))); + function_params.emplace_back (mapping, param_name, + std::unique_ptr<HIR::Type> (param_type)); } auto crate_num = mappings.get_current_crate (); diff --git a/gcc/rust/hir/rust-ast-lower-implitem.cc b/gcc/rust/hir/rust-ast-lower-implitem.cc index 5db11cb..8fd9d16 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.cc +++ b/gcc/rust/hir/rust-ast-lower-implitem.cc @@ -115,7 +115,7 @@ ASTLowerImplItem::visit (AST::Function &function) { HIR::WhereClauseItem *i = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); + where_clause_items.emplace_back (i); } HIR::WhereClause where_clause (std::move (where_clause_items)); @@ -162,10 +162,9 @@ ASTLowerImplItem::visit (AST::Function &function) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - auto hir_param - = HIR::FunctionParam (mapping, std::move (translated_pattern), - std::move (translated_type), param.get_locus ()); - function_params.push_back (std::move (hir_param)); + function_params.emplace_back (mapping, std::move (translated_pattern), + std::move (translated_type), + param.get_locus ()); } bool terminated = false; @@ -272,10 +271,9 @@ ASTLowerTraitItem::visit (AST::Function &func) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - auto hir_param - = HIR::FunctionParam (mapping, std::move (translated_pattern), - std::move (translated_type), param.get_locus ()); - function_params.push_back (std::move (hir_param)); + function_params.emplace_back (mapping, std::move (translated_pattern), + std::move (translated_type), + param.get_locus ()); } if (func.has_self_param ()) @@ -320,10 +318,10 @@ ASTLowerTraitItem::visit (AST::Function &func) } void -ASTLowerTraitItem::visit (AST::TraitItemConst &constant) +ASTLowerTraitItem::visit (AST::ConstantItem &constant) { HIR::Type *type = ASTLoweringType::translate (constant.get_type ()); - HIR::Expr *expr = constant.has_expression () + HIR::Expr *expr = constant.has_expr () ? ASTLoweringExpr::translate (constant.get_expr ()) : nullptr; diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h index 8331bba..dfcf567 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.h +++ b/gcc/rust/hir/rust-ast-lower-implitem.h @@ -49,7 +49,7 @@ class ASTLowerTraitItem : public ASTLoweringBase public: static HIR::TraitItem *translate (AST::AssociatedItem &item); void visit (AST::Function &func) override; - void visit (AST::TraitItemConst &constant) override; + void visit (AST::ConstantItem &constant) override; void visit (AST::TraitItemType &type) override; private: diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc index 4e5a747..81815ff 100644 --- a/gcc/rust/hir/rust-ast-lower-item.cc +++ b/gcc/rust/hir/rust-ast-lower-item.cc @@ -72,7 +72,7 @@ ASTLoweringItem::visit (AST::Module &module) // The item may be null if it doesn't need to live in the HIR - for // example, macro rules definitions if (transitem) - items.push_back (std::unique_ptr<Item> (transitem)); + items.emplace_back (transitem); } // should be lowered/copied from module.get_in/outer_attrs() @@ -90,12 +90,11 @@ void ASTLoweringItem::visit (AST::TypeAlias &alias) { std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve (alias.get_where_clause ().get_items ().size ()); + for (auto &item : alias.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (alias.get_visibility ()); @@ -130,17 +129,19 @@ ASTLoweringItem::visit (AST::TupleStruct &struct_decl) } std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + struct_decl.get_where_clause ().get_items ().size ()); + for (auto &item : struct_decl.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (struct_decl.get_visibility ()); std::vector<HIR::TupleField> fields; + fields.reserve (struct_decl.get_fields ().size ()); + for (AST::TupleField &field : struct_decl.get_fields ()) { if (field.get_field_type ().is_marked_for_strip ()) @@ -155,11 +156,8 @@ ASTLoweringItem::visit (AST::TupleStruct &struct_decl) mappings.get_next_hir_id (crate_num), mappings.get_next_localdef_id (crate_num)); - HIR::TupleField translated_field (mapping, - std::unique_ptr<HIR::Type> (type), vis, - field.get_locus (), - field.get_outer_attrs ()); - fields.push_back (std::move (translated_field)); + fields.emplace_back (mapping, std::unique_ptr<HIR::Type> (type), vis, + field.get_locus (), field.get_outer_attrs ()); } auto crate_num = mappings.get_current_crate (); @@ -185,12 +183,12 @@ ASTLoweringItem::visit (AST::StructStruct &struct_decl) } std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + struct_decl.get_where_clause ().get_items ().size ()); + for (auto &item : struct_decl.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); HIR::WhereClause where_clause (std::move (where_clause_items)); @@ -245,25 +243,26 @@ ASTLoweringItem::visit (AST::Enum &enum_decl) } std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + enum_decl.get_where_clause ().get_items ().size ()); + for (auto &item : enum_decl.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (enum_decl.get_visibility ()); // bool is_unit = enum_decl.is_zero_variant (); std::vector<std::unique_ptr<HIR::EnumItem>> items; + items.reserve (enum_decl.get_variants ().size ()); + for (auto &variant : enum_decl.get_variants ()) { if (variant->is_marked_for_strip ()) continue; - HIR::EnumItem *hir_item = ASTLoweringEnumItem::translate (variant.get ()); - items.push_back (std::unique_ptr<HIR::EnumItem> (hir_item)); + items.emplace_back (ASTLoweringEnumItem::translate (variant.get ())); } auto crate_num = mappings.get_current_crate (); @@ -288,17 +287,16 @@ ASTLoweringItem::visit (AST::Union &union_decl) { std::vector<std::unique_ptr<HIR::GenericParam>> generic_params; if (union_decl.has_generics ()) - { - generic_params = lower_generic_params (union_decl.get_generic_params ()); - } + generic_params = lower_generic_params (union_decl.get_generic_params ()); std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + union_decl.get_where_clause ().get_items ().size ()); + for (auto &item : union_decl.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); + HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (union_decl.get_visibility ()); @@ -390,12 +388,12 @@ ASTLoweringItem::visit (AST::Function &function) return; std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + function.get_where_clause ().get_items ().size ()); + for (auto &item : function.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::FunctionQualifiers qualifiers @@ -418,10 +416,41 @@ ASTLoweringItem::visit (AST::Function &function) : nullptr; std::vector<HIR::FunctionParam> function_params; + function_params.reserve (function.get_function_params ().size ()); + + auto crate_num = mappings.get_current_crate (); for (auto &p : function.get_function_params ()) { - if (p->is_variadic () || p->is_self ()) + if (p->is_variadic ()) continue; + if (p->is_self ()) + { + rich_location r (line_table, p->get_locus ()); + r.add_range (function.get_locus ()); + rust_error_at ( + r, "%<self%> parameter is only allowed in associated functions"); + + // rustc creates a synthetic regular fn-param here pointing to a + // generic Self as far as i can see but that seems over the top for + // now. + // + // see this example (invalid code): + // + // pub trait X { + // fn x() { + // fn f(&mut self) {} + // f(); + // } + // } + // + // without a synthetic param we wont get the number of args error as + // well but i think this is fine for now. + // + // problem is what we make the param type to become... + + continue; + } + auto param = static_cast<AST::FunctionParam &> (*p); auto translated_pattern = std::unique_ptr<HIR::Pattern> ( @@ -434,10 +463,9 @@ ASTLoweringItem::visit (AST::Function &function) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - auto hir_param - = HIR::FunctionParam (mapping, std::move (translated_pattern), - std::move (translated_type), param.get_locus ()); - function_params.push_back (std::move (hir_param)); + function_params.emplace_back (mapping, std::move (translated_pattern), + std::move (translated_type), + param.get_locus ()); } bool terminated = false; @@ -446,7 +474,6 @@ ASTLoweringItem::visit (AST::Function &function) ASTLoweringBlock::translate (*function.get_definition ().value (), &terminated)); - auto crate_num = mappings.get_current_crate (); Analysis::NodeMapping mapping (crate_num, function.get_node_id (), mappings.get_next_hir_id (crate_num), mappings.get_next_localdef_id (crate_num)); @@ -479,11 +506,12 @@ void ASTLoweringItem::visit (AST::InherentImpl &impl_block) { std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + impl_block.get_where_clause ().get_items ().size ()); + for (auto &item : impl_block.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i = ASTLowerWhereClauseItem::translate (*item); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item)); HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (impl_block.get_visibility ()); @@ -540,7 +568,7 @@ ASTLoweringItem::visit (AST::InherentImpl &impl_block) HIR::ImplItem *lowered = ASTLowerImplItem::translate (*impl_item, mapping.get_hirid ()); rust_assert (lowered != nullptr); - impl_items.push_back (std::unique_ptr<HIR::ImplItem> (lowered)); + impl_items.emplace_back (lowered); impl_item_ids.push_back (lowered->get_impl_mappings ().get_hirid ()); } @@ -563,12 +591,12 @@ void ASTLoweringItem::visit (AST::Trait &trait) { std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve (trait.get_where_clause ().get_items ().size ()); + for (auto &item : trait.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i - = ASTLowerWhereClauseItem::translate (*item.get ()); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item.get ())); + HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (trait.get_visibility ()); @@ -589,23 +617,24 @@ ASTLoweringItem::visit (AST::Trait &trait) if (trait.has_type_param_bounds ()) { for (auto &bound : trait.get_type_param_bounds ()) - { - HIR::TypeParamBound *b = lower_bound (*bound); - type_param_bounds.push_back ( - std::unique_ptr<HIR::TypeParamBound> (b)); - } + type_param_bounds.emplace_back (lower_bound (*bound)); } + auto trait_item_size = trait.get_trait_items ().size (); + std::vector<std::unique_ptr<HIR::TraitItem>> trait_items; + trait_items.reserve (trait_item_size); std::vector<HirId> trait_item_ids; + trait_item_ids.reserve (trait_item_size); + for (auto &item : trait.get_trait_items ()) { if (item->is_marked_for_strip ()) continue; HIR::TraitItem *lowered = ASTLowerTraitItem::translate (*item); - trait_items.push_back (std::unique_ptr<HIR::TraitItem> (lowered)); trait_item_ids.push_back (lowered->get_mappings ().get_hirid ()); + trait_items.emplace_back (lowered); } auto crate_num = mappings.get_current_crate (); @@ -636,13 +665,16 @@ ASTLoweringItem::visit (AST::Trait &trait) void ASTLoweringItem::visit (AST::TraitImpl &impl_block) { - std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; bool unsafe = impl_block.is_unsafe (); + + std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items; + where_clause_items.reserve ( + impl_block.get_where_clause ().get_items ().size ()); + for (auto &item : impl_block.get_where_clause ().get_items ()) - { - HIR::WhereClauseItem *i = ASTLowerWhereClauseItem::translate (*item); - where_clause_items.push_back (std::unique_ptr<HIR::WhereClauseItem> (i)); - } + where_clause_items.emplace_back ( + ASTLowerWhereClauseItem::translate (*item)); + HIR::WhereClause where_clause (std::move (where_clause_items)); HIR::Visibility vis = translate_visibility (impl_block.get_visibility ()); @@ -690,8 +722,13 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block) mappings.get_next_hir_id (crate_num), mappings.get_next_localdef_id (crate_num)); + auto impl_items_size = impl_block.get_impl_items ().size (); + std::vector<std::unique_ptr<HIR::ImplItem>> impl_items; + impl_items.reserve (impl_items_size); std::vector<HirId> impl_item_ids; + impl_item_ids.reserve (impl_items_size); + for (auto &impl_item : impl_block.get_impl_items ()) { if (impl_item->is_marked_for_strip ()) @@ -700,8 +737,8 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block) HIR::ImplItem *lowered = ASTLowerImplItem::translate (*impl_item, mapping.get_hirid ()); rust_assert (lowered != nullptr); - impl_items.push_back (std::unique_ptr<HIR::ImplItem> (lowered)); impl_item_ids.push_back (lowered->get_impl_mappings ().get_hirid ()); + impl_items.emplace_back (lowered); } BoundPolarity polarity = impl_block.is_exclam () diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc index 8aabcd8..4250adb 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.cc +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -81,26 +81,45 @@ ASTLoweringPattern::visit (AST::TupleStructPattern &pattern) auto &items = pattern.get_items (); switch (items.get_item_type ()) { - case AST::TupleStructItems::RANGE: + case AST::TupleStructItems::HAS_REST: { - // TODO - rust_unreachable (); + AST::TupleStructItemsHasRest &items_has_rest + = static_cast<AST::TupleStructItemsHasRest &> (items); + + std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns; + lower_patterns.reserve (items_has_rest.get_lower_patterns ().size ()); + for (auto &pattern_member : items_has_rest.get_lower_patterns ()) + { + lower_patterns.emplace_back ( + ASTLoweringPattern::translate (*pattern_member)); + } + + std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns; + upper_patterns.reserve (items_has_rest.get_upper_patterns ().size ()); + for (auto &pattern_member : items_has_rest.get_upper_patterns ()) + { + upper_patterns.emplace_back ( + ASTLoweringPattern::translate (*pattern_member)); + } + + lowered = new HIR::TupleStructItemsHasRest (std::move (lower_patterns), + std::move (upper_patterns)); } break; - case AST::TupleStructItems::NO_RANGE: + case AST::TupleStructItems::NO_REST: { - AST::TupleStructItemsNoRange &items_no_range - = static_cast<AST::TupleStructItemsNoRange &> (items); + AST::TupleStructItemsNoRest &items_no_rest + = static_cast<AST::TupleStructItemsNoRest &> (items); std::vector<std::unique_ptr<HIR::Pattern>> patterns; - for (auto &inner_pattern : items_no_range.get_patterns ()) - { - HIR::Pattern *p = ASTLoweringPattern::translate (*inner_pattern); - patterns.push_back (std::unique_ptr<HIR::Pattern> (p)); - } + patterns.reserve (items_no_rest.get_patterns ().size ()); + + for (auto &inner_pattern : items_no_rest.get_patterns ()) + patterns.emplace_back ( + ASTLoweringPattern::translate (*inner_pattern)); - lowered = new HIR::TupleStructItemsNoRange (std::move (patterns)); + lowered = new HIR::TupleStructItemsNoRest (std::move (patterns)); } break; } @@ -121,7 +140,6 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) = ASTLowerPathInExpression::translate (pattern.get_path ()); auto &raw_elems = pattern.get_struct_pattern_elems (); - rust_assert (!raw_elems.has_etc ()); std::vector<std::unique_ptr<HIR::StructPatternField>> fields; for (auto &field : raw_elems.get_struct_pattern_fields ()) @@ -196,7 +214,7 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) mappings.insert_node_to_hir (field_node_id, field_id); // add it to the lowered fields list - fields.push_back (std::unique_ptr<HIR::StructPatternField> (f)); + fields.emplace_back (f); } auto crate_num = mappings.get_current_crate (); @@ -204,7 +222,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - HIR::StructPatternElements elems (std::move (fields)); + HIR::StructPatternElements elems ( + std::move (fields), pattern.get_struct_pattern_elems ().has_rest ()); translated = new HIR::StructPattern (mapping, *path, std::move (elems)); } @@ -223,21 +242,20 @@ void ASTLoweringPattern::visit (AST::TuplePattern &pattern) { std::unique_ptr<HIR::TuplePatternItems> items; - switch (pattern.get_items ().get_pattern_type ()) + switch (pattern.get_items ().get_item_type ()) { - case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: + case AST::TuplePatternItems::ItemType::NO_REST: { - AST::TuplePatternItemsMultiple &ref - = static_cast<AST::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + AST::TuplePatternItemsNoRest &ref + = static_cast<AST::TuplePatternItemsNoRest &> (pattern.get_items ()); items = lower_tuple_pattern_multiple (ref); } break; - case AST::TuplePatternItems::TuplePatternItemType::RANGED: + case AST::TuplePatternItems::ItemType::HAS_REST: { - AST::TuplePatternItemsRanged &ref - = static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ()); + AST::TuplePatternItemsHasRest &ref + = static_cast<AST::TuplePatternItemsHasRest &> (pattern.get_items ()); items = lower_tuple_pattern_ranged (ref); } break; @@ -268,8 +286,6 @@ ASTLoweringPattern::visit (AST::LiteralPattern &pattern) void ASTLoweringPattern::visit (AST::RangePattern &pattern) { - if (pattern.get_range_kind () == AST::RangeKind::EXCLUDED) - rust_unreachable (); // Not supported yet auto upper_bound = lower_range_pattern_bound (pattern.get_upper_bound ()); auto lower_bound = lower_range_pattern_bound (pattern.get_lower_bound ()); @@ -278,9 +294,11 @@ ASTLoweringPattern::visit (AST::RangePattern &pattern) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - translated - = new HIR::RangePattern (mapping, std::move (lower_bound), - std::move (upper_bound), pattern.get_locus ()); + bool is_inclusive = (pattern.get_range_kind () == AST::RangeKind::INCLUDED); + + translated = new HIR::RangePattern (mapping, std::move (lower_bound), + std::move (upper_bound), + pattern.get_locus (), is_inclusive); } void @@ -322,26 +340,22 @@ ASTLoweringPattern::visit (AST::ReferencePattern &pattern) void ASTLoweringPattern::visit (AST::SlicePattern &pattern) { - std::vector<std::unique_ptr<HIR::Pattern>> items; + std::unique_ptr<HIR::SlicePatternItems> items; - switch (pattern.get_items ().get_pattern_type ()) + switch (pattern.get_items ().get_item_type ()) { - case AST::SlicePatternItems::SlicePatternItemType::NO_REST: + case AST::SlicePatternItems::ItemType::NO_REST: { - AST::SlicePatternItemsNoRest &ref + auto &ref = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ()); - for (auto &p : ref.get_patterns ()) - { - HIR::Pattern *item = ASTLoweringPattern::translate (*p); - items.push_back (std::unique_ptr<HIR::Pattern> (item)); - } + items = ASTLoweringBase::lower_slice_pattern_no_rest (ref); } break; - case AST::SlicePatternItems::SlicePatternItemType::HAS_REST: + case AST::SlicePatternItems::ItemType::HAS_REST: { - rust_error_at (pattern.get_locus (), - "lowering of slice patterns with rest elements are not " - "supported yet"); + auto &ref + = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ()); + items = ASTLoweringBase::lower_slice_pattern_has_rest (ref); } break; } @@ -364,12 +378,10 @@ ASTLoweringPattern::visit (AST::AltPattern &pattern) UNKNOWN_LOCAL_DEFID); std::vector<std::unique_ptr<HIR::Pattern>> alts; + alts.reserve (pattern.get_alts ().size ()); for (auto &alt : pattern.get_alts ()) - { - alts.push_back ( - std::unique_ptr<HIR::Pattern> (ASTLoweringPattern::translate (*alt))); - } + alts.emplace_back (ASTLoweringPattern::translate (*alt)); translated = new HIR::AltPattern (mapping, std::move (alts), pattern.get_locus ()); diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc index e6e327f..5b8e7c5 100644 --- a/gcc/rust/hir/rust-ast-lower.cc +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -80,7 +80,7 @@ ASTLowering::go () { auto translated = ASTLoweringItem::translate (*item); if (translated != nullptr) - items.push_back (std::unique_ptr<HIR::Item> (translated)); + items.emplace_back (translated); } auto &mappings = Analysis::Mappings::get (); @@ -127,7 +127,7 @@ ASTLoweringBlock::visit (AST::BlockExpr &expr) block_did_terminate |= terminated; if (translated_stmt) - block_stmts.push_back (std::unique_ptr<HIR::Stmt> (translated_stmt)); + block_stmts.emplace_back (translated_stmt); } if (expr.has_tail_expr () && block_did_terminate) @@ -231,6 +231,7 @@ ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr, { HIR::Expr *kase_expr; std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns; + match_arm_patterns.reserve (expr.get_patterns ().size ()); *branch_value = ASTLoweringExpr::translate (expr.get_value_expr ()); kase_expr = ASTLoweringExpr::translate (expr.get_if_block ()); @@ -241,10 +242,7 @@ ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr, rust_assert (expr.get_patterns ().size () == 1); for (auto &pattern : expr.get_patterns ()) - { - HIR::Pattern *ptrn = ASTLoweringPattern::translate (*pattern); - match_arm_patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn)); - } + match_arm_patterns.emplace_back (ASTLoweringPattern::translate (*pattern)); // The match arm corresponding to the if let pattern when it matches. HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (), nullptr, @@ -255,9 +253,8 @@ ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr, mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - HIR::MatchCase kase (std::move (mapping), std::move (arm), - std::unique_ptr<HIR::Expr> (kase_expr)); - match_arms.push_back (std::move (kase)); + match_arms.emplace_back (std::move (mapping), std::move (arm), + std::unique_ptr<HIR::Expr> (kase_expr)); // The default match arm when the if let pattern does not match std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns_wildcard; @@ -265,19 +262,14 @@ ASTLoweringIfLetBlock::desugar_iflet (AST::IfLetExpr &expr, mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - std::unique_ptr<HIR::WildcardPattern> wc - = std::unique_ptr<HIR::WildcardPattern> ( - new HIR::WildcardPattern (mapping_default, expr.get_locus ())); - - match_arm_patterns_wildcard.push_back (std::move (wc)); + match_arm_patterns_wildcard.emplace_back ( + new HIR::WildcardPattern (mapping_default, expr.get_locus ())); HIR::MatchArm arm_default (std::move (match_arm_patterns_wildcard), expr.get_locus (), nullptr, {}); - HIR::MatchCase kase_else (std::move (mapping_default), - std::move (arm_default), - std::unique_ptr<HIR::Expr> (kase_else_expr)); - match_arms.push_back (std::move (kase_else)); + match_arms.emplace_back (std::move (mapping_default), std::move (arm_default), + std::unique_ptr<HIR::Expr> (kase_else_expr)); } void @@ -442,11 +434,12 @@ ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr) } std::vector<std::unique_ptr<HIR::Pattern>> match_arm_patterns; + match_arm_patterns.reserve ( + match_case.get_arm ().get_patterns ().size ()); + for (auto &pattern : match_case.get_arm ().get_patterns ()) - { - HIR::Pattern *ptrn = ASTLoweringPattern::translate (*pattern); - match_arm_patterns.push_back (std::unique_ptr<HIR::Pattern> (ptrn)); - } + match_arm_patterns.emplace_back ( + ASTLoweringPattern::translate (*pattern)); HIR::MatchArm arm (std::move (match_arm_patterns), expr.get_locus (), std::unique_ptr<HIR::Expr> (kase_guard_expr), @@ -457,9 +450,8 @@ ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr) mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); - HIR::MatchCase kase (std::move (mapping), std::move (arm), - std::unique_ptr<HIR::Expr> (kase_expr)); - match_arms.push_back (std::move (kase)); + match_arms.emplace_back (std::move (mapping), std::move (arm), + std::unique_ptr<HIR::Expr> (kase_expr)); } auto crate_num = mappings.get_current_crate (); @@ -490,8 +482,11 @@ ASTLowerPathInExpression::visit (AST::PathInExpression &expr) return; } - std::vector<HIR::PathExprSegment> path_segments; auto &segments = expr.get_segments (); + + std::vector<HIR::PathExprSegment> path_segments; + path_segments.reserve (segments.size ()); + for (auto &s : segments) { path_segments.push_back (lower_path_expr_seg ((s))); @@ -531,8 +526,11 @@ ASTLowerQualPathInExpression::visit (AST::QualifiedPathInExpression &expr) HIR::QualifiedPathType qual_path_type = lower_qual_path_type (expr.get_qualified_path_type ()); - std::vector<HIR::PathExprSegment> path_segments; auto &segments = expr.get_segments (); + + std::vector<HIR::PathExprSegment> path_segments; + path_segments.reserve (segments.size ()); + for (auto &s : segments) { path_segments.push_back (lower_path_expr_seg ((s))); diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc index a0cdcb2..49ce143 100644 --- a/gcc/rust/hir/rust-hir-dump.cc +++ b/gcc/rust/hir/rust-hir-dump.cc @@ -2307,20 +2307,20 @@ Dump::visit (StructPattern &e) } void -Dump::visit (TupleStructItemsNoRange &e) +Dump::visit (TupleStructItemsNoRest &e) { - begin ("TupleStructItemsNoRange"); + begin ("TupleStructItemsNoRest"); visit_collection ("patterns", e.get_patterns ()); - end ("TupleStructItemsNoRange"); + end ("TupleStructItemsNoRest"); } void -Dump::visit (TupleStructItemsRange &e) +Dump::visit (TupleStructItemsHasRest &e) { - begin ("TupleStructItemsRange"); + begin ("TupleStructItemsHasRest"); visit_collection ("lower_patterns", e.get_lower_patterns ()); visit_collection ("upper_patterns", e.get_upper_patterns ()); - end ("TupleStructItemsRange"); + end ("TupleStructItemsHasRest"); } void @@ -2337,20 +2337,20 @@ Dump::visit (TupleStructPattern &e) } void -Dump::visit (TuplePatternItemsMultiple &e) +Dump::visit (TuplePatternItemsNoRest &e) { - begin ("TuplePatternItemsMultiple"); + begin ("TuplePatternItemsNoRest"); visit_collection ("patterns", e.get_patterns ()); - end ("TuplePatternItemsMultiple"); + end ("TuplePatternItemsNoRest"); } void -Dump::visit (TuplePatternItemsRanged &e) +Dump::visit (TuplePatternItemsHasRest &e) { - begin ("TuplePatternItemsRanged"); + begin ("TuplePatternItemsHasRest"); visit_collection ("lower_patterns", e.get_lower_patterns ()); visit_collection ("upper_patterns", e.get_upper_patterns ()); - end ("TuplePatternItemsRanged"); + end ("TuplePatternItemsHasRest"); } void @@ -2363,11 +2363,28 @@ Dump::visit (TuplePattern &e) } void +Dump::visit (SlicePatternItemsNoRest &e) +{ + begin ("SlicePatternItemsNoRest"); + visit_collection ("patterns", e.get_patterns ()); + end ("SlicePatternItemsNoRest"); +} + +void +Dump::visit (SlicePatternItemsHasRest &e) +{ + begin ("SlicePatternItemsHasRest"); + visit_collection ("lower_patterns", e.get_lower_patterns ()); + visit_collection ("upper_patterns", e.get_upper_patterns ()); + end ("SlicePatternItemsHasRest"); +} + +void Dump::visit (SlicePattern &e) { begin ("SlicePattern"); do_mappings (e.get_mappings ()); - visit_collection ("items", e.get_items ()); + visit_field ("items", e.get_items ()); end ("SlicePattern"); } diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h index 3e6ae30..4dfc885 100644 --- a/gcc/rust/hir/rust-hir-dump.h +++ b/gcc/rust/hir/rust-hir-dump.h @@ -223,14 +223,18 @@ private: virtual void visit (StructPatternFieldIdent &) override; virtual void visit (StructPattern &) override; - virtual void visit (TupleStructItemsNoRange &) override; - virtual void visit (TupleStructItemsRange &) override; + virtual void visit (TupleStructItemsNoRest &) override; + virtual void visit (TupleStructItemsHasRest &) override; virtual void visit (TupleStructPattern &) override; - virtual void visit (TuplePatternItemsMultiple &) override; - virtual void visit (TuplePatternItemsRanged &) override; + virtual void visit (TuplePatternItemsNoRest &) override; + virtual void visit (TuplePatternItemsHasRest &) override; virtual void visit (TuplePattern &) override; + + virtual void visit (SlicePatternItemsNoRest &) override; + virtual void visit (SlicePatternItemsHasRest &) override; virtual void visit (SlicePattern &) override; + virtual void visit (AltPattern &) override; virtual void visit (EmptyStmt &) override; diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h index 57b3a4d..aec2f36 100644 --- a/gcc/rust/hir/tree/rust-hir-full-decls.h +++ b/gcc/rust/hir/tree/rust-hir-full-decls.h @@ -199,13 +199,15 @@ class StructPatternFieldIdentPat; class StructPatternFieldIdent; class StructPattern; class TupleStructItems; -class TupleStructItemsNoRange; -class TupleStructItemsRange; +class TupleStructItemsNoRest; +class TupleStructItemsHasRest; class TupleStructPattern; class TuplePatternItems; -class TuplePatternItemsMultiple; -class TuplePatternItemsRanged; +class TuplePatternItemsNoRest; +class TuplePatternItemsHasRest; class TuplePattern; +class SlicePatternItemsNoRest; +class SlicePatternItemsHasRest; class SlicePattern; class AltPattern; diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index d9df602..eb9cec7 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -452,6 +452,7 @@ public: bool is_unsafe () const { return unsafety == Unsafety::Unsafe; } bool is_async () const { return async_status == Async::Yes; } + Unsafety get_unsafety () const { return unsafety; } ABI get_abi () const { return abi; } }; diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h index 9c636ca..89b9cc6 100644 --- a/gcc/rust/hir/tree/rust-hir-pattern.h +++ b/gcc/rust/hir/tree/rust-hir-pattern.h @@ -350,6 +350,7 @@ class RangePattern : public Pattern /* location only stored to avoid a dereference - lower pattern should give * correct location so maybe change in future */ location_t locus; + bool is_inclusive; Analysis::NodeMapping mappings; public: @@ -359,10 +360,10 @@ public: RangePattern (Analysis::NodeMapping mappings, std::unique_ptr<RangePatternBound> lower, std::unique_ptr<RangePatternBound> upper, location_t locus, - bool has_ellipsis_syntax = false) + bool is_inclusive, bool has_ellipsis_syntax = false) : lower (std::move (lower)), upper (std::move (upper)), has_ellipsis_syntax (has_ellipsis_syntax), locus (locus), - mappings (mappings) + is_inclusive (is_inclusive), mappings (mappings) {} // Copy constructor with clone @@ -370,7 +371,7 @@ public: : lower (other.lower->clone_range_pattern_bound ()), upper (other.upper->clone_range_pattern_bound ()), has_ellipsis_syntax (other.has_ellipsis_syntax), locus (other.locus), - mappings (other.mappings) + is_inclusive (other.is_inclusive), mappings (other.mappings) {} // Overloaded assignment operator to clone @@ -380,6 +381,7 @@ public: upper = other.upper->clone_range_pattern_bound (); has_ellipsis_syntax = other.has_ellipsis_syntax; locus = other.locus; + is_inclusive = other.is_inclusive; mappings = other.mappings; return *this; @@ -395,6 +397,7 @@ public: void accept_vis (HIRPatternVisitor &vis) override; bool get_has_ellipsis_syntax () { return has_ellipsis_syntax; }; + bool is_inclusive_range () const { return is_inclusive; } const Analysis::NodeMapping &get_mappings () const override final { @@ -680,6 +683,7 @@ protected: class StructPatternElements { std::vector<std::unique_ptr<StructPatternField>> fields; + bool has_rest_pattern; public: // Returns whether there are any struct pattern fields @@ -689,10 +693,18 @@ public: * no etc). */ bool is_empty () const { return !has_struct_pattern_fields (); } + bool has_rest () const { return has_rest_pattern; } + // Constructor for StructPatternElements with both (potentially) StructPatternElements ( std::vector<std::unique_ptr<StructPatternField>> fields) - : fields (std::move (fields)) + : fields (std::move (fields)), has_rest_pattern (false) + {} + + StructPatternElements ( + std::vector<std::unique_ptr<StructPatternField>> fields, + bool has_rest_pattern) + : fields (std::move (fields)), has_rest_pattern (has_rest_pattern) {} // Copy constructor with vector clone @@ -700,7 +712,8 @@ public: { fields.reserve (other.fields.size ()); for (const auto &e : other.fields) - fields.push_back (e->clone_struct_pattern_field ()); + fields.emplace_back (e->clone_struct_pattern_field ()); + has_rest_pattern = other.has_rest_pattern; } // Overloaded assignment operator with vector clone @@ -709,8 +722,8 @@ public: fields.clear (); fields.reserve (other.fields.size ()); for (const auto &e : other.fields) - fields.push_back (e->clone_struct_pattern_field ()); - + fields.emplace_back (e->clone_struct_pattern_field ()); + has_rest_pattern = other.has_rest_pattern; return *this; } @@ -778,24 +791,25 @@ protected: } }; -// Base abstract class for TupleStructItems and TuplePatternItems -class TupleItems : public FullVisitable +// Base abstract class for TupleStructItems, TuplePatternItems & +// SlicePatternItems +class PatternItems : public FullVisitable { public: enum ItemType { - MULTIPLE, - RANGED, + NO_REST, + HAS_REST, }; - virtual ~TupleItems () {} + virtual ~PatternItems () {} // TODO: should this store location data? // Unique pointer custom clone function - std::unique_ptr<TupleItems> clone_tuple_items () const + std::unique_ptr<PatternItems> clone_pattern_items () const { - return std::unique_ptr<TupleItems> (clone_tuple_items_impl ()); + return std::unique_ptr<PatternItems> (clone_pattern_items_impl ()); } virtual ItemType get_item_type () const = 0; @@ -804,36 +818,36 @@ public: protected: // pure virtual clone implementation - virtual TupleItems *clone_tuple_items_impl () const = 0; + virtual PatternItems *clone_pattern_items_impl () const = 0; }; // Base abstract class for patterns used in TupleStructPattern -class TupleStructItems : public TupleItems +class TupleStructItems : public PatternItems { public: // Unique pointer custom clone function std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const { - return std::unique_ptr<TupleStructItems> (clone_tuple_items_impl ()); + return std::unique_ptr<TupleStructItems> (clone_pattern_items_impl ()); } protected: // pure virtual clone implementation - virtual TupleStructItems *clone_tuple_items_impl () const override = 0; + virtual TupleStructItems *clone_pattern_items_impl () const override = 0; }; -// Class for non-ranged tuple struct pattern patterns -class TupleStructItemsNoRange : public TupleStructItems +// Class for patterns within a tuple struct pattern, without a rest pattern +class TupleStructItemsNoRest : public TupleStructItems { std::vector<std::unique_ptr<Pattern>> patterns; public: - TupleStructItemsNoRange (std::vector<std::unique_ptr<Pattern>> patterns) + TupleStructItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) : patterns (std::move (patterns)) {} // Copy constructor with vector clone - TupleStructItemsNoRange (TupleStructItemsNoRange const &other) + TupleStructItemsNoRest (TupleStructItemsNoRest const &other) { patterns.reserve (other.patterns.size ()); for (const auto &e : other.patterns) @@ -841,7 +855,7 @@ public: } // Overloaded assignment operator with vector clone - TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other) + TupleStructItemsNoRest &operator= (TupleStructItemsNoRest const &other) { patterns.clear (); patterns.reserve (other.patterns.size ()); @@ -852,9 +866,8 @@ public: } // move constructors - TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default; - TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other) - = default; + TupleStructItemsNoRest (TupleStructItemsNoRest &&other) = default; + TupleStructItemsNoRest &operator= (TupleStructItemsNoRest &&other) = default; std::string as_string () const override; @@ -866,32 +879,33 @@ public: return patterns; } - ItemType get_item_type () const override final { return ItemType::MULTIPLE; } + ItemType get_item_type () const override final { return ItemType::NO_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TupleStructItemsNoRange *clone_tuple_items_impl () const override + TupleStructItemsNoRest *clone_pattern_items_impl () const override { - return new TupleStructItemsNoRange (*this); + return new TupleStructItemsNoRest (*this); } }; -// Class for ranged tuple struct pattern patterns -class TupleStructItemsRange : public TupleStructItems +// Class for patterns within a tuple struct pattern, with a rest pattern +// included +class TupleStructItemsHasRest : public TupleStructItems { std::vector<std::unique_ptr<Pattern>> lower_patterns; std::vector<std::unique_ptr<Pattern>> upper_patterns; public: - TupleStructItemsRange (std::vector<std::unique_ptr<Pattern>> lower_patterns, - std::vector<std::unique_ptr<Pattern>> upper_patterns) + TupleStructItemsHasRest (std::vector<std::unique_ptr<Pattern>> lower_patterns, + std::vector<std::unique_ptr<Pattern>> upper_patterns) : lower_patterns (std::move (lower_patterns)), upper_patterns (std::move (upper_patterns)) {} // Copy constructor with vector clone - TupleStructItemsRange (TupleStructItemsRange const &other) + TupleStructItemsHasRest (TupleStructItemsHasRest const &other) { lower_patterns.reserve (other.lower_patterns.size ()); for (const auto &e : other.lower_patterns) @@ -903,7 +917,7 @@ public: } // Overloaded assignment operator to clone - TupleStructItemsRange &operator= (TupleStructItemsRange const &other) + TupleStructItemsHasRest &operator= (TupleStructItemsHasRest const &other) { lower_patterns.clear (); lower_patterns.reserve (other.lower_patterns.size ()); @@ -919,8 +933,9 @@ public: } // move constructors - TupleStructItemsRange (TupleStructItemsRange &&other) = default; - TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default; + TupleStructItemsHasRest (TupleStructItemsHasRest &&other) = default; + TupleStructItemsHasRest &operator= (TupleStructItemsHasRest &&other) + = default; std::string as_string () const override; @@ -945,14 +960,14 @@ public: return upper_patterns; } - ItemType get_item_type () const override final { return ItemType::RANGED; } + ItemType get_item_type () const override final { return ItemType::HAS_REST; } protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TupleStructItemsRange *clone_tuple_items_impl () const override + TupleStructItemsHasRest *clone_pattern_items_impl () const override { - return new TupleStructItemsRange (*this); + return new TupleStructItemsHasRest (*this); } }; @@ -1025,32 +1040,32 @@ protected: }; // Base abstract class representing TuplePattern patterns -class TuplePatternItems : public TupleItems +class TuplePatternItems : public PatternItems { public: // Unique pointer custom clone function std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const { - return std::unique_ptr<TuplePatternItems> (clone_tuple_items_impl ()); + return std::unique_ptr<TuplePatternItems> (clone_pattern_items_impl ()); } protected: // pure virtual clone implementation - virtual TuplePatternItems *clone_tuple_items_impl () const override = 0; + virtual TuplePatternItems *clone_pattern_items_impl () const override = 0; }; -// Class representing TuplePattern patterns where there are multiple patterns -class TuplePatternItemsMultiple : public TuplePatternItems +// Class representing patterns within a TuplePattern, without a rest pattern +class TuplePatternItemsNoRest : public TuplePatternItems { std::vector<std::unique_ptr<Pattern>> patterns; public: - TuplePatternItemsMultiple (std::vector<std::unique_ptr<Pattern>> patterns) + TuplePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) : patterns (std::move (patterns)) {} // Copy constructor with vector clone - TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other) + TuplePatternItemsNoRest (TuplePatternItemsNoRest const &other) { patterns.reserve (other.patterns.size ()); for (const auto &e : other.patterns) @@ -1058,7 +1073,7 @@ public: } // Overloaded assignment operator to vector clone - TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other) + TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest const &other) { patterns.clear (); patterns.reserve (other.patterns.size ()); @@ -1069,15 +1084,15 @@ public: } // move constructors - TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default; - TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other) + TuplePatternItemsNoRest (TuplePatternItemsNoRest &&other) = default; + TuplePatternItemsNoRest &operator= (TuplePatternItemsNoRest &&other) = default; std::string as_string () const override; void accept_vis (HIRFullVisitor &vis) override; - ItemType get_item_type () const override { return ItemType::MULTIPLE; } + ItemType get_item_type () const override { return ItemType::NO_REST; } std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; } const std::vector<std::unique_ptr<Pattern>> &get_patterns () const @@ -1088,27 +1103,29 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TuplePatternItemsMultiple *clone_tuple_items_impl () const override + TuplePatternItemsNoRest *clone_pattern_items_impl () const override { - return new TuplePatternItemsMultiple (*this); + return new TuplePatternItemsNoRest (*this); } }; -// Class representing TuplePattern patterns where there are a range of patterns -class TuplePatternItemsRanged : public TuplePatternItems +// Class representing patterns within a TuplePattern, with a rest pattern +// included +class TuplePatternItemsHasRest : public TuplePatternItems { std::vector<std::unique_ptr<Pattern>> lower_patterns; std::vector<std::unique_ptr<Pattern>> upper_patterns; public: - TuplePatternItemsRanged (std::vector<std::unique_ptr<Pattern>> lower_patterns, - std::vector<std::unique_ptr<Pattern>> upper_patterns) + TuplePatternItemsHasRest ( + std::vector<std::unique_ptr<Pattern>> lower_patterns, + std::vector<std::unique_ptr<Pattern>> upper_patterns) : lower_patterns (std::move (lower_patterns)), upper_patterns (std::move (upper_patterns)) {} // Copy constructor with vector clone - TuplePatternItemsRanged (TuplePatternItemsRanged const &other) + TuplePatternItemsHasRest (TuplePatternItemsHasRest const &other) { lower_patterns.reserve (other.lower_patterns.size ()); for (const auto &e : other.lower_patterns) @@ -1120,7 +1137,7 @@ public: } // Overloaded assignment operator to clone - TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other) + TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest const &other) { lower_patterns.clear (); lower_patterns.reserve (other.lower_patterns.size ()); @@ -1136,15 +1153,15 @@ public: } // move constructors - TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default; - TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other) + TuplePatternItemsHasRest (TuplePatternItemsHasRest &&other) = default; + TuplePatternItemsHasRest &operator= (TuplePatternItemsHasRest &&other) = default; std::string as_string () const override; void accept_vis (HIRFullVisitor &vis) override; - ItemType get_item_type () const override { return ItemType::RANGED; } + ItemType get_item_type () const override { return ItemType::HAS_REST; } std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () { @@ -1167,9 +1184,9 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TuplePatternItemsRanged *clone_tuple_items_impl () const override + TuplePatternItemsHasRest *clone_pattern_items_impl () const override { - return new TuplePatternItemsRanged (*this); + return new TuplePatternItemsHasRest (*this); } }; @@ -1234,10 +1251,161 @@ protected: } }; +// Base abstract class representing SlicePattern patterns +class SlicePatternItems : public PatternItems +{ +public: + // Unique pointer custom clone function + std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const + { + return std::unique_ptr<SlicePatternItems> (clone_pattern_items_impl ()); + } + +protected: + // pure virtual clone implementation + virtual SlicePatternItems *clone_pattern_items_impl () const override = 0; +}; + +// Class representing patterns within a SlicePattern, without a rest pattern +class SlicePatternItemsNoRest : public SlicePatternItems +{ + std::vector<std::unique_ptr<Pattern>> patterns; + +public: + SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns) + : patterns (std::move (patterns)) + {} + + // Copy constructor with vector clone + SlicePatternItemsNoRest (SlicePatternItemsNoRest const &other) + { + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to vector clone + SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest const &other) + { + patterns.clear (); + patterns.reserve (other.patterns.size ()); + for (const auto &e : other.patterns) + patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + SlicePatternItemsNoRest (SlicePatternItemsNoRest &&other) = default; + SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest &&other) + = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + ItemType get_item_type () const override { return ItemType::NO_REST; } + + std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; } + const std::vector<std::unique_ptr<Pattern>> &get_patterns () const + { + return patterns; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePatternItemsNoRest *clone_pattern_items_impl () const override + { + return new SlicePatternItemsNoRest (*this); + } +}; + +// Class representing patterns within a SlicePattern, with a rest pattern +// included +class SlicePatternItemsHasRest : public SlicePatternItems +{ + std::vector<std::unique_ptr<Pattern>> lower_patterns; + std::vector<std::unique_ptr<Pattern>> upper_patterns; + +public: + SlicePatternItemsHasRest ( + std::vector<std::unique_ptr<Pattern>> lower_patterns, + std::vector<std::unique_ptr<Pattern>> upper_patterns) + : lower_patterns (std::move (lower_patterns)), + upper_patterns (std::move (upper_patterns)) + {} + + // Copy constructor with vector clone + SlicePatternItemsHasRest (SlicePatternItemsHasRest const &other) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + } + + // Overloaded assignment operator to clone + SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest const &other) + { + lower_patterns.clear (); + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + lower_patterns.clear (); + upper_patterns.reserve (other.upper_patterns.size ()); + for (const auto &e : other.upper_patterns) + upper_patterns.push_back (e->clone_pattern ()); + + return *this; + } + + // move constructors + SlicePatternItemsHasRest (SlicePatternItemsHasRest &&other) = default; + SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest &&other) + = default; + + std::string as_string () const override; + + void accept_vis (HIRFullVisitor &vis) override; + + ItemType get_item_type () const override { return ItemType::HAS_REST; } + + std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () + { + return lower_patterns; + } + const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const + { + return lower_patterns; + } + + std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () + { + return upper_patterns; + } + const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const + { + return upper_patterns; + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePatternItemsHasRest *clone_pattern_items_impl () const override + { + return new SlicePatternItemsHasRest (*this); + } +}; + // HIR node representing patterns that can match slices and arrays class SlicePattern : public Pattern { - std::vector<std::unique_ptr<Pattern>> items; + std::unique_ptr<SlicePatternItems> items; location_t locus; Analysis::NodeMapping mappings; @@ -1245,30 +1413,23 @@ public: std::string as_string () const override; SlicePattern (Analysis::NodeMapping mappings, - std::vector<std::unique_ptr<Pattern>> items, location_t locus) + std::unique_ptr<SlicePatternItems> items, location_t locus) : items (std::move (items)), locus (locus), mappings (mappings) {} - // Copy constructor with vector clone + // Copy constructor requires clone SlicePattern (SlicePattern const &other) - : locus (other.locus), mappings (other.mappings) - { - items.reserve (other.items.size ()); - for (const auto &e : other.items) - items.push_back (e->clone_pattern ()); - } + : items (other.items->clone_slice_pattern_items ()), locus (other.locus), + mappings (other.mappings) + {} // Overloaded assignment operator to vector clone SlicePattern &operator= (SlicePattern const &other) { + items = other.items->clone_slice_pattern_items (); locus = other.locus; mappings = other.mappings; - items.clear (); - items.reserve (other.items.size ()); - for (const auto &e : other.items) - items.push_back (e->clone_pattern ()); - return *this; } @@ -1276,11 +1437,8 @@ public: SlicePattern (SlicePattern &&other) = default; SlicePattern &operator= (SlicePattern &&other) = default; - std::vector<std::unique_ptr<Pattern>> &get_items () { return items; } - const std::vector<std::unique_ptr<Pattern>> &get_items () const - { - return items; - } + SlicePatternItems &get_items () { return *items; } + const SlicePatternItems &get_items () const { return *items; } location_t get_locus () const override { return locus; } diff --git a/gcc/rust/hir/tree/rust-hir-visitor.cc b/gcc/rust/hir/tree/rust-hir-visitor.cc index 58c1e1a..1e201a5 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.cc +++ b/gcc/rust/hir/tree/rust-hir-visitor.cc @@ -1023,14 +1023,14 @@ DefaultHIRVisitor::walk (StructPattern &pattern) } void -DefaultHIRVisitor::walk (TupleStructItemsNoRange &tuple_items) +DefaultHIRVisitor::walk (TupleStructItemsNoRest &tuple_items) { for (auto &item : tuple_items.get_patterns ()) item->accept_vis (*this); } void -DefaultHIRVisitor::walk (TupleStructItemsRange &tuple_items) +DefaultHIRVisitor::walk (TupleStructItemsHasRest &tuple_items) { for (auto &lower : tuple_items.get_lower_patterns ()) lower->accept_vis (*this); @@ -1046,14 +1046,14 @@ DefaultHIRVisitor::walk (TupleStructPattern &pattern) } void -DefaultHIRVisitor::walk (TuplePatternItemsMultiple &tuple_items) +DefaultHIRVisitor::walk (TuplePatternItemsNoRest &tuple_items) { for (auto &pattern : tuple_items.get_patterns ()) pattern->accept_vis (*this); } void -DefaultHIRVisitor::walk (TuplePatternItemsRanged &tuple_items) +DefaultHIRVisitor::walk (TuplePatternItemsHasRest &tuple_items) { for (auto &lower : tuple_items.get_lower_patterns ()) lower->accept_vis (*this); @@ -1068,10 +1068,25 @@ DefaultHIRVisitor::walk (TuplePattern &pattern) } void +DefaultHIRVisitor::walk (SlicePatternItemsNoRest &items) +{ + for (auto &pattern : items.get_patterns ()) + pattern->accept_vis (*this); +} + +void +DefaultHIRVisitor::walk (SlicePatternItemsHasRest &items) +{ + for (auto &lower : items.get_lower_patterns ()) + lower->accept_vis (*this); + for (auto &upper : items.get_upper_patterns ()) + upper->accept_vis (*this); +} + +void DefaultHIRVisitor::walk (SlicePattern &pattern) { - for (auto &item : pattern.get_items ()) - item->accept_vis (*this); + pattern.get_items ().accept_vis (*this); } void diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h index 7996260..77760b0 100644 --- a/gcc/rust/hir/tree/rust-hir-visitor.h +++ b/gcc/rust/hir/tree/rust-hir-visitor.h @@ -132,12 +132,14 @@ public: virtual void visit (StructPatternFieldIdentPat &field) = 0; virtual void visit (StructPatternFieldIdent &field) = 0; virtual void visit (StructPattern &pattern) = 0; - virtual void visit (TupleStructItemsNoRange &tuple_items) = 0; - virtual void visit (TupleStructItemsRange &tuple_items) = 0; + virtual void visit (TupleStructItemsNoRest &tuple_items) = 0; + virtual void visit (TupleStructItemsHasRest &tuple_items) = 0; virtual void visit (TupleStructPattern &pattern) = 0; - virtual void visit (TuplePatternItemsMultiple &tuple_items) = 0; - virtual void visit (TuplePatternItemsRanged &tuple_items) = 0; + virtual void visit (TuplePatternItemsNoRest &tuple_items) = 0; + virtual void visit (TuplePatternItemsHasRest &tuple_items) = 0; virtual void visit (TuplePattern &pattern) = 0; + virtual void visit (SlicePatternItemsNoRest &items) = 0; + virtual void visit (SlicePatternItemsHasRest &items) = 0; virtual void visit (SlicePattern &pattern) = 0; virtual void visit (AltPattern &pattern) = 0; virtual void visit (EmptyStmt &stmt) = 0; @@ -305,12 +307,14 @@ public: } virtual void visit (StructPatternFieldIdent &node) override { walk (node); } virtual void visit (StructPattern &node) override { walk (node); } - virtual void visit (TupleStructItemsNoRange &node) override { walk (node); } - virtual void visit (TupleStructItemsRange &node) override { walk (node); } + virtual void visit (TupleStructItemsNoRest &node) override { walk (node); } + virtual void visit (TupleStructItemsHasRest &node) override { walk (node); } virtual void visit (TupleStructPattern &node) override { walk (node); } - virtual void visit (TuplePatternItemsMultiple &node) override { walk (node); } - virtual void visit (TuplePatternItemsRanged &node) override { walk (node); } + virtual void visit (TuplePatternItemsNoRest &node) override { walk (node); } + virtual void visit (TuplePatternItemsHasRest &node) override { walk (node); } virtual void visit (TuplePattern &node) override { walk (node); } + virtual void visit (SlicePatternItemsNoRest &node) override { walk (node); } + virtual void visit (SlicePatternItemsHasRest &node) override { walk (node); } virtual void visit (SlicePattern &node) override { walk (node); } virtual void visit (AltPattern &node) override { walk (node); } virtual void visit (EmptyStmt &node) override { walk (node); } @@ -438,12 +442,14 @@ protected: virtual void walk (StructPatternFieldIdentPat &) final; virtual void walk (StructPatternFieldIdent &) final; virtual void walk (StructPattern &) final; - virtual void walk (TupleStructItemsNoRange &) final; - virtual void walk (TupleStructItemsRange &) final; + virtual void walk (TupleStructItemsNoRest &) final; + virtual void walk (TupleStructItemsHasRest &) final; virtual void walk (TupleStructPattern &) final; - virtual void walk (TuplePatternItemsMultiple &) final; - virtual void walk (TuplePatternItemsRanged &) final; + virtual void walk (TuplePatternItemsNoRest &) final; + virtual void walk (TuplePatternItemsHasRest &) final; virtual void walk (TuplePattern &) final; + virtual void walk (SlicePatternItemsNoRest &) final; + virtual void walk (SlicePatternItemsHasRest &) final; virtual void walk (SlicePattern &) final; virtual void walk (AltPattern &) final; virtual void walk (EmptyStmt &) final; @@ -586,13 +592,16 @@ public: virtual void visit (StructPatternFieldIdent &) override {} virtual void visit (StructPattern &) override {} - virtual void visit (TupleStructItemsNoRange &) override {} - virtual void visit (TupleStructItemsRange &) override {} + virtual void visit (TupleStructItemsNoRest &) override {} + virtual void visit (TupleStructItemsHasRest &) override {} virtual void visit (TupleStructPattern &) override {} - virtual void visit (TuplePatternItemsMultiple &) override {} - virtual void visit (TuplePatternItemsRanged &) override {} + virtual void visit (TuplePatternItemsNoRest &) override {} + virtual void visit (TuplePatternItemsHasRest &) override {} virtual void visit (TuplePattern &) override {} + + virtual void visit (SlicePatternItemsNoRest &) override {} + virtual void visit (SlicePatternItemsHasRest &) override {} virtual void visit (SlicePattern &) override {} virtual void visit (AltPattern &) override {} diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index a802e8c..ce10b02 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -2239,8 +2239,8 @@ PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const // create segment and add to vector std::string segment_str = segment.as_string (); - simple_segments.push_back ( - AST::SimplePathSegment (std::move (segment_str), segment.get_locus ())); + simple_segments.emplace_back (std::move (segment_str), + segment.get_locus ()); } // kind of a HACK to get locus depending on opening scope resolution @@ -2281,9 +2281,8 @@ TypePath::as_simple_path () const // create segment and add to vector std::string segment_str = segment->as_string (); - simple_segments.push_back ( - AST::SimplePathSegment (std::move (segment_str), - segment->get_locus ())); + simple_segments.emplace_back (std::move (segment_str), + segment->get_locus ()); } return AST::SimplePath (std::move (simple_segments), @@ -2387,11 +2386,11 @@ RangePatternBoundLiteral::as_string () const } std::string -SlicePattern::as_string () const +SlicePatternItemsNoRest::as_string () const { - std::string str ("SlicePattern: "); + std::string str; - for (const auto &pattern : items) + for (const auto &pattern : patterns) { str += "\n " + pattern->as_string (); } @@ -2400,6 +2399,46 @@ SlicePattern::as_string () const } std::string +SlicePatternItemsHasRest::as_string () const +{ + std::string str; + + str += "\n Lower patterns: "; + if (lower_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &lower : lower_patterns) + { + str += "\n " + lower->as_string (); + } + } + + str += "\n Upper patterns: "; + if (upper_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &upper : upper_patterns) + { + str += "\n " + upper->as_string (); + } + } + + return str; +} + +std::string +SlicePattern::as_string () const +{ + return "SlicePattern: " + items->as_string (); +} + +std::string AltPattern::as_string () const { std::string str ("AltPattern: "); @@ -2413,7 +2452,7 @@ AltPattern::as_string () const } std::string -TuplePatternItemsMultiple::as_string () const +TuplePatternItemsNoRest::as_string () const { std::string str; @@ -2426,7 +2465,7 @@ TuplePatternItemsMultiple::as_string () const } std::string -TuplePatternItemsRanged::as_string () const +TuplePatternItemsHasRest::as_string () const { std::string str; @@ -2480,10 +2519,29 @@ StructPatternField::as_string () const * just the body */ for (const auto &attr : outer_attrs) { - str += "\n " + attr.as_string (); + str += "\n " + attr.as_string (); } } + str += "\n item type: "; + switch (get_item_type ()) + { + case ItemType::TUPLE_PAT: + str += "TUPLE_PAT"; + break; + case ItemType::IDENT_PAT: + str += "IDENT_PAT"; + break; + case ItemType::IDENT: + str += "IDENT"; + break; + default: + str += "UNKNOWN"; + break; + } + + str += "\n mapping: " + mappings.as_string (); + return str; } @@ -2620,7 +2678,7 @@ IdentifierPattern::as_string () const } std::string -TupleStructItemsNoRange::as_string () const +TupleStructItemsNoRest::as_string () const { std::string str; @@ -2633,7 +2691,7 @@ TupleStructItemsNoRange::as_string () const } std::string -TupleStructItemsRange::as_string () const +TupleStructItemsHasRest::as_string () const { std::string str ("\n Lower patterns: "); @@ -4471,13 +4529,13 @@ StructPattern::accept_vis (HIRFullVisitor &vis) } void -TupleStructItemsNoRange::accept_vis (HIRFullVisitor &vis) +TupleStructItemsNoRest::accept_vis (HIRFullVisitor &vis) { vis.visit (*this); } void -TupleStructItemsRange::accept_vis (HIRFullVisitor &vis) +TupleStructItemsHasRest::accept_vis (HIRFullVisitor &vis) { vis.visit (*this); } @@ -4489,13 +4547,13 @@ TupleStructPattern::accept_vis (HIRFullVisitor &vis) } void -TuplePatternItemsMultiple::accept_vis (HIRFullVisitor &vis) +TuplePatternItemsNoRest::accept_vis (HIRFullVisitor &vis) { vis.visit (*this); } void -TuplePatternItemsRanged::accept_vis (HIRFullVisitor &vis) +TuplePatternItemsHasRest::accept_vis (HIRFullVisitor &vis) { vis.visit (*this); } @@ -4507,6 +4565,18 @@ TuplePattern::accept_vis (HIRFullVisitor &vis) } void +SlicePatternItemsNoRest::accept_vis (HIRFullVisitor &vis) +{ + vis.visit (*this); +} + +void +SlicePatternItemsHasRest::accept_vis (HIRFullVisitor &vis) +{ + vis.visit (*this); +} + +void SlicePattern::accept_vis (HIRFullVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index 76ff15c..214161f 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -236,10 +236,11 @@ Lexer::dump_and_skip (int n) out << "<id="; out << tok->token_id_to_str (); - out << (tok->has_str () ? (std::string (", text=") + tok->get_str () - + std::string (", typehint=") - + std::string (tok->get_type_hint_str ())) - : "") + out << (tok->should_have_str () + ? (std::string (", text=") + tok->get_str () + + std::string (", typehint=") + + std::string (tok->get_type_hint_str ())) + : "") << " "; out << Linemap::location_to_string (loc) << '\n'; } diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc index c396e10..43682af 100644 --- a/gcc/rust/lex/rust-token.cc +++ b/gcc/rust/lex/rust-token.cc @@ -178,29 +178,6 @@ nfc_normalize_token_string (location_t loc, TokenId id, const std::string &str) return str; } -const std::string & -Token::get_str () const -{ - if (token_id_is_keyword (token_id)) - return token_id_keyword_string (token_id); - - // FIXME: attempt to return null again - // gcc_assert(str != NULL); - - // HACK: allow referencing an empty string - static const std::string empty = ""; - - if (str == NULL) - { - rust_error_at (get_locus (), - "attempted to get string for %qs, which has no string. " - "returning empty string instead", - get_token_description ()); - return empty; - } - return *str; -} - namespace { enum class Context { diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index 2021aec..71a7503 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -22,6 +22,7 @@ #include "rust-system.h" #include "rust-linemap.h" #include "rust-unicode.h" +#include "rust-diagnostics.h" namespace Rust { @@ -249,7 +250,7 @@ private: // Token location. location_t locus; // Associated text (if any) of token. - std::unique_ptr<std::string> str; + std::string str; // TODO: maybe remove issues and just store std::string as value? /* Type hint for token based on lexer data (e.g. type suffix). Does not exist * for most tokens. */ @@ -257,23 +258,21 @@ private: // Token constructor from token id and location. Has a null string. Token (TokenId token_id, location_t location) - : token_id (token_id), locus (location), str (nullptr), - type_hint (CORETYPE_UNKNOWN) + : token_id (token_id), locus (location), type_hint (CORETYPE_UNKNOWN) {} // Token constructor from token id, location, and a string. - Token (TokenId token_id, location_t location, std::string &¶mStr) + Token (TokenId token_id, location_t location, std::string paramStr) : token_id (token_id), locus (location), type_hint (CORETYPE_UNKNOWN) { // Normalize identifier tokens - str = std::make_unique<std::string> ( - nfc_normalize_token_string (location, token_id, paramStr)); + str = nfc_normalize_token_string (location, token_id, std::move (paramStr)); } // Token constructor from token id, location, and a char. Token (TokenId token_id, location_t location, char paramChar) - : token_id (token_id), locus (location), - str (new std::string (1, paramChar)), type_hint (CORETYPE_UNKNOWN) + : token_id (token_id), locus (location), str (1, paramChar), + type_hint (CORETYPE_UNKNOWN) { // Do not need to normalize 1byte char } @@ -283,19 +282,17 @@ private: : token_id (token_id), locus (location), type_hint (CORETYPE_UNKNOWN) { // Normalize identifier tokens - str = std::make_unique<std::string> ( - nfc_normalize_token_string (location, token_id, - paramCodepoint.as_string ())); + str = nfc_normalize_token_string (location, token_id, + paramCodepoint.as_string ()); } // Token constructor from token id, location, a string, and type hint. - Token (TokenId token_id, location_t location, std::string &¶mStr, + Token (TokenId token_id, location_t location, std::string paramStr, PrimitiveCoreType parType) : token_id (token_id), locus (location), type_hint (parType) { // Normalize identifier tokens - str = std::make_unique<std::string> ( - nfc_normalize_token_string (location, token_id, paramStr)); + str = nfc_normalize_token_string (location, token_id, std::move (paramStr)); } public: @@ -322,7 +319,7 @@ public: } // Makes and returns a new TokenPtr of type IDENTIFIER. - static TokenPtr make_identifier (location_t locus, std::string &&str) + static TokenPtr make_identifier (location_t locus, std::string str) { // return std::make_shared<Token> (IDENTIFIER, locus, str); return TokenPtr (new Token (IDENTIFIER, locus, std::move (str))); @@ -331,7 +328,7 @@ public: 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, + static TokenPtr make_int (location_t locus, std::string str, PrimitiveCoreType type_hint = CORETYPE_UNKNOWN) { // return std::make_shared<Token> (INT_LITERAL, locus, str, type_hint); @@ -340,7 +337,7 @@ public: } // Makes and returns a new TokenPtr of type FLOAT_LITERAL. - static TokenPtr make_float (location_t locus, std::string &&str, + static TokenPtr make_float (location_t locus, std::string str, PrimitiveCoreType type_hint = CORETYPE_UNKNOWN) { // return std::make_shared<Token> (FLOAT_LITERAL, locus, str, type_hint); @@ -349,7 +346,7 @@ public: } // Makes and returns a new TokenPtr of type STRING_LITERAL. - static TokenPtr make_string (location_t locus, std::string &&str) + static TokenPtr make_string (location_t locus, std::string str) { // return std::make_shared<Token> (STRING_LITERAL, locus, str, // CORETYPE_STR); @@ -372,32 +369,32 @@ public: } // Makes and returns a new TokenPtr of type BYTE_STRING_LITERAL (fix). - static TokenPtr make_byte_string (location_t locus, std::string &&str) + static TokenPtr make_byte_string (location_t locus, std::string str) { // return std::make_shared<Token> (BYTE_STRING_LITERAL, locus, str); return TokenPtr (new Token (BYTE_STRING_LITERAL, locus, std::move (str))); } // Makes and returns a new TokenPtr of type RAW_STRING_LITERAL. - static TokenPtr make_raw_string (location_t locus, std::string &&str) + static TokenPtr make_raw_string (location_t locus, std::string str) { return TokenPtr (new Token (RAW_STRING_LITERAL, locus, std::move (str))); } // Makes and returns a new TokenPtr of type INNER_DOC_COMMENT. - static TokenPtr make_inner_doc_comment (location_t locus, std::string &&str) + static TokenPtr make_inner_doc_comment (location_t locus, std::string str) { return TokenPtr (new Token (INNER_DOC_COMMENT, locus, std::move (str))); } // Makes and returns a new TokenPtr of type OUTER_DOC_COMMENT. - static TokenPtr make_outer_doc_comment (location_t locus, std::string &&str) + static TokenPtr make_outer_doc_comment (location_t locus, std::string str) { return TokenPtr (new Token (OUTER_DOC_COMMENT, locus, std::move (str))); } // Makes and returns a new TokenPtr of type LIFETIME. - static TokenPtr make_lifetime (location_t locus, std::string &&str) + static TokenPtr make_lifetime (location_t locus, std::string str) { // return std::make_shared<Token> (LIFETIME, locus, str); return TokenPtr (new Token (LIFETIME, locus, std::move (str))); @@ -413,16 +410,18 @@ public: void set_locus (location_t locus) { this->locus = locus; } // Gets string description of the token. - const std::string & - get_str () const; /*{ -// FIXME: put in header again when fix null problem -//gcc_assert(str != nullptr); -if (str == nullptr) { -error_at(get_locus(), "attempted to get string for '%s', which has no string. -returning empty string instead.", get_token_description()); return ""; -} -return *str; -}*/ + const std::string &get_str () const + { + if (token_id_is_keyword (token_id)) + return token_id_keyword_string (token_id); + + if (!should_have_str ()) + rust_internal_error_at ( + locus, "attempting to get string for %qs, which should have no string", + get_token_description ()); + + return str; + } // Gets token's type hint info. PrimitiveCoreType get_type_hint () const @@ -464,14 +463,11 @@ return *str; } } - /* Returns whether the token actually has a string (regardless of whether it - * should or not). */ - bool has_str () const { return str != nullptr; } - // Returns whether the token should have a string. bool should_have_str () const { - return is_literal () || token_id == IDENTIFIER || token_id == LIFETIME; + return is_literal () || token_id == IDENTIFIER || token_id == LIFETIME + || token_id == INNER_DOC_COMMENT || token_id == OUTER_DOC_COMMENT; } // Returns whether the token is a pure decimal int literal diff --git a/gcc/rust/metadata/rust-export-metadata.cc b/gcc/rust/metadata/rust-export-metadata.cc index 1829a85..4dfc280 100644 --- a/gcc/rust/metadata/rust-export-metadata.cc +++ b/gcc/rust/metadata/rust-export-metadata.cc @@ -91,8 +91,8 @@ ExportContext::emit_function (const HIR::Function &fn) AST::Function &function = static_cast<AST::Function &> (vis_item); std::vector<std::unique_ptr<AST::ExternalItem>> external_items; - external_items.push_back (std::unique_ptr<AST::ExternalItem> ( - static_cast<AST::ExternalItem *> (&function))); + external_items.emplace_back ( + static_cast<AST::ExternalItem *> (&function)); AST::ExternBlock extern_block (get_string_from_abi (Rust::ABI::RUST), std::move (external_items), diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 14bccbd..ec4c1c1 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -1053,6 +1053,7 @@ Parser<ManagedTokenSource>::parse_identifier_or_keyword_token () } else { + add_error (Error (t->get_locus (), "expected keyword or identifier")); return nullptr; } } @@ -1716,10 +1717,9 @@ Parser<ManagedTokenSource>::parse_decl_macro_def (AST::Visibility vis, return nullptr; } - AST::MacroRule macro_rule - = AST::MacroRule (std::move (matcher), std::move (transcriber), locus); std::vector<AST::MacroRule> macro_rules; - macro_rules.push_back (macro_rule); + macro_rules.emplace_back (std::move (matcher), std::move (transcriber), + locus); return std::unique_ptr<AST::MacroRulesDefinition> ( AST::MacroRulesDefinition::decl_macro (std::move (rule_name), @@ -3316,8 +3316,8 @@ Parser<ManagedTokenSource>::parse_lifetime_params () break; } - lifetime_params.push_back (std::unique_ptr<AST::LifetimeParam> ( - new AST::LifetimeParam (std::move (lifetime_param.value ())))); + lifetime_params.emplace_back ( + new AST::LifetimeParam (std::move (lifetime_param.value ()))); if (lexer.peek_token ()->get_id () != COMMA) break; @@ -3356,8 +3356,8 @@ Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token) return {}; } - lifetime_params.push_back (std::unique_ptr<AST::LifetimeParam> ( - new AST::LifetimeParam (std::move (lifetime_param)))); + lifetime_params.emplace_back ( + new AST::LifetimeParam (std::move (lifetime_param))); if (lexer.peek_token ()->get_id () != COMMA) break; @@ -5219,7 +5219,7 @@ Parser<ManagedTokenSource>::parse_trait_type (AST::AttrVec outer_attrs, // Parses a constant trait item. template <typename ManagedTokenSource> -std::unique_ptr<AST::TraitItemConst> +std::unique_ptr<AST::ConstantItem> Parser<ManagedTokenSource>::parse_trait_const (AST::AttrVec outer_attrs) { location_t locus = lexer.peek_token ()->get_locus (); @@ -5257,10 +5257,9 @@ Parser<ManagedTokenSource>::parse_trait_const (AST::AttrVec outer_attrs) return nullptr; } - return std::unique_ptr<AST::TraitItemConst> ( - new AST::TraitItemConst (std::move (ident), std::move (type), - std::move (const_body), std::move (outer_attrs), - locus)); + return std::unique_ptr<AST::ConstantItem> (new AST::ConstantItem ( + std::move (ident), AST::Visibility::create_private (), std::move (type), + std::move (const_body), std::move (outer_attrs), locus)); } /* Parses a struct "impl" item (both inherent impl and trait impl can be @@ -10484,16 +10483,22 @@ Parser<ManagedTokenSource>::parse_pattern () return first; std::vector<std::unique_ptr<AST::Pattern>> alts; - alts.push_back (std::move (first)); + if (first != nullptr) + alts.push_back (std::move (first)); do { lexer.skip_token (); - alts.push_back (parse_pattern_no_alt ()); + auto follow = parse_pattern_no_alt (); + if (follow != nullptr) + alts.push_back (std::move (follow)); } while (lexer.peek_token ()->get_id () == PIPE); + if (alts.empty ()) + return nullptr; + /* alternates */ return std::unique_ptr<AST::Pattern> ( new AST::AltPattern (std::move (alts), start_locus)); @@ -10812,9 +10817,9 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () return nullptr; } - // create ranged tuple pattern items with only upper items - std::unique_ptr<AST::TuplePatternItemsRanged> items ( - new AST::TuplePatternItemsRanged ( + // create tuple pattern items with only upper pattern items + std::unique_ptr<AST::TuplePatternItemsHasRest> items ( + new AST::TuplePatternItemsHasRest ( std::vector<std::unique_ptr<AST::Pattern>> (), std::move (patterns))); return std::unique_ptr<AST::TuplePattern> ( new AST::TuplePattern (std::move (items), paren_locus)); @@ -10822,8 +10827,8 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () else if (lexer.peek_token ()->get_id () == RIGHT_PAREN) { skip_token (RIGHT_PAREN); - auto items = std::unique_ptr<AST::TuplePatternItemsMultiple> ( - new AST::TuplePatternItemsMultiple ( + auto items = std::unique_ptr<AST::TuplePatternItemsNoRest> ( + new AST::TuplePatternItemsNoRest ( std::vector<std::unique_ptr<AST::Pattern>> ())); return std::unique_ptr<AST::TuplePattern> ( new AST::TuplePattern (std::move (items), paren_locus)); @@ -10887,8 +10892,8 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () // non-ranged tuple pattern lexer.skip_token (); - std::unique_ptr<AST::TuplePatternItemsMultiple> items ( - new AST::TuplePatternItemsMultiple (std::move (patterns))); + std::unique_ptr<AST::TuplePatternItemsNoRest> items ( + new AST::TuplePatternItemsNoRest (std::move (patterns))); return std::unique_ptr<AST::TuplePattern> ( new AST::TuplePattern (std::move (items), paren_locus)); } @@ -10928,9 +10933,9 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern () return nullptr; } - std::unique_ptr<AST::TuplePatternItemsRanged> items ( - new AST::TuplePatternItemsRanged (std::move (patterns), - std::move (upper_patterns))); + std::unique_ptr<AST::TuplePatternItemsHasRest> items ( + new AST::TuplePatternItemsHasRest (std::move (patterns), + std::move (upper_patterns))); return std::unique_ptr<AST::TuplePattern> ( new AST::TuplePattern (std::move (items), paren_locus)); } @@ -11113,7 +11118,7 @@ Parser<ManagedTokenSource>::parse_identifier_pattern () lexer.skip_token (); // parse required pattern to bind - bind_pattern = parse_pattern (); + bind_pattern = parse_pattern_no_alt (); if (bind_pattern == nullptr) { Error error (lexer.peek_token ()->get_locus (), @@ -11240,7 +11245,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern () // identifier with pattern bind lexer.skip_token (); - std::unique_ptr<AST::Pattern> bind_pattern = parse_pattern (); + std::unique_ptr<AST::Pattern> bind_pattern + = parse_pattern_no_alt (); if (bind_pattern == nullptr) { Error error ( @@ -11325,9 +11331,9 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items () rust_debug ( "finished parsing tuple struct items ranged (upper/none only)"); - return std::unique_ptr<AST::TupleStructItemsRange> ( - new AST::TupleStructItemsRange (std::move (lower_patterns), - std::move (upper_patterns))); + return std::unique_ptr<AST::TupleStructItemsHasRest> ( + new AST::TupleStructItemsHasRest (std::move (lower_patterns), + std::move (upper_patterns))); } // has at least some lower patterns @@ -11369,8 +11375,8 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items () switch (t->get_id ()) { case RIGHT_PAREN: - return std::unique_ptr<AST::TupleStructItemsNoRange> ( - new AST::TupleStructItemsNoRange (std::move (lower_patterns))); + return std::unique_ptr<AST::TupleStructItemsNoRest> ( + new AST::TupleStructItemsNoRest (std::move (lower_patterns))); case DOT_DOT: { // has an upper range that must be parsed separately @@ -11402,9 +11408,9 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items () t = lexer.peek_token (); } - return std::unique_ptr<AST::TupleStructItemsRange> ( - new AST::TupleStructItemsRange (std::move (lower_patterns), - std::move (upper_patterns))); + return std::unique_ptr<AST::TupleStructItemsHasRest> ( + new AST::TupleStructItemsHasRest (std::move (lower_patterns), + std::move (upper_patterns))); } default: // error @@ -11424,7 +11430,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems () std::vector<std::unique_ptr<AST::StructPatternField>> fields; AST::AttrVec etc_attrs; - bool has_etc = false; + bool has_rest = false; // try parsing struct pattern fields const_TokenPtr t = lexer.peek_token (); @@ -11437,7 +11443,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems () { lexer.skip_token (); etc_attrs = std::move (outer_attrs); - has_etc = true; + has_rest = true; break; } @@ -11462,7 +11468,7 @@ Parser<ManagedTokenSource>::parse_struct_pattern_elems () t = lexer.peek_token (); } - if (has_etc) + if (has_rest) return AST::StructPatternElements (std::move (fields), std::move (etc_attrs)); else @@ -11761,6 +11767,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr () std::unique_ptr<AST::MacroInvocation> invoc = parse_macro_invocation_partial (std::move (path), std::move (outer_attrs)); + if (invoc == nullptr) + return ExprOrStmt::create_error (); if (restrictions.consume_semi && maybe_skip_token (SEMICOLON)) { @@ -11772,9 +11780,12 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr () TokenId after_macro = lexer.peek_token ()->get_id (); - if (invoc->get_invoc_data ().get_delim_tok_tree ().get_delim_type () - == AST::CURLY - && after_macro != DOT && after_macro != QUESTION_MARK) + AST::DelimType delim_type = invoc->get_invoc_data () + .get_delim_tok_tree () + .get_delim_type (); + + if (delim_type == AST::CURLY && after_macro != DOT + && after_macro != QUESTION_MARK) { rust_debug ("braced macro statement"); return ExprOrStmt ( @@ -12149,20 +12160,12 @@ Parser<ManagedTokenSource>::parse_expr (int right_binding_power, return nullptr; } - if (current_token->get_id () == LEFT_SHIFT) - { - lexer.split_current_token (LEFT_ANGLE, LEFT_ANGLE); - current_token = lexer.peek_token (); - } - - lexer.skip_token (); - ParseRestrictions null_denotation_restrictions = restrictions; null_denotation_restrictions.expr_can_be_stmt = false; // parse null denotation (unary part of expression) std::unique_ptr<AST::Expr> expr - = null_denotation (current_token, {}, null_denotation_restrictions); + = null_denotation ({}, null_denotation_restrictions); return left_denotations (std::move (expr), right_binding_power, std::move (outer_attrs), restrictions); @@ -12230,8 +12233,7 @@ Parser<ManagedTokenSource>::parse_expr (AST::AttrVec outer_attrs, /* Determines action to take when finding token at beginning of expression. */ template <typename ManagedTokenSource> std::unique_ptr<AST::Expr> -Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok, - AST::AttrVec outer_attrs, +Parser<ManagedTokenSource>::null_denotation (AST::AttrVec outer_attrs, ParseRestrictions restrictions) { /* note: tok is previous character in input stream, not current one, as @@ -12241,6 +12243,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok, * denotation and then a left denotation), null denotations handle primaries * and unary operands (but only prefix unary operands) */ + auto tok = lexer.peek_token (); + switch (tok->get_id ()) { case IDENTIFIER: @@ -12249,28 +12253,26 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok, case DOLLAR_SIGN: case CRATE: case SUPER: + case SCOPE_RESOLUTION: { // DEBUG rust_debug ("beginning null denotation identifier handling"); /* best option: parse as path, then extract identifier, macro, * struct/enum, or just path info from it */ - AST::PathInExpression path = parse_path_in_expression_pratt (tok); + AST::PathInExpression path = parse_path_in_expression (); return null_denotation_path (std::move (path), std::move (outer_attrs), restrictions); } - 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 " - "have not written handling for it"); - add_error (std::move (error)); - - return nullptr; - } default: + if (tok->get_id () == LEFT_SHIFT) + { + lexer.split_current_token (LEFT_ANGLE, LEFT_ANGLE); + tok = lexer.peek_token (); + } + + lexer.skip_token (); return null_denotation_not_path (std::move (tok), std::move (outer_attrs), restrictions); } @@ -13035,12 +13037,6 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok, // array or slice index expression (pseudo binary infix) return parse_index_expr (tok, std::move (left), std::move (outer_attrs), restrictions); - case FLOAT_LITERAL: - /* HACK: get around lexer mis-identifying '.0' or '.1' or whatever as a - * float literal - TODO does this happen anymore? It shouldn't. */ - return parse_tuple_index_expr_float (tok, std::move (left), - std::move (outer_attrs), - restrictions); default: add_error (Error (tok->get_locus (), "found unexpected token %qs in left denotation", @@ -14436,119 +14432,6 @@ Parser<ManagedTokenSource>::parse_struct_expr_tuple_partial ( std::move (outer_attrs), path_locus)); } -/* Parses a path in expression with the first token passed as a parameter (as - * it is skipped in token stream). Note that this only parses segment-first - * paths, not global ones. */ -template <typename ManagedTokenSource> -AST::PathInExpression -Parser<ManagedTokenSource>::parse_path_in_expression_pratt (const_TokenPtr tok) -{ - // HACK-y way of making up for pratt-parsing consuming first token - - // DEBUG - rust_debug ("current peek token when starting path pratt parse: '%s'", - lexer.peek_token ()->get_token_description ()); - - // create segment vector - std::vector<AST::PathExprSegment> segments; - - std::string initial_str; - - switch (tok->get_id ()) - { - case IDENTIFIER: - initial_str = tok->get_str (); - break; - case SUPER: - initial_str = Values::Keywords::SUPER; - break; - case SELF: - initial_str = Values::Keywords::SELF; - break; - case SELF_ALIAS: - initial_str = Values::Keywords::SELF_ALIAS; - break; - case CRATE: - initial_str = Values::Keywords::CRATE; - break; - case DOLLAR_SIGN: - if (lexer.peek_token ()->get_id () == CRATE) - { - initial_str = "$crate"; - break; - } - gcc_fallthrough (); - default: - add_error (Error (tok->get_locus (), - "unrecognised token %qs in path in expression", - tok->get_token_description ())); - - return AST::PathInExpression::create_error (); - } - - // parse required initial segment - AST::PathExprSegment initial_segment (initial_str, tok->get_locus ()); - // parse generic args (and turbofish), if they exist - /* use lookahead to determine if they actually exist (don't want to - * accidently parse over next ident segment) */ - if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION - && lexer.peek_token (1)->get_id () == LEFT_ANGLE) - { - // skip scope resolution - lexer.skip_token (); - - AST::GenericArgs generic_args = parse_path_generic_args (); - - initial_segment - = AST::PathExprSegment (AST::PathIdentSegment (initial_str, - tok->get_locus ()), - tok->get_locus (), std::move (generic_args)); - } - if (initial_segment.is_error ()) - { - // skip after somewhere? - // don't necessarily throw error but yeah - - // DEBUG - rust_debug ("initial segment is error - returning null"); - - return AST::PathInExpression::create_error (); - } - segments.push_back (std::move (initial_segment)); - - // parse optional segments (as long as scope resolution operator exists) - const_TokenPtr t = lexer.peek_token (); - while (t->get_id () == SCOPE_RESOLUTION) - { - // skip scope resolution operator - lexer.skip_token (); - - // parse the actual segment - it is an error if it doesn't exist now - AST::PathExprSegment segment = parse_path_expr_segment (); - if (segment.is_error ()) - { - // skip after somewhere? - Error error (t->get_locus (), - "could not parse path expression segment"); - add_error (std::move (error)); - - return AST::PathInExpression::create_error (); - } - - segments.push_back (std::move (segment)); - - t = lexer.peek_token (); - } - - // DEBUG: - rust_debug ( - "current token (just about to return path to null denotation): '%s'", - lexer.peek_token ()->get_token_description ()); - - return AST::PathInExpression (std::move (segments), {}, tok->get_locus (), - false); -} - // Parses a closure expression with pratt parsing (from null denotation). template <typename ManagedTokenSource> std::unique_ptr<AST::ClosureExpr> @@ -14686,35 +14569,6 @@ Parser<ManagedTokenSource>::parse_closure_expr_pratt (const_TokenPtr tok, } } -/* Parses a tuple index expression (pratt-parsed) from a 'float' token as a - * result of lexer misidentification. */ -template <typename ManagedTokenSource> -std::unique_ptr<AST::TupleIndexExpr> -Parser<ManagedTokenSource>::parse_tuple_index_expr_float ( - const_TokenPtr tok, std::unique_ptr<AST::Expr> tuple_expr, - AST::AttrVec outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED) -{ - // only works on float literals - if (tok->get_id () != FLOAT_LITERAL) - return nullptr; - - // DEBUG: - rust_debug ("exact string form of float: '%s'", tok->get_str ().c_str ()); - - // get float string and remove dot and initial 0 - std::string index_str = tok->get_str (); - index_str.erase (index_str.begin ()); - - // get int from string - int index = atoi (index_str.c_str ()); - - location_t locus = tuple_expr->get_locus (); - - return std::unique_ptr<AST::TupleIndexExpr> ( - new AST::TupleIndexExpr (std::move (tuple_expr), index, - std::move (outer_attrs), locus)); -} - // Returns true if the next token is END, ELSE, or EOF; template <typename ManagedTokenSource> bool diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 8253885..7b40463 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -212,6 +212,11 @@ public: std::unique_ptr<AST::MacroInvocation> parse_macro_invocation (AST::AttrVec outer_attrs); + /* + * This has to be public for parsing expressions with outer attributes + */ + AST::AttrVec parse_outer_attributes (); + private: void skip_after_semicolon (); void skip_after_end (); @@ -228,7 +233,6 @@ private: // AST-related stuff - maybe move or something? AST::Attribute parse_inner_attribute (); - AST::AttrVec parse_outer_attributes (); AST::Attribute parse_outer_attribute (); std::unique_ptr<AST::AttrInput> parse_attr_input (); std::tuple<AST::SimplePath, std::unique_ptr<AST::AttrInput>, location_t> @@ -368,7 +372,7 @@ private: AST::AttrVec outer_attrs); std::unique_ptr<AST::TraitItemType> parse_trait_type (AST::AttrVec outer_attrs, AST::Visibility); - std::unique_ptr<AST::TraitItemConst> + std::unique_ptr<AST::ConstantItem> parse_trait_const (AST::AttrVec outer_attrs); tl::expected<std::unique_ptr<AST::Param>, ParseSelfError> parse_self_param (); @@ -393,7 +397,7 @@ private: AST::AttrVec outer_attrs = AST::AttrVec (), ParseRestrictions restrictions = ParseRestrictions ()); std::unique_ptr<AST::Expr> - null_denotation (const_TokenPtr t, AST::AttrVec outer_attrs = AST::AttrVec (), + null_denotation (AST::AttrVec outer_attrs = AST::AttrVec (), ParseRestrictions restrictions = ParseRestrictions ()); std::unique_ptr<AST::Expr> null_denotation_path (AST::PathInExpression path, AST::AttrVec outer_attrs, @@ -598,7 +602,6 @@ private: std::unique_ptr<AST::CallExpr> parse_struct_expr_tuple_partial (AST::PathInExpression path, AST::AttrVec outer_attrs); - AST::PathInExpression parse_path_in_expression_pratt (const_TokenPtr tok); std::unique_ptr<AST::ClosureExpr> parse_closure_expr_pratt (const_TokenPtr tok, AST::AttrVec outer_attrs = AST::AttrVec ()); @@ -782,7 +785,7 @@ private: // don't want to make things *only* AttributeParser uses public // TODO: fold more of AttributeParser into Parser? - friend class ::Rust::AST::AttributeParser; + friend struct ::Rust::AST::AttributeParser; }; std::string extract_module_path (const AST::AttrVec &inner_attrs, diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc deleted file mode 100644 index 3c7b425..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-base.cc +++ /dev/null @@ -1,691 +0,0 @@ -// Copyright (C) 2020-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-ast-resolve-base.h" -#include "rust-ast-resolve-expr.h" -#include "rust-ast-resolve-path.h" -#include "rust-item.h" -#include "rust-path.h" - -namespace Rust { -namespace Resolver { - -bool -ResolverBase::resolve_visibility (const AST::Visibility &vis) -{ - if (vis.has_path ()) - { - auto path = vis.get_path (); - ResolvePath::go (path); - - // Do we need to lookup something here? - // Is it just about resolving the names correctly so we can look them up - // later? - } - - return true; -} - -// Default visitors implementations - -void -ResolverBase::visit (AST::Token &) -{} - -void -ResolverBase::visit (AST::DelimTokenTree &) -{} - -void -ResolverBase::visit (AST::AttrInputMetaItemContainer &) -{} - -void -ResolverBase::visit (AST::IdentifierExpr &) -{} - -void -ResolverBase::visit (AST::Lifetime &) -{} - -void -ResolverBase::visit (AST::LifetimeParam &) -{} - -void -ResolverBase::visit (AST::ConstGenericParam &) -{} - -void -ResolverBase::visit (AST::PathInExpression &) -{} - -void -ResolverBase::visit (AST::TypePathSegment &) -{} - -void -ResolverBase::visit (AST::TypePathSegmentGeneric &) -{} - -void -ResolverBase::visit (AST::TypePathSegmentFunction &) -{} - -void -ResolverBase::visit (AST::TypePath &) -{} - -void -ResolverBase::visit (AST::QualifiedPathInExpression &) -{} - -void -ResolverBase::visit (AST::QualifiedPathInType &) -{} - -void -ResolverBase::visit (AST::LiteralExpr &) -{} - -void -ResolverBase::visit (AST::AttrInputLiteral &) -{} - -void -ResolverBase::visit (AST::AttrInputMacro &) -{} - -void -ResolverBase::visit (AST::MetaItemLitExpr &) -{} - -void -ResolverBase::visit (AST::MetaItemPathExpr &) -{} - -void -ResolverBase::visit (AST::BorrowExpr &) -{} - -void -ResolverBase::visit (AST::DereferenceExpr &) -{} - -void -ResolverBase::visit (AST::ErrorPropagationExpr &) -{} - -void -ResolverBase::visit (AST::NegationExpr &) -{} - -void -ResolverBase::visit (AST::ArithmeticOrLogicalExpr &) -{} - -void -ResolverBase::visit (AST::ComparisonExpr &) -{} - -void -ResolverBase::visit (AST::LazyBooleanExpr &) -{} - -void -ResolverBase::visit (AST::TypeCastExpr &) -{} - -void -ResolverBase::visit (AST::AssignmentExpr &) -{} - -void -ResolverBase::visit (AST::CompoundAssignmentExpr &) -{} - -void -ResolverBase::visit (AST::GroupedExpr &) -{} - -void -ResolverBase::visit (AST::ArrayElemsValues &) -{} - -void -ResolverBase::visit (AST::ArrayElemsCopied &) -{} - -void -ResolverBase::visit (AST::ArrayExpr &) -{} - -void -ResolverBase::visit (AST::ArrayIndexExpr &) -{} - -void -ResolverBase::visit (AST::TupleExpr &) -{} - -void -ResolverBase::visit (AST::TupleIndexExpr &) -{} - -void -ResolverBase::visit (AST::StructExprStruct &) -{} - -void -ResolverBase::visit (AST::StructExprFieldIdentifier &) -{} - -void -ResolverBase::visit (AST::StructExprFieldIdentifierValue &) -{} - -void -ResolverBase::visit (AST::StructExprFieldIndexValue &) -{} - -void -ResolverBase::visit (AST::StructExprStructFields &) -{} - -void -ResolverBase::visit (AST::StructExprStructBase &) -{} - -void -ResolverBase::visit (AST::CallExpr &) -{} - -void -ResolverBase::visit (AST::MethodCallExpr &) -{} - -void -ResolverBase::visit (AST::FieldAccessExpr &) -{} - -void -ResolverBase::visit (AST::ClosureExprInner &) -{} - -void -ResolverBase::visit (AST::BlockExpr &) -{} - -void -ResolverBase::visit (AST::AnonConst &) -{} - -void -ResolverBase::visit (AST::ConstBlock &) -{} - -void -ResolverBase::visit (AST::ClosureExprInnerTyped &) -{} - -void -ResolverBase::visit (AST::ContinueExpr &) -{} - -void -ResolverBase::visit (AST::BreakExpr &) -{} - -void -ResolverBase::visit (AST::RangeFromToExpr &) -{} - -void -ResolverBase::visit (AST::RangeFromExpr &) -{} - -void -ResolverBase::visit (AST::RangeToExpr &) -{} - -void -ResolverBase::visit (AST::RangeFullExpr &) -{} - -void -ResolverBase::visit (AST::RangeFromToInclExpr &) -{} - -void -ResolverBase::visit (AST::RangeToInclExpr &) -{} - -void -ResolverBase::visit (AST::BoxExpr &) -{} - -void -ResolverBase::visit (AST::ReturnExpr &) -{} - -void -ResolverBase::visit (AST::TryExpr &) -{} - -void -ResolverBase::visit (AST::UnsafeBlockExpr &) -{} - -void -ResolverBase::visit (AST::LoopExpr &) -{} - -void -ResolverBase::visit (AST::WhileLoopExpr &) -{} - -void -ResolverBase::visit (AST::WhileLetLoopExpr &) -{} - -void -ResolverBase::visit (AST::ForLoopExpr &) -{} - -void -ResolverBase::visit (AST::IfExpr &) -{} - -void -ResolverBase::visit (AST::IfExprConseqElse &) -{} - -void -ResolverBase::visit (AST::IfLetExpr &) -{} - -void -ResolverBase::visit (AST::IfLetExprConseqElse &) -{} - -void -ResolverBase::visit (AST::MatchExpr &) -{} - -void -ResolverBase::visit (AST::AwaitExpr &) -{} - -void -ResolverBase::visit (AST::AsyncBlockExpr &) -{} - -void -ResolverBase::visit (AST::InlineAsm &) -{} - -void -ResolverBase::visit (AST::LlvmInlineAsm &) -{} - -void -ResolverBase::visit (AST::TypeParam &) -{} - -void -ResolverBase::visit (AST::LifetimeWhereClauseItem &) -{} - -void -ResolverBase::visit (AST::TypeBoundWhereClauseItem &) -{} - -void -ResolverBase::visit (AST::Module &) -{} - -void -ResolverBase::visit (AST::ExternCrate &) -{} - -void -ResolverBase::visit (AST::UseTreeGlob &) -{} - -void -ResolverBase::visit (AST::UseTreeList &) -{} - -void -ResolverBase::visit (AST::UseTreeRebind &) -{} - -void -ResolverBase::visit (AST::UseDeclaration &) -{} - -void -ResolverBase::visit (AST::Function &) -{} - -void -ResolverBase::visit (AST::TypeAlias &) -{} - -void -ResolverBase::visit (AST::StructStruct &) -{} - -void -ResolverBase::visit (AST::TupleStruct &) -{} - -void -ResolverBase::visit (AST::EnumItem &) -{} - -void -ResolverBase::visit (AST::EnumItemTuple &) -{} - -void -ResolverBase::visit (AST::EnumItemStruct &) -{} - -void -ResolverBase::visit (AST::EnumItemDiscriminant &) -{} - -void -ResolverBase::visit (AST::Enum &) -{} - -void -ResolverBase::visit (AST::Union &) -{} - -void -ResolverBase::visit (AST::ConstantItem &) -{} - -void -ResolverBase::visit (AST::StaticItem &) -{} - -void -ResolverBase::visit (AST::TraitItemConst &) -{} - -void -ResolverBase::visit (AST::TraitItemType &) -{} - -void -ResolverBase::visit (AST::Trait &) -{} - -void -ResolverBase::visit (AST::InherentImpl &) -{} - -void -ResolverBase::visit (AST::TraitImpl &) -{} - -void -ResolverBase::visit (AST::ExternalTypeItem &) -{} - -void -ResolverBase::visit (AST::ExternalStaticItem &) -{} - -void -ResolverBase::visit (AST::ExternBlock &) -{} - -void -ResolverBase::visit (AST::MacroMatchFragment &) -{} - -void -ResolverBase::visit (AST::MacroMatchRepetition &) -{} - -void -ResolverBase::visit (AST::MacroMatcher &) -{} - -void -ResolverBase::visit (AST::MacroRulesDefinition &) -{} - -void -ResolverBase::visit (AST::MacroInvocation &) -{} - -void -ResolverBase::visit (AST::MetaItemPath &) -{} - -void -ResolverBase::visit (AST::MetaItemSeq &) -{} - -void -ResolverBase::visit (AST::MetaWord &) -{} - -void -ResolverBase::visit (AST::MetaNameValueStr &) -{} - -void -ResolverBase::visit (AST::MetaListPaths &) -{} - -void -ResolverBase::visit (AST::MetaListNameValueStr &) -{} - -void -ResolverBase::visit (AST::LiteralPattern &) -{} - -void -ResolverBase::visit (AST::IdentifierPattern &) -{} - -void -ResolverBase::visit (AST::WildcardPattern &) -{} - -void -ResolverBase::visit (AST::RestPattern &) -{} - -void -ResolverBase::visit (AST::RangePatternBoundLiteral &) -{} - -void -ResolverBase::visit (AST::RangePatternBoundPath &) -{} - -void -ResolverBase::visit (AST::RangePatternBoundQualPath &) -{} - -void -ResolverBase::visit (AST::RangePattern &) -{} - -void -ResolverBase::visit (AST::ReferencePattern &) -{} - -void -ResolverBase::visit (AST::StructPatternFieldTuplePat &) -{} - -void -ResolverBase::visit (AST::StructPatternFieldIdentPat &) -{} - -void -ResolverBase::visit (AST::StructPatternFieldIdent &) -{} - -void -ResolverBase::visit (AST::StructPattern &) -{} - -void -ResolverBase::visit (AST::TupleStructItemsNoRange &) -{} - -void -ResolverBase::visit (AST::TupleStructItemsRange &) -{} - -void -ResolverBase::visit (AST::TupleStructPattern &) -{} - -void -ResolverBase::visit (AST::TuplePatternItemsMultiple &) -{} - -void -ResolverBase::visit (AST::TuplePatternItemsRanged &) -{} - -void -ResolverBase::visit (AST::TuplePattern &) -{} - -void -ResolverBase::visit (AST::GroupedPattern &) -{} - -void -ResolverBase::visit (AST::SlicePatternItemsNoRest &) -{} - -void -ResolverBase::visit (AST::SlicePatternItemsHasRest &) -{} - -void -ResolverBase::visit (AST::SlicePattern &) -{} - -void -ResolverBase::visit (AST::AltPattern &) -{} - -void -ResolverBase::visit (AST::EmptyStmt &) -{} - -void -ResolverBase::visit (AST::LetStmt &) -{} - -void -ResolverBase::visit (AST::ExprStmt &) -{} - -void -ResolverBase::visit (AST::TraitBound &) -{} - -void -ResolverBase::visit (AST::ImplTraitType &) -{} - -void -ResolverBase::visit (AST::TraitObjectType &) -{} - -void -ResolverBase::visit (AST::ParenthesisedType &) -{} - -void -ResolverBase::visit (AST::ImplTraitTypeOneBound &) -{} - -void -ResolverBase::visit (AST::TraitObjectTypeOneBound &) -{} - -void -ResolverBase::visit (AST::TupleType &) -{} - -void -ResolverBase::visit (AST::NeverType &) -{} - -void -ResolverBase::visit (AST::RawPointerType &) -{} - -void -ResolverBase::visit (AST::ReferenceType &) -{} - -void -ResolverBase::visit (AST::ArrayType &) -{} - -void -ResolverBase::visit (AST::SliceType &) -{} - -void -ResolverBase::visit (AST::InferredType &) -{} - -void -ResolverBase::visit (AST::BareFunctionType &) -{} - -void -ResolverBase::visit (AST::SelfParam &) -{} - -void -ResolverBase::visit (AST::VariadicParam &) -{} - -void -ResolverBase::visit (AST::FunctionParam &) -{} - -void -ResolverBase::visit (AST::FormatArgs &fmt) -{} - -void -ResolverBase::visit (AST::OffsetOf &offset_of) -{} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h deleted file mode 100644 index 89c5c35..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (C) 2020-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_AST_RESOLVE_BASE_H -#define RUST_AST_RESOLVE_BASE_H - -#include "rust-ast-visitor.h" -#include "rust-ast.h" -#include "rust-builtin-ast-nodes.h" -#include "rust-expr.h" -#include "rust-name-resolver.h" -#include "rust-diagnostics.h" -#include "rust-location.h" - -namespace Rust { -namespace Resolver { -inline void -redefined_error (const rich_location &loc) -{ - rust_error_at (loc, "redefined multiple times"); -} - -class ResolverBase : public AST::ASTVisitor -{ -public: - virtual ~ResolverBase () {} - - void visit (AST::Token &); - void visit (AST::DelimTokenTree &); - void visit (AST::AttrInputMetaItemContainer &); - void visit (AST::IdentifierExpr &); - void visit (AST::Lifetime &); - void visit (AST::LifetimeParam &); - void visit (AST::ConstGenericParam &); - void visit (AST::PathInExpression &); - void visit (AST::TypePathSegment &); - void visit (AST::TypePathSegmentGeneric &); - void visit (AST::TypePathSegmentFunction &); - void visit (AST::TypePath &); - void visit (AST::QualifiedPathInExpression &); - void visit (AST::QualifiedPathInType &); - void visit (AST::LiteralExpr &); - void visit (AST::AttrInputLiteral &); - void visit (AST::AttrInputMacro &); - void visit (AST::MetaItemLitExpr &); - void visit (AST::MetaItemPathExpr &); - void visit (AST::BorrowExpr &); - void visit (AST::DereferenceExpr &); - void visit (AST::ErrorPropagationExpr &); - void visit (AST::NegationExpr &); - void visit (AST::ArithmeticOrLogicalExpr &); - void visit (AST::ComparisonExpr &); - void visit (AST::LazyBooleanExpr &); - void visit (AST::TypeCastExpr &); - void visit (AST::AssignmentExpr &); - void visit (AST::CompoundAssignmentExpr &); - void visit (AST::GroupedExpr &); - void visit (AST::ArrayElemsValues &); - void visit (AST::ArrayElemsCopied &); - void visit (AST::ArrayExpr &); - void visit (AST::ArrayIndexExpr &); - void visit (AST::TupleExpr &); - void visit (AST::TupleIndexExpr &); - void visit (AST::StructExprStruct &); - void visit (AST::StructExprFieldIdentifier &); - void visit (AST::StructExprFieldIdentifierValue &); - void visit (AST::StructExprFieldIndexValue &); - void visit (AST::StructExprStructFields &); - void visit (AST::StructExprStructBase &); - void visit (AST::CallExpr &); - void visit (AST::MethodCallExpr &); - 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 &); - void visit (AST::RangeFromToExpr &); - void visit (AST::RangeFromExpr &); - void visit (AST::RangeToExpr &); - void visit (AST::RangeFullExpr &); - void visit (AST::RangeFromToInclExpr &); - void visit (AST::RangeToInclExpr &); - void visit (AST::BoxExpr &); - void visit (AST::ReturnExpr &); - void visit (AST::TryExpr &); - void visit (AST::UnsafeBlockExpr &); - void visit (AST::LoopExpr &); - void visit (AST::WhileLoopExpr &); - void visit (AST::WhileLetLoopExpr &); - void visit (AST::ForLoopExpr &); - void visit (AST::IfExpr &); - void visit (AST::IfExprConseqElse &); - void visit (AST::IfLetExpr &); - void visit (AST::IfLetExprConseqElse &); - - void visit (AST::MatchExpr &); - void visit (AST::AwaitExpr &); - void visit (AST::AsyncBlockExpr &); - void visit (AST::InlineAsm &); - void visit (AST::LlvmInlineAsm &); - - void visit (AST::TypeParam &); - - void visit (AST::LifetimeWhereClauseItem &); - void visit (AST::TypeBoundWhereClauseItem &); - void visit (AST::Module &); - void visit (AST::ExternCrate &); - - void visit (AST::UseTreeGlob &); - void visit (AST::UseTreeList &); - void visit (AST::UseTreeRebind &); - void visit (AST::UseDeclaration &); - void visit (AST::Function &); - void visit (AST::TypeAlias &); - void visit (AST::StructStruct &); - void visit (AST::TupleStruct &); - void visit (AST::EnumItem &); - void visit (AST::EnumItemTuple &); - void visit (AST::EnumItemStruct &); - void visit (AST::EnumItemDiscriminant &); - void visit (AST::Enum &); - void visit (AST::Union &); - void visit (AST::ConstantItem &); - void visit (AST::StaticItem &); - void visit (AST::TraitItemConst &); - void visit (AST::TraitItemType &); - void visit (AST::Trait &); - void visit (AST::InherentImpl &); - void visit (AST::TraitImpl &); - - void visit (AST::ExternalTypeItem &); - void visit (AST::ExternalStaticItem &); - void visit (AST::ExternBlock &); - - void visit (AST::MacroMatchFragment &); - void visit (AST::MacroMatchRepetition &); - void visit (AST::MacroMatcher &); - void visit (AST::MacroRulesDefinition &); - void visit (AST::MacroInvocation &); - void visit (AST::MetaItemPath &); - void visit (AST::MetaItemSeq &); - void visit (AST::MetaWord &); - void visit (AST::MetaNameValueStr &); - void visit (AST::MetaListPaths &); - void visit (AST::MetaListNameValueStr &); - - void visit (AST::LiteralPattern &); - void visit (AST::IdentifierPattern &); - void visit (AST::WildcardPattern &); - void visit (AST::RestPattern &); - - void visit (AST::RangePatternBoundLiteral &); - void visit (AST::RangePatternBoundPath &); - void visit (AST::RangePatternBoundQualPath &); - void visit (AST::RangePattern &); - void visit (AST::ReferencePattern &); - - void visit (AST::StructPatternFieldTuplePat &); - void visit (AST::StructPatternFieldIdentPat &); - void visit (AST::StructPatternFieldIdent &); - void visit (AST::StructPattern &); - - void visit (AST::TupleStructItemsNoRange &); - void visit (AST::TupleStructItemsRange &); - void visit (AST::TupleStructPattern &); - - void visit (AST::TuplePatternItemsMultiple &); - void visit (AST::TuplePatternItemsRanged &); - void visit (AST::TuplePattern &); - void visit (AST::GroupedPattern &); - void visit (AST::SlicePatternItemsNoRest &); - void visit (AST::SlicePatternItemsHasRest &); - void visit (AST::SlicePattern &); - void visit (AST::AltPattern &); - - void visit (AST::EmptyStmt &); - void visit (AST::LetStmt &); - void visit (AST::ExprStmt &); - - void visit (AST::TraitBound &); - void visit (AST::ImplTraitType &); - void visit (AST::TraitObjectType &); - void visit (AST::ParenthesisedType &); - void visit (AST::ImplTraitTypeOneBound &); - void visit (AST::TraitObjectTypeOneBound &); - void visit (AST::TupleType &); - void visit (AST::NeverType &); - void visit (AST::RawPointerType &); - void visit (AST::ReferenceType &); - void visit (AST::ArrayType &); - void visit (AST::SliceType &); - void visit (AST::InferredType &); - void visit (AST::BareFunctionType &); - void visit (AST::FunctionParam ¶m); - void visit (AST::VariadicParam ¶m); - void visit (AST::SelfParam ¶m); - - void visit (AST::FormatArgs &fmt); - void visit (AST::OffsetOf &offset_of); - -protected: - ResolverBase () - : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()), - resolved_node (UNKNOWN_NODEID) - {} - - /** - * Resolve a visibility's path through the name resolver - */ - bool resolve_visibility (const AST::Visibility &vis); - - Resolver *resolver; - Analysis::Mappings &mappings; - NodeId resolved_node; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_BASE_H diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc deleted file mode 100644 index a410193..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-expr.cc +++ /dev/null @@ -1,816 +0,0 @@ -// Copyright (C) 2020-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-ast-resolve-expr.h" -#include "rust-ast-resolve-stmt.h" -#include "rust-ast-resolve-struct-expr-field.h" -#include "rust-ast-resolve-type.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-path.h" -#include "rust-expr.h" -#include "rust-ice-finalizer.h" - -namespace Rust { -namespace Resolver { - -void -ResolveExpr::go (AST::Expr &expr, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, bool funny_error) -{ - ResolveExpr resolver (prefix, canonical_prefix, funny_error); - expr.accept_vis (resolver); -} - -void -ResolveExpr::visit (AST::TupleIndexExpr &expr) -{ - ResolveExpr::go (expr.get_tuple_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::TupleExpr &expr) -{ - if (expr.is_unit ()) - return; - - for (auto &elem : expr.get_tuple_elems ()) - ResolveExpr::go (*elem, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::PathInExpression &expr) -{ - ResolvePath::go (expr); -} - -void -ResolveExpr::visit (AST::QualifiedPathInExpression &expr) -{ - ResolvePath::go (expr); -} - -void -ResolveExpr::visit (AST::ReturnExpr &expr) -{ - if (expr.has_returned_expr ()) - ResolveExpr::go (expr.get_returned_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::CallExpr &expr) -{ - ResolveExpr::go (expr.get_function_expr (), prefix, canonical_prefix); - for (auto ¶m : expr.get_params ()) - ResolveExpr::go (*param, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::MethodCallExpr &expr) -{ - ResolveExpr::go (expr.get_receiver_expr (), prefix, canonical_prefix); - - if (expr.get_method_name ().has_generic_args ()) - { - AST::GenericArgs &args = expr.get_method_name ().get_generic_args (); - ResolveGenericArgs::go (args, prefix, canonical_prefix); - } - - auto const &in_params = expr.get_params (); - for (auto ¶m : in_params) - ResolveExpr::go (*param, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ErrorPropagationExpr &expr) -{ - ResolveExpr::go (expr.get_propagating_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::AssignmentExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IdentifierExpr &expr) -{ - if (resolver->get_name_scope ().lookup ( - CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()), - &resolved_node)) - { - resolver->insert_resolved_name (expr.get_node_id (), resolved_node); - } - else if (resolver->get_type_scope ().lookup ( - CanonicalPath::new_seg (expr.get_node_id (), expr.as_string ()), - &resolved_node)) - { - resolver->insert_resolved_type (expr.get_node_id (), resolved_node); - } - else if (funny_error) - { - /* This was a "break rust" or "break gcc", and the identifier failed to - resolve. Emit a funny ICE. We set the finalizer to our custom one, - and use the lower-level emit_diagnostic () instead of the more common - internal_error_no_backtrace () in order to pass our locus. */ - diagnostics::text_finalizer (global_dc) = 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 ()); - } - else - { - rust_error_at (expr.get_locus (), ErrorCode::E0425, - "cannot find value %qs in this scope", - expr.as_string ().c_str ()); - } -} - -void -ResolveExpr::visit (AST::ArithmeticOrLogicalExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::CompoundAssignmentExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ComparisonExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::LazyBooleanExpr &expr) -{ - ResolveExpr::go (expr.get_left_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_right_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::NegationExpr &expr) -{ - ResolveExpr::go (expr.get_negated_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::TypeCastExpr &expr) -{ - ResolveType::go (expr.get_type_to_cast_to ()); - ResolveExpr::go (expr.get_casted_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IfExpr &expr) -{ - ResolveExpr::go (expr.get_condition_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IfExprConseqElse &expr) -{ - ResolveExpr::go (expr.get_condition_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_else_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::IfLetExpr &expr) -{ - ResolveExpr::go (expr.get_value_expr (), prefix, canonical_prefix); - - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // We know expr.get_patterns () has one pattern at most - // so there's no reason to handle it like an AltPattern. - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - for (auto &pattern : expr.get_patterns ()) - { - PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings); - } - - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::IfLetExprConseqElse &expr) -{ - ResolveExpr::go (expr.get_value_expr (), prefix, canonical_prefix); - - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // We know expr.get_patterns () has one pattern at most - // so there's no reason to handle it like an AltPattern. - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - for (auto &pattern : expr.get_patterns ()) - { - PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings); - } - - ResolveExpr::go (expr.get_if_block (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_else_block (), prefix, canonical_prefix); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::BlockExpr &expr) -{ - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (expr.has_label ()) - { - auto label = expr.get_label (); - if (label.get_lifetime ().get_lifetime_type () - != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - auto label_name = label.get_lifetime ().get_lifetime_name (); - auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); - resolver->get_label_scope ().insert ( - CanonicalPath::new_seg (label.get_node_id (), label_name), - label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - - for (auto &s : expr.get_statements ()) - { - if (s->is_item ()) - ResolveStmt::go (*s, prefix, canonical_prefix, - CanonicalPath::create_empty ()); - } - - for (auto &s : expr.get_statements ()) - { - if (!s->is_item ()) - ResolveStmt::go (*s, prefix, canonical_prefix, - CanonicalPath::create_empty ()); - } - - if (expr.has_tail_expr ()) - ResolveExpr::go (expr.get_tail_expr (), prefix, canonical_prefix); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -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) -{ - const auto &operands = expr.get_operands (); - using RegisterType = AST::InlineAsmOperand::RegisterType; - for (auto &operand : operands) - { - switch (operand.get_register_type ()) - { - case RegisterType::In: - { - auto in = operand.get_in (); - ResolveExpr::go (*in.expr, prefix, canonical_prefix); - break; - } - case RegisterType::Out: - { - auto out = operand.get_out (); - ResolveExpr::go (*out.expr, prefix, canonical_prefix); - break; - } - case RegisterType::InOut: - { - auto in_out = operand.get_in_out (); - ResolveExpr::go (*in_out.expr, prefix, canonical_prefix); - break; - } - 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: - { - auto anon_const = operand.get_const ().anon_const; - ResolveExpr::go (anon_const.get_inner_expr (), prefix, - canonical_prefix); - break; - } - case RegisterType::Sym: - { - auto sym = operand.get_sym (); - ResolveExpr::go (*sym.expr, prefix, canonical_prefix); - break; - } - case RegisterType::Label: - { - auto label = operand.get_label (); - ResolveExpr::go (*label.expr, prefix, canonical_prefix); - break; - } - } - } -} -void -ResolveExpr::visit (AST::InlineAsm &expr) -{ - translate_operand (expr, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::LlvmInlineAsm &expr) -{ - for (auto &output : expr.get_outputs ()) - ResolveExpr::go (*output.expr, prefix, canonical_prefix); - - for (auto &input : expr.get_inputs ()) - ResolveExpr::go (*input.expr, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::UnsafeBlockExpr &expr) -{ - expr.get_block_expr ().accept_vis (*this); -} - -void -ResolveExpr::visit (AST::ArrayElemsValues &elems) -{ - for (auto &elem : elems.get_values ()) - ResolveExpr::go (*elem, prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ArrayExpr &expr) -{ - expr.get_array_elems ()->accept_vis (*this); -} - -void -ResolveExpr::visit (AST::ArrayIndexExpr &expr) -{ - ResolveExpr::go (expr.get_array_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_index_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ArrayElemsCopied &expr) -{ - ResolveExpr::go (expr.get_num_copies (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_elem_to_copy (), prefix, canonical_prefix); -} - -// this this an empty struct constructor like 'S {}' -void -ResolveExpr::visit (AST::StructExprStruct &struct_expr) -{ - ResolveExpr::go (struct_expr.get_struct_name (), prefix, canonical_prefix); -} - -// this this a struct constructor with fields -void -ResolveExpr::visit (AST::StructExprStructFields &struct_expr) -{ - ResolveExpr::go (struct_expr.get_struct_name (), prefix, canonical_prefix); - - if (struct_expr.has_struct_base ()) - { - AST::StructBase &base = struct_expr.get_struct_base (); - ResolveExpr::go (base.get_base_struct (), prefix, canonical_prefix); - } - - auto const &struct_fields = struct_expr.get_fields (); - for (auto &struct_field : struct_fields) - { - ResolveStructExprField::go (*struct_field, prefix, canonical_prefix); - } -} - -void -ResolveExpr::visit (AST::GroupedExpr &expr) -{ - ResolveExpr::go (expr.get_expr_in_parens (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::FieldAccessExpr &expr) -{ - ResolveExpr::go (expr.get_receiver_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::LoopExpr &expr) -{ - if (expr.has_loop_label ()) - { - auto label = expr.get_loop_label (); - if (label.get_lifetime ().get_lifetime_type () - != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - auto label_name = label.get_lifetime ().get_lifetime_name (); - auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); - resolver->get_label_scope ().insert ( - CanonicalPath::new_seg (expr.get_node_id (), label_name), - label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::BreakExpr &expr) -{ - if (expr.has_label ()) - { - auto label = expr.get_label_unchecked ().get_lifetime (); - if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->get_label_scope ().lookup ( - CanonicalPath::new_seg (label.get_node_id (), - label.get_lifetime_name ()), - &resolved_node)) - { - rust_error_at (label.get_locus (), ErrorCode::E0426, - "use of undeclared label %qs", - label.as_string ().c_str ()); - return; - } - resolver->insert_resolved_label (label.get_node_id (), resolved_node); - } - - if (expr.has_break_expr ()) - { - bool funny_error = false; - auto &break_expr = expr.get_break_expr (); - if (break_expr.get_expr_kind () == AST::Expr::Kind::Identifier) - { - /* This is a break with an expression, and the expression is - just a single identifier. See if the identifier is either - "rust" or "gcc", in which case we have "break rust" or "break - gcc", and so may need to emit our funny error. We cannot yet - emit the error here though, because the identifier may still - be in scope, and ICE'ing on valid programs would not be very - funny. */ - std::string ident - = static_cast<AST::IdentifierExpr &> (break_expr).as_string (); - if (ident == "rust" || ident == "gcc") - funny_error = true; - } - ResolveExpr::go (break_expr, prefix, canonical_prefix, funny_error); - } -} - -void -ResolveExpr::visit (AST::WhileLoopExpr &expr) -{ - if (expr.has_loop_label ()) - { - auto label = expr.get_loop_label (); - if (label.get_lifetime ().get_lifetime_type () - != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - auto label_name = label.get_lifetime ().get_lifetime_name (); - auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); - resolver->get_label_scope ().insert ( - CanonicalPath::new_seg (label.get_node_id (), label_name), - label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - - ResolveExpr::go (expr.get_predicate_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ForLoopExpr &expr) -{ - if (expr.has_loop_label ()) - { - auto label = expr.get_loop_label (); - if (label.get_lifetime ().get_lifetime_type () - != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - auto label_name = label.get_lifetime ().get_lifetime_name (); - auto label_lifetime_node_id = label.get_lifetime ().get_node_id (); - resolver->get_label_scope ().insert ( - CanonicalPath::new_seg (label.get_node_id (), label_name), - label_lifetime_node_id, label.get_locus (), false, Rib::ItemType::Label, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (label.get_locus (), "label defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - } - - // this needs a new rib to contain the pattern - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // resolve the expression - PatternDeclaration::go (expr.get_pattern (), Rib::ItemType::Var); - ResolveExpr::go (expr.get_iterator_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_loop_block (), prefix, canonical_prefix); - - // done - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::ContinueExpr &expr) -{ - if (expr.has_label ()) - { - auto label = expr.get_label_unchecked (); - if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED) - { - rust_error_at (label.get_locus (), - "Labels must be a named lifetime value"); - return; - } - - NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->get_label_scope ().lookup ( - CanonicalPath::new_seg (label.get_node_id (), - label.get_lifetime_name ()), - &resolved_node)) - { - rust_error_at (expr.get_label_unchecked ().get_locus (), - ErrorCode::E0426, "use of undeclared label %qs", - label.as_string ().c_str ()); - return; - } - resolver->insert_resolved_label (label.get_node_id (), resolved_node); - } -} - -void -ResolveExpr::visit (AST::BorrowExpr &expr) -{ - ResolveExpr::go (expr.get_borrowed_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::DereferenceExpr &expr) -{ - ResolveExpr::go (expr.get_dereferenced_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::MatchExpr &expr) -{ - ResolveExpr::go (expr.get_scrutinee_expr (), prefix, canonical_prefix); - for (auto &match_case : expr.get_match_cases ()) - { - // each arm is in its own scope - NodeId scope_node_id = match_case.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // resolve - AST::MatchArm &arm = match_case.get_arm (); - if (arm.has_match_arm_guard ()) - ResolveExpr::go (arm.get_guard_expr (), prefix, canonical_prefix); - - // We know expr.get_patterns () has one pattern at most - // so there's no reason to handle it like an AltPattern. - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - // insert any possible new patterns - for (auto &pattern : arm.get_patterns ()) - { - PatternDeclaration::go (*pattern, Rib::ItemType::Var, bindings); - } - - // resolve the body - ResolveExpr::go (match_case.get_expr (), prefix, canonical_prefix); - - // done - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - } -} - -void -ResolveExpr::visit (AST::RangeFromToExpr &expr) -{ - ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::RangeFromExpr &expr) -{ - ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::RangeToExpr &expr) -{ - ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::RangeFullExpr &) -{ - // nothing to do -} - -void -ResolveExpr::visit (AST::RangeFromToInclExpr &expr) -{ - ResolveExpr::go (expr.get_from_expr (), prefix, canonical_prefix); - ResolveExpr::go (expr.get_to_expr (), prefix, canonical_prefix); -} - -void -ResolveExpr::visit (AST::ClosureExprInner &expr) -{ - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - for (auto &p : expr.get_params ()) - { - resolve_closure_param (p, bindings); - } - - resolver->push_closure_context (expr.get_node_id ()); - - ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix); - - resolver->pop_closure_context (); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::visit (AST::ClosureExprInnerTyped &expr) -{ - NodeId scope_node_id = expr.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - for (auto &p : expr.get_params ()) - { - resolve_closure_param (p, bindings); - } - - ResolveType::go (expr.get_return_type ()); - - resolver->push_closure_context (expr.get_node_id ()); - - ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix); - - resolver->pop_closure_context (); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExpr::resolve_closure_param (AST::ClosureParam ¶m, - std::vector<PatternBinding> &bindings) -{ - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, bindings); - - if (param.has_type_given ()) - ResolveType::go (param.get_type ()); -} - -ResolveExpr::ResolveExpr (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - bool funny_error) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix), - funny_error (funny_error) -{} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h deleted file mode 100644 index aad1605..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (C) 2020-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_AST_RESOLVE_EXPR_H -#define RUST_AST_RESOLVE_EXPR_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-expr.h" - -namespace Rust { -namespace Resolver { - -class ResolveExpr : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Expr &expr, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - bool funny_error = false); - - void visit (AST::TupleIndexExpr &expr) override; - void visit (AST::TupleExpr &expr) override; - void visit (AST::PathInExpression &expr) override; - void visit (AST::QualifiedPathInExpression &expr) override; - void visit (AST::ReturnExpr &expr) override; - void visit (AST::CallExpr &expr) override; - void visit (AST::MethodCallExpr &expr) override; - void visit (AST::AssignmentExpr &expr) override; - void visit (AST::IdentifierExpr &expr) override; - void visit (AST::ArithmeticOrLogicalExpr &expr) override; - void visit (AST::CompoundAssignmentExpr &expr) override; - void visit (AST::ComparisonExpr &expr) override; - void visit (AST::LazyBooleanExpr &expr) override; - void visit (AST::NegationExpr &expr) override; - void visit (AST::TypeCastExpr &expr) override; - void visit (AST::IfExpr &expr) override; - void visit (AST::IfExprConseqElse &expr) override; - 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; - void visit (AST::ArrayElemsValues &elems) override; - void visit (AST::ArrayExpr &expr) override; - void visit (AST::ArrayIndexExpr &expr) override; - void visit (AST::ArrayElemsCopied &elems) override; - void visit (AST::StructExprStruct &struct_expr) override; - void visit (AST::StructExprStructFields &struct_expr) override; - void visit (AST::GroupedExpr &expr) override; - void visit (AST::FieldAccessExpr &expr) override; - void visit (AST::LoopExpr &expr) override; - void visit (AST::BreakExpr &expr) override; - void visit (AST::WhileLoopExpr &expr) override; - void visit (AST::ForLoopExpr &expr) override; - void visit (AST::ContinueExpr &expr) override; - void visit (AST::BorrowExpr &expr) override; - void visit (AST::DereferenceExpr &expr) override; - void visit (AST::MatchExpr &expr) override; - void visit (AST::RangeFromToExpr &expr) override; - void visit (AST::RangeFromExpr &expr) override; - void visit (AST::RangeToExpr &expr) override; - void visit (AST::RangeFullExpr &expr) override; - void visit (AST::RangeFromToInclExpr &expr) override; - void visit (AST::ClosureExprInner &expr) override; - void visit (AST::ClosureExprInnerTyped &expr) override; - void visit (AST::ErrorPropagationExpr &expr) override; - -protected: - void resolve_closure_param (AST::ClosureParam ¶m, - std::vector<PatternBinding> &bindings); - -private: - ResolveExpr (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, bool funny_error); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; - bool funny_error; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_EXPR_H diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h deleted file mode 100644 index 2081697..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (C) 2020-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_AST_RESOLVE_IMPLITEM_H -#define RUST_AST_RESOLVE_IMPLITEM_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-type.h" -#include "rust-ast-full.h" - -namespace Rust { -namespace Resolver { - -class ResolveToplevelImplItem : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::AssociatedItem &item, const CanonicalPath &prefix) - { - if (item.is_marked_for_strip ()) - return; - - ResolveToplevelImplItem resolver (prefix); - item.accept_vis (resolver); - } - - void visit (AST::TypeAlias &type) override - { - auto decl = CanonicalPath::new_seg (type.get_node_id (), - type.get_new_type_name ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, type.get_node_id (), type.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, type.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - } - - void visit (AST::ConstantItem &constant) override - { - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ()); - auto path = prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, constant.get_node_id (), constant.get_locus (), false, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - } - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - } - -private: - ResolveToplevelImplItem (const CanonicalPath &prefix) - : ResolverBase (), prefix (prefix) - { - rust_assert (!prefix.is_empty ()); - } - - const CanonicalPath &prefix; -}; - -class ResolveTopLevelTraitItems : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::AssociatedItem *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - ResolveTopLevelTraitItems resolver (prefix, canonical_prefix); - item->accept_vis (resolver); - }; - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (function.get_node_id (), cpath); - } - - void visit (AST::TraitItemConst &constant) override - { - auto decl - = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, constant.get_node_id (), constant.get_locus (), false, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (constant.get_node_id (), cpath); - } - - void visit (AST::TraitItemType &type) override - { - auto decl = CanonicalPath::new_seg (type.get_node_id (), - type.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, type.get_node_id (), type.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, type.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (type.get_node_id (), cpath); - } - -private: - ResolveTopLevelTraitItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) - {} - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class ResolveToplevelExternItem : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::ExternalItem &item, const CanonicalPath &prefix) - { - ResolveToplevelExternItem resolver (prefix); - item.accept_vis (resolver); - }; - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - } - - void visit (AST::ExternalStaticItem &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, - Rib::ItemType::Static, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - } - - void visit (AST::ExternalTypeItem &type) override - { - auto decl = CanonicalPath::new_seg (type.get_node_id (), - type.get_identifier ().as_string ()); - auto path = prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, type.get_node_id (), type.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, type.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - } - -private: - ResolveToplevelExternItem (const CanonicalPath &prefix) - : ResolverBase (), prefix (prefix) - {} - - const CanonicalPath &prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_IMPLITEM_H diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc deleted file mode 100644 index 1d5ebed..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ /dev/null @@ -1,1247 +0,0 @@ -// Copyright (C) 2020-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-ast-resolve-item.h" -#include "rust-ast-full-decls.h" -#include "rust-ast-resolve-toplevel.h" -#include "rust-ast-resolve-type.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-path.h" - -#include "rust-item.h" -#include "selftest.h" - -namespace Rust { -namespace Resolver { - -ResolveTraitItems::ResolveTraitItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) -{} - -void -ResolveTraitItems::go (AST::AssociatedItem *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - if (item->is_marked_for_strip ()) - return; - - ResolveTraitItems resolver (prefix, canonical_prefix); - item->accept_vis (resolver); -} - -void -ResolveTraitItems::visit (AST::Function &function) -{ - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (function.get_node_id (), cpath); - - NodeId scope_node_id = function.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - // self turns into (self: Self) as a function param - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto &p : function.get_function_params ()) - { - if (p->is_variadic ()) - { - auto param = static_cast<AST::VariadicParam &> (*p); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - else if (p->is_self ()) - { - auto ¶m = static_cast<AST::SelfParam &> (*p); - // FIXME: which location should be used for Rust::Identifier `self`? - AST::IdentifierPattern self_pattern ( - param.get_node_id (), {"self"}, param.get_locus (), - param.get_has_ref (), param.get_is_mut (), - std::unique_ptr<AST::Pattern> (nullptr)); - - PatternDeclaration::go (self_pattern, Rib::ItemType::Param); - - if (param.has_type ()) - { - // This shouldn't happen the parser should already error for this - rust_assert (!param.get_has_ref ()); - ResolveType::go (param.get_type ()); - } - else - { - // here we implicitly make self have a type path of Self - std::vector<std::unique_ptr<AST::TypePathSegment>> segments; - segments.push_back (std::unique_ptr<AST::TypePathSegment> ( - new AST::TypePathSegment ("Self", false, param.get_locus ()))); - - AST::TypePath self_type_path (std::move (segments), - param.get_locus ()); - ResolveType::go (self_type_path); - } - } - else - { - auto ¶m = static_cast<AST::FunctionParam &> (*p); - ResolveType::go (param.get_type ()); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - } - - if (function.has_where_clause ()) - ResolveWhereClause::Resolve (function.get_where_clause ()); - - // trait items have an optional body - if (function.has_body ()) - ResolveExpr::go (*function.get_definition ().value (), path, cpath); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} -void -ResolveTraitItems::visit (AST::TraitItemType &type) -{ - auto decl = CanonicalPath::new_seg (type.get_node_id (), - type.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (type.get_node_id (), cpath); - - for (auto &bound : type.get_type_param_bounds ()) - ResolveTypeBound::go (*bound); -} - -void -ResolveTraitItems::visit (AST::TraitItemConst &constant) -{ - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - - ResolveType::go (constant.get_type ()); - - if (constant.has_expr ()) - ResolveExpr::go (constant.get_expr (), path, cpath); -} - -ResolveItem::ResolveItem (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) -{} - -void -ResolveItem::go (AST::Item &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveItem resolver (prefix, canonical_prefix); - item.accept_vis (resolver); -} - -void -ResolveItem::visit (AST::TypeAlias &alias) -{ - auto talias - = CanonicalPath::new_seg (alias.get_node_id (), - alias.get_new_type_name ().as_string ()); - auto path = prefix.append (talias); - auto cpath = canonical_prefix.append (talias); - mappings.insert_canonical_path (alias.get_node_id (), cpath); - - NodeId scope_node_id = alias.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (alias.has_generics ()) - ResolveGenericParams::go (alias.get_generic_params (), prefix, - canonical_prefix); - - if (alias.has_where_clause ()) - ResolveWhereClause::Resolve (alias.get_where_clause ()); - - ResolveType::go (alias.get_type_aliased ()); - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::Module &module) -{ - auto mod = CanonicalPath::new_seg (module.get_node_id (), - module.get_name ().as_string ()); - auto path = prefix.append (mod); - auto cpath = canonical_prefix.append (mod); - mappings.insert_canonical_path (module.get_node_id (), cpath); - - resolve_visibility (module.get_visibility ()); - - NodeId scope_node_id = module.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // FIXME: Should we reinsert a child here? Any reason we ResolveTopLevel::go - // in ResolveTopLevel::visit (AST::Module) as well as here? - for (auto &item : module.get_items ()) - ResolveTopLevel::go (*item, CanonicalPath::create_empty (), cpath); - - resolver->push_new_module_scope (module.get_node_id ()); - for (auto &item : module.get_items ()) - ResolveItem::go (*item, path, cpath); - - resolver->pop_module_scope (); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveItem::visit (AST::TupleStruct &struct_decl) -{ - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolve_visibility (struct_decl.get_visibility ()); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - if (struct_decl.has_where_clause ()) - ResolveWhereClause::Resolve (struct_decl.get_where_clause ()); - - for (AST::TupleField &field : struct_decl.get_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - resolve_visibility (field.get_visibility ()); - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::Enum &enum_decl) -{ - auto decl = CanonicalPath::new_seg (enum_decl.get_node_id (), - enum_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (enum_decl.get_node_id (), cpath); - - resolve_visibility (enum_decl.get_visibility ()); - - NodeId scope_node_id = enum_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (enum_decl.has_generics ()) - ResolveGenericParams::go (enum_decl.get_generic_params (), prefix, - canonical_prefix); - - if (enum_decl.has_where_clause ()) - ResolveWhereClause::Resolve (enum_decl.get_where_clause ()); - - /* The actual fields are inside the variants. */ - for (auto &variant : enum_decl.get_variants ()) - ResolveItem::go (*variant, path, cpath); - - resolver->get_type_scope ().pop (); -} - -/* EnumItem doesn't need to be handled, no fields. */ -void -ResolveItem::visit (AST::EnumItem &item) -{ - // Since at this point we cannot have visibilities on enum items anymore, we - // can skip handling them - - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); -} - -void -ResolveItem::visit (AST::EnumItemTuple &item) -{ - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - for (auto &field : item.get_tuple_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } -} - -void -ResolveItem::visit (AST::EnumItemStruct &item) -{ - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - for (auto &field : item.get_struct_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } -} - -void -ResolveItem::visit (AST::EnumItemDiscriminant &item) -{ - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - ResolveExpr::go (item.get_expr (), path, cpath); -} - -void -ResolveItem::visit (AST::StructStruct &struct_decl) -{ - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolve_visibility (struct_decl.get_visibility ()); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - if (struct_decl.has_where_clause ()) - ResolveWhereClause::Resolve (struct_decl.get_where_clause ()); - - for (AST::StructField &field : struct_decl.get_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - resolve_visibility (field.get_visibility ()); - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::Union &union_decl) -{ - auto decl - = CanonicalPath::new_seg (union_decl.get_node_id (), - union_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (union_decl.get_node_id (), cpath); - - resolve_visibility (union_decl.get_visibility ()); - - NodeId scope_node_id = union_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (union_decl.has_generics ()) - ResolveGenericParams::go (union_decl.get_generic_params (), prefix, - canonical_prefix); - - if (union_decl.has_where_clause ()) - ResolveWhereClause::Resolve (union_decl.get_where_clause ()); - - for (AST::StructField &field : union_decl.get_variants ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); -} - -void -ResolveItem::visit (AST::StaticItem &var) -{ - auto decl = CanonicalPath::new_seg (var.get_node_id (), - var.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (var.get_node_id (), cpath); - - ResolveType::go (var.get_type ()); - ResolveExpr::go (var.get_expr (), path, cpath); -} - -void -ResolveItem::visit (AST::ConstantItem &constant) -{ - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - - resolve_visibility (constant.get_visibility ()); - - ResolveType::go (constant.get_type ()); - if (constant.has_expr ()) - ResolveExpr::go (constant.get_expr (), path, cpath); -} - -void -ResolveItem::visit (AST::Function &function) -{ - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - mappings.insert_canonical_path (function.get_node_id (), cpath); - - resolve_visibility (function.get_visibility ()); - - NodeId scope_node_id = function.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - // resolve any where clause items - if (function.has_where_clause ()) - ResolveWhereClause::Resolve (function.get_where_clause ()); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - if (function.has_self_param ()) - { - // self turns into (self: Self) as a function param - AST::Param &s_param = function.get_self_param (); - auto &self_param = static_cast<AST::SelfParam &> (s_param); - - // FIXME: which location should be used for Rust::Identifier `self`? - AST::IdentifierPattern self_pattern ( - self_param.get_node_id (), {"self"}, self_param.get_locus (), - self_param.get_has_ref (), self_param.get_is_mut (), - std::unique_ptr<AST::Pattern> (nullptr)); - PatternDeclaration::go (self_pattern, Rib::ItemType::Param); - - if (self_param.has_type ()) - { - // This shouldn't happen the parser should already error for this - rust_assert (!self_param.get_has_ref ()); - ResolveType::go (self_param.get_type ()); - } - else - { - // here we implicitly make self have a type path of Self - std::vector<std::unique_ptr<AST::TypePathSegment>> segments; - segments.push_back (std::unique_ptr<AST::TypePathSegment> ( - new AST::TypePathSegment ("Self", false, self_param.get_locus ()))); - - AST::TypePath self_type_path (std::move (segments), - self_param.get_locus ()); - ResolveType::go (self_type_path); - } - } - - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto &p : function.get_function_params ()) - { - if (p->is_variadic ()) - { - auto ¶m = static_cast<AST::VariadicParam &> (*p); - if (param.has_pattern ()) - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - else if (p->is_self ()) - { - auto ¶m = static_cast<AST::SelfParam &> (*p); - if (param.has_type ()) - ResolveType::go (param.get_type ()); - } - else - { - auto ¶m = static_cast<AST::FunctionParam &> (*p); - ResolveType::go (param.get_type ()); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - } - - // resolve the function body - ResolveExpr::go (*function.get_definition ().value (), path, cpath); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveItem::visit (AST::InherentImpl &impl_block) -{ - NodeId scope_node_id = impl_block.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - - resolve_visibility (impl_block.get_visibility ()); - - if (impl_block.has_generics ()) - ResolveGenericParams::go (impl_block.get_generic_params (), prefix, - canonical_prefix); - - // resolve any where clause items - if (impl_block.has_where_clause ()) - ResolveWhereClause::Resolve (impl_block.get_where_clause ()); - - // FIXME this needs to be protected behind nominal type-checks see: - // rustc --explain E0118 - // issue #2634 - ResolveType::go (impl_block.get_type ()); - - // Setup paths - CanonicalPath self_cpath = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (impl_block.get_type (), self_cpath); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - rust_debug ("AST::InherentImpl resolve Self: {%s}", - self_cpath.get ().c_str ()); - - CanonicalPath impl_type = self_cpath; - CanonicalPath impl_type_seg - = CanonicalPath::inherent_impl_seg (impl_block.get_node_id (), impl_type); - CanonicalPath impl_prefix = prefix.append (impl_type_seg); - - // see https://godbolt.org/z/a3vMbsT6W - CanonicalPath cpath = CanonicalPath::create_empty (); - if (canonical_prefix.size () <= 1) - { - cpath = impl_prefix; - } - else - { - cpath = canonical_prefix.append (impl_type_seg); - } - - // done setup paths - - auto Self - = CanonicalPath::get_big_self (impl_block.get_type ().get_node_id ()); - - resolver->get_type_scope ().insert (Self, - impl_block.get_type ().get_node_id (), - impl_block.get_type ().get_locus ()); - - for (auto &impl_item : impl_block.get_impl_items ()) - { - rust_debug ( - "AST::InherentImpl resolve_impl_item: impl_prefix={%s} cpath={%s}", - impl_prefix.get ().c_str (), cpath.get ().c_str ()); - resolve_impl_item (*impl_item, impl_prefix, cpath); - } - - resolver->get_type_scope ().peek ()->clear_name ( - Self, impl_block.get_type ().get_node_id ()); - - resolver->get_type_scope ().pop (); - resolver->get_name_scope ().pop (); -} - -void -ResolveItem::visit (AST::TraitImpl &impl_block) -{ - NodeId scope_node_id = impl_block.get_node_id (); - - resolve_visibility (impl_block.get_visibility ()); - - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (impl_block.has_generics ()) - ResolveGenericParams::go (impl_block.get_generic_params (), prefix, - canonical_prefix); - - // resolve any where clause items - if (impl_block.has_where_clause ()) - ResolveWhereClause::Resolve (impl_block.get_where_clause ()); - - // CanonicalPath canonical_trait_type = CanonicalPath::create_empty (); - NodeId trait_resolved_node = ResolveType::go (impl_block.get_trait_path ()); - if (trait_resolved_node == UNKNOWN_NODEID) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - // CanonicalPath canonical_impl_type = CanonicalPath::create_empty (); - NodeId type_resolved_node = ResolveType::go (impl_block.get_type ()); - if (type_resolved_node == UNKNOWN_NODEID) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - bool ok = true; - - // setup paths - CanonicalPath canonical_trait_type = CanonicalPath::create_empty (); - - ok = ResolveTypeToCanonicalPath::go (impl_block.get_trait_path (), - canonical_trait_type); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - rust_debug ("AST::TraitImpl resolve trait type: {%s}", - canonical_trait_type.get ().c_str ()); - - CanonicalPath canonical_impl_type = CanonicalPath::create_empty (); - ok = ResolveTypeToCanonicalPath::go (impl_block.get_type (), - canonical_impl_type); - if (!ok) - { - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - return; - } - - rust_debug ("AST::TraitImpl resolve self: {%s}", - canonical_impl_type.get ().c_str ()); - - // raw paths - CanonicalPath impl_type_seg = canonical_impl_type; - CanonicalPath trait_type_seg = canonical_trait_type; - CanonicalPath projection - = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (), - trait_type_seg, impl_type_seg); - CanonicalPath impl_prefix = prefix.append (projection); - - // setup canonical-path - CanonicalPath canonical_projection - = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (), - canonical_trait_type, - canonical_impl_type); - CanonicalPath cpath = CanonicalPath::create_empty (); - if (canonical_prefix.size () <= 1) - { - cpath = canonical_projection; - } - else - { - cpath = canonical_prefix.append (canonical_projection); - } - - // DONE setup canonical-path - - auto Self - = CanonicalPath::get_big_self (impl_block.get_type ().get_node_id ()); - - resolver->get_type_scope ().insert (Self, - impl_block.get_type ().get_node_id (), - impl_block.get_type ().get_locus ()); - - for (auto &impl_item : impl_block.get_impl_items ()) - { - rust_debug ( - "AST::TraitImpl resolve_impl_item: impl_prefix={%s} cpath={%s}", - impl_prefix.get ().c_str (), cpath.get ().c_str ()); - resolve_impl_item (*impl_item, impl_prefix, cpath); - } - - Rib *r = resolver->get_type_scope ().peek (); - r->clear_name (Self, impl_block.get_type ().get_node_id ()); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveItem::visit (AST::Trait &trait) -{ - NodeId scope_node_id = trait.get_node_id (); - - resolve_visibility (trait.get_visibility ()); - - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - - ResolveGenericParams::go_single (trait.get_implicit_self (), prefix, - canonical_prefix); - ResolveGenericParams::go (trait.get_generic_params (), prefix, - canonical_prefix); - - // Self is an implicit TypeParam so lets mark it as such - resolver->get_type_scope ().append_reference_for_def ( - trait.get_node_id (), trait.get_implicit_self ().get_node_id ()); - - if (trait.has_type_param_bounds ()) - { - for (auto &bound : trait.get_type_param_bounds ()) - { - ResolveTypeBound::go (*bound); - } - } - - // resolve any where clause items - if (trait.has_where_clause ()) - ResolveWhereClause::Resolve (trait.get_where_clause ()); - - // resolve the paths - CanonicalPath path = CanonicalPath::create_empty (); - CanonicalPath cpath = CanonicalPath::create_empty (); - // - - for (auto &item : trait.get_trait_items ()) - { - ResolveTraitItems::go (item.get (), path, cpath); - } - - resolver->get_type_scope ().pop (); - resolver->get_name_scope ().pop (); -} - -void -ResolveItem::visit (AST::ExternBlock &extern_block) -{ - resolve_visibility (extern_block.get_visibility ()); - - for (auto &item : extern_block.get_extern_items ()) - { - resolve_extern_item (*item); - } -} - -void -ResolveItem::resolve_impl_item (AST::AssociatedItem &item, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveImplItems::go (item, prefix, canonical_prefix); -} - -void -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 (const AST::UseTree *tree, std::vector<Import> &imports) -{ - switch (tree->get_kind ()) - { - case AST::UseTree::Glob: - { - auto glob = static_cast<const AST::UseTreeGlob *> (tree); - flatten_glob (*glob, imports); - break; - } - case AST::UseTree::Rebind: - { - auto rebind = static_cast<const AST::UseTreeRebind *> (tree); - flatten_rebind (*rebind, imports); - break; - } - case AST::UseTree::List: - { - auto list = static_cast<const AST::UseTreeList *> (tree); - flatten_list (*list, imports); - break; - } - break; - } -} - -static void -flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports) -{ - if (glob.has_path ()) - imports.emplace_back (glob.get_path (), true, std::string ()); -} - -static void -flatten_rebind (const AST::UseTreeRebind &rebind, std::vector<Import> &imports) -{ - auto path = rebind.get_path (); - - std::string label; - if (rebind.has_identifier ()) - label = rebind.get_identifier ().as_string (); - else - label = path.get_final_segment ().as_string (); - - imports.emplace_back (path, false, label); -} - -static void -flatten_list (const AST::UseTreeList &list, std::vector<Import> &imports) -{ - auto prefix = AST::SimplePath::create_empty (); - if (list.has_path ()) - prefix = list.get_path (); - - for (const auto &tree : list.get_trees ()) - { - // append imports to the main list, then modify them in-place - auto start_idx = imports.size (); - flatten (tree.get (), imports); - - for (auto import = imports.begin () + start_idx; import != imports.end (); - import++) - { - // avoid duplicate node ids - auto prefix_copy - = AST::SimplePath ({}, prefix.has_opening_scope_resolution (), - prefix.get_locus ()); - for (auto &seg : prefix.get_segments ()) - prefix_copy.get_segments ().push_back ( - AST::SimplePathSegment (seg.get_segment_name (), - seg.get_locus ())); - - import->add_prefix (std::move (prefix_copy)); - } - } -} - -void -Import::add_prefix (AST::SimplePath prefix) -{ - AST::SimplePath old_path (std::move (path)); - path = std::move (prefix); - std::move (old_path.get_segments ().begin (), old_path.get_segments ().end (), - std::back_inserter (path.get_segments ())); -} - -/** - * Flatten a UseDeclaration's UseTree into multiple simple paths to resolve. - * - * Given the following use declarations: - * ``` - * use some::path::to_resolve; #1 - * use some::path::to_glob::*; #2 - * use some::path::{one, two}; #2 - * ``` - * - * In the first case, we simply want to return a vector with a single - * SimplePath: - * [some::path::to_resolve] - * - * In the second case, we want to resolve the glob's "origin path": - * [some::path::to_glob] - * - * Finally in the third case, we want to create two SimplePaths to resolve: - * [some::path::one, some::path::two] - */ -static std::vector<Import> -flatten_use_dec_to_imports (const AST::UseDeclaration &use_item) -{ - auto imports = std::vector<Import> (); - - const auto &tree = use_item.get_tree (); - flatten (tree.get (), imports); - - return imports; -} - -void -ResolveItem::visit (AST::UseDeclaration &use_item) -{ - std::vector<Import> to_resolve = flatten_use_dec_to_imports (use_item); - - // FIXME: I think this does not actually resolve glob use-decls and is going - // the wrong way about it. RFC #1560 specifies the following: - // - // > When we find a glob import, we have to record a 'back link', so that when - // a public name is added for the supplying module, we can add it for the - // importing module. - // - // Which is the opposite of what we're doing if I understand correctly? - - NodeId current_module = resolver->peek_current_module_scope (); - for (auto &import : to_resolve) - { - auto &path = import.get_path (); - - rust_debug ("resolving use-decl path: [%s]", path.as_string ().c_str ()); - NodeId resolved_node_id = ResolvePath::go (path); - bool ok = resolved_node_id != UNKNOWN_NODEID; - if (!ok) - continue; - - if (import.is_glob ()) - continue; - - auto decl = CanonicalPath::new_seg (resolved_node_id, import.get_name ()); - mappings.insert_module_child_item (current_module, decl); - - resolver->get_type_scope ().insert (decl, resolved_node_id, - path.get_locus (), - Rib::ItemType::Type); - rust_debug ("use-decl rexporting: [%s]", decl.get ().c_str ()); - } -} - -ResolveImplItems::ResolveImplItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolveItem (prefix, canonical_prefix) -{} - -void -ResolveImplItems::go (AST::AssociatedItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - if (item.is_marked_for_strip ()) - return; - - ResolveImplItems resolver (prefix, canonical_prefix); - item.accept_vis (resolver); -} - -void -ResolveImplItems::visit (AST::TypeAlias &alias) -{ - ResolveItem::visit (alias); - - resolve_visibility (alias.get_visibility ()); - - // FIXME this stops the erronious unused decls which will be fixed later on - resolver->get_type_scope ().append_reference_for_def (alias.get_node_id (), - alias.get_node_id ()); -} - -void -ResolveExternItem::go (AST::ExternalItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveExternItem resolver (prefix, canonical_prefix); - item.accept_vis (resolver); -} - -void -ResolveExternItem::visit (AST::Function &function) -{ - NodeId scope_node_id = function.get_node_id (); - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - mappings.insert_canonical_path (function.get_node_id (), cpath); - - resolve_visibility (function.get_visibility ()); - - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // resolve the generics - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto ¶m : function.get_function_params ()) - if (!param->is_variadic ()) - { - auto &p = static_cast<AST::FunctionParam &> (*param); - ResolveType::go (p.get_type ()); - } - - // done - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); -} - -void -ResolveExternItem::visit (AST::ExternalStaticItem &item) -{ - resolve_visibility (item.get_visibility ()); - - ResolveType::go (item.get_type ()); -} - -} // namespace Resolver -} // namespace Rust - -#if CHECKING_P - -namespace selftest { - -static void -rust_flatten_nested_glob (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto foobar = Rust::AST::SimplePath ({foo, bar}); - - auto glob - = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED, - foobar, UNDEF_LOCATION); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_glob (glob, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); -} - -static void -rust_flatten_glob (void) -{ - auto frob = Rust::AST::SimplePath::from_str ("frobulator", UNDEF_LOCATION); - - auto glob - = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED, - frob, UNDEF_LOCATION); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_glob (glob, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path (), "frobulator"); -} - -static void -rust_flatten_rebind_none (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto foobar = Rust::AST::SimplePath ({foo, bar}); - - auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, - foobar, UNDEF_LOCATION); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_rebind (rebind, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); -} - -static void -rust_flatten_rebind (void) -{ - auto frob = Rust::AST::SimplePath::from_str ("frobulator", UNDEF_LOCATION); - - auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER, - frob, UNDEF_LOCATION, {"saindoux"}); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_rebind (rebind, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path (), "frobulator"); - ASSERT_EQ (imports[0].get_name (), "saindoux"); -} - -static void -rust_flatten_rebind_nested (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto baz = Rust::AST::SimplePathSegment ("baz", UNDEF_LOCATION); - - auto foo_bar_baz = Rust::AST::SimplePath ({foo, bar, baz}); - - auto rebind - = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER, - foo_bar_baz, UNDEF_LOCATION, {"saindoux"}); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_rebind (rebind, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 1); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz"); - ASSERT_EQ (imports[0].get_name (), "saindoux"); -} - -static void -rust_flatten_list (void) -{ - auto foo = Rust::AST::SimplePathSegment ("foo", UNDEF_LOCATION); - auto bar = Rust::AST::SimplePathSegment ("bar", UNDEF_LOCATION); - auto foo_bar = Rust::AST::SimplePath ({foo, bar}); - - auto baz = Rust::AST::SimplePath::from_str ("baz", UNDEF_LOCATION); - auto bul = Rust::AST::SimplePath::from_str ("bul", UNDEF_LOCATION); - - // use foo::bar::{baz, bul}; - - auto use0 = std::unique_ptr<Rust::AST::UseTree> ( - new Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, baz, - UNDEF_LOCATION)); - auto use1 = std::unique_ptr<Rust::AST::UseTree> ( - new Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, bul, - UNDEF_LOCATION)); - - auto uses = std::vector<std::unique_ptr<Rust::AST::UseTree>> (); - uses.emplace_back (std::move (use0)); - uses.emplace_back (std::move (use1)); - - auto list - = Rust::AST::UseTreeList (Rust::AST::UseTreeList::PATH_PREFIXED, foo_bar, - std::move (uses), UNDEF_LOCATION); - - auto imports = std::vector<Rust::Resolver::Import> (); - Rust::Resolver::flatten_list (list, imports); - - ASSERT_TRUE (!imports.empty ()); - ASSERT_EQ (imports.size (), 2); - ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz"); - ASSERT_EQ (imports[1].get_path ().get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (imports[1].get_path ().get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (imports[1].get_path ().get_segments ()[2].as_string (), "bul"); -} - -static void -rust_use_dec_flattening (void) -{ - rust_flatten_glob (); - rust_flatten_nested_glob (); - rust_flatten_rebind_none (); - rust_flatten_rebind (); - rust_flatten_rebind_nested (); - rust_flatten_list (); -} - -void -rust_simple_path_resolve_test (void) -{ - rust_use_dec_flattening (); -} - -} // namespace selftest - -#endif // CHECKING_P diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h deleted file mode 100644 index d31f910..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (C) 2020-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_AST_RESOLVE_ITEM_H -#define RUST_AST_RESOLVE_ITEM_H - -#include "rust-ast-full-decls.h" -#include "rust-ast-resolve-base.h" - -#include "config.h" - -namespace Rust { -namespace Resolver { - -class ResolveTraitItems : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::AssociatedItem *item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::Function &type) override; - void visit (AST::TraitItemType &type) override; - void visit (AST::TraitItemConst &constant) override; - -private: - ResolveTraitItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class ResolveItem : public ResolverBase -{ -public: - using Rust::Resolver::ResolverBase::visit; - - static void go (AST::Item &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::TypeAlias &alias) override; - void visit (AST::Module &module) override; - void visit (AST::TupleStruct &struct_decl) override; - void visit (AST::Enum &enum_decl) override; - /* EnumItem doesn't need to be handled, no fields. */ - void visit (AST::EnumItem &item) override; - void visit (AST::EnumItemTuple &item) override; - void visit (AST::EnumItemStruct &item) override; - void visit (AST::EnumItemDiscriminant &item) override; - void visit (AST::StructStruct &struct_decl) override; - void visit (AST::Union &union_decl) override; - void visit (AST::StaticItem &var) override; - void visit (AST::ConstantItem &constant) override; - void visit (AST::Function &function) override; - void visit (AST::InherentImpl &impl_block) override; - void visit (AST::TraitImpl &impl_block) override; - void visit (AST::Trait &trait) override; - void visit (AST::ExternBlock &extern_block) override; - void visit (AST::UseDeclaration &) override; - -protected: - void resolve_impl_item (AST::AssociatedItem &item, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - void resolve_extern_item (AST::ExternalItem &item); - - ResolveItem (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class ResolveImplItems : public ResolveItem -{ - using Rust::Resolver::ResolveItem::visit; - -public: - static void go (AST::AssociatedItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::TypeAlias &alias) override; - -private: - ResolveImplItems (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); -}; - -class ResolveExternItem : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::ExternalItem &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::Function &function) override; - void visit (AST::ExternalStaticItem &item) override; - -private: - ResolveExternItem (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) - {} - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class Import -{ -public: - Import (AST::SimplePath path, bool is_glob, std::string name) - : path (path), is_glob_f (is_glob), name (name) - {} - - AST::SimplePath &get_path () { return path; } - - const AST::SimplePath &get_path () const { return path; } - - bool is_glob () const { return is_glob_f; } - - const std::string &get_name () const { return name; } - - void add_prefix (AST::SimplePath prefix); - -private: - AST::SimplePath path; - bool is_glob_f; - std::string name; -}; - -} // namespace Resolver -} // namespace Rust - -#if CHECKING_P - -namespace selftest { -extern void rust_simple_path_resolve_test (void); -} // namespace selftest - -#endif // CHECKING_P - -#endif // RUST_AST_RESOLVE_ITEM_H diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc deleted file mode 100644 index fb6715d..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-path.cc +++ /dev/null @@ -1,558 +0,0 @@ -// Copyright (C) 2020-2024 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-ast-resolve-path.h" -#include "rust-ast-resolve-type.h" -#include "rust-hir-map.h" -#include "rust-path.h" - -namespace Rust { -namespace Resolver { - -ResolvePath::ResolvePath () : ResolverBase () {} - -NodeId -ResolvePath::go (AST::PathInExpression &expr) -{ - ResolvePath resolver; - return resolver.resolve_path (expr); -} - -NodeId -ResolvePath::go (AST::QualifiedPathInExpression &expr) -{ - ResolvePath resolver; - return resolver.resolve_path (expr); -} - -NodeId -ResolvePath::go (AST::SimplePath &expr) -{ - ResolvePath resolver; - return resolver.resolve_path (expr); -} - -NodeId -ResolvePath::resolve_path (AST::PathInExpression &expr) -{ - if (expr.is_lang_item ()) - return Analysis::Mappings::get ().get_lang_item_node ( - expr.get_lang_item ()); - - NodeId resolved_node_id = UNKNOWN_NODEID; - NodeId module_scope_id = resolver->peek_current_module_scope (); - NodeId previous_resolved_node_id = module_scope_id; - for (size_t i = 0; i < expr.get_segments ().size (); i++) - { - auto &segment = expr.get_segments ().at (i); - const AST::PathIdentSegment &ident_seg = segment.get_ident_segment (); - bool is_first_segment = i == 0; - resolved_node_id = UNKNOWN_NODEID; - - bool in_middle_of_path = i > 0; - if (in_middle_of_path && segment.is_lower_self_seg ()) - { - rust_error_at (segment.get_locus (), ErrorCode::E0433, - "%qs in paths can only be used in start position", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - - NodeId crate_scope_id = resolver->peek_crate_module_scope (); - if (segment.is_crate_path_seg ()) - { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - continue; - } - else if (segment.is_super_path_seg ()) - { - if (module_scope_id == crate_scope_id) - { - rust_error_at (segment.get_locus (), - "cannot use %<super%> at the crate scope"); - return UNKNOWN_NODEID; - } - - module_scope_id = resolver->peek_parent_module_scope (); - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - continue; - } - - // resolve any generic args - if (segment.has_generic_args ()) - ResolveGenericArgs::go (segment.get_generic_args ()); - - // logic is awkward here there are a few cases - // - // T::Default - // mod::foo::impl_item - // super::super::module::item - // self - // self::foo - // self::foo::baz - // - // T::Default we can only resolve the T and cant do anything about Default - // its dependant on associated types - // - // mod::foo::impl_item - // we can resolve mod::foo but nothing about impl_item but we need to - // _always resolve generic arguments - // - // self is a simple single lookup - // - // we have module_scope_id for the next module_scope to lookup - // resolved_node_id is the thing we have resolve this segment to - // - // new algo? - // we can only use module resolution when the previous segment is either - // unknown or equal to this module_scope_id - // - // can only use old resolution when previous segment is unkown - - if (is_first_segment) - { - // name scope first - NodeId resolved_node = UNKNOWN_NODEID; - const CanonicalPath path - = CanonicalPath::new_seg (segment.get_node_id (), - ident_seg.as_string ()); - if (resolver->get_name_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - // check the type scope - else if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - else if (segment.is_lower_self_seg ()) - { - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - continue; - } - else - { - // no error handling here since we might be able to resolve via - // the module hierarchy and handle errors at the end - } - } - - if (resolved_node_id == UNKNOWN_NODEID - && previous_resolved_node_id == module_scope_id) - { - tl::optional<CanonicalPath &> resolved_child - = mappings.lookup_module_child (module_scope_id, - ident_seg.as_string ()); - if (resolved_child.has_value ()) - { - NodeId resolved_node = resolved_child->get_node_id (); - if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - } - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - } - else - { - rust_error_at (segment.get_locus (), - "Cannot find path %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - } - } - - bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID; - if (did_resolve_segment) - { - if (mappings.node_is_module (resolved_node_id) - || mappings.node_is_crate (resolved_node_id)) - { - module_scope_id = resolved_node_id; - } - previous_resolved_node_id = resolved_node_id; - } - else if (is_first_segment) - { - rust_error_at (segment.get_locus (), ErrorCode::E0433, - "Cannot find path %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - } - - resolved_node = resolved_node_id; - if (resolved_node_id != UNKNOWN_NODEID) - { - // name scope first - if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_name (expr.get_node_id (), - resolved_node_id); - } - // check the type scope - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_type (expr.get_node_id (), - resolved_node_id); - } - else - { - rust_unreachable (); - } - } - return resolved_node_id; -} - -NodeId -ResolvePath::resolve_path (AST::QualifiedPathInExpression &expr) -{ - auto &root_segment = expr.get_qualified_path_type (); - ResolveType::go (root_segment.get_type ()); - if (root_segment.has_as_clause ()) - ResolveType::go (root_segment.get_as_type_path ()); - - for (auto &segment : expr.get_segments ()) - { - // we cant actually do anything with the segment itself since this is all - // the job of the type system to figure it out but we can resolve any - // generic arguments used - if (segment.has_generic_args ()) - ResolveGenericArgs::go (segment.get_generic_args ()); - } - - // cannot fully resolve a qualified path as it is dependant on associated - // items - return UNKNOWN_NODEID; -} - -NodeId -ResolvePath::resolve_path (AST::SimplePath &expr) -{ - NodeId crate_scope_id = resolver->peek_crate_module_scope (); - NodeId module_scope_id = resolver->peek_current_module_scope (); - - NodeId previous_resolved_node_id = UNKNOWN_NODEID; - NodeId resolved_node_id = UNKNOWN_NODEID; - for (size_t i = 0; i < expr.get_segments ().size (); i++) - { - AST::SimplePathSegment &segment = expr.get_segments ().at (i); - bool is_first_segment = i == 0; - bool is_final_segment = i >= (expr.get_segments ().size () - 1); - resolved_node_id = UNKNOWN_NODEID; - - if (segment.is_crate_path_seg ()) - { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - resolved_node_id = module_scope_id; - - continue; - } - else if (segment.is_super_path_seg ()) - { - if (!is_first_segment) - { - rust_error_at ( - segment.get_locus (), ErrorCode::E0433, - "%<super%> in paths can only be used in start position"); - return UNKNOWN_NODEID; - } - if (module_scope_id == crate_scope_id) - { - rust_error_at (segment.get_locus (), - "cannot use %<super%> at the crate scope"); - return UNKNOWN_NODEID; - } - - module_scope_id = resolver->peek_parent_module_scope (); - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment.get_node_id (), - module_scope_id); - resolved_node_id = module_scope_id; - - continue; - } - - tl::optional<CanonicalPath &> resolved_child - = mappings.lookup_module_child (module_scope_id, - segment.get_segment_name ()); - if (resolved_child.has_value ()) - { - NodeId resolved_node = resolved_child->get_node_id (); - if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - } - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - } - else - { - rust_error_at (segment.get_locus (), - "Cannot find path %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - } - - if (resolved_node_id == UNKNOWN_NODEID && is_first_segment) - { - // name scope first - NodeId resolved_node = UNKNOWN_NODEID; - const CanonicalPath path - = CanonicalPath::new_seg (segment.get_node_id (), - segment.get_segment_name ()); - if (resolver->get_name_scope ().lookup (path, &resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment.get_node_id (), - resolved_node); - } - // check the type scope - else if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment.get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment.get_node_id (), - resolved_node); - } - } - - // if we still have not resolved and this is the final segment and the - // final segment is self its likely the case: pub use - // - // result::Result::{self, Err, Ok}; - // - // Then the resolved_node_id is just the previous one so long as it is a - // resolved node id - // rust_debug_loc (segment.get_locus (), - // "trying to resolve seg: [%s] first [%s] last [%s]", - // segment.get_segment_name ().c_str (), - // is_first_segment ? "true" : "false", - // is_final_segment ? "true" : "false"); - if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment - && is_final_segment && segment.is_lower_self_seg ()) - resolved_node_id = previous_resolved_node_id; - - // final check - if (resolved_node_id == UNKNOWN_NODEID) - { - rust_error_at (segment.get_locus (), - "cannot find simple path segment %<%s%> in this scope", - segment.as_string ().c_str ()); - return UNKNOWN_NODEID; - } - - if (mappings.node_is_module (resolved_node_id)) - { - module_scope_id = resolved_node_id; - } - - previous_resolved_node_id = resolved_node_id; - } - - resolved_node = resolved_node_id; - if (resolved_node_id != UNKNOWN_NODEID) - { - // name scope first - if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_name (expr.get_node_id (), - resolved_node_id); - } - // check the type scope - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (expr.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_type (expr.get_node_id (), - resolved_node_id); - } - else - { - rust_unreachable (); - } - } - return resolved_node_id; -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-path.h b/gcc/rust/resolve/rust-ast-resolve-path.h deleted file mode 100644 index cddb54a..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-path.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2020-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_AST_RESOLVE_PATH_H -#define RUST_AST_RESOLVE_PATH_H - -#include "rust-ast-resolve-base.h" - -namespace Rust { -namespace Resolver { - -class ResolvePath : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static NodeId go (AST::PathInExpression &expr); - static NodeId go (AST::QualifiedPathInExpression &expr); - static NodeId go (AST::SimplePath &expr); - -private: - ResolvePath (); - - NodeId resolve_path (AST::PathInExpression &expr); - NodeId resolve_path (AST::QualifiedPathInExpression &expr); - NodeId resolve_path (AST::SimplePath &expr); - - void - resolve_simple_path_segments (CanonicalPath prefix, size_t offs, - const std::vector<AST::SimplePathSegment> &segs, - NodeId expr_node_id, location_t expr_locus); -}; - -} // namespace Resolver -} // namespace Rust - -#endif // !RUST_AST_RESOLVE_PATH_H diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc deleted file mode 100644 index 3b80f9f..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc +++ /dev/null @@ -1,419 +0,0 @@ -// Copyright (C) 2020-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-ast-resolve-pattern.h" -#include "rust-ast-resolve-path.h" - -namespace Rust { -namespace Resolver { - -void -PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type) -{ - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - PatternDeclaration::go (pattern, type, bindings); -} - -void -PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type, - std::vector<PatternBinding> &bindings) -{ - PatternDeclaration resolver (bindings, type); - pattern.accept_vis (resolver); - - for (auto &map_entry : resolver.missing_bindings) - { - auto ident = map_entry.first; // key - auto info = map_entry.second; // value - - rust_error_at (info.get_locus (), ErrorCode::E0408, - "variable '%s' is not bound in all patterns", - ident.as_string ().c_str ()); - } - - for (auto &map_entry : resolver.inconsistent_bindings) - { - auto ident = map_entry.first; // key - auto info = map_entry.second; // value - - rust_error_at ( - info.get_locus (), ErrorCode::E0409, - "variable '%s' is bound inconsistently across pattern alternatives", - ident.as_string ().c_str ()); - } -} - -void -PatternDeclaration::visit (AST::IdentifierPattern &pattern) -{ - if (pattern.has_subpattern ()) - { - pattern.get_subpattern ().accept_vis (*this); - } - - Mutability mut = pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm; - add_new_binding (pattern.get_ident (), pattern.get_node_id (), - BindingTypeInfo (mut, pattern.get_is_ref (), - pattern.get_locus ())); -} - -void -PatternDeclaration::visit (AST::GroupedPattern &pattern) -{ - pattern.get_pattern_in_parens ().accept_vis (*this); -} - -void -PatternDeclaration::visit (AST::ReferencePattern &pattern) -{ - pattern.get_referenced_pattern ().accept_vis (*this); -} - -void -PatternDeclaration::visit (AST::PathInExpression &pattern) -{ - ResolvePath::go (pattern); -} - -void -PatternDeclaration::visit (AST::TupleStructPattern &pattern) -{ - ResolvePath::go (pattern.get_path ()); - - AST::TupleStructItems &items = pattern.get_items (); - switch (items.get_item_type ()) - { - case AST::TupleStructItems::RANGE: - { - // TODO - rust_unreachable (); - } - break; - - case AST::TupleStructItems::NO_RANGE: - { - auto &items_no_range - = static_cast<AST::TupleStructItemsNoRange &> (items); - - for (auto &inner_pattern : items_no_range.get_patterns ()) - { - inner_pattern->accept_vis (*this); - } - } - break; - } -} - -void -PatternDeclaration::visit (AST::StructPattern &pattern) -{ - ResolvePath::go (pattern.get_path ()); - - auto &struct_pattern_elems = pattern.get_struct_pattern_elems (); - for (auto &field : struct_pattern_elems.get_struct_pattern_fields ()) - { - switch (field->get_item_type ()) - { - case AST::StructPatternField::ItemType::TUPLE_PAT: - { - AST::StructPatternFieldTuplePat &tuple - = static_cast<AST::StructPatternFieldTuplePat &> (*field); - - tuple.get_index_pattern ().accept_vis (*this); - } - break; - - case AST::StructPatternField::ItemType::IDENT_PAT: - { - AST::StructPatternFieldIdentPat &ident - = static_cast<AST::StructPatternFieldIdentPat &> (*field); - - ident.get_ident_pattern ().accept_vis (*this); - } - break; - - case AST::StructPatternField::ItemType::IDENT: - { - auto &ident = static_cast<AST::StructPatternFieldIdent &> (*field); - - Mutability mut - = ident.is_mut () ? Mutability::Mut : Mutability::Imm; - - add_new_binding (ident.get_identifier (), ident.get_node_id (), - BindingTypeInfo (mut, ident.is_ref (), - ident.get_locus ())); - } - break; - } - } -} - -void -PatternDeclaration::visit (AST::TuplePattern &pattern) -{ - auto &items = pattern.get_items (); - switch (items.get_pattern_type ()) - { - case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: - { - auto &ref = static_cast<AST::TuplePatternItemsMultiple &> ( - pattern.get_items ()); - - for (auto &p : ref.get_patterns ()) - p->accept_vis (*this); - } - break; - - case AST::TuplePatternItems::TuplePatternItemType::RANGED: - { - auto &ref - = static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ()); - - for (auto &p : ref.get_lower_patterns ()) - p->accept_vis (*this); - for (auto &p : ref.get_upper_patterns ()) - p->accept_vis (*this); - } - break; - } -} - -void -PatternDeclaration::visit (AST::AltPattern &pattern) -{ - // push a new set of 'Or' bindings to the stack. Accounts for the - // alternatives. e.g. in `p_0 | p_1`, bindings to the same identifier between - // p_0 and p_1 shouldn't cause an error. - bindings_with_ctx.push_back ( - PatternBinding (PatternBoundCtx::Or, std::set<Identifier> ())); - - // This is a hack to avoid creating a separate visitor class for the - // consistency checks. We empty out the binding_info_map before each iteration - // to separate between the alts' binding_maps. And right after the alt - // visit... - auto tmp_binding_map = binding_info_map; - binding_info_map.clear (); - - std::vector<BindingMap> alts_binding_maps; - - for (auto &alt : pattern.get_alts ()) - { - // before this visit, the binding_info_map is guaranteed to be empty - rust_assert (binding_info_map.empty ()); - - // push a new `Product` context to correctly reject multiple bindings - // within this single alt. - bindings_with_ctx.push_back ( - PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())); - - alt->accept_vis (*this); - - // ...the binding_info_map is (potentially) populated. We copy it to the - // vector, and empty it out to be ready for the next iteration. And after - // all the iterations are finished... - alts_binding_maps.push_back (binding_info_map); - binding_info_map.clear (); - - // Remove the last (i.e. `Product`) context and add the bindings from the - // visited alt to the one before last (i.e. `Or`). Now (after checking - // with the alt internally), the bindings from this alt will reside in the - // `Or` context. - auto last_bound_idents = bindings_with_ctx.back ().idents; - bindings_with_ctx.pop_back (); - - for (auto &ident : last_bound_idents) - { - bindings_with_ctx.back ().idents.insert (ident); - } - } - - // Now we can finally check for consistency. - check_bindings_consistency (alts_binding_maps); - - // Now we remove the `Or` context we pushed earlier. - // e.g. in `(a, (p_0 | p_1), c)`: after finishing up inside the alt pattern, - // we return to the tuple (`Product`) context and push the new bindings. - auto idents = bindings_with_ctx.back ().idents; - bindings_with_ctx.pop_back (); - for (auto &ident : idents) - bindings_with_ctx.back ().idents.insert (ident.as_string ()); - - // ...we repopulate the binding_info_map correctly (the initial bindings - // stored in the tmp_binding_map + all the bindings from all the alts) - binding_info_map = tmp_binding_map; - for (auto &alt_map : alts_binding_maps) - for (auto &map_entry : alt_map) - binding_info_map.insert (map_entry); -} - -void -PatternDeclaration::add_new_binding (Identifier ident, NodeId node_id, - BindingTypeInfo info) -{ - bool has_binding_ctx = bindings_with_ctx.size () > 0; - rust_assert (has_binding_ctx); - - bool identifier_or_bound = false, identifier_product_bound = false; - - for (auto binding : bindings_with_ctx) - { - bool identifier_bound_here - = (binding.idents.find (ident) != binding.idents.end ()); - if (identifier_bound_here) - { - identifier_product_bound |= binding.ctx == PatternBoundCtx::Product; - identifier_or_bound |= binding.ctx == PatternBoundCtx::Or; - } - } - - if (identifier_product_bound) - { - if (type == Rib::ItemType::Param) - { - rust_error_at (info.get_locus (), ErrorCode::E0415, - "identifier '%s' is bound more than once in the " - "same parameter list", - ident.as_string ().c_str ()); - } - else - { - rust_error_at ( - info.get_locus (), ErrorCode::E0416, - "identifier '%s' is bound more than once in the same pattern", - ident.as_string ().c_str ()); - } - - return; - } - - if (!identifier_or_bound) - { - bindings_with_ctx.back ().idents.insert (ident); - resolver->get_name_scope ().insert ( - CanonicalPath::new_seg (node_id, ident.as_string ()), node_id, - info.get_locus (), type); - } - - binding_info_map.insert ({ident, info}); -} - -// Verifies that all the alts in an AltPattern have the same set of bindings -// with the same mutability and reference states. -void -PatternDeclaration::check_bindings_consistency ( - std::vector<BindingMap> &binding_maps) -{ - for (size_t i = 0; i < binding_maps.size (); i++) - { - auto &outer_bindings_map = binding_maps[i]; - - for (size_t j = 0; j < binding_maps.size (); j++) - { - // skip comparing the current outer map with itself. - if (j == i) - continue; - - auto &inner_bindings_map = binding_maps[j]; - - // iterate over the inner map entries and check if they exist in outer - // map - for (auto map_entry : inner_bindings_map) - { - auto ident = map_entry.first; // key - auto inner_info = map_entry.second; // value - bool ident_is_outer_bound = outer_bindings_map.count (ident); - - if (!ident_is_outer_bound && !missing_bindings.count (ident)) - missing_bindings.insert ({ident, inner_info}); - - else if (outer_bindings_map.count (ident) - && outer_bindings_map[ident] != inner_info - && !inconsistent_bindings.count (ident)) - inconsistent_bindings.insert ({ident, inner_info}); - } - } - } -} - -static void -resolve_range_pattern_bound (AST::RangePatternBound &bound) -{ - switch (bound.get_bound_type ()) - { - case AST::RangePatternBound::RangePatternBoundType::LITERAL: - // Nothing to resolve for a literal. - break; - - case AST::RangePatternBound::RangePatternBoundType::PATH: - { - auto &ref = static_cast<AST::RangePatternBoundPath &> (bound); - - ResolvePath::go (ref.get_path ()); - } - break; - - case AST::RangePatternBound::RangePatternBoundType::QUALPATH: - { - auto &ref = static_cast<AST::RangePatternBoundQualPath &> (bound); - - ResolvePath::go (ref.get_qualified_path ()); - } - break; - } -} - -void -PatternDeclaration::visit (AST::RangePattern &pattern) -{ - resolve_range_pattern_bound (pattern.get_upper_bound ()); - resolve_range_pattern_bound (pattern.get_lower_bound ()); -} - -void -PatternDeclaration::visit (AST::SlicePattern &pattern) -{ - auto &items = pattern.get_items (); - switch (items.get_pattern_type ()) - { - case AST::SlicePatternItems::SlicePatternItemType::NO_REST: - { - auto &ref - = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ()); - - for (auto &p : ref.get_patterns ()) - p->accept_vis (*this); - } - break; - - case AST::SlicePatternItems::SlicePatternItemType::HAS_REST: - { - auto &ref - = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ()); - - for (auto &p : ref.get_lower_patterns ()) - p->accept_vis (*this); - for (auto &p : ref.get_upper_patterns ()) - p->accept_vis (*this); - } - break; - } -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h deleted file mode 100644 index 876de16..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (C) 2020-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_AST_RESOLVE_PATTERN_H -#define RUST_AST_RESOLVE_PATTERN_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-full.h" - -namespace Rust { -namespace Resolver { - -// Specifies whether the set of already bound patterns are related by 'Or' or -// 'Product'. Used to check for multiple bindings to the same identifier. -enum PatternBoundCtx -{ - // A product pattern context (e.g. struct and tuple patterns) - Product, - // An or-pattern context (e.g. p_0 | p_1 | ...) - Or, -}; - -struct PatternBinding -{ - PatternBoundCtx ctx; - std::set<Identifier> idents; - - PatternBinding (PatternBoundCtx ctx, std::set<Identifier> idents) - : ctx (ctx), idents (idents) - {} -}; - -// Info that gets stored in the map. Helps us detect if two bindings to the same -// identifier have different mutability or ref states. -class BindingTypeInfo -{ - Mutability mut; - bool is_ref; - location_t locus; - -public: - BindingTypeInfo (Mutability mut, bool is_ref, location_t locus) - : mut (mut), is_ref (is_ref), locus (locus) - {} - - BindingTypeInfo (BindingTypeInfo const &other) - : mut (other.mut), is_ref (other.is_ref), locus (other.get_locus ()) - {} - - BindingTypeInfo (){}; - - location_t get_locus () const { return locus; } - Mutability get_mut () const { return mut; } - bool get_is_ref () const { return is_ref; } - - BindingTypeInfo operator= (BindingTypeInfo const &other) - { - mut = other.mut; - is_ref = other.is_ref; - locus = other.get_locus (); - - return *this; - } - - bool operator== (BindingTypeInfo const &other) - { - return mut == other.mut && is_ref == other.is_ref; - } - - bool operator!= (BindingTypeInfo const &other) - { - return !BindingTypeInfo::operator== (other); - } -}; - -typedef std::map<Identifier, BindingTypeInfo> BindingMap; - -class PatternDeclaration : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Pattern &pattern, Rib::ItemType type); - static void go (AST::Pattern &pattern, Rib::ItemType type, - std::vector<PatternBinding> &bindings); - - void visit (AST::IdentifierPattern &pattern) override; - void visit (AST::GroupedPattern &pattern) override; - void visit (AST::ReferencePattern &pattern) override; - void visit (AST::PathInExpression &pattern) override; - void visit (AST::StructPattern &pattern) override; - void visit (AST::TupleStructPattern &pattern) override; - void visit (AST::TuplePattern &pattern) override; - void visit (AST::RangePattern &pattern) override; - void visit (AST::AltPattern &pattern) override; - void visit (AST::SlicePattern &pattern) override; - - void add_new_binding (Identifier ident, NodeId node_id, BindingTypeInfo info); - void check_bindings_consistency (std::vector<BindingMap> &binding_maps); - -private: - PatternDeclaration (std::vector<PatternBinding> &bindings_with_ctx, - Rib::ItemType type) - : ResolverBase (), bindings_with_ctx (bindings_with_ctx), type (type) - {} - - // To avoid having a separate visitor for consistency checks, we store - // bindings in two forms: - - // 1) Bindings as a vector of context-related sets. - // Used for checking multiple bindings to the same identifier (i.e. E0415, - // E0416). - std::vector<PatternBinding> &bindings_with_ctx; - - // 2) Bindings as a map between identifiers and binding info. - // Used for checking consistency between alt patterns (i.e. E0408, E0409). - BindingMap binding_info_map; - - // we need to insert the missing and inconsistent bindings (found in - // check_bindings_consistency) into maps to avoid duplication of error - // messages. - BindingMap inconsistent_bindings; - BindingMap missing_bindings; - - Rib::ItemType type; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_PATTERN_H diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.cc b/gcc/rust/resolve/rust-ast-resolve-stmt.cc deleted file mode 100644 index bfba302..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.cc +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2020-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-ast-resolve-toplevel.h" -#include "rust-ast-resolve-item.h" -#include "rust-ast-resolve-stmt.h" -#include "rust-ast-resolve-implitem.h" - -namespace Rust { -namespace Resolver { - -void -ResolveStmt::visit (AST::ExternBlock &extern_block) -{ - resolve_visibility (extern_block.get_visibility ()); - for (auto &item : extern_block.get_extern_items ()) - { - ResolveToplevelExternItem::go (*item, CanonicalPath::create_empty ()); - ResolveExternItem::go (*item, prefix, canonical_prefix); - } -} - -void -ResolveStmt::visit (AST::Trait &trait) -{ - ResolveTopLevel::go (trait, prefix, canonical_prefix); - ResolveItem::go (trait, prefix, canonical_prefix); -} - -void -ResolveStmt::visit (AST::InherentImpl &impl_block) -{ - ResolveTopLevel::go (impl_block, prefix, canonical_prefix); - ResolveItem::go (impl_block, prefix, canonical_prefix); -} - -void -ResolveStmt::visit (AST::TraitImpl &impl_block) -{ - ResolveTopLevel::go (impl_block, prefix, canonical_prefix); - ResolveItem::go (impl_block, prefix, canonical_prefix); -} - -void -ResolveStmt::visit (AST::StaticItem &var) -{ - auto decl = CanonicalPath::new_seg (var.get_node_id (), - var.get_identifier ().as_string ()); - auto path = decl; - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (var.get_node_id (), cpath); - - resolver->get_name_scope ().insert ( - path, var.get_node_id (), var.get_locus (), false, Rib::ItemType::Static, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, var.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - ResolveType::go (var.get_type ()); - ResolveExpr::go (var.get_expr (), path, cpath); -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h deleted file mode 100644 index d714511..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ /dev/null @@ -1,408 +0,0 @@ -// Copyright (C) 2020-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_AST_RESOLVE_STMT_H -#define RUST_AST_RESOLVE_STMT_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-type.h" -#include "rust-ast-resolve-pattern.h" -#include "rust-ast-resolve-expr.h" -#include "rust-item.h" - -namespace Rust { -namespace Resolver { - -class ResolveStmt : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Stmt &stmt, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - const CanonicalPath &enum_prefix) - { - if (stmt.is_marked_for_strip ()) - return; - - ResolveStmt resolver (prefix, canonical_prefix, enum_prefix); - stmt.accept_vis (resolver); - } - - void visit (AST::ExprStmt &stmt) override - { - ResolveExpr::go (stmt.get_expr (), prefix, canonical_prefix); - } - - void visit (AST::ConstantItem &constant) override - { - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - - resolver->get_name_scope ().insert ( - path, constant.get_node_id (), constant.get_locus (), false, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - ResolveType::go (constant.get_type ()); - if (constant.has_expr ()) - ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix); - } - - void visit (AST::LetStmt &stmt) override - { - if (stmt.has_init_expr ()) - ResolveExpr::go (stmt.get_init_expr (), prefix, canonical_prefix); - - if (stmt.has_else_expr ()) - ResolveExpr::go (stmt.get_else_expr (), prefix, canonical_prefix); - - PatternDeclaration::go (stmt.get_pattern (), Rib::ItemType::Var); - if (stmt.has_type ()) - ResolveType::go (stmt.get_type ()); - } - - void visit (AST::TupleStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, struct_decl.get_node_id (), struct_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - for (AST::TupleField &field : struct_decl.get_fields ()) - ResolveType::go (field.get_field_type ()); - - resolver->get_type_scope ().pop (); - } - - void visit (AST::Enum &enum_decl) override - { - auto decl - = CanonicalPath::new_seg (enum_decl.get_node_id (), - enum_decl.get_identifier ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (enum_decl.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, enum_decl.get_node_id (), enum_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, enum_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = enum_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (enum_decl.has_generics ()) - ResolveGenericParams::go (enum_decl.get_generic_params (), prefix, - canonical_prefix); - - for (auto &variant : enum_decl.get_variants ()) - ResolveStmt::go (*variant, path, canonical_prefix, path); - - resolver->get_type_scope ().pop (); - } - - void visit (AST::EnumItem &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - // Done, no fields. - } - - void visit (AST::EnumItemTuple &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - for (auto &field : item.get_tuple_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - } - - void visit (AST::EnumItemStruct &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - for (auto &field : item.get_struct_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - } - - void visit (AST::EnumItemDiscriminant &item) override - { - auto decl = enum_prefix.append ( - CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ())); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (item.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - // Done, no fields. - } - - void visit (AST::StructStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, struct_decl.get_node_id (), struct_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = struct_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (struct_decl.has_generics ()) - ResolveGenericParams::go (struct_decl.get_generic_params (), prefix, - canonical_prefix); - - for (AST::StructField &field : struct_decl.get_fields ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); - } - - void visit (AST::Union &union_decl) override - { - auto decl - = CanonicalPath::new_seg (union_decl.get_node_id (), - union_decl.get_identifier ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (union_decl.get_node_id (), cpath); - - resolver->get_type_scope ().insert ( - path, union_decl.get_node_id (), union_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, union_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = union_decl.get_node_id (); - resolver->get_type_scope ().push (scope_node_id); - - if (union_decl.has_generics ()) - ResolveGenericParams::go (union_decl.get_generic_params (), prefix, - canonical_prefix); - - for (AST::StructField &field : union_decl.get_variants ()) - { - if (field.get_field_type ().is_marked_for_strip ()) - continue; - - ResolveType::go (field.get_field_type ()); - } - - resolver->get_type_scope ().pop (); - } - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = decl; // this ensures we have the correct relative resolution - auto cpath = canonical_prefix.append (decl); - mappings.insert_canonical_path (function.get_node_id (), cpath); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId scope_node_id = function.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - if (function.has_generics ()) - ResolveGenericParams::go (function.get_generic_params (), prefix, - canonical_prefix); - - if (function.has_return_type ()) - ResolveType::go (function.get_return_type ()); - - std::vector<PatternBinding> bindings - = {PatternBinding (PatternBoundCtx::Product, std::set<Identifier> ())}; - - // we make a new scope so the names of parameters are resolved and shadowed - // correctly - for (auto &p : function.get_function_params ()) - { - if (p->is_variadic ()) - { - auto ¶m = static_cast<AST::VariadicParam &> (*p); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - - else if (p->is_self ()) - { - auto ¶m = static_cast<AST::SelfParam &> (*p); - ResolveType::go (param.get_type ()); - } - else - { - auto ¶m = static_cast<AST::FunctionParam &> (*p); - - ResolveType::go (param.get_type ()); - PatternDeclaration::go (param.get_pattern (), Rib::ItemType::Param, - bindings); - } - } - - // resolve the function body - ResolveExpr::go (*function.get_definition ().value (), path, cpath); - - resolver->get_name_scope ().pop (); - resolver->get_type_scope ().pop (); - resolver->get_label_scope ().pop (); - } - - void visit (AST::ExternBlock &extern_block) override; - void visit (AST::Trait &trait) override; - void visit (AST::InherentImpl &impl_block) override; - void visit (AST::TraitImpl &impl_block) override; - void visit (AST::StaticItem &var) override; - -private: - ResolveStmt (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix, - const CanonicalPath &enum_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix), - enum_prefix (enum_prefix) - {} - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; - - /* item declaration statements are not given a canonical path, but enum items - * (variants) do inherit the enum path/identifier name. */ - const CanonicalPath &enum_prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_STMT_H diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc deleted file mode 100644 index 9b38e6a..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.cc +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2020-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-ast-resolve-struct-expr-field.h" -#include "rust-ast-resolve-expr.h" - -namespace Rust { -namespace Resolver { - -void -ResolveStructExprField::go (AST::StructExprField &field, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - ResolveStructExprField resolver (prefix, canonical_prefix); - field.accept_vis (resolver); -} - -ResolveStructExprField::ResolveStructExprField ( - const CanonicalPath &prefix, const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) -{} - -void -ResolveStructExprField::visit (AST::StructExprFieldIdentifierValue &field) -{ - ResolveExpr::go (field.get_value (), prefix, canonical_prefix); -} - -void -ResolveStructExprField::visit (AST::StructExprFieldIndexValue &field) -{ - ResolveExpr::go (field.get_value (), prefix, canonical_prefix); -} - -void -ResolveStructExprField::visit (AST::StructExprFieldIdentifier &field) -{ - AST::IdentifierExpr expr (field.get_field_name (), {}, field.get_locus ()); - expr.set_node_id (field.get_node_id ()); - - ResolveExpr::go (expr, prefix, canonical_prefix); -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h b/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h deleted file mode 100644 index 87fa60d..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-struct-expr-field.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2020-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_AST_RESOLVE_STRUCT_EXPR_FIELD -#define RUST_AST_RESOLVE_STRUCT_EXPR_FIELD - -#include "rust-ast-resolve-base.h" - -namespace Rust { -namespace Resolver { - -// this resolves values being assigned not that the field actually exists yet. - -class ResolveStructExprField : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::StructExprField &field, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - void visit (AST::StructExprFieldIdentifierValue &field) override; - - void visit (AST::StructExprFieldIndexValue &field) override; - - void visit (AST::StructExprFieldIdentifier &field) override; - -private: - ResolveStructExprField (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_STRUCT_EXPR_FIELD diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h deleted file mode 100644 index f52fb8a..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ /dev/null @@ -1,500 +0,0 @@ -// Copyright (C) 2020-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_AST_RESOLVE_TOPLEVEL_H -#define RUST_AST_RESOLVE_TOPLEVEL_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-implitem.h" -#include "rust-name-resolver.h" - -namespace Rust { -namespace Resolver { - -class ResolveTopLevel : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::Item &item, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - if (item.is_marked_for_strip ()) - return; - - ResolveTopLevel resolver (prefix, canonical_prefix); - item.accept_vis (resolver); - - NodeId current_module = resolver.resolver->peek_current_module_scope (); - resolver.mappings.insert_child_item_to_parent_module_mapping ( - item.get_node_id (), current_module); - } - - void visit (AST::Module &module) override - { - auto mod = CanonicalPath::new_seg (module.get_node_id (), - module.get_name ().as_string ()); - auto path = prefix.append (mod); - auto cpath = canonical_prefix.append (mod); - - resolver->get_name_scope ().insert ( - path, module.get_node_id (), module.get_locus (), false, - Rib::ItemType::Module, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, module.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, mod); - mappings.insert_module_child (current_module, module.get_node_id ()); - - resolver->push_new_module_scope (module.get_node_id ()); - for (auto &item : module.get_items ()) - ResolveTopLevel::go (*item, path, cpath); - - resolver->pop_module_scope (); - - mappings.insert_canonical_path (module.get_node_id (), cpath); - } - - void visit (AST::TypeAlias &alias) override - { - auto talias - = CanonicalPath::new_seg (alias.get_node_id (), - alias.get_new_type_name ().as_string ()); - auto path = prefix.append (talias); - auto cpath = canonical_prefix.append (talias); - - resolver->get_type_scope ().insert ( - path, alias.get_node_id (), alias.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, alias.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, talias); - mappings.insert_canonical_path (alias.get_node_id (), cpath); - } - - void visit (AST::TupleStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, struct_decl.get_node_id (), struct_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - } - - void visit (AST::Enum &enum_decl) override - { - auto decl - = CanonicalPath::new_seg (enum_decl.get_node_id (), - enum_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, enum_decl.get_node_id (), enum_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, enum_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - resolver->push_new_module_scope (enum_decl.get_node_id ()); - for (auto &variant : enum_decl.get_variants ()) - ResolveTopLevel::go (*variant, path, cpath); - - resolver->pop_module_scope (); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (enum_decl.get_node_id (), cpath); - } - - void visit (AST::EnumItem &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::EnumItemTuple &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::EnumItemStruct &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::EnumItemDiscriminant &item) override - { - auto decl = CanonicalPath::new_seg (item.get_node_id (), - item.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, item.get_node_id (), item.get_locus (), false, Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, item.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - mappings.insert_canonical_path (item.get_node_id (), cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_module_child (current_module, item.get_node_id ()); - } - - void visit (AST::StructStruct &struct_decl) override - { - auto decl - = CanonicalPath::new_seg (struct_decl.get_node_id (), - struct_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - auto duplicate_item - = [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, struct_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }; - - resolver->get_type_scope ().insert (path, struct_decl.get_node_id (), - struct_decl.get_locus (), false, - Rib::ItemType::Type, duplicate_item); - - if (struct_decl.is_unit_struct ()) - resolver->get_name_scope ().insert (path, struct_decl.get_node_id (), - struct_decl.get_locus (), false, - Rib::ItemType::Type, duplicate_item); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (struct_decl.get_node_id (), cpath); - } - - void visit (AST::Union &union_decl) override - { - auto decl - = CanonicalPath::new_seg (union_decl.get_node_id (), - union_decl.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, union_decl.get_node_id (), union_decl.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, union_decl.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (union_decl.get_node_id (), cpath); - } - - void visit (AST::StaticItem &var) override - { - auto decl = CanonicalPath::new_seg (var.get_node_id (), - var.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, var.get_node_id (), var.get_locus (), false, Rib::ItemType::Static, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, var.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (var.get_node_id (), cpath); - } - - void visit (AST::ConstantItem &constant) override - { - auto decl = CanonicalPath::new_seg (constant.get_node_id (), - constant.get_identifier ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, constant.get_node_id (), constant.get_locus (), false, - Rib::ItemType::Const, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, constant.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (constant.get_node_id (), cpath); - } - - void visit (AST::Function &function) override - { - auto decl - = CanonicalPath::new_seg (function.get_node_id (), - function.get_function_name ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_name_scope ().insert ( - path, function.get_node_id (), function.get_locus (), false, - Rib::ItemType::Function, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, function.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (function.get_node_id (), cpath); - } - - void visit (AST::InherentImpl &impl_block) override - { - std::string raw_impl_type_path = impl_block.get_type ().as_string (); - CanonicalPath impl_type_seg - = CanonicalPath::new_seg (impl_block.get_type ().get_node_id (), - raw_impl_type_path); - - CanonicalPath impl_type - = CanonicalPath::inherent_impl_seg (impl_block.get_node_id (), - impl_type_seg); - CanonicalPath impl_prefix = prefix.append (impl_type_seg); - - for (auto &impl_item : impl_block.get_impl_items ()) - ResolveToplevelImplItem::go (*impl_item, impl_prefix); - } - - void visit (AST::TraitImpl &impl_block) override - { - std::string raw_impl_type_path = impl_block.get_type ().as_string (); - CanonicalPath impl_type_seg - = CanonicalPath::new_seg (impl_block.get_type ().get_node_id (), - raw_impl_type_path); - - std::string raw_trait_type_path = impl_block.get_trait_path ().as_string (); - CanonicalPath trait_type_seg - = CanonicalPath::new_seg (impl_block.get_trait_path ().get_node_id (), - raw_trait_type_path); - - CanonicalPath projection - = CanonicalPath::trait_impl_projection_seg (impl_block.get_node_id (), - trait_type_seg, - impl_type_seg); - CanonicalPath impl_prefix = prefix.append (projection); - - resolver->get_name_scope ().insert ( - impl_prefix, impl_block.get_node_id (), impl_block.get_locus (), false, - Rib::ItemType::TraitImpl, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, impl_block.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - for (auto &impl_item : impl_block.get_impl_items ()) - ResolveToplevelImplItem::go (*impl_item, impl_prefix); - } - - void visit (AST::Trait &trait) override - { - auto decl = CanonicalPath::new_seg (trait.get_node_id (), - trait.get_identifier ().as_string ()); - auto path = prefix.append (decl); - auto cpath = canonical_prefix.append (decl); - - resolver->get_type_scope ().insert ( - path, trait.get_node_id (), trait.get_locus (), false, - Rib::ItemType::Trait, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, trait.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - - for (auto &item : trait.get_trait_items ()) - ResolveTopLevelTraitItems::go (item.get (), path, cpath); - - NodeId current_module = resolver->peek_current_module_scope (); - mappings.insert_module_child_item (current_module, decl); - mappings.insert_canonical_path (trait.get_node_id (), cpath); - } - - void visit (AST::ExternBlock &extern_block) override - { - for (auto &item : extern_block.get_extern_items ()) - { - ResolveToplevelExternItem::go (*item, prefix); - } - } - - void visit (AST::ExternCrate &extern_crate) override - { - if (extern_crate.is_marked_for_strip ()) - return; - - NodeId resolved_crate = UNKNOWN_NODEID; - if (extern_crate.references_self ()) - { - CrateNum crate_num = mappings.get_current_crate (); - resolved_crate = mappings.crate_num_to_nodeid (crate_num).value (); - } - else - { - auto cnum - = mappings.lookup_crate_name (extern_crate.get_referenced_crate ()); - if (!cnum) - { - rust_error_at (extern_crate.get_locus (), "unknown crate %qs", - extern_crate.get_referenced_crate ().c_str ()); - return; - } - if (auto resolved = mappings.crate_num_to_nodeid (*cnum)) - resolved_crate = resolved.value (); - else - { - rust_internal_error_at (extern_crate.get_locus (), - "failed to resolve crate to nodeid"); - return; - } - } - - if (resolved_crate == UNKNOWN_NODEID) - { - rust_error_at (extern_crate.get_locus (), "failed to resolve crate"); - return; - } - - // mark the node as resolved - resolver->insert_resolved_name (extern_crate.get_node_id (), - resolved_crate); - CanonicalPath decl - = extern_crate.has_as_clause () - ? CanonicalPath::new_seg (extern_crate.get_node_id (), - extern_crate.get_as_clause ()) - : CanonicalPath::new_seg (extern_crate.get_node_id (), - extern_crate.get_referenced_crate ()); - - resolver->get_type_scope ().insert ( - decl, resolved_crate, extern_crate.get_locus (), false, - Rib::ItemType::ExternCrate, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rich_location r (line_table, extern_crate.get_locus ()); - r.add_range (locus); - redefined_error (r); - }); - } - -private: - ResolveTopLevel (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) - {} - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_TOPLEVEL_H diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc deleted file mode 100644 index a040228..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-type.cc +++ /dev/null @@ -1,785 +0,0 @@ -// Copyright (C) 2020-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-ast-resolve-type.h" -#include "rust-ast-resolve-expr.h" -#include "rust-canonical-path.h" -#include "rust-type.h" -#include "rust-hir-map.h" - -namespace Rust { -namespace Resolver { - -// rust-ast-resolve-type.h - -NodeId -ResolveType::go (AST::Type &type) -{ - ResolveType resolver; - type.accept_vis (resolver); - return resolver.resolved_node; -} - -void -ResolveType::visit (AST::BareFunctionType &fntype) -{ - for (auto ¶m : fntype.get_function_params ()) - ResolveType::go (param.get_type ()); - - if (fntype.has_return_type ()) - ResolveType::go (fntype.get_return_type ()); -} - -void -ResolveType::visit (AST::TupleType &tuple) -{ - if (tuple.is_unit_type ()) - { - resolved_node = resolver->get_unit_type_node_id (); - return; - } - - for (auto &elem : tuple.get_elems ()) - ResolveType::go (*elem); -} - -void -ResolveType::visit (AST::TypePath &path) -{ - ResolveRelativeTypePath::go (path, resolved_node); -} - -void -ResolveType::visit (AST::QualifiedPathInType &path) -{ - ResolveRelativeQualTypePath::go (path); -} - -void -ResolveType::visit (AST::ArrayType &type) -{ - type.get_elem_type ().accept_vis (*this); - ResolveExpr::go (type.get_size_expr (), CanonicalPath::create_empty (), - CanonicalPath::create_empty ()); -} - -void -ResolveType::visit (AST::TraitObjectTypeOneBound &type) -{ - ResolveTypeBound::go (type.get_trait_bound ()); -} - -void -ResolveType::visit (AST::TraitObjectType &type) -{ - for (auto &bound : type.get_type_param_bounds ()) - { - /* NodeId bound_resolved_id = */ - ResolveTypeBound::go (*bound); - } -} - -void -ResolveType::visit (AST::ParenthesisedType &type) -{ - resolved_node = ResolveType::go (*type.get_type_in_parens ()); -} - -void -ResolveType::visit (AST::ReferenceType &type) -{ - resolved_node = ResolveType::go (type.get_type_referenced ()); -} - -void -ResolveType::visit (AST::RawPointerType &type) -{ - resolved_node = ResolveType::go (type.get_type_pointed_to ()); -} - -void -ResolveType::visit (AST::InferredType &) -{ - // nothing to do -} - -void -ResolveType::visit (AST::NeverType &) -{ - resolved_node = resolver->get_never_type_node_id (); -} - -void -ResolveType::visit (AST::SliceType &type) -{ - resolved_node = ResolveType::go (type.get_elem_type ()); -} - -void -ResolveType::visit (AST::ImplTraitType &type) -{ - for (auto &bound : type.get_type_param_bounds ()) - ResolveTypeBound::go (*bound); -} - -void -ResolveType::visit (AST::ImplTraitTypeOneBound &type) -{ - ResolveTypeBound::go (*type.get_trait_bound ().get ()); -} - -// resolve relative type-paths - -bool -ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id) -{ - auto resolver = Resolver::get (); - auto &mappings = Analysis::Mappings::get (); - - NodeId module_scope_id = resolver->peek_current_module_scope (); - NodeId previous_resolved_node_id = module_scope_id; - for (size_t i = 0; i < path.get_segments ().size (); i++) - { - auto &segment = path.get_segments ().at (i); - bool is_first_segment = i == 0; - NodeId crate_scope_id = resolver->peek_crate_module_scope (); - auto ident_string = segment->is_lang_item () - ? LangItem::PrettyString (segment->get_lang_item ()) - : segment->get_ident_segment ().as_string (); - - resolved_node_id = UNKNOWN_NODEID; - - if (segment->is_lang_item ()) - { - resolved_node_id = Analysis::Mappings::get ().get_lang_item_node ( - segment->get_lang_item ()); - previous_resolved_node_id = resolved_node_id; - } - else - { - bool in_middle_of_path = i > 0; - if (in_middle_of_path && segment->is_lower_self_seg ()) - { - rust_error_at (segment->get_locus (), ErrorCode::E0433, - "%qs in paths can only be used in start position", - segment->as_string ().c_str ()); - return false; - } - - if (segment->is_crate_path_seg ()) - { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - resolver->insert_resolved_name (segment->get_node_id (), - module_scope_id); - - continue; - } - else if (segment->is_super_path_seg ()) - { - if (module_scope_id == crate_scope_id) - { - rust_error_at (segment->get_locus (), - "cannot use super at the crate scope"); - return false; - } - - module_scope_id = resolver->peek_parent_module_scope (); - previous_resolved_node_id = module_scope_id; - resolver->insert_resolved_name (segment->get_node_id (), - module_scope_id); - continue; - } - } - - switch (segment->get_type ()) - { - case AST::TypePathSegment::SegmentType::GENERIC: - { - AST::TypePathSegmentGeneric *s - = static_cast<AST::TypePathSegmentGeneric *> (segment.get ()); - if (s->has_generic_args ()) - ResolveGenericArgs::go (s->get_generic_args ()); - } - break; - - case AST::TypePathSegment::SegmentType::REG: - // nothing to do - break; - - case AST::TypePathSegment::SegmentType::FUNCTION: - AST::TypePathSegmentFunction *fnseg - = static_cast<AST::TypePathSegmentFunction *> (segment.get ()); - - AST::TypePathFunction &fn = fnseg->get_type_path_function (); - for (auto ¶m : fn.get_params ()) - { - ResolveType::go (*param); - } - - if (fn.has_return_type ()) - { - ResolveType::go (fn.get_return_type ()); - } - - break; - } - - if (is_first_segment) - { - // name scope first - NodeId resolved_node = UNKNOWN_NODEID; - const CanonicalPath path - = CanonicalPath::new_seg (segment->get_node_id (), ident_string); - if (resolver->get_type_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_type (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment->get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - else if (resolver->get_name_scope ().lookup (path, &resolved_node)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment->get_node_id (), - resolved_node); - resolved_node_id = resolved_node; - } - else if (!segment->is_lang_item () && segment->is_lower_self_seg ()) - { - // what is the current crate scope node id? - module_scope_id = crate_scope_id; - previous_resolved_node_id = module_scope_id; - - NodeId existing = UNKNOWN_NODEID; - bool ok = resolver->lookup_resolved_name (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == module_scope_id); - else - resolver->insert_resolved_name (segment->get_node_id (), - module_scope_id); - - continue; - } - } - - if (resolved_node_id == UNKNOWN_NODEID - && previous_resolved_node_id == module_scope_id) - { - tl::optional<CanonicalPath &> resolved_child - = mappings.lookup_module_child (module_scope_id, ident_string); - if (resolved_child.has_value ()) - { - NodeId resolved_node = resolved_child->get_node_id (); - if (resolver->get_name_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_name (segment->get_node_id (), - resolved_node); - } - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node)) - { - resolved_node_id = resolved_node; - - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (segment->get_node_id (), - &existing); - - if (ok) - rust_assert (existing == resolved_node); - else - resolver->insert_resolved_type (segment->get_node_id (), - resolved_node); - } - else - { - rust_error_at (segment->get_locus (), - "Cannot find path %qs in this scope", - segment->as_string ().c_str ()); - return false; - } - } - } - - bool did_resolve_segment = resolved_node_id != UNKNOWN_NODEID; - if (did_resolve_segment) - { - if (mappings.node_is_module (resolved_node_id) - || mappings.node_is_crate (resolved_node_id)) - { - module_scope_id = resolved_node_id; - } - previous_resolved_node_id = resolved_node_id; - } - else if (is_first_segment) - { - rust_error_at (segment->get_locus (), ErrorCode::E0412, - "could not resolve type path %qs", - segment->get_ident_segment ().as_string ().c_str ()); - return false; - } - } - - if (resolved_node_id != UNKNOWN_NODEID) - { - // name scope first - if (resolver->get_name_scope ().decl_was_declared_here (resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_name (path.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_name (path.get_node_id (), - resolved_node_id); - } - // check the type scope - else if (resolver->get_type_scope ().decl_was_declared_here ( - resolved_node_id)) - { - NodeId existing = UNKNOWN_NODEID; - bool ok - = resolver->lookup_resolved_type (path.get_node_id (), &existing); - - if (ok) - rust_assert (existing == resolved_node_id); - else - resolver->insert_resolved_type (path.get_node_id (), - resolved_node_id); - } - else - { - rust_unreachable (); - } - } - - return true; -} - -// qualified type paths - -ResolveRelativeQualTypePath::ResolveRelativeQualTypePath () - : failure_flag (false) -{} - -bool -ResolveRelativeQualTypePath::go (AST::QualifiedPathInType &path) -{ - ResolveRelativeQualTypePath o; - - // resolve the type and trait path - auto &qualified_path = path.get_qualified_path_type (); - if (!o.resolve_qual_seg (qualified_path)) - return false; - - // qualified types are similar to other paths in that we cannot guarantee - // that we can resolve the path at name resolution. We must look up - // associated types and type information to figure this out properly - - std::unique_ptr<AST::TypePathSegment> &associated - = path.get_associated_segment (); - - associated->accept_vis (o); - if (o.failure_flag) - return false; - - for (auto &seg : path.get_segments ()) - { - seg->accept_vis (o); - if (o.failure_flag) - return false; - } - - return true; -} - -bool -ResolveRelativeQualTypePath::resolve_qual_seg (AST::QualifiedPathType &seg) -{ - if (seg.is_error ()) - { - rust_error_at (seg.get_locus (), "segment has error: %s", - seg.as_string ().c_str ()); - return false; - } - - auto &type = seg.get_type (); - ResolveType::go (type); - - if (seg.has_as_clause ()) - ResolveType::go (seg.get_as_type_path ()); - - return true; -} - -void -ResolveRelativeQualTypePath::visit (AST::TypePathSegmentGeneric &seg) -{ - if (seg.is_error ()) - { - failure_flag = true; - rust_error_at (seg.get_locus (), "segment has error: %s", - seg.as_string ().c_str ()); - return; - } - - ResolveGenericArgs::go (seg.get_generic_args ()); -} - -void -ResolveRelativeQualTypePath::visit (AST::TypePathSegment &seg) -{ - if (seg.is_error ()) - { - failure_flag = true; - rust_error_at (seg.get_locus (), "segment has error: %s", - seg.as_string ().c_str ()); - return; - } -} - -// resolve to canonical path - -bool -ResolveTypeToCanonicalPath::go (AST::Type &type, CanonicalPath &result) -{ - ResolveTypeToCanonicalPath resolver; - type.accept_vis (resolver); - result = resolver.result; - return !resolver.result.is_empty (); -} - -void -ResolveTypeToCanonicalPath::visit (AST::TypePath &path) -{ - NodeId resolved_node = UNKNOWN_NODEID; - if (!resolver->lookup_resolved_name (path.get_node_id (), &resolved_node)) - { - resolver->lookup_resolved_type (path.get_node_id (), &resolved_node); - } - - if (resolved_node == UNKNOWN_NODEID) - return; - - if (auto type_path = mappings.lookup_canonical_path (resolved_node)) - { - auto &final_seg = path.get_segments ().back (); - switch (final_seg->get_type ()) - { - case AST::TypePathSegment::SegmentType::GENERIC: - { - AST::TypePathSegmentGeneric *s - = static_cast<AST::TypePathSegmentGeneric *> (final_seg.get ()); - - std::vector<CanonicalPath> args; - if (s->has_generic_args ()) - { - ResolveGenericArgs::go (s->get_generic_args ()); - for (auto &generic : s->get_generic_args ().get_generic_args ()) - { - // FIXME: What do we want to do here in case there is a - // constant or an ambiguous const generic? - // TODO: At that point, will all generics have been - // disambiguated? Can we thus canonical resolve types and - // const and `rust_unreachable` on ambiguous types? - // This is probably fine as we just want to canonicalize - // types, right? - if (generic.get_kind () == AST::GenericArg::Kind::Type) - { - CanonicalPath arg = CanonicalPath::create_empty (); - bool ok - = ResolveTypeToCanonicalPath::go (generic.get_type (), - arg); - if (ok) - args.push_back (std::move (arg)); - } - } - } - - result = *type_path; - if (!args.empty ()) - { - // append this onto the path - std::string buf; - for (size_t i = 0; i < args.size (); i++) - { - bool has_next = (i + 1) < args.size (); - const auto &arg = args.at (i); - - buf += arg.get (); - if (has_next) - buf += ", "; - } - - std::string arg_seg = "<" + buf + ">"; - CanonicalPath argument_seg - = CanonicalPath::new_seg (s->get_node_id (), arg_seg); - result = result.append (argument_seg); - } - } - break; - - default: - result = *type_path; - break; - } - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::ReferenceType &type) -{ - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (type.get_type_referenced (), path); - if (ok) - { - std::string ref_type_str = type.is_mut () ? "mut" : ""; - std::string ref_path = "&" + ref_type_str + " " + path.get (); - result = CanonicalPath::new_seg (type.get_node_id (), ref_path); - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::RawPointerType &type) -{ - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (type.get_type_pointed_to (), path); - if (ok) - { - std::string ptr_type_str - = type.get_pointer_type () == AST::RawPointerType::CONST ? "const" - : "mut"; - std::string ptr_path = "*" + ptr_type_str + " " + path.get (); - result = CanonicalPath::new_seg (type.get_node_id (), ptr_path); - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::SliceType &type) -{ - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (type.get_elem_type (), path); - if (ok) - { - std::string slice_path = "[" + path.get () + "]"; - result = CanonicalPath::new_seg (type.get_node_id (), slice_path); - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::TraitObjectTypeOneBound &type) -{ - CanonicalPath path = CanonicalPath::create_empty (); - bool ok - = ResolveTypeToCanonicalPath::go (type.get_trait_bound ().get_type_path (), - path); - if (ok) - { - std::string slice_path = "<dyn " + path.get () + ">"; - result = CanonicalPath::new_seg (type.get_node_id (), slice_path); - } -} - -void -ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &type) -{ - rust_assert (!type.get_type_param_bounds ().empty ()); - - auto &first_bound = type.get_type_param_bounds ().front (); - - // Is it allowed or even possible to have a lifetime bound as a first bound? - if (first_bound->get_bound_type () == AST::TraitBound::LIFETIME) - rust_unreachable (); - - auto &trait = static_cast<AST::TraitBound &> (*first_bound); - - CanonicalPath path = CanonicalPath::create_empty (); - bool ok = ResolveTypeToCanonicalPath::go (trait.get_type_path (), path); - - // right? - rust_assert (ok); - - auto slice_path = "<dyn " + path.get (); - - for (size_t idx = 1; idx < type.get_type_param_bounds ().size (); idx++) - { - auto &additional_bound = type.get_type_param_bounds ()[idx]; - - std::string str; - - switch (additional_bound->get_bound_type ()) - { - case AST::TypeParamBound::TRAIT: - { - auto bound_path = CanonicalPath::create_empty (); - - auto &bound_type_path - = static_cast<AST::TraitBound &> (*additional_bound) - .get_type_path (); - bool ok - = ResolveTypeToCanonicalPath::go (bound_type_path, bound_path); - - if (!ok) - continue; - - str = bound_path.get (); - break; - } - case AST::TypeParamBound::LIFETIME: - rust_unreachable (); - break; - } - slice_path += " + " + str; - } - - slice_path += ">"; - - result = CanonicalPath::new_seg (type.get_node_id (), slice_path); -} - -void -ResolveTypeToCanonicalPath::visit (AST::NeverType &type) -{ - result = CanonicalPath::new_seg (type.get_node_id (), "!"); -} - -void -ResolveTypeToCanonicalPath::visit (AST::TupleType &type) -{ - if (!type.is_unit_type ()) - rust_unreachable (); - - result = CanonicalPath::new_seg (type.get_node_id (), "()"); -} - -ResolveTypeToCanonicalPath::ResolveTypeToCanonicalPath () - : ResolverBase (), result (CanonicalPath::create_empty ()) -{} - -bool -ResolveGenericArgs::is_const_value_name (const CanonicalPath &path) -{ - NodeId resolved; - auto found = resolver->get_name_scope ().lookup (path, &resolved); - - return found; -} - -bool -ResolveGenericArgs::is_type_name (const CanonicalPath &path) -{ - NodeId resolved; - auto found = resolver->get_type_scope ().lookup (path, &resolved); - - return found; -} - -void -ResolveGenericArgs::disambiguate (AST::GenericArg &arg) -{ - auto path = canonical_prefix.append ( - CanonicalPath::new_seg (UNKNOWN_NODEID, arg.get_path ())); - - auto is_type = is_type_name (path); - auto is_value = is_const_value_name (path); - - // In case we cannot find anything, we resolve the ambiguity to a type. - // This causes the typechecker to error out properly and when necessary. - // But types also take priority over const values in the case of - // ambiguities, hence the weird control flow - if (is_type || (!is_type && !is_value)) - arg = arg.disambiguate_to_type (); - else if (is_value) - arg = arg.disambiguate_to_const (); -} - -void -ResolveGenericArgs::resolve_disambiguated_generic (AST::GenericArg &arg) -{ - switch (arg.get_kind ()) - { - case AST::GenericArg::Kind::Const: - ResolveExpr::go (arg.get_expression (), prefix, canonical_prefix); - break; - case AST::GenericArg::Kind::Type: - ResolveType::go (arg.get_type ()); - break; - default: - rust_unreachable (); - } -} -void -ResolveGenericArgs::go (AST::GenericArgs &generic_args) -{ - auto empty = CanonicalPath::create_empty (); - - go (generic_args, empty, empty); -} - -void -ResolveGenericArgs::go (AST::GenericArgs &generic_args, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) -{ - auto resolver = ResolveGenericArgs (prefix, canonical_prefix); - - for (auto &arg : generic_args.get_generic_args ()) - { - if (arg.get_kind () == AST::GenericArg::Kind::Either) - resolver.disambiguate (arg); - - resolver.resolve_disambiguated_generic (arg); - } - - for (auto &binding : generic_args.get_binding_args ()) - { - ResolveType::go (binding.get_type ()); - } -} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h deleted file mode 100644 index f1481fc..0000000 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright (C) 2020-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_AST_RESOLVE_TYPE_H -#define RUST_AST_RESOLVE_TYPE_H - -#include "rust-ast-resolve-base.h" -#include "rust-ast-resolve-expr.h" -#include "rust-diagnostics.h" -#include "rust-hir-map.h" -#include "rust-path.h" -#include "rust-type.h" -#include "util/rust-hir-map.h" - -namespace Rust { -namespace Resolver { - -class ResolveRelativeTypePath -{ -public: - static bool go (AST::TypePath &path, NodeId &resolved_node_id); -}; - -class ResolveRelativeQualTypePath : public ResolverBase -{ - using ResolverBase::visit; - -public: - static bool go (AST::QualifiedPathInType &path); - - void visit (AST::TypePathSegmentGeneric &seg) override; - - void visit (AST::TypePathSegment &seg) override; - -protected: - bool resolve_qual_seg (AST::QualifiedPathType &seg); - -private: - ResolveRelativeQualTypePath (); - - bool failure_flag; -}; - -class ResolveType : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static NodeId go (AST::Type &type); - - void visit (AST::BareFunctionType &fntype) override; - void visit (AST::TupleType &tuple) override; - void visit (AST::TypePath &path) override; - void visit (AST::QualifiedPathInType &path) override; - void visit (AST::ArrayType &type) override; - void visit (AST::ReferenceType &type) override; - void visit (AST::InferredType &type) override; - void visit (AST::NeverType &type) override; - void visit (AST::RawPointerType &type) override; - void visit (AST::TraitObjectTypeOneBound &type) override; - void visit (AST::TraitObjectType &type) override; - void visit (AST::ParenthesisedType &type) override; - void visit (AST::SliceType &type) override; - void visit (AST::ImplTraitType &type) override; - void visit (AST::ImplTraitTypeOneBound &type) override; - -private: - ResolveType () : ResolverBase () {} -}; - -class ResolveTypeBound : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static NodeId go (AST::TypeParamBound &type) - { - ResolveTypeBound resolver; - type.accept_vis (resolver); - return resolver.resolved_node; - }; - - void visit (AST::TraitBound &bound) override - { - resolved_node = ResolveType::go (bound.get_type_path ()); - } - -private: - ResolveTypeBound () : ResolverBase () {} -}; - -class ResolveGenericParams : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (std::vector<std::unique_ptr<AST::GenericParam>> ¶ms, - const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - ResolveGenericParams resolver (prefix, canonical_prefix); - - // this needs to be done in two phases as they can be used and defined later - // in bounds - for (auto ¶m : params) - param->accept_vis (resolver); - - resolver.first_pass = false; - - for (auto ¶m : params) - param->accept_vis (resolver); - } - - static void go_single (AST::GenericParam ¶m, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - { - ResolveGenericParams resolver (prefix, canonical_prefix); - - param.accept_vis (resolver); - resolver.first_pass = false; - param.accept_vis (resolver); - } - - void visit (AST::ConstGenericParam ¶m) override - { - if (first_pass) - ResolveType::go (param.get_type ()); - else if (param.has_default_value ()) - ResolveExpr::go (param.get_default_value_unchecked ().get_expression (), - prefix, canonical_prefix); - } - - void visit (AST::TypeParam ¶m) override - { - if (first_pass) - { - // if it has a type lets resolve it - if (param.has_type ()) - ResolveType::go (param.get_type ()); - - auto seg = CanonicalPath::new_seg ( - param.get_node_id (), param.get_type_representation ().as_string ()); - resolver->get_type_scope ().insert ( - seg, param.get_node_id (), param.get_locus (), false, - Rib::ItemType::Type, - [&] (const CanonicalPath &, NodeId, location_t locus) -> void { - rust_error_at (param.get_locus (), - "generic param defined multiple times"); - rust_error_at (locus, "was defined here"); - }); - - mappings.insert_canonical_path (param.get_node_id (), seg); - } - else if (param.has_type_param_bounds ()) - { - for (auto &bound : param.get_type_param_bounds ()) - ResolveTypeBound::go (*bound); - } - } - -private: - ResolveGenericParams (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), first_pass (true), prefix (prefix), - canonical_prefix (canonical_prefix) - {} - - bool first_pass; - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -class ResolveWhereClause : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void Resolve (AST::WhereClause &where_clause) - { - ResolveWhereClause r; - for (auto &clause : where_clause.get_items ()) - clause->accept_vis (r); - } - - void visit (AST::TypeBoundWhereClauseItem &item) override - { - ResolveType::go (item.get_type ()); - if (item.has_type_param_bounds ()) - { - for (auto &bound : item.get_type_param_bounds ()) - { - ResolveTypeBound::go (*bound); - } - } - } - -private: - ResolveWhereClause () : ResolverBase () {} -}; - -class ResolveTypeToCanonicalPath : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static bool go (AST::Type &type, CanonicalPath &result); - - void visit (AST::TypePath &path) override; - - void visit (AST::ReferenceType &type) override; - - void visit (AST::RawPointerType &type) override; - - void visit (AST::SliceType &type) override; - - void visit (AST::TraitObjectTypeOneBound &type) override; - - void visit (AST::TraitObjectType &type) override; - - void visit (AST::NeverType &type) override; - - void visit (AST::TupleType &type) override; - -private: - ResolveTypeToCanonicalPath (); - - CanonicalPath result; -}; - -class ResolveGenericArgs : public ResolverBase -{ - using Rust::Resolver::ResolverBase::visit; - -public: - static void go (AST::GenericArgs &generic_args); - static void go (AST::GenericArgs &generic_args, const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix); - -private: - ResolveGenericArgs (const CanonicalPath &prefix, - const CanonicalPath &canonical_prefix) - : ResolverBase (), prefix (prefix), canonical_prefix (canonical_prefix) - {} - - bool is_type_name (const CanonicalPath &path); - bool is_const_value_name (const CanonicalPath &path); - - /** - * Resolve a disambiguated generic arg - */ - void disambiguate (AST::GenericArg &arg); - - /** - * Resolve a disambiguated generic arg - */ - void resolve_disambiguated_generic (AST::GenericArg &arg); - - const CanonicalPath &prefix; - const CanonicalPath &canonical_prefix; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_AST_RESOLVE_TYPE_H diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc deleted file mode 100644 index 2208f70..0000000 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (C) 2020-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-ast-resolve.h" -#include "rust-ast-full.h" -#include "rust-tyty.h" -#include "rust-ast-resolve-toplevel.h" -#include "rust-ast-resolve-item.h" -#include "rust-ast-resolve-expr.h" -#include "rust-ast-resolve-struct-expr-field.h" - -extern bool saw_errors (void); - -namespace Rust { -namespace Resolver { - -// NameResolution - -NameResolution * -NameResolution::get () -{ - static NameResolution *instance; - if (instance == nullptr) - instance = new NameResolution (); - - return instance; -} - -NameResolution::NameResolution () - : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()) -{ - // these are global - resolver->get_type_scope ().push (mappings.get_next_node_id ()); - resolver->insert_builtin_types (resolver->get_type_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); -} - -void -NameResolution::Resolve (AST::Crate &crate) -{ - auto resolver = get (); - resolver->go (crate); -} - -void -NameResolution::go (AST::Crate &crate) -{ - // lookup current crate name - CrateNum cnum = mappings.get_current_crate (); - - // Clones the crate name instead of references due to gcc's possibly - // dangling references warnings - const auto crate_name = mappings.get_crate_name (cnum).value (); - - // setup the ribs - NodeId scope_node_id = crate.get_node_id (); - resolver->get_name_scope ().push (scope_node_id); - resolver->get_type_scope ().push (scope_node_id); - resolver->get_label_scope ().push (scope_node_id); - resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); - resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); - resolver->push_new_label_rib (resolver->get_label_scope ().peek ()); - - // get the root segment - CanonicalPath crate_prefix - = CanonicalPath::new_seg (scope_node_id, crate_name); - crate_prefix.set_crate_num (cnum); - - // setup a dummy crate node - resolver->get_name_scope ().insert ( - CanonicalPath::new_seg (crate.get_node_id (), "__$$crate__"), - crate.get_node_id (), UNDEF_LOCATION); - - // setup the root scope - resolver->push_new_module_scope (scope_node_id); - - // first gather the top-level namespace names then we drill down so this - // allows for resolving forward declarations since an impl block might have - // a Self type Foo which is defined after the impl block for example. - for (auto &item : crate.items) - ResolveTopLevel::go (*item, CanonicalPath::create_empty (), crate_prefix); - - // FIXME remove this - if (saw_errors ()) - { - resolver->pop_module_scope (); - return; - } - - // next we can drill down into the items and their scopes - for (auto &item : crate.items) - ResolveItem::go (*item, CanonicalPath::create_empty (), crate_prefix); - - // done - resolver->pop_module_scope (); -} - -} // namespace Resolver -} // namespace Rust 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 4fd1dd2..0dff831 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -438,7 +438,9 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping) // We don't want to insert `self` with `use module::self` if (path.get_final_segment ().is_lower_self_seg ()) { - rust_assert (segments.size () > 1); + // Erroneous `self` or `{self}` use declaration + if (segments.size () == 1) + break; declared_name = segments[segments.size () - 2].as_string (); } else @@ -447,8 +449,8 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping) break; } case AST::UseTreeRebind::NewBindType::WILDCARD: - rust_unreachable (); - break; + // We don't want to insert it into the trie + return; } for (auto &&definition : data.definitions ()) @@ -459,6 +461,19 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping) void Early::visit (AST::UseDeclaration &decl) { + // We do not want to visit the use trees, we're only looking for top level + // rebind. eg. `use something;` or `use something::other;` + if (decl.get_tree ()->get_kind () == AST::UseTree::Kind::Rebind) + { + auto &rebind = static_cast<AST::UseTreeRebind &> (*decl.get_tree ()); + if (rebind.get_path ().get_final_segment ().is_lower_self_seg ()) + { + collect_error ( + Error (decl.get_locus (), ErrorCode::E0429, + "%<self%> imports are only allowed within a { } list")); + } + } + auto &imports = toplevel.get_imports_to_resolve (); auto current_import = imports.find (decl.get_node_id ()); if (current_import != imports.end ()) @@ -484,5 +499,31 @@ Early::visit (AST::UseDeclaration &decl) DefaultResolver::visit (decl); } +void +Early::visit (AST::UseTreeList &use_list) +{ + if (!use_list.has_path ()) + { + for (auto &&tree : use_list.get_trees ()) + { + if (tree->get_kind () == AST::UseTree::Kind::Rebind) + { + auto &rebind = static_cast<AST::UseTreeRebind &> (*tree); + auto path_size = rebind.get_path ().get_segments ().size (); + if (path_size == 1 + && rebind.get_path () + .get_final_segment () + .is_lower_self_seg ()) + { + collect_error (Error (rebind.get_locus (), ErrorCode::E0431, + "%<self%> import can only appear in an " + "import list with a non-empty prefix")); + } + } + } + } + DefaultResolver::visit (use_list); +} + } // namespace Resolver2_0 } // namespace Rust diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h index 960de0e..3940386 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h @@ -61,6 +61,7 @@ public: void visit (AST::Function &) override; void visit (AST::StructStruct &) override; void visit (AST::UseDeclaration &) override; + void visit (AST::UseTreeList &) override; struct ImportData { diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc deleted file mode 100644 index 7b365ef..0000000 --- a/gcc/rust/resolve/rust-early-name-resolver.cc +++ /dev/null @@ -1,589 +0,0 @@ -// Copyright (C) 2020-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-early-name-resolver.h" -#include "rust-pattern.h" -#include "rust-name-resolver.h" -#include "rust-macro-builtins.h" -#include "rust-attribute-values.h" - -namespace Rust { -namespace Resolver { - -// Check if a module contains the `#[macro_use]` attribute -static bool -is_macro_use_module (const AST::Module &mod) -{ - for (const auto &attr : mod.get_outer_attrs ()) - if (attr.get_path ().as_string () == Values::Attributes::MACRO_USE) - return true; - - return false; -} - -std::vector<std::unique_ptr<AST::Item>> -EarlyNameResolver::accumulate_escaped_macros (AST::Module &module) -{ - if (!is_macro_use_module (module)) - return {}; - - // Parse the module's items if they haven't been expanded and the file - // should be parsed (i.e isn't hidden behind an untrue or impossible cfg - // directive) - if (module.get_kind () == AST::Module::UNLOADED) - module.load_items (); - - std::vector<std::unique_ptr<AST::Item>> escaped_macros; - - scoped (module.get_node_id (), [&module, &escaped_macros, this] { - for (auto &item : module.get_items ()) - { - if (item->get_item_kind () == AST::Item::Kind::Module) - { - auto &module = *static_cast<AST::Module *> (item.get ()); - auto new_macros = accumulate_escaped_macros (module); - - std::move (new_macros.begin (), new_macros.end (), - std::back_inserter (escaped_macros)); - - continue; - } - - if (item->get_item_kind () == AST::Item::Kind::MacroRulesDefinition) - escaped_macros.emplace_back (item->clone_item ()); - } - }); - - return escaped_macros; -} - -EarlyNameResolver::EarlyNameResolver () - : current_scope (UNKNOWN_NODEID), resolver (*Resolver::get ()), - mappings (Analysis::Mappings::get ()) -{} - -void -EarlyNameResolver::go (AST::Crate &crate) -{ - visit (crate); -} - -void -EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args) -{ - for (auto &arg : generic_args.get_generic_args ()) - arg.accept_vis (*this); - - for (auto &arg : generic_args.get_binding_args ()) - arg.get_type ().accept_vis (*this); -} - -void -EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path) -{ - path.get_type ().accept_vis (*this); - - if (path.has_as_clause ()) - path.get_as_type_path ().accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::Crate &crate) -{ - std::vector<std::unique_ptr<AST::Item>> new_items; - auto items = crate.take_items (); - - scoped (crate.get_node_id (), [&items, &new_items, this] { - for (auto &&item : items) - { - auto new_macros = std::vector<std::unique_ptr<AST::Item>> (); - - if (item->get_item_kind () == AST::Item::Kind::Module) - new_macros = accumulate_escaped_macros ( - *static_cast<AST::Module *> (item.get ())); - - new_items.emplace_back (std::move (item)); - std::move (new_macros.begin (), new_macros.end (), - std::back_inserter (new_items)); - } - }); - - crate.set_items (std::move (new_items)); - - scoped (crate.get_node_id (), [&crate, this] () { - for (auto &item : crate.items) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::DelimTokenTree &) -{} - -void -EarlyNameResolver::visit (AST::AttrInputMetaItemContainer &) -{} - -void -EarlyNameResolver::visit (AST::IdentifierExpr &) -{} - -void -EarlyNameResolver::visit (AST::LifetimeParam &) -{} - -void -EarlyNameResolver::visit (AST::ConstGenericParam &) -{} - -// FIXME: ARTHUR: Do we need to perform macro resolution for paths as well? -// std::arch::asm!()? -void -EarlyNameResolver::visit (AST::PathInExpression &path) -{ - if (!path.is_lang_item ()) - for (auto &segment : path.get_segments ()) - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); -} - -void -EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment) -{ - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); -} - -void -EarlyNameResolver::visit (AST::QualifiedPathInExpression &path) -{ - resolve_qualified_path_type (path.get_qualified_path_type ()); - - for (auto &segment : path.get_segments ()) - if (segment.has_generic_args ()) - resolve_generic_args (segment.get_generic_args ()); -} - -void -EarlyNameResolver::visit (AST::QualifiedPathInType &path) -{ - resolve_qualified_path_type (path.get_qualified_path_type ()); - - for (auto &segment : path.get_segments ()) - segment->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::LiteralExpr &) -{} - -void -EarlyNameResolver::visit (AST::AttrInputLiteral &) -{} - -void -EarlyNameResolver::visit (AST::AttrInputMacro &) -{} - -void -EarlyNameResolver::visit (AST::MetaItemLitExpr &) -{} - -void -EarlyNameResolver::visit (AST::MetaItemPathExpr &) -{} - -void -EarlyNameResolver::visit (AST::StructExprStruct &) -{} - -void -EarlyNameResolver::visit (AST::StructExprFieldIdentifier &) -{} - -void -EarlyNameResolver::visit (AST::StructExprStructBase &) -{} - -void -EarlyNameResolver::visit (AST::BlockExpr &expr) -{ - scoped (expr.get_node_id (), [&expr, this] () { - for (auto &stmt : expr.get_statements ()) - stmt->accept_vis (*this); - - if (expr.has_tail_expr ()) - expr.get_tail_expr ().accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::ContinueExpr &) -{} - -void -EarlyNameResolver::visit (AST::RangeFullExpr &) -{} - -void -EarlyNameResolver::visit (AST::ForLoopExpr &expr) -{ - scoped (expr.get_node_id (), [&expr, this] () { - expr.get_pattern ().accept_vis (*this); - expr.get_iterator_expr ().accept_vis (*this); - expr.get_loop_block ().accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::IfLetExpr &expr) -{ - expr.get_value_expr ().accept_vis (*this); - - scoped (expr.get_node_id (), - [&expr, this] () { expr.get_if_block ().accept_vis (*this); }); -} - -void -EarlyNameResolver::visit (AST::MatchExpr &expr) -{ - expr.get_scrutinee_expr ().accept_vis (*this); - - scoped (expr.get_node_id (), [&expr, this] () { - for (auto &arm : expr.get_match_cases ()) - { - scoped (arm.get_node_id (), [&arm, this] () { - if (arm.get_arm ().has_match_arm_guard ()) - arm.get_arm ().get_guard_expr ().accept_vis (*this); - - for (auto &pattern : arm.get_arm ().get_patterns ()) - pattern->accept_vis (*this); - - arm.get_expr ().accept_vis (*this); - }); - } - }); -} - -void -EarlyNameResolver::visit (AST::LifetimeWhereClauseItem &) -{} - -void -EarlyNameResolver::visit (AST::Module &module) -{ - if (module.get_kind () == AST::Module::UNLOADED) - module.load_items (); - - // so we need to only go "one scope down" for fetching macros. Macros within - // functions are still scoped only within that function. But we have to be - // careful because nested modules with #[macro_use] actually works! - std::vector<std::unique_ptr<AST::Item>> new_items; - auto items = module.take_items (); - - scoped (module.get_node_id (), [&items, &new_items, this] { - for (auto &&item : items) - { - auto new_macros = std::vector<std::unique_ptr<AST::Item>> (); - - if (item->get_item_kind () == AST::Item::Kind::Module) - new_macros = accumulate_escaped_macros ( - *static_cast<AST::Module *> (item.get ())); - - new_items.emplace_back (std::move (item)); - std::move (new_macros.begin (), new_macros.end (), - std::back_inserter (new_items)); - } - }); - - module.set_items (std::move (new_items)); - - scoped (module.get_node_id (), [&module, this] () { - for (auto &item : module.get_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::ExternCrate &) -{} - -void -EarlyNameResolver::visit (AST::UseTreeGlob &) -{} - -void -EarlyNameResolver::visit (AST::UseTreeList &) -{} - -void -EarlyNameResolver::visit (AST::UseTreeRebind &) -{} - -void -EarlyNameResolver::visit (AST::UseDeclaration &) -{} - -void -EarlyNameResolver::visit (AST::EnumItem &) -{} - -void -EarlyNameResolver::visit (AST::Union &) -{} - -void -EarlyNameResolver::visit (AST::TraitItemType &) -{} - -void -EarlyNameResolver::visit (AST::Trait &trait) -{ - // shouldn't need to visit trait.get_implicit_self () - - for (auto &generic : trait.get_generic_params ()) - generic->accept_vis (*this); - - scoped (trait.get_node_id (), [&trait, this] () { - for (auto &item : trait.get_trait_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::InherentImpl &impl) -{ - impl.get_type ().accept_vis (*this); - - for (auto &generic : impl.get_generic_params ()) - generic->accept_vis (*this); - - scoped (impl.get_node_id (), [&impl, this] () { - for (auto &item : impl.get_impl_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::TraitImpl &impl) -{ - impl.get_type ().accept_vis (*this); - - for (auto &generic : impl.get_generic_params ()) - generic->accept_vis (*this); - - scoped (impl.get_node_id (), [&impl, this] () { - for (auto &item : impl.get_impl_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::ExternalTypeItem &item) -{ - // nothing to do? -} - -void -EarlyNameResolver::visit (AST::ExternBlock &block) -{ - scoped (block.get_node_id (), [&block, this] () { - for (auto &item : block.get_extern_items ()) - item->accept_vis (*this); - }); -} - -void -EarlyNameResolver::visit (AST::MacroMatchRepetition &) -{} - -void -EarlyNameResolver::visit (AST::MacroMatcher &) -{} - -void -EarlyNameResolver::visit (AST::MacroRulesDefinition &rules_def) -{ - auto path = CanonicalPath::new_seg (rules_def.get_node_id (), - rules_def.get_rule_name ().as_string ()); - resolver.get_macro_scope ().insert (path, rules_def.get_node_id (), - rules_def.get_locus ()); - - /* Since the EarlyNameResolver runs multiple time (fixed point algorithm) - * we could be inserting the same macro def over and over again until we - * implement some optimizations */ - // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead - if (mappings.lookup_macro_def (rules_def.get_node_id ())) - return; - - mappings.insert_macro_def (&rules_def); - rust_debug_loc (rules_def.get_locus (), "inserting macro def: [%s]", - path.get ().c_str ()); -} - -void -EarlyNameResolver::visit (AST::MacroInvocation &invoc) -{ - auto &invoc_data = invoc.get_invoc_data (); - auto has_semicolon = invoc.has_semicolon (); - - if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin) - for (auto &pending_invoc : invoc.get_pending_eager_invocations ()) - pending_invoc->accept_vis (*this); - - // ?? - // switch on type of macro: - // - '!' syntax macro (inner switch) - // - procedural macro - "A token-based function-like macro" - // - 'macro_rules' (by example/pattern-match) macro? or not? "an - // AST-based function-like macro" - // - else is unreachable - // - attribute syntax macro (inner switch) - // - procedural macro attribute syntax - "A token-based attribute - // macro" - // - legacy macro attribute syntax? - "an AST-based attribute macro" - // - non-macro attribute: mark known - // - else is unreachable - // - derive macro (inner switch) - // - derive or legacy derive - "token-based" vs "AST-based" - // - else is unreachable - // - derive container macro - unreachable - - // lookup the rules for this macro - NodeId resolved_node = UNKNOWN_NODEID; - NodeId source_node = UNKNOWN_NODEID; - if (has_semicolon) - source_node = invoc.get_macro_node_id (); - else - source_node = invoc.get_node_id (); - auto seg - = CanonicalPath::new_seg (source_node, invoc_data.get_path ().as_string ()); - - bool found = resolver.get_macro_scope ().lookup (seg, &resolved_node); - if (!found) - { - rust_error_at (invoc.get_locus (), ErrorCode::E0433, - "could not resolve macro invocation %qs", - seg.get ().c_str ()); - return; - } - - // lookup the rules - auto rules_def = mappings.lookup_macro_def (resolved_node); - - auto &outer_attrs = rules_def.value ()->get_outer_attrs (); - bool is_builtin - = std::any_of (outer_attrs.begin (), outer_attrs.end (), - [] (AST::Attribute attr) { - return attr.get_path () - == Values::Attributes::RUSTC_BUILTIN_MACRO; - }); - - if (is_builtin) - { - auto builtin_kind = builtin_macro_from_string ( - rules_def.value ()->get_rule_name ().as_string ()); - invoc.map_to_builtin (builtin_kind.value ()); - } - - auto attributes = rules_def.value ()->get_outer_attrs (); - - /* Since the EarlyNameResolver runs multiple time (fixed point algorithm) - * we could be inserting the same macro def over and over again until we - * implement some optimizations */ - // FIXME: ARTHUR: Remove that lookup and add proper optimizations instead - if (mappings.lookup_macro_invocation (invoc)) - return; - - mappings.insert_macro_invocation (invoc, *rules_def); -} - -// FIXME: ARTHUR: Do we need to resolve these as well here? - -void -EarlyNameResolver::visit (AST::MetaItemPath &) -{} - -void -EarlyNameResolver::visit (AST::MetaItemSeq &) -{} - -void -EarlyNameResolver::visit (AST::MetaNameValueStr &) -{} - -void -EarlyNameResolver::visit (AST::MetaListPaths &) -{} - -void -EarlyNameResolver::visit (AST::MetaListNameValueStr &) -{} - -void -EarlyNameResolver::visit (AST::RangePatternBoundLiteral &) -{} - -void -EarlyNameResolver::visit (AST::RangePatternBoundPath &) -{} - -void -EarlyNameResolver::visit (AST::RangePatternBoundQualPath &) -{} - -void -EarlyNameResolver::visit (AST::StructPatternFieldIdent &) -{} - -void -EarlyNameResolver::visit (AST::StructPattern &) -{} - -void -EarlyNameResolver::visit (AST::TupleStructPattern &pattern) -{ - pattern.get_items ().accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TupleType &) -{} - -void -EarlyNameResolver::visit (AST::RawPointerType &) -{} - -void -EarlyNameResolver::visit (AST::ReferenceType &) -{} - -void -EarlyNameResolver::visit (AST::ArrayType &) -{} - -void -EarlyNameResolver::visit (AST::SliceType &) -{} - -void -EarlyNameResolver::visit (AST::InferredType &) -{} - -} // namespace Resolver -} // namespace Rust diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h deleted file mode 100644 index d3c5225..0000000 --- a/gcc/rust/resolve/rust-early-name-resolver.h +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (C) 2020-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_EARLY_NAME_RESOLVER_H -#define RUST_EARLY_NAME_RESOLVER_H - -#include "rust-name-resolver.h" -#include "rust-system.h" -#include "rust-ast.h" -#include "rust-ast-visitor.h" - -namespace Rust { -namespace Resolver { - -class EarlyNameResolver : public AST::DefaultASTVisitor -{ -public: - EarlyNameResolver (); - - void go (AST::Crate &crate); - -private: - using AST::DefaultASTVisitor::visit; - - /** - * Execute a lambda within a scope. This is equivalent to calling - * `enter_scope` before your code and `exit_scope` after. This ensures - * no errors can be committed - */ - void scoped (NodeId scope_id, std::function<void ()> fn) - { - auto old_scope = current_scope; - current_scope = scope_id; - resolver.get_macro_scope ().push (scope_id); - resolver.push_new_macro_rib (resolver.get_macro_scope ().peek ()); - - fn (); - - resolver.get_macro_scope ().pop (); - current_scope = old_scope; - } - - /** - * Accumulate all of the nested macros which escape their module through the - * use of the #[macro_use] attribute. - * - * This function recursively accumulates macros in all of the nested modules - * of an item container (an AST::Crate or an AST::Module) and returns this new - * list of items. You can then use the `take_items` and `set_items` functions - * on these containers to replace their list of items. - */ - std::vector<std::unique_ptr<AST::Item>> - accumulate_escaped_macros (AST::Module &module); - - /** - * The "scope" we are currently in. - * - * This involves lexical scopes: - * - * ```rust - * // current_scope = crate_id; - * macro_rules! foo { () => {} ) - * - * { - * // current_scope = current_block_id; - * macro_rules! foo { () => { something!(); } } - * } - * // current_scope = crate_id; - * ``` - * - * as well as any sort of scope-like structure that might impact import name - * resolution or macro name resolution: - * - * ```rust - * macro_rules! foo { - * () => { fn empty() {} } - * } - * - * - * trait Foo { - * fn foo() { - * fn inner_foo() { - * macro_rules! foo { () => {} ) - * - * foo!(); - * } - * - * foo!(); - * } - * - * foo!(); - * } - * - * foo!(); - * ``` - */ - NodeId current_scope; - - /* The crate's scope */ - NodeId crate_scope; - - Resolver &resolver; - Analysis::Mappings &mappings; - - /** - * Early name-resolve generic args, which can be macro invocations - */ - void resolve_generic_args (AST::GenericArgs &generic_args); - - /** - * Early name-resolve a qualified path type, which can contain macro - * invocations - */ - void resolve_qualified_path_type (AST::QualifiedPathType &path); - - virtual void visit (AST::Crate &crate); - virtual void visit (AST::DelimTokenTree &delim_tok_tree); - virtual void visit (AST::AttrInputMetaItemContainer &input); - virtual void visit (AST::IdentifierExpr &ident_expr); - virtual void visit (AST::LifetimeParam &lifetime_param); - virtual void visit (AST::ConstGenericParam &const_param); - virtual void visit (AST::PathInExpression &path); - virtual void visit (AST::TypePathSegmentGeneric &segment); - virtual void visit (AST::QualifiedPathInExpression &path); - virtual void visit (AST::QualifiedPathInType &path); - virtual void visit (AST::LiteralExpr &expr); - virtual void visit (AST::AttrInputLiteral &attr_input); - virtual void visit (AST::AttrInputMacro &attr_input); - virtual void visit (AST::MetaItemLitExpr &meta_item); - virtual void visit (AST::MetaItemPathExpr &meta_item); - virtual void visit (AST::StructExprStruct &expr); - virtual void visit (AST::StructExprFieldIdentifier &field); - virtual void visit (AST::StructExprStructBase &expr); - virtual void visit (AST::BlockExpr &expr); - virtual void visit (AST::ContinueExpr &expr); - virtual void visit (AST::RangeFullExpr &expr); - virtual void visit (AST::ForLoopExpr &expr); - virtual void visit (AST::IfLetExpr &expr); - virtual void visit (AST::MatchExpr &expr); - virtual void visit (AST::LifetimeWhereClauseItem &item); - virtual void visit (AST::Module &module); - virtual void visit (AST::ExternCrate &crate); - virtual void visit (AST::UseTreeGlob &use_tree); - virtual void visit (AST::UseTreeList &use_tree); - virtual void visit (AST::UseTreeRebind &use_tree); - virtual void visit (AST::UseDeclaration &use_decl); - virtual void visit (AST::EnumItem &item); - virtual void visit (AST::Union &union_item); - virtual void visit (AST::TraitItemType &item); - virtual void visit (AST::Trait &trait); - virtual void visit (AST::InherentImpl &impl); - virtual void visit (AST::TraitImpl &impl); - virtual void visit (AST::ExternalTypeItem &item); - virtual void visit (AST::ExternBlock &block); - virtual void visit (AST::MacroMatchRepetition &match); - virtual void visit (AST::MacroMatcher &matcher); - virtual void visit (AST::MacroRulesDefinition &rules_def); - virtual void visit (AST::MacroInvocation ¯o_invoc); - virtual void visit (AST::MetaItemPath &meta_item); - virtual void visit (AST::MetaItemSeq &meta_item); - virtual void visit (AST::MetaNameValueStr &meta_item); - virtual void visit (AST::MetaListPaths &meta_item); - virtual void visit (AST::MetaListNameValueStr &meta_item); - virtual void visit (AST::RangePatternBoundLiteral &bound); - virtual void visit (AST::RangePatternBoundPath &bound); - virtual void visit (AST::RangePatternBoundQualPath &bound); - virtual void visit (AST::StructPatternFieldIdent &field); - virtual void visit (AST::StructPattern &pattern); - virtual void visit (AST::TupleStructPattern &pattern); - virtual void visit (AST::TupleType &type); - virtual void visit (AST::RawPointerType &type); - virtual void visit (AST::ReferenceType &type); - virtual void visit (AST::ArrayType &type); - virtual void visit (AST::SliceType &type); - virtual void visit (AST::InferredType &type); -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_EARLY_NAME_RESOLVER_H diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 1ed87b3..848f5e6 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -531,7 +531,7 @@ ForeverStack<N>::resolve_segments ( || seg.is_lower_self_seg ())) return tl::nullopt; - tl::optional<typename ForeverStack<N>::Node &> child = tl::nullopt; + tl::optional<std::reference_wrapper<Node>> child = tl::nullopt; /* * On every iteration this loop either @@ -583,10 +583,17 @@ ForeverStack<N>::resolve_segments ( break; } - if (N == Namespace::Types) + auto rib_lookup = current_node->rib.get (seg.as_string ()); + if (rib_lookup && !rib_lookup->is_ambiguous ()) { - auto rib_lookup = current_node->rib.get (seg.as_string ()); - if (rib_lookup && !rib_lookup->is_ambiguous ()) + if (Analysis::Mappings::get () + .lookup_glob_container (rib_lookup->get_node_id ()) + .has_value ()) + { + child = dfs_node (root, rib_lookup->get_node_id ()).value (); + break; + } + else { insert_segment_resolution (outer_seg, rib_lookup->get_node_id ()); @@ -611,9 +618,9 @@ ForeverStack<N>::resolve_segments ( current_node = ¤t_node->parent.value (); } - // if child didn't contain a value - // the while loop above should have return'd or kept looping - current_node = &child.value (); + // if child didn't point to a value + // the while loop above would have returned or kept looping + current_node = &child->get (); insert_segment_resolution (outer_seg, current_node->id); } 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 e39ca15..96b38f4 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -24,6 +24,7 @@ #include "rust-late-name-resolver-2.0.h" #include "rust-default-resolver.h" #include "rust-name-resolution-context.h" +#include "rust-resolve-builtins.h" #include "rust-path.h" #include "rust-system.h" #include "rust-tyty.h" @@ -38,84 +39,10 @@ Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx), funny_error (false), block_big_self (false) {} -static NodeId -next_node_id () -{ - return Analysis::Mappings::get ().get_next_node_id (); -}; - -static HirId -next_hir_id () -{ - return Analysis::Mappings::get ().get_next_hir_id (); -}; - -void -Late::setup_builtin_types () -{ - // access the global type context to setup the TyTys - auto &ty_ctx = *Resolver::TypeCheckContext::get (); - - // Late builtin type struct helper - struct LType - { - std::string name; - NodeId node_id; - NodeId hir_id; - TyTy::BaseType *type; - - explicit LType (std::string name, TyTy::BaseType *type) - : name (name), node_id (next_node_id ()), hir_id (type->get_ref ()), - type (type) - {} - }; - - static const LType builtins[] = { - {LType ("bool", new TyTy::BoolType (next_hir_id ()))}, - {LType ("u8", new TyTy::UintType (next_hir_id (), TyTy::UintType::U8))}, - {LType ("u16", new TyTy::UintType (next_hir_id (), TyTy::UintType::U16))}, - {LType ("u32", new TyTy::UintType (next_hir_id (), TyTy::UintType::U32))}, - {LType ("u64", new TyTy::UintType (next_hir_id (), TyTy::UintType::U64))}, - {LType ("u128", new TyTy::UintType (next_hir_id (), TyTy::UintType::U128))}, - {LType ("i8", new TyTy::IntType (next_hir_id (), TyTy::IntType::I8))}, - {LType ("i16", new TyTy::IntType (next_hir_id (), TyTy::IntType::I16))}, - {LType ("i32", new TyTy::IntType (next_hir_id (), TyTy::IntType::I32))}, - {LType ("i64", new TyTy::IntType (next_hir_id (), TyTy::IntType::I64))}, - {LType ("i128", new TyTy::IntType (next_hir_id (), TyTy::IntType::I128))}, - {LType ("f32", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F32))}, - {LType ("f64", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F64))}, - {LType ("usize", new TyTy::USizeType (next_hir_id ()))}, - {LType ("isize", new TyTy::ISizeType (next_hir_id ()))}, - {LType ("char", new TyTy::CharType (next_hir_id ()))}, - {LType ("str", new TyTy::StrType (next_hir_id ()))}, - {LType ("!", new TyTy::NeverType (next_hir_id ()))}, - - // the unit type `()` does not play a part in name-resolution - so we only - // insert it in the type context... - }; - - // There's a special Rib for putting prelude items, since prelude items need - // to satisfy certain special rules. - ctx.scoped (Rib::Kind::Prelude, 0, [this, &ty_ctx] (void) -> void { - for (const auto &builtin : builtins) - { - auto ok = ctx.types.insert (builtin.name, builtin.node_id); - rust_assert (ok); - - ctx.mappings.insert_node_to_hir (builtin.node_id, builtin.hir_id); - ty_ctx.insert_builtin (builtin.hir_id, builtin.node_id, builtin.type); - } - }); - - // ...here! - auto *unit_type = TyTy::TupleType::get_unit_type (); - ty_ctx.insert_builtin (unit_type->get_ref (), next_node_id (), unit_type); -} - void Late::go (AST::Crate &crate) { - setup_builtin_types (); + Builtins::setup_type_ctx (); visit (crate); } @@ -521,20 +448,22 @@ Late::visit_impl_type (AST::Type &type) block_big_self = false; } -void -Late::visit (AST::TypePath &type) +template <typename P> +static void +resolve_type_path_like (NameResolutionContext &ctx, bool block_big_self, + P &type) { // should we add type path resolution in `ForeverStack` directly? Since it's // quite more complicated. // maybe we can overload `resolve_path<Namespace::Types>` to only do // typepath-like path resolution? that sounds good - 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) + && !unwrap_segment_get_lang_item (type.get_segments ().front ()) + .has_value () + && unwrap_type_segment (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"); @@ -547,17 +476,17 @@ Late::visit (AST::TypePath &type) if (!resolved.has_value ()) { - if (!ctx.lookup (type.get_segments ().front ()->get_node_id ())) + if (!ctx.lookup (unwrap_segment_node_id (type.get_segments ().front ()))) rust_error_at (type.get_locus (), ErrorCode::E0412, "could not resolve type path %qs", - type.make_debug_string ().c_str ()); + unwrap_segment_error_string (type).c_str ()); return; } if (resolved->is_ambiguous ()) { rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous", - type.make_debug_string ().c_str ()); + unwrap_segment_error_string (type).c_str ()); return; } @@ -574,6 +503,14 @@ Late::visit (AST::TypePath &type) } void +Late::visit (AST::TypePath &type) +{ + DefaultResolver::visit (type); + + resolve_type_path_like (ctx, block_big_self, type); +} + +void Late::visit (AST::Visibility &vis) { if (!vis.has_path ()) @@ -649,10 +586,7 @@ Late::visit (AST::StructExprStruct &s) visit_inner_attrs (s); DefaultResolver::visit (s.get_struct_name ()); - auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types); - - ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), - Definition (resolved->get_node_id ())); + resolve_type_path_like (ctx, block_big_self, s.get_struct_name ()); } void @@ -663,10 +597,7 @@ Late::visit (AST::StructExprStructBase &s) DefaultResolver::visit (s.get_struct_name ()); visit (s.get_struct_base ()); - auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types); - - ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), - Definition (resolved->get_node_id ())); + resolve_type_path_like (ctx, block_big_self, s.get_struct_name ()); } void @@ -680,10 +611,7 @@ Late::visit (AST::StructExprStructFields &s) for (auto &field : s.get_fields ()) visit (field); - auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types); - - ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()), - Definition (resolved->get_node_id ())); + resolve_type_path_like (ctx, block_big_self, s.get_struct_name ()); } // needed because Late::visit (AST::GenericArg &) is non-virtual 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 95540e3..608ae38 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -75,9 +75,6 @@ public: private: void resolve_label (AST::Lifetime &lifetime); - /* Setup Rust's builtin types (u8, i32, !...) in the resolver */ - void setup_builtin_types (); - bool funny_error; /* used to prevent "impl Self {}", "impl (Self, i32) {}", etc */ diff --git a/gcc/rust/resolve/rust-resolve-builtins.cc b/gcc/rust/resolve/rust-resolve-builtins.cc new file mode 100644 index 0000000..b16db9a --- /dev/null +++ b/gcc/rust/resolve/rust-resolve-builtins.cc @@ -0,0 +1,125 @@ +// 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-resolve-builtins.h" +#include "rust-name-resolution-context.h" +#include "rust-tyty.h" +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Resolver2_0 { +namespace Builtins { + +// Use X-macros + +#define TYPE_UINT(n, enum_ident) TYPE1 (n, UintType, UintType::enum_ident) +#define TYPE_INT(n, enum_ident) TYPE1 (n, IntType, IntType::enum_ident) + +#define BUILTIN_TYPES \ + TYPE0 ("bool", BoolType) \ + TYPE_UINT ("u8", U8) \ + TYPE_UINT ("u16", U16) \ + TYPE_UINT ("u32", U32) \ + TYPE_UINT ("u64", U64) \ + TYPE_UINT ("u128", U128) \ + TYPE_INT ("i8", I8) \ + TYPE_INT ("i16", I16) \ + TYPE_INT ("i32", I32) \ + TYPE_INT ("i64", I64) \ + TYPE_INT ("i128", I128) \ + TYPE1 ("f32", FloatType, FloatType::F32) \ + TYPE1 ("f64", FloatType, FloatType::F64) \ + TYPE0 ("usize", USizeType) \ + TYPE0 ("isize", ISizeType) \ + TYPE0 ("char", CharType) \ + TYPE0 ("str", StrType) \ + TYPE0 ("!", NeverType) + +// Define constants using X macros + +#define TYPE0(...) 1 + +#define TYPE1(...) 1 + +static constexpr size_t builtin_count = BUILTIN_TYPES 0; +#undef TYPE0 +#undef TYPE1 + +#define TYPE0(n, ...) n, +#define TYPE1(n, ...) n, +static constexpr const char *builtin_names[] = {BUILTIN_TYPES}; +#undef TYPE0 +#undef TYPE1 + +static NodeId builtin_node_ids[builtin_count]; + +void +setup_lang_prelude (NameResolutionContext &ctx) +{ + auto &mappings = Analysis::Mappings::get (); + + // insert into prelude rib + ctx.scoped (Rib::Kind::Prelude, 0, [&mappings, &ctx] (void) -> void { + for (size_t i = 0; i < builtin_count; i++) + { + NodeId node_id = mappings.get_next_node_id (); + rust_assert (ctx.types.insert (Identifier (builtin_names[i]), node_id)); + builtin_node_ids[i] = node_id; + } + }); +} + +void +setup_type_ctx () +{ + auto &mappings = Analysis::Mappings::get (); + auto &ty_ctx = *Resolver::TypeCheckContext::get (); + + HirId hir_ids[builtin_count]; + for (size_t i = 0; i < builtin_count; i++) + hir_ids[i] = mappings.get_next_hir_id (); + + TyTy::BaseType *types[builtin_count]; + { + size_t i = 0; +#define TYPE_BASE(stub) \ + types[i] = new TyTy::stub; \ + i++; +#define TYPE0(n, ty) TYPE_BASE (ty (hir_ids[i])) +#define TYPE1(n, ty, p1) TYPE_BASE (ty (hir_ids[i], TyTy::p1)) + BUILTIN_TYPES +#undef TYPE_BASE +#undef TYPE0 +#undef TYPE1 + } + + for (size_t i = 0; i < builtin_count; i++) + { + NodeId node_id = builtin_node_ids[i]; + HirId hir_id = hir_ids[i]; + mappings.insert_node_to_hir (node_id, hir_id); + ty_ctx.insert_builtin (hir_id, node_id, types[i]); + } + + // handle unit type separately + auto *unit_type = TyTy::TupleType::get_unit_type (); + ty_ctx.insert_builtin (unit_type->get_ref (), mappings.get_next_node_id (), + unit_type); +} + +} // namespace Builtins +} // namespace Resolver2_0 +} // namespace Rust diff --git a/gcc/rust/resolve/rust-resolve-builtins.h b/gcc/rust/resolve/rust-resolve-builtins.h new file mode 100644 index 0000000..e7e1bd2 --- /dev/null +++ b/gcc/rust/resolve/rust-resolve-builtins.h @@ -0,0 +1,37 @@ +// 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_RESOLVE_BUILTINS_H +#define RUST_RESOLVE_BUILTINS_H + +namespace Rust { +namespace Resolver2_0 { + +// forward declare +class NameResolutionContext; + +namespace Builtins { + +void setup_lang_prelude (NameResolutionContext &ctx); +void setup_type_ctx (); + +} // namespace Builtins +} // namespace Resolver2_0 +} // namespace Rust + +#endif // RUST_RESOLVE_BUILTINS_H diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 398dea1..8f950d17 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -1258,7 +1258,7 @@ constructor_expression (tree type_tree, bool is_variant, return error_mark_node; vec<constructor_elt, va_gc> *init; - vec_alloc (init, vals.size ()); + vec_alloc (init, union_index != -1 ? 1 : vals.size ()); tree sink = NULL_TREE; bool is_constant = true; diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc index 93ce041..1088845 100644 --- a/gcc/rust/rust-lang.cc +++ b/gcc/rust/rust-lang.cc @@ -34,7 +34,6 @@ #include "selftest.h" #include "rust-cfg-parser.h" #include "rust-privacy-ctx.h" -#include "rust-ast-resolve-item.h" #include "rust-lex.h" #include "optional.h" #include "rust-unicode.h" @@ -442,7 +441,6 @@ run_rust_tests () rust_cfg_parser_test (); rust_privacy_ctx_test (); rust_crate_name_validation_test (); - rust_simple_path_resolve_test (); } } // namespace selftest diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 17f9c06..6418118 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -29,7 +29,6 @@ #include "rust-lex.h" #include "rust-parse.h" #include "rust-macro-expand.h" -#include "rust-ast-resolve.h" #include "rust-ast-lower.h" #include "rust-hir-type-check.h" #include "rust-privacy-check.h" @@ -46,10 +45,10 @@ #include "rust-imports.h" #include "rust-extern-crate.h" #include "rust-attributes.h" -#include "rust-early-name-resolver.h" #include "rust-name-resolution-context.h" #include "rust-early-name-resolver-2.0.h" #include "rust-late-name-resolver-2.0.h" +#include "rust-resolve-builtins.h" #include "rust-cfg-strip.h" #include "rust-expand-visitor.h" #include "rust-unicode.h" @@ -422,32 +421,31 @@ Session::handle_crate_name (const char *filename, { if (attr.get_path () != "crate_name") continue; - if (!attr.has_attr_input ()) + + auto msg_str = Analysis::Attributes::extract_string_literal (attr); + if (!msg_str.has_value ()) { rust_error_at (attr.get_locus (), - "%<crate_name%> accepts one argument"); + "malformed %<crate_name%> attribute input"); continue; } - auto &literal - = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ()); - const auto &msg_str = literal.get_literal ().as_string (); - if (!validate_crate_name (msg_str, error)) + if (!validate_crate_name (*msg_str, error)) { error.locus = attr.get_locus (); error.emit (); continue; } - if (options.crate_name_set_manually && (options.crate_name != msg_str)) + if (options.crate_name_set_manually && (options.crate_name != *msg_str)) { rust_error_at (attr.get_locus (), "%<-frust-crate-name%> and %<#[crate_name]%> are " "required to match, but %qs does not match %qs", - options.crate_name.c_str (), msg_str.c_str ()); + options.crate_name.c_str (), msg_str->c_str ()); } crate_name_found = true; - options.set_crate_name (msg_str); + options.set_crate_name (*msg_str); } options.crate_name_set_manually |= crate_name_found; @@ -551,10 +549,6 @@ Session::compile_crate (const char *filename) handle_crate_name (filename, *ast_crate.get ()); // dump options except lexer dump - if (options.dump_option_enabled (CompileOptions::AST_DUMP_PRETTY)) - { - dump_ast_pretty (*ast_crate.get ()); - } if (options.dump_option_enabled (CompileOptions::TARGET_OPTION_DUMP)) { options.target_data.dump_target_options (); @@ -563,6 +557,11 @@ Session::compile_crate (const char *filename) if (saw_errors ()) return; + if (options.dump_option_enabled (CompileOptions::AST_DUMP_PRETTY)) + { + dump_ast_pretty (*ast_crate.get ()); + } + // setup the mappings for this AST CrateNum current_crate = mappings.get_current_crate (); AST::Crate &parsed_crate @@ -613,13 +612,13 @@ Session::compile_crate (const char *filename) if (last_step == CompileOptions::CompileStep::Expansion) return; - AST::CollectLangItems ().go (parsed_crate); - auto name_resolution_ctx = Resolver2_0::NameResolutionContext (); // expansion pipeline stage expansion (parsed_crate, name_resolution_ctx); + AST::CollectLangItems ().go (parsed_crate); + rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m"); if (options.dump_option_enabled (CompileOptions::EXPANSION_DUMP)) { @@ -644,10 +643,7 @@ Session::compile_crate (const char *filename) return; // resolution pipeline stage - if (flag_name_resolution_2_0) - Resolver2_0::Late (name_resolution_ctx).go (parsed_crate); - else - Resolver::NameResolution::Resolve (parsed_crate); + Resolver2_0::Late (name_resolution_ctx).go (parsed_crate); if (options.dump_option_enabled (CompileOptions::RESOLUTION_DUMP)) dump_name_resolution (name_resolution_ctx); @@ -738,7 +734,7 @@ Session::compile_crate (const char *filename) // lints Analysis::ScanDeadcode::Scan (hir); Analysis::UnusedVariables::Lint (*ctx); - Analysis::ReadonlyCheck::Lint (*ctx); + HIR::ReadonlyChecker ().go (hir); // metadata bool specified_emit_metadata @@ -758,6 +754,9 @@ Session::compile_crate (const char *filename) } } + if (saw_errors ()) + return; + // pass to GCC middle-end ctx->write_to_backend (); } @@ -937,28 +936,23 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx) MacroExpander expander (crate, cfg, *this); std::vector<Error> macro_errors; + Resolver2_0::Builtins::setup_lang_prelude (ctx); + while (!fixed_point_reached && iterations < cfg.recursion_limit) { - CfgStrip ().go (crate); + CfgStrip (cfg).go (crate); // Errors might happen during cfg strip pass - bool visitor_dirty = false; - if (flag_name_resolution_2_0) - { - Resolver2_0::Early early (ctx); - early.go (crate); - macro_errors = early.get_macro_resolve_errors (); - visitor_dirty = early.is_dirty (); - } - else - Resolver::EarlyNameResolver ().go (crate); + Resolver2_0::Early early (ctx); + early.go (crate); + macro_errors = early.get_macro_resolve_errors (); if (saw_errors ()) break; ExpandVisitor (expander).go (crate); - fixed_point_reached = !expander.has_changed () && !visitor_dirty; + fixed_point_reached = !expander.has_changed () && !early.is_dirty (); expander.reset_changed_state (); iterations++; @@ -993,8 +987,7 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx) // HACK: we may need a final TopLevel pass // however, this should not count towards the recursion limit // and we don't need a full Early pass - if (flag_name_resolution_2_0) - Resolver2_0::TopLevel (ctx).go (crate); + Resolver2_0::TopLevel (ctx).go (crate); } // error reporting - check unused macros, get missing fragment specifiers @@ -1190,14 +1183,6 @@ Session::load_extern_crate (const std::string &crate_name, location_t locus) mappings.insert_bang_proc_macros (crate_num, bang_macros); mappings.insert_derive_proc_macros (crate_num, derive_macros); - // if flag_name_resolution_2_0 is enabled - // then we perform resolution later - if (!flag_name_resolution_2_0) - { - // name resolve it - Resolver::NameResolution::Resolve (parsed_crate); - } - // always restore the crate_num mappings.set_current_crate (saved_crate_num); diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc index 10a59bd..8cc2b7b 100644 --- a/gcc/rust/typecheck/rust-autoderef.cc +++ b/gcc/rust/typecheck/rust-autoderef.cc @@ -425,8 +425,7 @@ AutoderefCycle::try_autoderefed (TyTy::BaseType *r) TyTy::ReferenceType *r1 = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()), Mutability::Imm); - adjustments.push_back ( - Adjustment (Adjustment::AdjustmentType::IMM_REF, r, r1)); + adjustments.emplace_back (Adjustment::AdjustmentType::IMM_REF, r, r1); if (select (*r1)) return true; @@ -436,8 +435,7 @@ AutoderefCycle::try_autoderefed (TyTy::BaseType *r) TyTy::ReferenceType *r2 = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()), Mutability::Mut); - adjustments.push_back ( - Adjustment (Adjustment::AdjustmentType::MUT_REF, r, r2)); + adjustments.emplace_back (Adjustment::AdjustmentType::MUT_REF, r, r2); if (select (*r2)) return true; diff --git a/gcc/rust/typecheck/rust-casts.cc b/gcc/rust/typecheck/rust-casts.cc index f06d9ed..7d08601 100644 --- a/gcc/rust/typecheck/rust-casts.cc +++ b/gcc/rust/typecheck/rust-casts.cc @@ -277,6 +277,7 @@ TypeCastRules::cast_rules () break; case TyTy::TypeKind::REF: + case TyTy::TypeKind::FNPTR: case TyTy::TypeKind::POINTER: switch (to.get_ty ()->get_kind ()) { @@ -286,8 +287,9 @@ TypeCastRules::cast_rules () case TyTy::TypeKind::INT: { // refs should not cast to numeric type - bool from_ptr - = from.get_ty ()->get_kind () == TyTy::TypeKind::POINTER; + auto kind = from.get_ty ()->get_kind (); + bool from_ptr = kind == TyTy::TypeKind::POINTER + || kind == TyTy::TypeKind::FNPTR; if (from_ptr) { return TypeCoercionRules::CoercionResult{ diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc index fd12839..e027d9c 100644 --- a/gcc/rust/typecheck/rust-coercion.cc +++ b/gcc/rust/typecheck/rust-coercion.cc @@ -61,60 +61,21 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver) // see: // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs - // handle never - // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L155 if (receiver->get_kind () == TyTy::TypeKind::NEVER) { - // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound - // type variable, we want `?T` to fallback to `!` if not - // otherwise constrained. An example where this arises: - // - // let _: Option<?T> = Some({ return; }); - // - // here, we would coerce from `!` to `?T`. - if (expected->has_substitutions_defined () && !expected->is_concrete ()) - { - location_t locus = mappings.lookup_location (receiver->get_ref ()); - TyTy::TyVar implicit_var - = TyTy::TyVar::get_implicit_infer_var (locus); - try_result = CoercionResult{{}, implicit_var.get_tyty ()}; - return true; - } - else - { - bool expected_is_infer_var - = expected->get_kind () == TyTy::TypeKind::INFER; - bool expected_is_general_infer_var - = expected_is_infer_var - && (static_cast<TyTy::InferType *> (expected)->get_infer_kind () - == TyTy::InferType::InferTypeKind::GENERAL); - - // FIXME this 'expected_is_general_infer_var' case needs to eventually - // should go away see: compile/never_type_err1.rs - // - // I think we need inference obligations to say that yes we have a - // general inference variable but we add the oligation to the expected - // type that it could default to '!' - if (expected_is_general_infer_var) - try_result = CoercionResult{{}, receiver}; - else - try_result = CoercionResult{{}, expected->clone ()}; - - return true; - } + try_result = coerce_never (receiver); + return true; } // unsize - bool unsafe_error = false; - CoercionResult unsize_coercion - = coerce_unsized (receiver, expected, unsafe_error); - bool valid_unsize_coercion = !unsize_coercion.is_error (); - if (valid_unsize_coercion) + tl::expected<CoercionResult, CoerceUnsizedError> unsize_coercion + = coerce_unsized (receiver, expected); + if (unsize_coercion) { - try_result = unsize_coercion; + try_result = unsize_coercion.value (); return true; } - else if (unsafe_error) + else if (unsize_coercion.error () == CoerceUnsizedError::Unsafe) { // location_t lhs = mappings.lookup_location (receiver->get_ref ()); // location_t rhs = mappings.lookup_location (expected->get_ref ()); @@ -127,15 +88,14 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver) { case TyTy::TypeKind::POINTER: { - TyTy::PointerType *ptr = static_cast<TyTy::PointerType *> (expected); + auto *ptr = expected->as<TyTy::PointerType> (); try_result = coerce_unsafe_ptr (receiver, ptr, ptr->mutability ()); return !try_result.is_error (); } case TyTy::TypeKind::REF: { - TyTy::ReferenceType *ptr - = static_cast<TyTy::ReferenceType *> (expected); + auto *ptr = expected->as<TyTy::ReferenceType> (); try_result = coerce_borrowed_pointer (receiver, ptr, ptr->mutability ()); return !try_result.is_error (); @@ -174,6 +134,44 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver) } TypeCoercionRules::CoercionResult +TypeCoercionRules::coerce_never (TyTy::BaseType *receiver) +{ + // handle never + // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L155 + + // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound + // type variable, we want `?T` to fallback to `!` if not + // otherwise constrained. An example where this arises: + // + // let _: Option<?T> = Some({ return; }); + // + // here, we would coerce from `!` to `?T`. + if (expected->has_substitutions_defined () && !expected->is_concrete ()) + { + location_t locus = mappings.lookup_location (receiver->get_ref ()); + TyTy::TyVar implicit_var = TyTy::TyVar::get_implicit_infer_var (locus); + return CoercionResult{{}, implicit_var.get_tyty ()}; + } + + bool expected_is_infer_var = expected->get_kind () == TyTy::TypeKind::INFER; + bool expected_is_general_infer_var + = expected_is_infer_var + && (static_cast<TyTy::InferType *> (expected)->get_infer_kind () + == TyTy::InferType::InferTypeKind::GENERAL); + + // FIXME this 'expected_is_general_infer_var' case needs to eventually + // should go away see: compile/never_type_err1.rs + // + // I think we need inference obligations to say that yes we have a + // general inference variable but we add the oligation to the expected + // type that it could default to '!' + if (expected_is_general_infer_var) + return CoercionResult{{}, receiver}; + else + return CoercionResult{{}, expected->clone ()}; +} + +TypeCoercionRules::CoercionResult TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver, TyTy::PointerType *expected, Mutability to_mutbl) @@ -273,12 +271,9 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver, { case TyTy::TypeKind::REF: { - TyTy::ReferenceType *from - = static_cast<TyTy::ReferenceType *> (receiver); - from_mutbl = from->mutability (); + from_mutbl = receiver->as<TyTy::ReferenceType> ()->mutability (); } break; - default: { rust_debug ("coerce_borrowed_pointer -- unify"); @@ -318,9 +313,10 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver, // &[T; n] or &mut [T; n] -> &[T] // or &mut [T; n] -> &mut [T] // or &Concrete -> &Trait, etc. -TypeCoercionRules::CoercionResult +tl::expected<TypeCoercionRules::CoercionResult, + TypeCoercionRules::CoerceUnsizedError> TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, - TyTy::BaseType *target, bool &unsafe_error) + TyTy::BaseType *target) { rust_debug ("coerce_unsized(source={%s}, target={%s})", source->debug_str ().c_str (), target->debug_str ().c_str ()); @@ -344,11 +340,11 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, Mutability to_mutbl = target_ref->mutability (); if (!coerceable_mutability (from_mutbl, to_mutbl)) { - unsafe_error = true; location_t lhs = mappings.lookup_location (source->get_ref ()); location_t rhs = mappings.lookup_location (target->get_ref ()); mismatched_mutability_error (locus, lhs, rhs); - return TypeCoercionRules::CoercionResult::get_error (); + return tl::unexpected<CoerceUnsizedError> ( + CoerceUnsizedError::Unsafe); } ty_a = source_ref->get_base (); @@ -356,8 +352,8 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, needs_reborrow = true; expected_mutability = to_mutbl; - adjustments.push_back ( - Adjustment (Adjustment::AdjustmentType::INDIRECTION, source_ref, ty_a)); + adjustments.emplace_back (Adjustment::AdjustmentType::INDIRECTION, + source_ref, ty_a); } else if (source_is_ref && target_is_ptr) { @@ -369,11 +365,11 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, Mutability to_mutbl = target_ref->mutability (); if (!coerceable_mutability (from_mutbl, to_mutbl)) { - unsafe_error = true; location_t lhs = mappings.lookup_location (source->get_ref ()); location_t rhs = mappings.lookup_location (target->get_ref ()); mismatched_mutability_error (locus, lhs, rhs); - return TypeCoercionRules::CoercionResult::get_error (); + return tl::unexpected<CoerceUnsizedError> ( + CoerceUnsizedError::Unsafe); } ty_a = source_ref->get_base (); @@ -381,8 +377,8 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, needs_reborrow = true; expected_mutability = to_mutbl; - adjustments.push_back ( - Adjustment (Adjustment::AdjustmentType::INDIRECTION, source_ref, ty_a)); + adjustments.emplace_back (Adjustment::AdjustmentType::INDIRECTION, + source_ref, ty_a); } // FIXME @@ -401,17 +397,14 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, { bool bounds_compatible = b->bounds_compatible (*a, locus, false); if (!bounds_compatible) - { - unsafe_error = true; - return TypeCoercionRules::CoercionResult::get_error (); - } + return tl::unexpected<CoerceUnsizedError> (CoerceUnsizedError::Unsafe); // return the unsize coercion TyTy::BaseType *result = b->clone (); // result->set_ref (a->get_ref ()); // append a dyn coercion adjustment - adjustments.push_back (Adjustment (Adjustment::UNSIZE, a, result)); + adjustments.emplace_back (Adjustment::UNSIZE, a, result); // reborrow if needed if (needs_reborrow) @@ -424,7 +417,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, Adjustment::AdjustmentType borrow_type = expected_mutability == Mutability::Imm ? Adjustment::IMM_REF : Adjustment::MUT_REF; - adjustments.push_back (Adjustment (borrow_type, result, reborrow)); + adjustments.emplace_back (borrow_type, result, reborrow); result = reborrow; } @@ -432,7 +425,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source, } adjustments.clear (); - return TypeCoercionRules::CoercionResult::get_error (); + return tl::unexpected<CoerceUnsizedError> (CoerceUnsizedError::Regular); } bool @@ -446,7 +439,8 @@ TypeCoercionRules::select (TyTy::BaseType &autoderefed) = unify_site_and (autoderefed.get_ref (), TyTy::TyWithLocation (expected), TyTy::TyWithLocation (&autoderefed), UNDEF_LOCATION /* locus */, false /*emit_errors*/, - false /*commit_if_ok*/, true /*infer*/, true /*cleanup*/); + !try_flag /*commit_if_ok*/, try_flag /*infer*/, + try_flag /*cleanup*/); bool ok = result->get_kind () != TyTy::TypeKind::ERROR; if (!ok) return false; diff --git a/gcc/rust/typecheck/rust-coercion.h b/gcc/rust/typecheck/rust-coercion.h index b268966..864f48a 100644 --- a/gcc/rust/typecheck/rust-coercion.h +++ b/gcc/rust/typecheck/rust-coercion.h @@ -21,6 +21,7 @@ #include "rust-autoderef.h" #include "rust-hir-type-check.h" +#include "expected.h" namespace Rust { namespace Resolver { @@ -28,6 +29,12 @@ namespace Resolver { class TypeCoercionRules : protected AutoderefCycle { public: + enum class CoerceUnsizedError + { + Regular, + Unsafe + }; + struct CoercionResult { std::vector<Adjustment> adjustments; @@ -51,6 +58,7 @@ public: bool allow_autoderef, bool is_cast_site = false); + CoercionResult coerce_never (TyTy::BaseType *receiver); CoercionResult coerce_unsafe_ptr (TyTy::BaseType *receiver, TyTy::PointerType *expected, Mutability mutability); @@ -59,8 +67,8 @@ public: TyTy::ReferenceType *expected, Mutability mutability); - CoercionResult coerce_unsized (TyTy::BaseType *receiver, - TyTy::BaseType *expected, bool &unsafe_error); + tl::expected<CoercionResult, CoerceUnsizedError> + coerce_unsized (TyTy::BaseType *receiver, TyTy::BaseType *expected); static bool coerceable_mutability (Mutability from_mutbl, Mutability to_mutbl); diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc index 7b7944c..296cc44 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.cc +++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc @@ -51,6 +51,9 @@ MethodResolver::Select (std::set<MethodCandidate> &candidates, { TyTy::BaseType *candidate_type = candidate.candidate.ty; rust_assert (candidate_type->get_kind () == TyTy::TypeKind::FNDEF); + if (candidate_type == nullptr + || candidate_type->get_kind () != TyTy::TypeKind::FNDEF) + continue; TyTy::FnType &fn = *static_cast<TyTy::FnType *> (candidate_type); // match the number of arguments @@ -136,11 +139,11 @@ MethodResolver::assemble_inherent_impl_candidates ( TyTy::BaseType *ty = nullptr; if (!query_type (func->get_mappings ().get_hirid (), &ty)) return true; - rust_assert (ty != nullptr); - if (ty->get_kind () == TyTy::TypeKind::ERROR) + if (ty == nullptr || ty->get_kind () == TyTy::TypeKind::ERROR) + return true; + if (ty->get_kind () != TyTy::TypeKind::FNDEF) return true; - rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF); TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty); const TyTy::BaseType *impl_self = TypeCheckItem::ResolveImplBlockSelf (*impl); @@ -175,7 +178,7 @@ MethodResolver::assemble_inherent_impl_candidates ( return true; } - inherent_impl_fns.push_back ({func, impl, fnty}); + inherent_impl_fns.emplace_back (func, impl, fnty); return true; }); @@ -220,10 +223,11 @@ MethodResolver::assemble_trait_impl_candidates ( TyTy::BaseType *ty = nullptr; if (!query_type (func->get_mappings ().get_hirid (), &ty)) continue; - if (ty->get_kind () == TyTy::TypeKind::ERROR) + if (ty == nullptr || ty->get_kind () == TyTy::TypeKind::ERROR) + continue; + if (ty->get_kind () != TyTy::TypeKind::FNDEF) continue; - rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF); TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty); const TyTy::BaseType *impl_self = TypeCheckItem::ResolveImplBlockSelf (*impl); @@ -259,7 +263,7 @@ MethodResolver::assemble_trait_impl_candidates ( continue; } - impl_candidates.push_back ({func, impl, fnty}); + impl_candidates.emplace_back (func, impl, fnty); return true; } @@ -282,11 +286,11 @@ MethodResolver::assemble_trait_impl_candidates ( return true; TyTy::BaseType *ty = item_ref->get_tyty (); - rust_assert (ty->get_kind () == TyTy::TypeKind::FNDEF); + if (ty == nullptr || ty->get_kind () != TyTy::TypeKind::FNDEF) + return true; TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty); - trait_item_candidate candidate{func, trait, fnty, trait_ref, item_ref}; - trait_candidates.push_back (candidate); + trait_candidates.emplace_back (func, trait, fnty, trait_ref, item_ref); return true; }); @@ -299,7 +303,8 @@ MethodResolver::try_select_predicate_candidates (TyTy::BaseType &receiver) for (const auto &predicate : predicate_items) { const TyTy::FnType *fn = predicate.fntype; - rust_assert (fn->is_method ()); + if (!fn->is_method ()) + continue; TyTy::BaseType *fn_self = fn->get_self_type (); rust_debug ("dot-operator predicate fn_self={%s} can_eq receiver={%s}", @@ -346,7 +351,8 @@ MethodResolver::try_select_inherent_impl_candidates ( continue; TyTy::FnType *fn = impl_item.ty; - rust_assert (fn->is_method ()); + if (!fn->is_method ()) + continue; TyTy::BaseType *fn_self = fn->get_self_type (); @@ -384,7 +390,8 @@ MethodResolver::try_select_trait_impl_candidates ( for (auto trait_item : candidates) { TyTy::FnType *fn = trait_item.ty; - rust_assert (fn->is_method ()); + if (!fn->is_method ()) + continue; TyTy::BaseType *fn_self = fn->get_self_type (); rust_debug ("dot-operator trait_item fn_self={%s} can_eq receiver={%s}", @@ -464,20 +471,17 @@ MethodResolver::get_predicate_items ( std::vector<predicate_candidate> predicate_items; for (auto &bound : specified_bounds) { - TyTy::TypeBoundPredicateItem lookup + tl::optional<TyTy::TypeBoundPredicateItem> lookup = bound.lookup_associated_item (segment_name.as_string ()); - if (lookup.is_error ()) + if (!lookup.has_value ()) continue; - TyTy::BaseType *ty = lookup.get_tyty_for_receiver (&receiver); + TyTy::BaseType *ty = lookup->get_tyty_for_receiver (&receiver); if (ty->get_kind () == TyTy::TypeKind::FNDEF) { TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty); if (fnty->is_method ()) - { - predicate_candidate candidate{lookup, fnty}; - predicate_items.push_back (candidate); - } + predicate_items.emplace_back (lookup.value (), fnty); } } diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h index cc40472..d2f11d1 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.h +++ b/gcc/rust/typecheck/rust-hir-dot-operator.h @@ -49,6 +49,10 @@ class MethodResolver : private TypeCheckBase, protected AutoderefCycle public: struct predicate_candidate { + predicate_candidate (TyTy::TypeBoundPredicateItem lookup, + TyTy::FnType *fntype) + : lookup (lookup), fntype (fntype) + {} TyTy::TypeBoundPredicateItem lookup; TyTy::FnType *fntype; }; @@ -67,6 +71,11 @@ public: struct impl_item_candidate { + impl_item_candidate (HIR::Function *item, HIR::ImplBlock *impl_block, + TyTy::FnType *ty) + : item (item), impl_block (impl_block), ty (ty) + {} + HIR::Function *item; HIR::ImplBlock *impl_block; TyTy::FnType *ty; @@ -74,6 +83,13 @@ public: struct trait_item_candidate { + trait_item_candidate (const HIR::TraitItemFunc *item, + const HIR::Trait *trait, TyTy::FnType *ty, + const TraitReference *reference, + const TraitItemReference *item_ref) + : item (item), trait (trait), ty (ty), reference (reference), + item_ref (item_ref) + {} const HIR::TraitItemFunc *item; const HIR::Trait *trait; TyTy::FnType *ty; diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc index c02702f..59118e6 100644 --- a/gcc/rust/typecheck/rust-hir-path-probe.cc +++ b/gcc/rust/typecheck/rust-hir-path-probe.cc @@ -302,11 +302,10 @@ PathProbeType::process_impl_item_candidate (HirId id, HIR::ImplItem *item, if (!query_type (impl_ty_id, &impl_block_ty)) return; - if (!receiver->can_eq (impl_block_ty, false)) - { - if (!impl_block_ty->can_eq (receiver, false)) - return; - } + if (!types_compatable (TyTy::TyWithLocation (receiver), + TyTy::TyWithLocation (impl_block_ty), + impl->get_locus (), false)) + return; // lets visit the impl_item item->accept_vis (*this); @@ -367,15 +366,15 @@ PathProbeType::process_predicate_for_candidates ( { const TraitReference *trait_ref = predicate.get (); - TyTy::TypeBoundPredicateItem item + tl::optional<TyTy::TypeBoundPredicateItem> item = predicate.lookup_associated_item (search.as_string ()); - if (item.is_error ()) + if (!item.has_value ()) return; - if (ignore_mandatory_trait_items && item.needs_implementation ()) + if (ignore_mandatory_trait_items && item->needs_implementation ()) return; - const TraitItemReference *trait_item_ref = item.get_raw_item (); + const TraitItemReference *trait_item_ref = item->get_raw_item (); PathProbeCandidate::CandidateType candidate_type; switch (trait_item_ref->get_trait_item_type ()) { @@ -395,9 +394,9 @@ PathProbeType::process_predicate_for_candidates ( break; } - TyTy::BaseType *trait_item_tyty = item.get_raw_item ()->get_tyty (); + TyTy::BaseType *trait_item_tyty = item->get_raw_item ()->get_tyty (); if (receiver->get_kind () != TyTy::DYNAMIC) - trait_item_tyty = item.get_tyty_for_receiver (receiver); + trait_item_tyty = item->get_tyty_for_receiver (receiver); PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref, trait_item_ref, @@ -425,10 +424,10 @@ PathProbeType::union_bounds ( } std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_set; + for (auto it = mapper.begin (); it != mapper.end (); it++) - { - union_set.push_back ({it->second.first, it->second.second}); - } + union_set.emplace_back (it->second.first, it->second.second); + return union_set; } diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc index 0fd0147..03121d1 100644 --- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc +++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc @@ -224,8 +224,7 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference) apply_sized); context->insert_type (generic_param->get_mappings (), param_type); - substitutions.push_back ( - TyTy::SubstitutionParamMapping (typaram, param_type)); + substitutions.emplace_back (typaram, param_type); if (is_self) { @@ -247,17 +246,17 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference) // copy the substitition mappings std::vector<TyTy::SubstitutionParamMapping> self_subst_copy; + self_subst_copy.reserve (substitutions.size ()); + for (auto &sub : substitutions) self_subst_copy.push_back (sub.clone ()); // They also inherit themselves as a bound this enables a trait item to // reference other Self::trait_items - auto self_hrtb - = TyTy::TypeBoundPredicate (trait_reference->get_mappings ().get_defid (), - std::move (self_subst_copy), - BoundPolarity::RegularBound, - trait_reference->get_locus ()); - specified_bounds.push_back (self_hrtb); + specified_bounds.emplace_back (trait_reference->get_mappings ().get_defid (), + std::move (self_subst_copy), + BoundPolarity::RegularBound, + trait_reference->get_locus ()); // look for any std::vector<TyTy::TypeBoundPredicate> super_traits; @@ -291,6 +290,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference) { // make a copy of the substs std::vector<TyTy::SubstitutionParamMapping> item_subst; + item_subst.reserve (substitutions.size ()); + for (auto &sub : substitutions) item_subst.push_back (sub.clone ()); @@ -553,9 +554,9 @@ AssociatedImplTrait::setup_associated_types ( generic_param->get_mappings ().get_hirid (), &l); if (ok && l->get_kind () == TyTy::TypeKind::PARAM) { - substitutions.push_back (TyTy::SubstitutionParamMapping ( - static_cast<HIR::TypeParam &> (*generic_param), - static_cast<TyTy::ParamType *> (l))); + substitutions.emplace_back (static_cast<HIR::TypeParam &> ( + *generic_param), + static_cast<TyTy::ParamType *> (l)); } } break; @@ -579,14 +580,13 @@ AssociatedImplTrait::setup_associated_types ( if (p.needs_substitution () && infer) { TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus); - subst_args.push_back ( - TyTy::SubstitutionArg (&p, infer_var.get_tyty ())); + subst_args.emplace_back (&p, infer_var.get_tyty ()); } else { auto param = p.get_param_ty (); auto resolved = param->destructure (); - subst_args.push_back (TyTy::SubstitutionArg (&p, resolved)); + subst_args.emplace_back (&p, resolved); param_mappings[param->get_symbol ()] = resolved->get_ref (); } } diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h index 5384700..392ff20 100644 --- a/gcc/rust/typecheck/rust-hir-type-bounds.h +++ b/gcc/rust/typecheck/rust-hir-type-bounds.h @@ -30,7 +30,7 @@ class TypeBoundsProbe : public TypeCheckBase { public: static std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> - Probe (const TyTy::BaseType *receiver); + Probe (TyTy::BaseType *receiver); static bool is_bound_satisfied_for_type (TyTy::BaseType *receiver, TraitReference *ref); @@ -46,9 +46,9 @@ private: void assemble_builtin_candidate (LangItem::Kind item); private: - TypeBoundsProbe (const TyTy::BaseType *receiver); + TypeBoundsProbe (TyTy::BaseType *receiver); - const TyTy::BaseType *receiver; + TyTy::BaseType *receiver; std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> trait_references; }; diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc index 68001bf..f878720 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-base.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc @@ -56,7 +56,9 @@ walk_types_to_constrain (std::set<HirId> &constrained_symbols, if (arg != nullptr) { const auto p = arg->get_root (); + constrained_symbols.insert (p->get_ref ()); constrained_symbols.insert (p->get_ty_ref ()); + if (p->has_substitutions_defined ()) { walk_types_to_constrain (constrained_symbols, @@ -66,6 +68,83 @@ walk_types_to_constrain (std::set<HirId> &constrained_symbols, } } +static void +walk_type_to_constrain (std::set<HirId> &constrained_symbols, TyTy::BaseType &r) +{ + switch (r.get_kind ()) + { + case TyTy::TypeKind::POINTER: + { + auto &p = static_cast<TyTy::PointerType &> (r); + walk_type_to_constrain (constrained_symbols, *p.get_base ()); + } + break; + case TyTy::TypeKind::REF: + { + auto &ref = static_cast<TyTy::ReferenceType &> (r); + walk_type_to_constrain (constrained_symbols, *ref.get_base ()); + } + break; + case TyTy::TypeKind::ARRAY: + { + auto &arr = static_cast<TyTy::ArrayType &> (r); + walk_type_to_constrain (constrained_symbols, *arr.get_element_type ()); + } + break; + case TyTy::TypeKind::FNDEF: + { + auto &fn = static_cast<TyTy::FnType &> (r); + for (auto ¶m : fn.get_params ()) + walk_type_to_constrain (constrained_symbols, *param.get_type ()); + walk_type_to_constrain (constrained_symbols, *fn.get_return_type ()); + } + break; + case TyTy::TypeKind::PARAM: + { + auto ¶m = static_cast<TyTy::ParamType &> (r); + constrained_symbols.insert (param.get_ty_ref ()); + } + break; + case TyTy::SLICE: + { + auto &slice = static_cast<TyTy::SliceType &> (r); + walk_type_to_constrain (constrained_symbols, + *slice.get_element_type ()); + } + break; + case TyTy::FNPTR: + { + auto &ptr = static_cast<TyTy::FnPtr &> (r); + for (auto ¶m : ptr.get_params ()) + walk_type_to_constrain (constrained_symbols, *param.get_tyty ()); + walk_type_to_constrain (constrained_symbols, *ptr.get_return_type ()); + } + break; + case TyTy::TUPLE: + { + auto &tuple = static_cast<TyTy::TupleType &> (r); + for (auto &ty : tuple.get_fields ()) + walk_type_to_constrain (constrained_symbols, *ty.get_tyty ()); + } + break; + case TyTy::DYNAMIC: + { + auto &dyn = static_cast<TyTy::DynamicObjectType &> (r); + constrained_symbols.insert (dyn.get_ty_ref ()); + } + break; + case TyTy::CLOSURE: + { + auto &clos = static_cast<TyTy::ClosureType &> (r); + walk_type_to_constrain (constrained_symbols, clos.get_parameters ()); + walk_type_to_constrain (constrained_symbols, *clos.get_return_type ()); + } + break; + default: + break; + } +} + bool TypeCheckBase::check_for_unconstrained ( const std::vector<TyTy::SubstitutionParamMapping> ¶ms_to_constrain, @@ -87,21 +166,13 @@ TypeCheckBase::check_for_unconstrained ( HirId ref = p.get_param_ty ()->get_ref (); symbols_to_constrain.insert (ref); symbol_to_location.insert ({ref, p.get_param_locus ()}); - - rust_debug_loc (p.get_param_locus (), "XX constrain THIS"); } // set up the set of constrained symbols std::set<HirId> constrained_symbols; walk_types_to_constrain (constrained_symbols, constraint_a); walk_types_to_constrain (constrained_symbols, constraint_b); - - const auto root = reference->get_root (); - if (root->get_kind () == TyTy::TypeKind::PARAM) - { - const TyTy::ParamType *p = static_cast<const TyTy::ParamType *> (root); - constrained_symbols.insert (p->get_ty_ref ()); - } + walk_type_to_constrain (constrained_symbols, *reference); // check for unconstrained bool unconstrained = false; @@ -296,17 +367,17 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings, tree capacity = Compile::HIRCompileBase::query_compile_const_expr ( ctx, expected_ty, *literal_capacity); - TyTy::ConstType *capacity_expr - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", - expected_ty, capacity, {}, - literal_capacity->get_locus (), - literal_capacity->get_mappings ().get_hirid (), - literal_capacity->get_mappings ().get_hirid (), - {}); - - TyTy::ArrayType *array - = new TyTy::ArrayType (array_mapping.get_hirid (), locus, - capacity_expr, TyTy::TyVar (u8->get_ref ())); + HirId capacity_expr_id = literal_capacity->get_mappings ().get_hirid (); + auto capacity_expr + = new TyTy::ConstValueType (capacity, expected_ty, capacity_expr_id, + capacity_expr_id); + context->insert_type (literal_capacity->get_mappings (), + capacity_expr->as_base_type ()); + + TyTy::ArrayType *array = new TyTy::ArrayType ( + array_mapping.get_hirid (), locus, + TyTy::TyVar (capacity_expr->as_base_type ()->get_ty_ref ()), + TyTy::TyVar (u8->get_ref ())); context->insert_type (array_mapping, array); infered = new TyTy::ReferenceType (expr_mappings.get_hirid (), @@ -341,7 +412,7 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) bool is_repr = attr.get_path ().as_string () == Values::Attributes::REPR; if (is_repr && !attr.has_attr_input ()) { - rust_error_at (attr.get_locus (), "malformed %qs attribute", "repr"); + rust_error_at (attr.get_locus (), "malformed %<repr%> attribute"); continue; } @@ -350,7 +421,11 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus) const AST::AttrInput &input = attr.get_attr_input (); bool is_token_tree = input.get_attr_input_type () == AST::AttrInput::AttrInputType::TOKEN_TREE; - rust_assert (is_token_tree); + if (!is_token_tree) + { + rust_error_at (attr.get_locus (), "malformed %<repr%> attribute"); + continue; + } const auto &option = static_cast<const AST::DelimTokenTree &> (input); AST::AttrInputMetaItemContainer *meta_items = option.parse_to_meta_item (); @@ -526,22 +601,21 @@ TypeCheckBase::resolve_generic_params ( = Compile::HIRCompileBase::query_compile_const_expr ( ctx, specified_type, expr); - TyTy::ConstType *default_const_decl - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - param.get_name (), specified_type, - default_value, {}, param.get_locus (), - expr.get_mappings ().get_hirid (), - expr.get_mappings ().get_hirid (), {}); + auto default_const_decl + = new TyTy::ConstValueType (default_value, specified_type, + expr.get_mappings ().get_hirid (), + expr.get_mappings ().get_hirid (), + {}); context->insert_type (expr.get_mappings (), default_const_decl); } - TyTy::ConstType *const_decl - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Decl, - param.get_name (), specified_type, - error_mark_node, {}, param.get_locus (), - param.get_mappings ().get_hirid (), - param.get_mappings ().get_hirid (), {}); + TyTy::BaseGeneric *const_decl + = new TyTy::ConstParamType (param.get_name (), param.get_locus (), + specified_type, + param.get_mappings ().get_hirid (), + param.get_mappings ().get_hirid (), + {}); context->insert_type (generic_param->get_mappings (), const_decl); TyTy::SubstitutionParamMapping p (*generic_param, const_decl); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 438200b..7885dfc 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -34,6 +34,7 @@ #include "rust-immutable-name-resolution-context.h" #include "rust-compile-base.h" #include "rust-tyty-util.h" +#include "rust-tyty.h" #include "tree.h" namespace Rust { @@ -125,7 +126,13 @@ TypeCheckExpr::visit (HIR::TupleIndexExpr &expr) } TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (resolved); - rust_assert (!adt->is_enum ()); + if (!adt->is_tuple_struct ()) + { + rust_error_at (expr.get_locus (), + "expected tuple or tuple struct, found %qs", + adt->get_name ().c_str ()); + return; + } rust_assert (adt->number_of_variants () == 1); TyTy::VariantDef *variant = adt->get_variants ().at (0); @@ -160,7 +167,7 @@ TypeCheckExpr::visit (HIR::TupleExpr &expr) for (auto &elem : expr.get_tuple_elems ()) { auto field_ty = TypeCheckExpr::Resolve (*elem); - fields.push_back (TyTy::TyVar (field_ty->get_ref ())); + fields.emplace_back (field_ty->get_ref ()); } infered = new TyTy::TupleType (expr.get_mappings ().get_hirid (), expr.get_locus (), fields); @@ -629,10 +636,9 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) if (s->is_unit_check_needed () && !resolved->is_unit ()) { auto unit = TyTy::TupleType::get_unit_type (); - resolved - = unify_site (s->get_mappings ().get_hirid (), - TyTy::TyWithLocation (unit), - TyTy::TyWithLocation (resolved), s->get_locus ()); + unify_site (s->get_mappings ().get_hirid (), + TyTy::TyWithLocation (unit), + TyTy::TyWithLocation (resolved), s->get_locus ()); } } @@ -669,16 +675,9 @@ TypeCheckExpr::visit (HIR::AnonConst &expr) return; } - auto locus = expr.get_locus (); - auto infer_ty_var = TyTy::TyVar::get_implicit_infer_var (locus); - - HirId next = mappings.get_next_hir_id (); - infered = new TyTy::ConstType (TyTy::ConstType::ConstKind::Infer, "", - infer_ty_var.get_tyty (), error_mark_node, {}, - locus, next, next, {}); - - context->insert_implicit_type (infered->get_ref (), infered); - mappings.insert_location (infered->get_ref (), locus); + TyTy::TyVar var + = TyTy::TyVar::get_implicit_const_infer_var (expr.get_locus ()); + infered = var.get_tyty (); } void @@ -730,7 +729,7 @@ TypeCheckExpr::visit (HIR::RangeFromToExpr &expr) // substitute it in std::vector<TyTy::SubstitutionArg> subst_mappings; const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0); - subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified)); + subst_mappings.emplace_back (param_ref, unified); TyTy::SubstitutionArgumentMappings subst ( subst_mappings, {}, adt->get_substitution_arguments ().get_regions (), @@ -774,7 +773,7 @@ TypeCheckExpr::visit (HIR::RangeFromExpr &expr) // substitute it in std::vector<TyTy::SubstitutionArg> subst_mappings; const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0); - subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty)); + subst_mappings.emplace_back (param_ref, from_ty); TyTy::SubstitutionArgumentMappings subst ( subst_mappings, {}, adt->get_substitution_arguments ().get_regions (), @@ -818,7 +817,7 @@ TypeCheckExpr::visit (HIR::RangeToExpr &expr) // substitute it in std::vector<TyTy::SubstitutionArg> subst_mappings; const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0); - subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, from_ty)); + subst_mappings.emplace_back (param_ref, from_ty); TyTy::SubstitutionArgumentMappings subst ( subst_mappings, {}, adt->get_substitution_arguments ().get_regions (), @@ -991,7 +990,7 @@ TypeCheckExpr::visit (HIR::RangeFromToInclExpr &expr) // substitute it in std::vector<TyTy::SubstitutionArg> subst_mappings; const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0); - subst_mappings.push_back (TyTy::SubstitutionArg (param_ref, unified)); + subst_mappings.emplace_back (param_ref, unified); TyTy::SubstitutionArgumentMappings subst ( subst_mappings, {}, adt->get_substitution_arguments ().get_regions (), @@ -1091,15 +1090,19 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) auto capacity_expr_ty = TypeCheckExpr::Resolve (elems.get_num_copies_expr ()); + if (capacity_expr_ty->is<TyTy::ErrorType> ()) + return; context->insert_type (elems.get_num_copies_expr ().get_mappings (), expected_ty); - unify_site ( + auto result = unify_site ( expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty), TyTy::TyWithLocation (capacity_expr_ty, elems.get_num_copies_expr ().get_locus ()), expr.get_locus ()); + if (result->is<TyTy::ErrorType> ()) + return; capacity_expr = &elems.get_num_copies_expr (); capacity_type = expected_ty; @@ -1152,14 +1155,23 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr) tree capacity_value = Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type, *capacity_expr); - HirId size_id = capacity_expr->get_mappings ().get_hirid (); - TyTy::ConstType *const_type - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", expected_ty, - capacity_value, {}, capacity_expr->get_locus (), - size_id, size_id); + + // Create ConstValueType with ref == ty_ref (both pointing to capacity_expr) + // ty_ref gets updated during substitution via set_ty_ref() + HirId capacity_expr_id = capacity_expr->get_mappings ().get_hirid (); + auto const_type + = new TyTy::ConstValueType (capacity_value, expected_ty, capacity_expr_id, + capacity_expr_id); + + // Insert the ConstValueType at its ref + context->insert_type (capacity_expr->get_mappings (), + const_type->as_base_type ()); + infered = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), expr.get_locus (), - const_type, TyTy::TyVar (element_type->get_ref ())); + TyTy::TyVar ( + const_type->as_base_type ()->get_ty_ref ()), + TyTy::TyVar (element_type->get_ref ())); } // empty struct @@ -1888,7 +1900,7 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr) // auto resolve because the hir id's match , expr.get_locus ()); - args.get_type_args ().push_back (std::unique_ptr<HIR::Type> (implicit_tuple)); + args.get_type_args ().emplace_back (implicit_tuple); // apply the arguments predicate.apply_generic_arguments (&args, false, false); @@ -1974,13 +1986,13 @@ TypeCheckExpr::resolve_operator_overload ( std::vector<TyTy::SubstitutionArg> mappings; auto &self_param_mapping = trait_subst[0]; - mappings.push_back (TyTy::SubstitutionArg (&self_param_mapping, lhs)); + mappings.emplace_back (&self_param_mapping, lhs); if (rhs != nullptr) { rust_assert (trait_subst.size () == 2); auto &rhs_param_mapping = trait_subst[1]; - mappings.push_back (TyTy::SubstitutionArg (&rhs_param_mapping, lhs)); + mappings.emplace_back (&rhs_param_mapping, lhs); } std::map<std::string, TyTy::BaseType *> binding_args; @@ -2033,24 +2045,6 @@ TypeCheckExpr::resolve_operator_overload ( rust_debug ("is_impl_item_candidate: %s", resolved_candidate.is_impl_candidate () ? "true" : "false"); - if (resolved_candidate.is_impl_candidate ()) - { - auto infer_arguments = TyTy::SubstitutionArgumentMappings::error (); - HIR::ImplBlock &impl = *resolved_candidate.item.impl.parent; - TyTy::BaseType *impl_self_infer - = TypeCheckItem::ResolveImplBlockSelfWithInference (impl, - expr.get_locus (), - &infer_arguments); - if (impl_self_infer->get_kind () == TyTy::TypeKind::ERROR) - { - return false; - } - if (!infer_arguments.is_empty ()) - { - lookup = SubstMapperInternal::Resolve (lookup, infer_arguments); - } - } - // in the case where we resolve to a trait bound we have to be careful we are // able to do so there is a case where we are currently resolving the deref // operator overload function which is generic and this might resolve to the @@ -2312,7 +2306,7 @@ TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr, for (auto &arg : expr.get_arguments ()) { TyTy::BaseType *a = TypeCheckExpr::Resolve (*arg); - call_args.push_back (TyTy::TyVar (a->get_ref ())); + call_args.emplace_back (a->get_ref ()); } // crate implicit tuple @@ -2325,9 +2319,8 @@ TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr, context->insert_implicit_type (implicit_arg_id, tuple); std::vector<TyTy::Argument> args; - TyTy::Argument a (mapping, tuple, - expr.get_locus () /*FIXME is there a better location*/); - args.push_back (std::move (a)); + args.emplace_back (mapping, tuple, + expr.get_locus () /*FIXME is there a better location*/); TyTy::BaseType *function_ret_tyty = TyTy::TypeCheckMethodCallExpr::go (fn, expr.get_mappings (), args, diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc index c8544a1..e7f6632 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc @@ -121,7 +121,7 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function) UNDEF_LOCATION, false, Mutability::Imm, std::unique_ptr<HIR::Pattern> (nullptr))); - params.push_back (TyTy::FnParam (std::move (param_pattern), param_tyty)); + params.emplace_back (std::move (param_pattern), param_tyty); context->insert_type (param.get_mappings (), param_tyty); @@ -324,7 +324,7 @@ TypeCheckImplItem::visit (HIR::Function &function) } context->insert_type (self_param.get_mappings (), self_type); - params.push_back (TyTy::FnParam (std::move (self_pattern), self_type)); + params.emplace_back (std::move (self_pattern), self_type); } for (auto ¶m : function.get_function_params ()) @@ -335,8 +335,8 @@ TypeCheckImplItem::visit (HIR::Function &function) context->insert_type (param.get_mappings (), param_tyty); TypeCheckPattern::Resolve (param.get_param_name (), param_tyty); - params.push_back ( - TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty)); + params.emplace_back (param.get_param_name ().clone_pattern (), + param_tyty); } auto &nr_ctx @@ -469,8 +469,8 @@ TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant) } // get the item from the predicate - resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item); - rust_assert (!resolved_trait_item.is_error ()); + resolved_trait_item + = trait_reference.lookup_associated_item (raw_trait_item).value (); // merge the attributes const HIR::TraitItem *hir_trait_item @@ -519,8 +519,8 @@ TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type) } // get the item from the predicate - resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item); - rust_assert (!resolved_trait_item.is_error ()); + resolved_trait_item + = trait_reference.lookup_associated_item (raw_trait_item).value (); // merge the attributes const HIR::TraitItem *hir_trait_item @@ -578,8 +578,8 @@ TypeCheckImplItemWithTrait::visit (HIR::Function &function) } // get the item from the predicate - resolved_trait_item = trait_reference.lookup_associated_item (raw_trait_item); - rust_assert (!resolved_trait_item.is_error ()); + resolved_trait_item + = trait_reference.lookup_associated_item (raw_trait_item).value (); // merge the attributes const HIR::TraitItem *hir_trait_item diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 3ba607b..4987c88a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -115,13 +115,13 @@ TypeCheckItem::ResolveImplBlockSelfWithInference ( if (p.needs_substitution ()) { TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus); - args.push_back (TyTy::SubstitutionArg (&p, infer_var.get_tyty ())); + args.emplace_back (&p, infer_var.get_tyty ()); } else { auto param = p.get_param_ty (); auto resolved = param->destructure (); - args.push_back (TyTy::SubstitutionArg (&p, resolved)); + args.emplace_back (&p, resolved); } } @@ -554,8 +554,8 @@ TypeCheckItem::visit (HIR::Function &function) auto param_tyty = TypeCheckType::Resolve (param.get_type ()); context->insert_type (param.get_mappings (), param_tyty); TypeCheckPattern::Resolve (param.get_param_name (), param_tyty); - params.push_back ( - TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty)); + params.emplace_back (param.get_param_name ().clone_pattern (), + param_tyty); } auto &nr_ctx diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc index cc5c412..ffa0990 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-path.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc @@ -77,9 +77,9 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr) // lookup the associated item from the specified bound HIR::PathExprSegment &item_seg = expr.get_segments ().at (0); HIR::PathIdentSegment item_seg_identifier = item_seg.get_segment (); - TyTy::TypeBoundPredicateItem item + tl::optional<TyTy::TypeBoundPredicateItem> item = specified_bound.lookup_associated_item (item_seg_identifier.as_string ()); - if (item.is_error ()) + if (!item.has_value ()) { rust_error_at (item_seg.get_locus (), "unknown associated item"); return; @@ -116,9 +116,9 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr) // and we dont need to worry if the trait item is actually implemented or // not because this will have already been validated as part of the trait // impl block - infered = item.get_tyty_for_receiver (root); + infered = item->get_tyty_for_receiver (root); root_resolved_node_id - = item.get_raw_item ()->get_mappings ().get_nodeid (); + = item->get_raw_item ()->get_mappings ().get_nodeid (); } else { @@ -517,9 +517,8 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id, const auto &predicate = impl_block_ty->lookup_predicate (trait_ref.get_defid ()); if (!predicate.is_error ()) - impl_block_ty - = associated->setup_associated_types (prev_segment, predicate, - nullptr, false); + associated->setup_associated_types (prev_segment, predicate, + nullptr, false); } } diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc index be926fc..7dae303 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc @@ -21,6 +21,8 @@ #include "rust-hir-type-check-expr.h" #include "rust-type-util.h" #include "rust-immutable-name-resolution-context.h" +#include "rust-tyty.h" +#include "tree.h" namespace Rust { namespace Resolver { @@ -160,19 +162,32 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern) infered = pattern_ty; TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered); - rust_assert (adt->number_of_variants () > 0); - TyTy::VariantDef *variant = adt->get_variants ().at (0); + TyTy::VariantDef *variant = nullptr; if (adt->is_enum ()) { HirId variant_id = UNKNOWN_HIRID; bool ok = context->lookup_variant_definition ( pattern.get_path ().get_mappings ().get_hirid (), &variant_id); - rust_assert (ok); + if (!ok) + { + rust_error_at ( + pattern.get_locus (), ErrorCode::E0532, + "expected tuple struct or tuple variant, found enum %qs", + pattern_ty->get_name ().c_str ()); + return; + } ok = adt->lookup_variant_by_id (variant_id, &variant); rust_assert (ok); } + else + { + rust_assert (adt->number_of_variants () > 0); + variant = adt->get_variants ().at (0); + } + + rust_assert (variant != nullptr); // error[E0532]: expected tuple struct or tuple variant, found struct // variant `Foo::D`, E0532 by rustc 1.49.0 , E0164 by rustc 1.71.0 @@ -200,33 +215,144 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern) auto &items = pattern.get_items (); switch (items.get_item_type ()) { - case HIR::TupleStructItems::RANGED: + case HIR::TupleStructItems::HAS_REST: { - // TODO - rust_unreachable (); + HIR::TupleStructItemsHasRest &items_has_rest + = static_cast<HIR::TupleStructItemsHasRest &> (items); + auto &lower_patterns = items_has_rest.get_lower_patterns (); + auto &upper_patterns = items_has_rest.get_upper_patterns (); + size_t pattern_min_cap + = lower_patterns.size () + upper_patterns.size (); + if (variant->num_fields () < pattern_min_cap) + { + if (!lower_patterns.empty ()) + { + // TODO initialize rich_locus with loc of ADT definition instead + rich_location rich_locus (line_table, + lower_patterns[0]->get_locus ()); + for (auto &pattern : lower_patterns) + { + if (pattern == lower_patterns[0]) + continue; + rich_locus.add_range (pattern->get_locus (), + SHOW_RANGE_WITH_CARET); + } + for (auto &pattern : upper_patterns) + { + rich_locus.add_range (pattern->get_locus (), + SHOW_RANGE_WITH_CARET); + } + rust_error_at (rich_locus, ErrorCode::E0023, + "this pattern has %lu %s but the corresponding " + "tuple variant has %lu %s", + (unsigned long) (pattern_min_cap), + pattern_min_cap == 1 ? "field" : "fields", + (unsigned long) variant->num_fields (), + variant->num_fields () == 1 ? "field" + : "fields"); + } + else + { + // TODO initialize rich_locus with loc of ADT definition instead + rich_location rich_locus (line_table, + upper_patterns[0]->get_locus ()); + for (auto &pattern : upper_patterns) + { + if (pattern == upper_patterns[0]) + continue; + rich_locus.add_range (pattern->get_locus (), + SHOW_RANGE_WITH_CARET); + } + rust_error_at (rich_locus, ErrorCode::E0023, + "this pattern has %lu %s but the corresponding " + "tuple variant has %lu %s", + (unsigned long) (pattern_min_cap), + pattern_min_cap == 1 ? "field" : "fields", + (unsigned long) variant->num_fields (), + variant->num_fields () == 1 ? "field" + : "fields"); + } + // we continue on to try and setup the types as best we can for + // type checking + } + + // iterate the fields manually to set them up + size_t i = 0; + for (auto &pattern : lower_patterns) + { + if (i >= variant->num_fields ()) + break; + + TyTy::StructFieldType *field = variant->get_field_at_index (i++); + TyTy::BaseType *fty = field->get_field_type (); + + // setup the type on this pattern type + context->insert_type (pattern->get_mappings (), fty); + TypeCheckPattern::Resolve (*pattern, fty); + } + + i = variant->num_fields () - upper_patterns.size (); + for (auto &pattern : upper_patterns) + { + if (i >= variant->num_fields ()) + break; + + TyTy::StructFieldType *field = variant->get_field_at_index (i++); + TyTy::BaseType *fty = field->get_field_type (); + + // setup the type on this pattern type + context->insert_type (pattern->get_mappings (), fty); + TypeCheckPattern::Resolve (*pattern, fty); + } } break; - case HIR::TupleStructItems::MULTIPLE: + case HIR::TupleStructItems::NO_REST: { - HIR::TupleStructItemsNoRange &items_no_range - = static_cast<HIR::TupleStructItemsNoRange &> (items); + HIR::TupleStructItemsNoRest &items_no_rest + = static_cast<HIR::TupleStructItemsNoRest &> (items); + auto &patterns = items_no_rest.get_patterns (); - if (items_no_range.get_patterns ().size () != variant->num_fields ()) + if (patterns.size () != variant->num_fields ()) { - rust_error_at ( - pattern.get_locus (), ErrorCode::E0023, - "this pattern has %lu fields but the corresponding " - "tuple variant has %lu field", - (unsigned long) items_no_range.get_patterns ().size (), - (unsigned long) variant->num_fields ()); + if (patterns.empty ()) + { + rust_error_at (pattern.get_locus (), ErrorCode::E0023, + "this pattern has %lu %s but the corresponding " + "tuple variant has %lu %s", + (unsigned long) patterns.size (), + patterns.size () == 1 ? "field" : "fields", + (unsigned long) variant->num_fields (), + variant->num_fields () == 1 ? "field" + : "fields"); + } + else + { + rich_location rich_locus (line_table, + patterns[0]->get_locus ()); + for (auto &pattern : items_no_rest.get_patterns ()) + { + if (pattern == patterns[0]) + continue; + rich_locus.add_range (pattern->get_locus (), + SHOW_RANGE_WITH_CARET); + } + rust_error_at (rich_locus, ErrorCode::E0023, + "this pattern has %lu %s but the corresponding " + "tuple variant has %lu %s", + (unsigned long) patterns.size (), + patterns.size () == 1 ? "field" : "fields", + (unsigned long) variant->num_fields (), + variant->num_fields () == 1 ? "field" + : "fields"); + } // we continue on to try and setup the types as best we can for // type checking } // iterate the fields and set them up, I wish we had ZIP size_t i = 0; - for (auto &pattern : items_no_range.get_patterns ()) + for (auto &pattern : items_no_rest.get_patterns ()) { if (i >= variant->num_fields ()) break; @@ -299,7 +425,30 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) // error[E0532]: expected tuple struct or tuple variant, found struct // variant `Foo::D` - if (variant->get_variant_type () != TyTy::VariantDef::VariantType::STRUCT) + bool error_E0532 = false; + if (variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE) + { + // Tuple structs can still be matched with struct patterns via index + // numbers e.g. Foo {0: a, .., 3: b}, so check whether the fields are of + // type TUPLE_PAT. Throw E0532 if not. + auto &struct_pattern_elems = pattern.get_struct_pattern_elems (); + for (auto &field : struct_pattern_elems.get_struct_pattern_fields ()) + { + if (field->get_item_type () + != HIR::StructPatternField::ItemType::TUPLE_PAT) + { + error_E0532 = true; + break; + } + } + } + else if (variant->get_variant_type () + != TyTy::VariantDef::VariantType::STRUCT) + { + error_E0532 = true; + } + + if (error_E0532) { std::string variant_type = TyTy::VariantDef::variant_type_string (variant->get_variant_type ()); @@ -407,7 +556,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern) // Expects enum struct or struct struct. // error[E0027]: pattern does not mention fields `x`, `y` // error[E0026]: variant `Foo::D` does not have a field named `b` - if (named_fields.size () != variant->num_fields ()) + if (!pattern.get_struct_pattern_elems ().has_rest () + && named_fields.size () != variant->num_fields ()) { std::map<std::string, bool> missing_names; @@ -463,10 +613,10 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) switch (pattern.get_items ().get_item_type ()) { - case HIR::TuplePatternItems::ItemType::MULTIPLE: + case HIR::TuplePatternItems::ItemType::NO_REST: { - auto &ref = static_cast<HIR::TuplePatternItemsMultiple &> ( - pattern.get_items ()); + auto &ref + = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ()); const auto &patterns = ref.get_patterns (); size_t nitems_to_resolve = patterns.size (); @@ -486,17 +636,17 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) TyTy::BaseType *par_type = par.get_field (i); TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type); - pattern_elems.push_back (TyTy::TyVar (elem->get_ref ())); + pattern_elems.emplace_back (elem->get_ref ()); } infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (), pattern.get_locus (), pattern_elems); } break; - case HIR::TuplePatternItems::ItemType::RANGED: + case HIR::TuplePatternItems::ItemType::HAS_REST: { - HIR::TuplePatternItemsRanged &ref - = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); + HIR::TuplePatternItemsHasRest &ref + = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ()); const auto &lower = ref.get_lower_patterns (); const auto &upper = ref.get_upper_patterns (); @@ -507,37 +657,45 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern) { emit_pattern_size_error (pattern, par.get_fields ().size (), min_size_required); - // TODO attempt to continue to do typechecking even after wrong size - break; + // continue and attempt to resolve individual items in the pattern } // Resolve lower patterns std::vector<TyTy::TyVar> pattern_elems; - for (size_t i = 0; i < lower.size (); i++) + size_t nlower_items_to_resolve + = std::min (lower.size (), par.get_fields ().size ()); + for (size_t i = 0; i < nlower_items_to_resolve; i++) { auto &p = lower[i]; TyTy::BaseType *par_type = par.get_field (i); TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type); - pattern_elems.push_back (TyTy::TyVar (elem->get_ref ())); + pattern_elems.emplace_back (elem->get_ref ()); } + if (lower.size () > par.get_fields ().size ()) + break; + // Pad pattern_elems until needing to resolve upper patterns - size_t rest_end = par.get_fields ().size () - upper.size (); + size_t rest_end + = std::max (par.get_fields ().size () - upper.size (), lower.size ()); for (size_t i = lower.size (); i < rest_end; i++) { TyTy::BaseType *par_type = par.get_field (i); - pattern_elems.push_back (TyTy::TyVar (par_type->get_ref ())); + pattern_elems.emplace_back (par_type->get_ref ()); } + size_t nupper_items_to_resolve + = std::min (upper.size (), + par.get_fields ().size () - pattern_elems.size ()); // Resolve upper patterns - for (size_t i = 0; i < upper.size (); i++) + for (size_t i = 0; i < nupper_items_to_resolve; i++) { auto &p = upper[i]; TyTy::BaseType *par_type = par.get_field (rest_end + i); TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type); - pattern_elems.push_back (TyTy::TyVar (elem->get_ref ())); + pattern_elems.emplace_back (elem->get_ref ()); } infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (), @@ -642,7 +800,32 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern) auto &array_ty_ty = static_cast<TyTy::ArrayType &> (*parent); parent_element_ty = array_ty_ty.get_element_type (); auto capacity = array_ty_ty.get_capacity (); - tree cap = capacity->get_value (); + + tree cap = error_mark_node; + if (capacity->get_kind () != TyTy::TypeKind::CONST) + { + // Error case - capacity is not a const type + break; + } + + auto *capacity_const = capacity->as_const_type (); + switch (capacity_const->const_kind ()) + { + case TyTy::BaseConstType::ConstKind::Value: + { + const auto &const_value + = *static_cast<TyTy::ConstValueType *> (capacity); + cap = const_value.get_value (); + } + break; + + case TyTy::BaseConstType::ConstKind::Decl: + case TyTy::BaseConstType::ConstKind::Infer: + case TyTy::BaseConstType::ConstKind::Error: + cap = error_mark_node; + break; + } + if (error_operand_p (cap)) { rust_error_at (parent->get_locus (), @@ -651,14 +834,45 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern) break; } auto cap_wi = wi::to_wide (cap).to_uhwi (); - if (cap_wi != pattern.get_items ().size ()) + + // size check during compile time + switch (pattern.get_items ().get_item_type ()) { - rust_error_at (pattern.get_locus (), ErrorCode::E0527, - "pattern requires %lu elements but array has %lu", - (unsigned long) pattern.get_items ().size (), - (unsigned long) cap_wi); + case HIR::SlicePatternItems::ItemType::NO_REST: + { + auto &ref = static_cast<HIR::SlicePatternItemsNoRest &> ( + pattern.get_items ()); + if (cap_wi != ref.get_patterns ().size ()) + { + rust_error_at ( + pattern.get_locus (), ErrorCode::E0527, + "pattern requires %lu elements but array has %lu", + (unsigned long) ref.get_patterns ().size (), + (unsigned long) cap_wi); + break; + } + } + break; + case HIR::SlicePatternItems::ItemType::HAS_REST: + { + auto &ref = static_cast<HIR::SlicePatternItemsHasRest &> ( + pattern.get_items ()); + auto pattern_min_cap = ref.get_lower_patterns ().size () + + ref.get_upper_patterns ().size (); + + if (cap_wi < pattern_min_cap) + { + rust_error_at (pattern.get_locus (), ErrorCode::E0528, + "pattern requires at least %lu elements but " + "array has %lu", + (unsigned long) pattern_min_cap, + (unsigned long) cap_wi); + break; + } + } break; } + break; } case TyTy::SLICE: @@ -694,10 +908,32 @@ TypeCheckPattern::visit (HIR::SlicePattern &pattern) infered->set_ref (pattern.get_mappings ().get_hirid ()); // Type check every item in the SlicePattern against parent's element ty - // TODO update this after adding support for RestPattern in SlicePattern - for (const auto &item : pattern.get_items ()) + switch (pattern.get_items ().get_item_type ()) { - TypeCheckPattern::Resolve (*item, parent_element_ty); + case HIR::SlicePatternItems::ItemType::NO_REST: + { + auto &ref + = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ()); + for (const auto &pattern_member : ref.get_patterns ()) + { + TypeCheckPattern::Resolve (*pattern_member, parent_element_ty); + } + break; + } + case HIR::SlicePatternItems::ItemType::HAS_REST: + { + auto &ref + = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ()); + for (const auto &pattern_member : ref.get_lower_patterns ()) + { + TypeCheckPattern::Resolve (*pattern_member, parent_element_ty); + } + for (const auto &pattern_member : ref.get_upper_patterns ()) + { + TypeCheckPattern::Resolve (*pattern_member, parent_element_ty); + } + break; + } } } @@ -814,6 +1050,11 @@ ClosureParamInfer::visit (HIR::WildcardPattern &pattern) void ClosureParamInfer::visit (HIR::IdentifierPattern &pattern) { + if (pattern.has_subpattern ()) + { + ClosureParamInfer::Resolve (pattern.get_subpattern ()); + } + HirId id = pattern.get_mappings ().get_hirid (); infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, TyTy::InferType::TypeHint::Default (), diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index 4ef8348..eb44279 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -214,8 +214,7 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) rust_assert (ok); adtFieldIndexToField[field_index] = implicit_field; - struct_expr.get_fields ().push_back ( - std::unique_ptr<HIR::StructExprField> (implicit_field)); + struct_expr.get_fields ().emplace_back (implicit_field); } } } @@ -245,11 +244,11 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) field.release (); std::vector<std::unique_ptr<HIR::StructExprField> > ordered_fields; + ordered_fields.reserve (adtFieldIndexToField.size ()); + for (size_t i = 0; i < adtFieldIndexToField.size (); i++) - { - ordered_fields.push_back ( - std::unique_ptr<HIR::StructExprField> (adtFieldIndexToField[i])); - } + ordered_fields.emplace_back (adtFieldIndexToField[i]); + struct_expr.set_fields_as_owner (std::move (ordered_fields)); } diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 78037bd..799efc8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -97,15 +97,20 @@ TypeCheckType::visit (HIR::BareFunctionType &fntype) } std::vector<TyTy::TyVar> params; + params.reserve (fntype.get_function_params ().size ()); + for (auto ¶m : fntype.get_function_params ()) { TyTy::BaseType *ptype = TypeCheckType::Resolve (param.get_type ()); - params.push_back (TyTy::TyVar (ptype->get_ref ())); + params.emplace_back (ptype->get_ref ()); } - translated = new TyTy::FnPtr (fntype.get_mappings ().get_hirid (), - fntype.get_locus (), std::move (params), - TyTy::TyVar (return_type->get_ref ())); + translated + = new TyTy::FnPtr (fntype.get_mappings ().get_hirid (), fntype.get_locus (), + std::move (params), + TyTy::TyVar (return_type->get_ref ()), + fntype.get_function_qualifiers ().get_abi (), + fntype.get_function_qualifiers ().get_unsafety ()); } void @@ -118,10 +123,12 @@ TypeCheckType::visit (HIR::TupleType &tuple) } std::vector<TyTy::TyVar> fields; + fields.reserve (tuple.get_elems ().size ()); + for (auto &elem : tuple.get_elems ()) { auto field_ty = TypeCheckType::Resolve (*elem); - fields.push_back (TyTy::TyVar (field_ty->get_ref ())); + fields.emplace_back (field_ty->get_ref ()); } translated = new TyTy::TupleType (tuple.get_mappings ().get_hirid (), @@ -207,9 +214,9 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path) // lookup the associated item from the specified bound HIR::TypePathSegment &item_seg = path.get_associated_segment (); HIR::PathIdentSegment item_seg_identifier = item_seg.get_ident_segment (); - TyTy::TypeBoundPredicateItem item + tl::optional<TyTy::TypeBoundPredicateItem> item = specified_bound.lookup_associated_item (item_seg_identifier.as_string ()); - if (item.is_error ()) + if (!item.has_value ()) { std::string item_seg_ident_name, rich_msg; item_seg_ident_name = qual_path_type.get_trait ().as_string (); @@ -261,7 +268,7 @@ TypeCheckType::visit (HIR::QualifiedPathInType &path) // and we dont need to worry if the trait item is actually implemented or // not because this will have already been validated as part of the trait // impl block - translated = item.get_tyty_for_receiver (root); + translated = item->get_tyty_for_receiver (root); } else { @@ -699,38 +706,47 @@ TypeCheckType::visit (HIR::ArrayType &type) rust_assert (ok); context->insert_type (type.get_size_expr ().get_mappings (), expected_ty); - TyTy::ConstType *const_type = nullptr; + TyTy::BaseConstType *const_type = nullptr; if (capacity_type->get_kind () == TyTy::TypeKind::CONST) { - const_type = static_cast<TyTy::ConstType *> (capacity_type); + const_type = capacity_type->as_const_type (); unify_site (type.get_size_expr ().get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty), - TyTy::TyWithLocation (const_type->get_ty (), + TyTy::TyWithLocation (const_type->get_specified_type (), type.get_size_expr ().get_locus ()), type.get_size_expr ().get_locus ()); } else { HirId size_id = type.get_size_expr ().get_mappings ().get_hirid (); - unify_site (size_id, TyTy::TyWithLocation (expected_ty), - TyTy::TyWithLocation (capacity_type, - type.get_size_expr ().get_locus ()), - type.get_size_expr ().get_locus ()); - - auto ctx = Compile::Context::get (); - tree capacity_expr = Compile::HIRCompileBase::query_compile_const_expr ( - ctx, capacity_type, type.get_size_expr ()); - - const_type = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", - expected_ty, capacity_expr, {}, - type.get_size_expr ().get_locus (), - size_id, size_id); + TyTy::BaseType *result + = unify_site (size_id, TyTy::TyWithLocation (expected_ty), + TyTy::TyWithLocation (capacity_type, + type.get_size_expr ().get_locus ()), + type.get_size_expr ().get_locus ()); + + if (result->is<TyTy::ErrorType> ()) + const_type = new TyTy::ConstErrorType (expected_ty, size_id, size_id); + else + { + auto ctx = Compile::Context::get (); + tree capacity_expr + = Compile::HIRCompileBase::query_compile_const_expr ( + ctx, capacity_type, type.get_size_expr ()); + + const_type = new TyTy::ConstValueType (capacity_expr, expected_ty, + size_id, size_id); + context->insert_type (type.get_size_expr ().get_mappings (), + const_type->as_base_type ()); + } } translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (), - const_type, TyTy::TyVar (element_type->get_ref ())); + TyTy::TyVar ( + const_type->as_base_type ()->get_ty_ref ()), + TyTy::TyVar (element_type->get_ref ())); } void diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index aba4ab5..64f4314 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -260,7 +260,7 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const } context->insert_type (self_param.get_mappings (), self_type); - params.push_back (TyTy::FnParam (std::move (self_pattern), self_type)); + params.emplace_back (std::move (self_pattern), self_type); } for (auto ¶m : function.get_function_params ()) @@ -270,8 +270,8 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const context->insert_type (param.get_mappings (), param_tyty); TypeCheckPattern::Resolve (param.get_param_name (), param_tyty); // FIXME: Should we take the name ? Use a shared pointer instead ? - params.push_back ( - TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty)); + params.emplace_back (param.get_param_name ().clone_pattern (), + param_tyty); } auto &nr_ctx diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc index c5b823e..238ede4 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.cc +++ b/gcc/rust/typecheck/rust-substitution-mapper.cc @@ -268,12 +268,30 @@ SubstMapperInternal::visit (TyTy::ParamType &type) } void -SubstMapperInternal::visit (TyTy::ConstType &type) +SubstMapperInternal::visit (TyTy::ConstParamType &type) { resolved = type.handle_substitions (mappings); } void +SubstMapperInternal::visit (TyTy::ConstValueType &type) +{ + resolved = type.clone (); +} + +void +SubstMapperInternal::visit (TyTy::ConstInferType &type) +{ + resolved = type.clone (); +} + +void +SubstMapperInternal::visit (TyTy::ConstErrorType &type) +{ + resolved = type.clone (); +} + +void SubstMapperInternal::visit (TyTy::PlaceholderType &type) { rust_assert (type.can_resolve ()); @@ -310,15 +328,15 @@ SubstMapperInternal::visit (TyTy::SliceType &type) { resolved = type.handle_substitions (mappings); } - -// nothing to do for these void -SubstMapperInternal::visit (TyTy::InferType &type) +SubstMapperInternal::visit (TyTy::FnPtr &type) { - resolved = type.clone (); + resolved = type.handle_substitions (mappings); } + +// nothing to do for these void -SubstMapperInternal::visit (TyTy::FnPtr &type) +SubstMapperInternal::visit (TyTy::InferType &type) { resolved = type.clone (); } diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index 2389d83..98f9e72 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -61,7 +61,10 @@ public: void visit (TyTy::ReferenceType &) override { rust_unreachable (); } void visit (TyTy::PointerType &) override { rust_unreachable (); } void visit (TyTy::ParamType &) override { rust_unreachable (); } - void visit (TyTy::ConstType &) override { rust_unreachable (); } + void visit (TyTy::ConstParamType &) override { rust_unreachable (); } + void visit (TyTy::ConstValueType &) override { rust_unreachable (); } + void visit (TyTy::ConstInferType &) override { rust_unreachable (); } + void visit (TyTy::ConstErrorType &) override { rust_unreachable (); } void visit (TyTy::StrType &) override { rust_unreachable (); } void visit (TyTy::NeverType &) override { rust_unreachable (); } void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); } @@ -93,7 +96,10 @@ public: void visit (TyTy::ReferenceType &type) override; void visit (TyTy::PointerType &type) override; void visit (TyTy::ParamType &type) override; - void visit (TyTy::ConstType &type) override; + void visit (TyTy::ConstParamType &type) override; + void visit (TyTy::ConstValueType &type) override; + void visit (TyTy::ConstInferType &type) override; + void visit (TyTy::ConstErrorType &type) override; void visit (TyTy::PlaceholderType &type) override; void visit (TyTy::ProjectionType &type) override; void visit (TyTy::ClosureType &type) override; @@ -147,13 +153,16 @@ public: void visit (TyTy::ReferenceType &) override { rust_unreachable (); } void visit (TyTy::PointerType &) override { rust_unreachable (); } void visit (TyTy::ParamType &) override { rust_unreachable (); } - void visit (TyTy::ConstType &) override { rust_unreachable (); } + void visit (TyTy::ConstParamType &) override { rust_unreachable (); } + void visit (TyTy::ConstValueType &) override { rust_unreachable (); } + void visit (TyTy::ConstInferType &) override { rust_unreachable (); } + void visit (TyTy::ConstErrorType &) override { rust_unreachable (); } void visit (TyTy::StrType &) override { rust_unreachable (); } void visit (TyTy::NeverType &) override { rust_unreachable (); } void visit (TyTy::PlaceholderType &) override { rust_unreachable (); } void visit (TyTy::ProjectionType &) override { rust_unreachable (); } void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); } - void visit (TyTy::OpaqueType &type) override { rust_unreachable (); } + void visit (TyTy::OpaqueType &) override { rust_unreachable (); } private: SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver); @@ -188,7 +197,10 @@ public: void visit (const TyTy::ReferenceType &) override {} void visit (const TyTy::PointerType &) override {} void visit (const TyTy::ParamType &) override {} - void visit (const TyTy::ConstType &) override {} + void visit (const TyTy::ConstParamType &) override {} + void visit (const TyTy::ConstValueType &) override {} + void visit (const TyTy::ConstInferType &) override {} + void visit (const TyTy::ConstErrorType &) override {} void visit (const TyTy::StrType &) override {} void visit (const TyTy::NeverType &) override {} void visit (const TyTy::PlaceholderType &) override {} diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc index 2d66166..6f30ebf 100644 --- a/gcc/rust/typecheck/rust-type-util.cc +++ b/gcc/rust/typecheck/rust-type-util.cc @@ -152,11 +152,12 @@ query_type (HirId reference, TyTy::BaseType **result) bool types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t unify_locus, bool emit_errors) + location_t unify_locus, bool emit_errors, bool check_bounds) { TyTy::BaseType *result = unify_site_and (UNKNOWN_HIRID, lhs, rhs, unify_locus, emit_errors, - false /*commit*/, true /*infer*/, true /*cleanup*/); + false /*commit*/, true /*infer*/, true /*cleanup*/, + check_bounds); return result->get_kind () != TyTy::TypeKind::ERROR; } @@ -173,32 +174,34 @@ unify_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, std::vector<UnifyRules::CommitSite> commits; std::vector<UnifyRules::InferenceSite> infers; return UnifyRules::Resolve (lhs, rhs, unify_locus, true /*commit*/, - true /*emit_error*/, false /*infer*/, commits, - infers); + true /*emit_error*/, false /*infer*/, + true /*check_bounds*/, commits, infers); } 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) + bool implicit_infer_vars, bool cleanup, bool check_bounds) { TypeCheckContext &context = *TypeCheckContext::get (); TyTy::BaseType *expected = lhs.get_ty (); TyTy::BaseType *expr = rhs.get_ty (); - rust_debug_loc ( - unify_locus, - "begin unify_site_and commit %s infer %s id={%u} expected={%s} expr={%s}", - commit_if_ok ? "true" : "false", implicit_infer_vars ? "true" : "false", - id == UNKNOWN_HIRID ? 0 : id, expected->debug_str ().c_str (), - expr->debug_str ().c_str ()); + rust_debug_loc (unify_locus, + "begin unify_site_and commit %s infer %s check_bounds %s " + "id={%u} expected={%s} expr={%s}", + commit_if_ok ? "true" : "false", + implicit_infer_vars ? "true" : "false", + check_bounds ? "true" : "false", id == UNKNOWN_HIRID ? 0 : id, + expected->debug_str ().c_str (), expr->debug_str ().c_str ()); std::vector<UnifyRules::CommitSite> commits; std::vector<UnifyRules::InferenceSite> infers; TyTy::BaseType *result = UnifyRules::Resolve (lhs, rhs, unify_locus, false /*commit inline*/, - emit_errors, implicit_infer_vars, commits, infers); + emit_errors, implicit_infer_vars, check_bounds, + commits, infers); bool ok = result->get_kind () != TyTy::TypeKind::ERROR; rust_debug_loc (unify_locus, @@ -228,7 +231,8 @@ unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, // remove the inference variable context.clear_type (i.infer); - delete i.infer; + // FIXME: Don't delete - result might point to this + // delete i.infer; } } return result; @@ -325,7 +329,7 @@ cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to, AssociatedImplTrait * lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound, - const TyTy::BaseType *binding, bool *ambigious) + TyTy::BaseType *binding, bool *ambigious) { auto context = TypeCheckContext::get (); diff --git a/gcc/rust/typecheck/rust-type-util.h b/gcc/rust/typecheck/rust-type-util.h index dd97f1e..7f4a94e 100644 --- a/gcc/rust/typecheck/rust-type-util.h +++ b/gcc/rust/typecheck/rust-type-util.h @@ -28,7 +28,8 @@ namespace Resolver { bool query_type (HirId reference, TyTy::BaseType **result); bool types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, - location_t unify_locus, bool emit_errors); + location_t unify_locus, bool emit_errors, + bool check_bounds = true); TyTy::BaseType *unify_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, location_t unify_locus); @@ -37,7 +38,7 @@ 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); + bool cleanup, bool check_bounds = true); TyTy::BaseType *coercion_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, @@ -52,7 +53,7 @@ TyTy::BaseType *cast_site (HirId id, TyTy::TyWithLocation from, AssociatedImplTrait * lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound, - const TyTy::BaseType *binding, + TyTy::BaseType *binding, bool *ambigious = nullptr); } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc index c74a920..3419ef6 100644 --- a/gcc/rust/typecheck/rust-typecheck-context.cc +++ b/gcc/rust/typecheck/rust-typecheck-context.cc @@ -154,7 +154,7 @@ void TypeCheckContext::push_return_type (TypeCheckContextItem item, TyTy::BaseType *return_type) { - return_type_stack.push_back ({std::move (item), return_type}); + return_type_stack.emplace_back (std::move (item), return_type); } void @@ -310,7 +310,7 @@ TypeCheckContext::insert_associated_impl_mapping (HirId trait_id, associated_traits_to_impls[trait_id] = {}; } - associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id}); + associated_traits_to_impls[trait_id].emplace_back (impl_type, impl_id); } bool diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc index 6cf9b04..a59de99 100644 --- a/gcc/rust/typecheck/rust-tyty-bounds.cc +++ b/gcc/rust/typecheck/rust-tyty-bounds.cc @@ -26,12 +26,12 @@ namespace Rust { namespace Resolver { -TypeBoundsProbe::TypeBoundsProbe (const TyTy::BaseType *receiver) +TypeBoundsProbe::TypeBoundsProbe (TyTy::BaseType *receiver) : TypeCheckBase (), receiver (receiver) {} std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> -TypeBoundsProbe::Probe (const TyTy::BaseType *receiver) +TypeBoundsProbe::Probe (TyTy::BaseType *receiver) { TypeBoundsProbe probe (receiver); probe.scan (); @@ -75,22 +75,18 @@ TypeBoundsProbe::process_impl_block ( HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ()); if (t == nullptr) return true; - // DefId trait_id = t->get_mappings ().get_defid (); - // if (context->trait_query_in_progress (trait_id)) - // return true; HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid (); TyTy::BaseType *impl_type = nullptr; if (!query_type (impl_ty_id, &impl_type)) return true; - if (!receiver->can_eq (impl_type, false)) - { - if (!impl_type->can_eq (receiver, false)) - return true; - } + if (!types_compatable (TyTy::TyWithLocation (receiver), + TyTy::TyWithLocation (impl_type), impl->get_locus (), + false /*emit_errors*/, false /*check-bounds*/)) + return true; - possible_trait_paths.push_back ({&impl->get_trait_ref (), impl}); + possible_trait_paths.emplace_back (&impl->get_trait_ref (), impl); return true; } @@ -110,7 +106,7 @@ TypeBoundsProbe::scan () TraitReference *trait_ref = TraitResolver::Resolve (*trait_path); if (!trait_ref->is_error ()) - trait_references.push_back ({trait_ref, path.second}); + trait_references.emplace_back (trait_ref, path.second); } // marker traits... @@ -185,7 +181,7 @@ TypeBoundsProbe::add_trait_bound (HIR::Trait *trait) { auto trait_ref = TraitResolver::Resolve (*trait); - trait_references.push_back ({trait_ref, mappings.lookup_builtin_marker ()}); + trait_references.emplace_back (trait_ref, mappings.lookup_builtin_marker ()); } void @@ -306,11 +302,9 @@ TypeCheckBase::get_predicate_from_bound ( std::vector<HIR::GenericArgsBinding> bindings; location_t output_locus = fn.get_return_type ().get_locus (); - HIR::GenericArgsBinding binding (Identifier ( - trait_item->trait_identifier ()), - fn.get_return_type ().clone_type (), - output_locus); - bindings.push_back (std::move (binding)); + bindings.emplace_back (Identifier (trait_item->trait_identifier ()), + fn.get_return_type ().clone_type (), + output_locus); args = HIR::GenericArgs ({} /* lifetimes */, std::move (inputs) /* type_args*/, @@ -468,8 +462,8 @@ TypeBoundPredicate::operator= (const TypeBoundPredicate &other) { TyTy::BaseType *argument = m.get_tyty () == nullptr ? nullptr : m.get_tyty ()->clone (); - SubstitutionArg c (&substitutions.at (i++), argument); - copied_arg_mappings.push_back (std::move (c)); + + copied_arg_mappings.emplace_back (&substitutions.at (i++), argument); } used_arguments @@ -577,10 +571,13 @@ TypeBoundPredicate::apply_argument_mappings ( std::string identifier = it.first; TyTy::BaseType *type = it.second; - TypeBoundPredicateItem item = lookup_associated_item (identifier); - rust_assert (!item.is_error ()); + tl::optional<TypeBoundPredicateItem> item + = lookup_associated_item (identifier); - const auto item_ref = item.get_raw_item (); + if (!item.has_value ()) + continue; + + const auto item_ref = item->get_raw_item (); item_ref->associated_type_set (type); } @@ -601,7 +598,7 @@ TypeBoundPredicate::contains_item (const std::string &search) const return trait_ref->lookup_trait_item (search, &trait_item_ref); } -TypeBoundPredicateItem +tl::optional<TypeBoundPredicateItem> TypeBoundPredicate::lookup_associated_item (const std::string &search) const { auto trait_ref = get (); @@ -613,11 +610,11 @@ TypeBoundPredicate::lookup_associated_item (const std::string &search) const for (auto &super_trait : super_traits) { auto lookup = super_trait.lookup_associated_item (search); - if (!lookup.is_error ()) + if (lookup.has_value ()) return lookup; } - return TypeBoundPredicateItem::error (); + return tl::nullopt; } TypeBoundPredicateItem::TypeBoundPredicateItem ( @@ -658,7 +655,7 @@ TypeBoundPredicateItem::get_parent () const return &parent; } -TypeBoundPredicateItem +tl::optional<TypeBoundPredicateItem> TypeBoundPredicate::lookup_associated_item ( const Resolver::TraitItemReference *ref) const { @@ -691,8 +688,7 @@ TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver) TyTy::BaseType *argument = is_implicit_self ? receiver->clone () : mapping.get_tyty (); - SubstitutionArg arg (mapping.get_param_mapping (), argument); - adjusted_mappings.push_back (std::move (arg)); + adjusted_mappings.emplace_back (mapping.get_param_mapping (), argument); } SubstitutionArgumentMappings adjusted (adjusted_mappings, {}, @@ -735,10 +731,11 @@ TypeBoundPredicate::handle_substitions ( std::string identifier = it.first; TyTy::BaseType *type = it.second; - TypeBoundPredicateItem item = lookup_associated_item (identifier); - if (!item.is_error ()) + tl::optional<TypeBoundPredicateItem> item + = lookup_associated_item (identifier); + if (item.has_value ()) { - const auto item_ref = item.get_raw_item (); + const auto item_ref = item->get_raw_item (); item_ref->associated_type_set (type); } } @@ -802,18 +799,18 @@ TypeBoundPredicate::get_trait_hierachy ( TypeBoundPredicateItem TypeBoundPredicate::lookup_associated_type (const std::string &search) { - TypeBoundPredicateItem item = lookup_associated_item (search); + tl::optional<TypeBoundPredicateItem> item = lookup_associated_item (search); // only need to check that it is infact an associated type because other // wise if it was not found it will just be an error node anyway - if (!item.is_error ()) + if (item.has_value ()) { - const auto raw = item.get_raw_item (); + const auto raw = item->get_raw_item (); if (raw->get_trait_item_type () != Resolver::TraitItemReference::TraitItemType::TYPE) return TypeBoundPredicateItem::error (); } - return item; + return item.value (); } std::vector<TypeBoundPredicateItem> @@ -827,10 +824,7 @@ TypeBoundPredicate::get_associated_type_items () = trait_item.get_trait_item_type () == Resolver::TraitItemReference::TraitItemType::TYPE; if (is_associated_type) - { - TypeBoundPredicateItem item (*this, &trait_item); - items.push_back (std::move (item)); - } + items.emplace_back (*this, &trait_item); } return items; } diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc index 63bb1ff..e82e618 100644 --- a/gcc/rust/typecheck/rust-tyty-call.cc +++ b/gcc/rust/typecheck/rust-tyty-call.cc @@ -59,7 +59,7 @@ TypeCheckCallExpr::visit (ADTType &type) if (variant.get_variant_type () != TyTy::VariantDef::VariantType::TUPLE) { rust_error_at ( - call.get_locus (), ErrorCode::E0423, + call.get_locus (), ErrorCode::E0618, "expected function, tuple struct or tuple variant, found struct %qs", type.get_name ().c_str ()); return; @@ -327,8 +327,8 @@ TypeCheckMethodCallExpr::go (FnType *ref, HIR::MethodCallExpr &call, return new ErrorType (ref->get_ref ()); } - Argument a (arg->get_mappings (), argument_expr_tyty, arg->get_locus ()); - args.push_back (std::move (a)); + args.emplace_back (arg->get_mappings (), argument_expr_tyty, + arg->get_locus ()); } TypeCheckMethodCallExpr checker (call.get_mappings (), args, diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h index 9e4aab5..025a1ad 100644 --- a/gcc/rust/typecheck/rust-tyty-call.h +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -60,9 +60,12 @@ public: void visit (PlaceholderType &) override { rust_unreachable (); } void visit (ProjectionType &) override { rust_unreachable (); } void visit (DynamicObjectType &) override { rust_unreachable (); } - void visit (ClosureType &type) override { rust_unreachable (); } - void visit (OpaqueType &type) override { rust_unreachable (); } - void visit (ConstType &type) override { rust_unreachable (); } + void visit (ClosureType &) override { rust_unreachable (); } + void visit (OpaqueType &) override { rust_unreachable (); } + void visit (ConstParamType &) override { rust_unreachable (); } + void visit (ConstValueType &) override { rust_unreachable (); } + void visit (ConstInferType &) override { rust_unreachable (); } + void visit (ConstErrorType &) override { rust_unreachable (); } // tuple-structs void visit (ADTType &type) override; diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h deleted file mode 100644 index c22dfdd..0000000 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ /dev/null @@ -1,1645 +0,0 @@ -// Copyright (C) 2020-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_TYTY_CMP_H -#define RUST_TYTY_CMP_H - -#include "rust-diagnostics.h" -#include "rust-tyty.h" -#include "rust-tyty-visitor.h" -#include "rust-hir-map.h" -#include "rust-hir-type-check.h" - -namespace Rust { -namespace TyTy { - -class BaseCmp : public TyConstVisitor -{ -public: - virtual bool can_eq (const BaseType *other) - { - if (other->get_kind () == TypeKind::PARAM) - { - const ParamType *p = static_cast<const ParamType *> (other); - other = p->resolve (); - } - if (other->get_kind () == TypeKind::PLACEHOLDER) - { - const PlaceholderType *p = static_cast<const PlaceholderType *> (other); - if (p->can_resolve ()) - { - other = p->resolve (); - } - } - if (other->get_kind () == TypeKind::PROJECTION) - { - const ProjectionType *p = static_cast<const ProjectionType *> (other); - other = p->get (); - } - - other->accept_vis (*this); - return ok; - } - - virtual void visit (const TupleType &type) override - { - ok = false; - - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ADTType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const InferType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const FnType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const FnPtr &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ArrayType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const SliceType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const BoolType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const IntType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const UintType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const USizeType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ISizeType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const FloatType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ErrorType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const CharType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ReferenceType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const PointerType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const StrType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const NeverType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ProjectionType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const PlaceholderType &type) override - { - // it is ok for types to can eq to a placeholder - ok = true; - } - - virtual void visit (const ParamType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const DynamicObjectType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ClosureType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const OpaqueType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - - virtual void visit (const ConstType &type) override - { - ok = false; - if (emit_error_flag) - { - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - location_t base_locus - = mappings.lookup_location (get_base ()->get_ref ()); - rich_location r (line_table, ref_locus); - r.add_range (base_locus); - rust_error_at (r, "expected [%s] got [%s]", - get_base ()->as_string ().c_str (), - type.as_string ().c_str ()); - } - } - -protected: - BaseCmp (const BaseType *base, bool emit_errors) - : mappings (Analysis::Mappings::get ()), - context (Resolver::TypeCheckContext::get ()), ok (false), - emit_error_flag (emit_errors) - {} - - Analysis::Mappings &mappings; - Resolver::TypeCheckContext *context; - - bool ok; - bool emit_error_flag; - -private: - /* Returns a pointer to the ty that created this rule. */ - virtual const BaseType *get_base () const = 0; -}; - -class InferCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - InferCmp (const InferType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const BoolType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const IntType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const UintType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const USizeType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const ISizeType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () - == TyTy::InferType::InferTypeKind::INTEGRAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const FloatType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL) - || (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const ArrayType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const SliceType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const ADTType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const TupleType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const InferType &type) override - { - switch (base->get_infer_kind ()) - { - case InferType::InferTypeKind::GENERAL: - ok = true; - return; - - case InferType::InferTypeKind::INTEGRAL: - { - if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL) - { - ok = true; - return; - } - else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL) - { - ok = true; - return; - } - } - break; - - case InferType::InferTypeKind::FLOAT: - { - if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT) - { - ok = true; - return; - } - else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL) - { - ok = true; - return; - } - } - break; - } - - BaseCmp::visit (type); - } - - void visit (const CharType &type) override - { - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - } - - void visit (const ReferenceType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const PointerType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const ParamType &) override { ok = true; } - - void visit (const DynamicObjectType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - - void visit (const ClosureType &type) override - { - bool is_valid - = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); - if (is_valid) - { - ok = true; - return; - } - - BaseCmp::visit (type); - } - -private: - const BaseType *get_base () const override { return base; } - const InferType *base; -}; - -class FnCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - FnCmp (const FnType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL; - } - - void visit (const FnType &type) override - { - if (base->num_params () != type.num_params ()) - { - BaseCmp::visit (type); - return; - } - - for (size_t i = 0; i < base->num_params (); i++) - { - auto a = base->param_at (i).get_type (); - auto b = type.param_at (i).get_type (); - - if (!a->can_eq (b, emit_error_flag)) - { - emit_error_flag = false; - BaseCmp::visit (type); - return; - } - } - - if (!base->get_return_type ()->can_eq (type.get_return_type (), - emit_error_flag)) - { - emit_error_flag = false; - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const FnType *base; -}; - -class FnptrCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - FnptrCmp (const FnPtr *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - - void visit (const FnPtr &type) override - { - if (base->num_params () != type.num_params ()) - { - BaseCmp::visit (type); - return; - } - - auto this_ret_type = base->get_return_type (); - auto other_ret_type = type.get_return_type (); - if (!this_ret_type->can_eq (other_ret_type, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - - for (size_t i = 0; i < base->num_params (); i++) - { - auto this_param = base->get_param_type_at (i); - auto other_param = type.get_param_type_at (i); - if (!this_param->can_eq (other_param, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - } - - ok = true; - } - - void visit (const FnType &type) override - { - if (base->num_params () != type.num_params ()) - { - BaseCmp::visit (type); - return; - } - - auto this_ret_type = base->get_return_type (); - auto other_ret_type = type.get_return_type (); - if (!this_ret_type->can_eq (other_ret_type, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - - for (size_t i = 0; i < base->num_params (); i++) - { - auto this_param = base->get_param_type_at (i); - auto other_param = type.param_at (i).get_type (); - if (!this_param->can_eq (other_param, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const FnPtr *base; -}; - -class ClosureCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ClosureCmp (const ClosureType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - - void visit (const ClosureType &type) override - { - if (base->get_def_id () != type.get_def_id ()) - { - BaseCmp::visit (type); - return; - } - - if (!base->get_parameters ().can_eq (&type.get_parameters (), false)) - { - BaseCmp::visit (type); - return; - } - - if (!base->get_result_type ().can_eq (&type.get_result_type (), false)) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const ClosureType *base; -}; - -class ArrayCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ArrayCmp (const ArrayType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const ArrayType &type) override - { - // check base type - const BaseType *base_element = base->get_element_type (); - const BaseType *other_element = type.get_element_type (); - if (!base_element->can_eq (other_element, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const ArrayType *base; -}; - -class SliceCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - SliceCmp (const SliceType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const SliceType &type) override - { - // check base type - const BaseType *base_element = base->get_element_type (); - const BaseType *other_element = type.get_element_type (); - if (!base_element->can_eq (other_element, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const SliceType *base; -}; - -class BoolCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - BoolCmp (const BoolType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const BoolType &type) override { ok = true; } - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL; - } - -private: - const BaseType *get_base () const override { return base; } - const BoolType *base; -}; - -class IntCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - IntCmp (const IntType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () != InferType::InferTypeKind::FLOAT; - } - - void visit (const IntType &type) override - { - ok = type.get_int_kind () == base->get_int_kind (); - } - -private: - const BaseType *get_base () const override { return base; } - const IntType *base; -}; - -class UintCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - UintCmp (const UintType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () != InferType::InferTypeKind::FLOAT; - } - - void visit (const UintType &type) override - { - ok = type.get_uint_kind () == base->get_uint_kind (); - } - -private: - const BaseType *get_base () const override { return base; } - const UintType *base; -}; - -class FloatCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - FloatCmp (const FloatType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () != InferType::InferTypeKind::INTEGRAL; - } - - void visit (const FloatType &type) override - { - ok = type.get_float_kind () == base->get_float_kind (); - } - -private: - const BaseType *get_base () const override { return base; } - const FloatType *base; -}; - -class ADTCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ADTCmp (const ADTType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const ADTType &type) override - { - if (base->get_adt_kind () != type.get_adt_kind ()) - { - BaseCmp::visit (type); - return; - } - - if (base->get_identifier ().compare (type.get_identifier ()) != 0) - { - BaseCmp::visit (type); - return; - } - - if (base->number_of_variants () != type.number_of_variants ()) - { - BaseCmp::visit (type); - return; - } - - for (size_t i = 0; i < type.number_of_variants (); ++i) - { - TyTy::VariantDef *a = base->get_variants ().at (i); - TyTy::VariantDef *b = type.get_variants ().at (i); - - if (a->num_fields () != b->num_fields ()) - { - BaseCmp::visit (type); - return; - } - - for (size_t j = 0; j < a->num_fields (); j++) - { - TyTy::StructFieldType *base_field = a->get_field_at_index (j); - TyTy::StructFieldType *other_field = b->get_field_at_index (j); - - TyTy::BaseType *this_field_ty = base_field->get_field_type (); - TyTy::BaseType *other_field_ty = other_field->get_field_type (); - - if (!this_field_ty->can_eq (other_field_ty, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - } - } - - ok = true; - } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const ADTType *base; -}; - -class TupleCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - TupleCmp (const TupleType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const TupleType &type) override - { - if (base->num_fields () != type.num_fields ()) - { - BaseCmp::visit (type); - return; - } - - for (size_t i = 0; i < base->num_fields (); i++) - { - BaseType *bo = base->get_field (i); - BaseType *fo = type.get_field (i); - - if (!bo->can_eq (fo, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - } - - ok = true; - } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const TupleType *base; -}; - -class USizeCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - USizeCmp (const USizeType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () != InferType::InferTypeKind::FLOAT; - } - - void visit (const USizeType &type) override { ok = true; } - -private: - const BaseType *get_base () const override { return base; } - const USizeType *base; -}; - -class ISizeCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ISizeCmp (const ISizeType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () != InferType::InferTypeKind::FLOAT; - } - - void visit (const ISizeType &type) override { ok = true; } - -private: - const BaseType *get_base () const override { return base; } - const ISizeType *base; -}; - -class CharCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - CharCmp (const CharType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const InferType &type) override - { - ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL; - } - - void visit (const CharType &type) override { ok = true; } - -private: - const BaseType *get_base () const override { return base; } - const CharType *base; -}; - -class ReferenceCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ReferenceCmp (const ReferenceType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const ReferenceType &type) override - { - auto base_type = base->get_base (); - auto other_base_type = type.get_base (); - - bool mutability_ok = base->is_mutable () ? type.is_mutable () : true; - if (!mutability_ok) - { - BaseCmp::visit (type); - return; - } - - if (!base_type->can_eq (other_base_type, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const ReferenceType *base; -}; - -class PointerCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - PointerCmp (const PointerType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const PointerType &type) override - { - auto base_type = base->get_base (); - auto other_base_type = type.get_base (); - - bool mutability_ok = base->is_mutable () ? type.is_mutable () : true; - if (!mutability_ok) - { - BaseCmp::visit (type); - return; - } - - if (!base_type->can_eq (other_base_type, emit_error_flag)) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const PointerType *base; -}; - -class ParamCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ParamCmp (const ParamType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - // param types are a placeholder we shouldn't have cases where we unify - // against it. eg: struct foo<T> { a: T }; When we invoke it we can do either: - // - // foo<i32>{ a: 123 }. - // Then this enforces the i32 type to be referenced on the - // field via an hirid. - // - // rust also allows for a = foo{a:123}; Where we can use an Inference Variable - // to handle the typing of the struct - bool can_eq (const BaseType *other) override - { - if (!base->can_resolve ()) - return BaseCmp::can_eq (other); - - auto lookup = base->resolve (); - return lookup->can_eq (other, emit_error_flag); - } - - // imagine the case where we have: - // struct Foo<T>(T); - // Then we declare a generic impl block - // impl <X>Foo<X> { ... } - // both of these types are compatible so we mostly care about the number of - // generic arguments - void visit (const ParamType &) override { ok = true; } - - void visit (const TupleType &) override { ok = true; } - - void visit (const InferType &) override { ok = true; } - - void visit (const FnType &) override { ok = true; } - - void visit (const FnPtr &) override { ok = true; } - - void visit (const ADTType &) override { ok = true; } - - void visit (const ArrayType &) override { ok = true; } - - void visit (const SliceType &) override { ok = true; } - - void visit (const BoolType &) override { ok = true; } - - void visit (const IntType &) override { ok = true; } - - void visit (const UintType &) override { ok = true; } - - void visit (const USizeType &) override { ok = true; } - - void visit (const ISizeType &) override { ok = true; } - - void visit (const FloatType &) override { ok = true; } - - void visit (const CharType &) override { ok = true; } - - void visit (const ReferenceType &) override { ok = true; } - - void visit (const PointerType &) override { ok = true; } - - void visit (const StrType &) override { ok = true; } - - void visit (const NeverType &) override { ok = true; } - - void visit (const DynamicObjectType &) override { ok = true; } - - void visit (const PlaceholderType &type) override - { - ok = base->get_symbol ().compare (type.get_symbol ()) == 0; - } - -private: - const BaseType *get_base () const override { return base; } - const ParamType *base; -}; - -class StrCmp : public BaseCmp -{ - // FIXME we will need a enum for the StrType like ByteBuf etc.. - using Rust::TyTy::BaseCmp::visit; - -public: - StrCmp (const StrType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const StrType &type) override { ok = true; } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const StrType *base; -}; - -class NeverCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - NeverCmp (const NeverType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const NeverType &type) override { ok = true; } - - void visit (const InferType &type) override - { - if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL) - { - BaseCmp::visit (type); - return; - } - - ok = true; - } - -private: - const BaseType *get_base () const override { return base; } - const NeverType *base; -}; - -class PlaceholderCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - PlaceholderCmp (const PlaceholderType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - bool can_eq (const BaseType *other) override - { - if (!base->can_resolve ()) - return BaseCmp::can_eq (other); - - BaseType *lookup = base->resolve (); - return lookup->can_eq (other, emit_error_flag); - } - - void visit (const TupleType &) override { ok = true; } - - void visit (const ADTType &) override { ok = true; } - - void visit (const InferType &) override { ok = true; } - - void visit (const FnType &) override { ok = true; } - - void visit (const FnPtr &) override { ok = true; } - - void visit (const ArrayType &) override { ok = true; } - - void visit (const BoolType &) override { ok = true; } - - void visit (const IntType &) override { ok = true; } - - void visit (const UintType &) override { ok = true; } - - void visit (const USizeType &) override { ok = true; } - - void visit (const ISizeType &) override { ok = true; } - - void visit (const FloatType &) override { ok = true; } - - void visit (const ErrorType &) override { ok = true; } - - void visit (const CharType &) override { ok = true; } - - void visit (const ReferenceType &) override { ok = true; } - - void visit (const ParamType &) override { ok = true; } - - void visit (const StrType &) override { ok = true; } - - void visit (const NeverType &) override { ok = true; } - - void visit (const SliceType &) override { ok = true; } - -private: - const BaseType *get_base () const override { return base; } - - const PlaceholderType *base; -}; - -class DynamicCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - DynamicCmp (const DynamicObjectType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - void visit (const DynamicObjectType &type) override - { - if (base->num_specified_bounds () != type.num_specified_bounds ()) - { - BaseCmp::visit (type); - return; - } - - location_t ref_locus = mappings.lookup_location (type.get_ref ()); - ok = base->bounds_compatible (type, ref_locus, false); - } - -private: - const BaseType *get_base () const override { return base; } - - const DynamicObjectType *base; -}; - -class OpaqueCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - OpaqueCmp (const OpaqueType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - // TODO - -private: - const BaseType *get_base () const override { return base; } - - const OpaqueType *base; -}; - -class ConstCmp : public BaseCmp -{ - using Rust::TyTy::BaseCmp::visit; - -public: - ConstCmp (const ConstType *base, bool emit_errors) - : BaseCmp (base, emit_errors), base (base) - {} - - // TODO - -private: - const BaseType *get_base () const override { return base; } - - const ConstType *base; -}; - -} // namespace TyTy -} // namespace Rust - -#endif // RUST_TYTY_CMP_H diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc index 817910b..e82e8a3 100644 --- a/gcc/rust/typecheck/rust-tyty-subst.cc +++ b/gcc/rust/typecheck/rust-tyty-subst.cc @@ -54,8 +54,8 @@ SubstitutionParamMapping::as_string () const SubstitutionParamMapping SubstitutionParamMapping::clone () const { - return SubstitutionParamMapping (generic, - static_cast<ParamType *> (param->clone ())); + return SubstitutionParamMapping (generic, static_cast<BaseGeneric *> ( + param->clone ())); } BaseGeneric * @@ -167,7 +167,12 @@ SubstitutionParamMapping::fill_param_ty ( } else if (type.get_kind () == TyTy::TypeKind::CONST) { - param = static_cast<BaseGeneric *> (type.clone ()); + rust_assert (param->get_kind () == TyTy::TypeKind::CONST); + auto *const_type = type.as_const_type (); + if (const_type->const_kind () == TyTy::BaseConstType::ConstKind::Decl) + param = static_cast<BaseGeneric *> (type.clone ()); + else + param->set_ty_ref (type.get_ref ()); } else if (param->get_kind () == TypeKind::PARAM) { @@ -554,6 +559,7 @@ std::vector<SubstitutionParamMapping> SubstitutionRef::clone_substs () const { std::vector<SubstitutionParamMapping> clone; + clone.reserve (substitutions.size ()); for (auto &sub : substitutions) clone.push_back (sub.clone ()); @@ -767,7 +773,7 @@ SubstitutionRef::get_mappings_from_generic_args ( } else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST) { - if (!resolved->is<ConstType> ()) + if (resolved->get_kind () != TyTy::TypeKind::CONST) { rich_location r (line_table, arg->get_locus ()); r.add_fixit_remove (arg->get_locus ()); @@ -777,9 +783,8 @@ SubstitutionRef::get_mappings_from_generic_args ( } } - SubstitutionArg subst_arg (¶m_mapping, resolved); + mappings.emplace_back (¶m_mapping, resolved); offs++; - mappings.push_back (std::move (subst_arg)); } for (auto &arg : args.get_const_args ()) @@ -802,40 +807,73 @@ SubstitutionRef::get_mappings_from_generic_args ( // get the const generic specified type const auto base_generic = param_mapping.get_param_ty (); - rust_assert (base_generic->is<ConstType> ()); + rust_assert (base_generic->get_kind () == TyTy::TypeKind::CONST); const auto const_param - = static_cast<const TyTy::ConstType *> (base_generic); - auto specified_type = const_param->get_ty (); + = static_cast<const TyTy::ConstParamType *> (base_generic); + auto specified_type = const_param->get_specified_type (); // validate this const generic is of the correct type - auto coereced_type - = Resolver::coercion_site (expr.get_mappings ().get_hirid (), - TyTy::TyWithLocation (specified_type), - TyTy::TyWithLocation (expr_type, - expr.get_locus ()), - arg.get_locus ()); - if (coereced_type->is<ErrorType> ()) - return SubstitutionArgumentMappings::error (); - - // const fold it - auto ctx = Compile::Context::get (); - tree folded - = Compile::HIRCompileBase::query_compile_const_expr (ctx, coereced_type, - expr); + TyTy::BaseType *coereced_type = nullptr; + if (expr_type->get_kind () == TyTy::TypeKind::CONST) + { + auto const_expr_type = expr_type->as_const_type (); + auto const_value_type = const_expr_type->get_specified_type (); + coereced_type + = Resolver::coercion_site (expr.get_mappings ().get_hirid (), + TyTy::TyWithLocation (specified_type), + TyTy::TyWithLocation (const_value_type, + expr.get_locus ()), + arg.get_locus ()); + } + else + { + coereced_type + = Resolver::coercion_site (expr.get_mappings ().get_hirid (), + TyTy::TyWithLocation (specified_type), + TyTy::TyWithLocation (expr_type, + expr.get_locus ()), + arg.get_locus ()); + } - if (folded == error_mark_node) + if (coereced_type == nullptr || coereced_type->is<ErrorType> ()) return SubstitutionArgumentMappings::error (); - // create const type - auto const_value - = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", - coereced_type, folded, {}, expr.get_locus (), - expr.get_mappings ().get_hirid (), - expr.get_mappings ().get_hirid (), {}); + TyTy::BaseType *const_value_ty = nullptr; + if (expr_type->get_kind () == TyTy::TypeKind::CONST) + const_value_ty = expr_type; + else + { + // const fold it if available + auto ctx = Compile::Context::get (); + tree folded + = Compile::HIRCompileBase::query_compile_const_expr (ctx, + coereced_type, + expr); + + if (folded == error_mark_node) + { + rich_location r (line_table, arg.get_locus ()); + r.add_range (expr.get_locus ()); + rust_error_at (r, "failed to resolve const expression"); + return SubstitutionArgumentMappings::error (); + } + + // Use a fresh HirId to avoid conflicts with the expr's type + auto &global_mappings = Analysis::Mappings::get (); + HirId const_value_id = global_mappings.get_next_hir_id (); + const_value_ty + = new TyTy::ConstValueType (folded, coereced_type, const_value_id, + const_value_id, {}); + + // Insert the ConstValueType into the context so it can be looked up + auto context = Resolver::TypeCheckContext::get (); + context->insert_type ( + Analysis::NodeMapping (0, 0, const_value_ty->get_ref (), 0), + const_value_ty); + } - SubstitutionArg subst_arg (¶m_mapping, const_value); + mappings.emplace_back (¶m_mapping, const_value_ty); offs++; - mappings.push_back (std::move (subst_arg)); } // we must need to fill out defaults @@ -865,8 +903,7 @@ SubstitutionRef::get_mappings_from_generic_args ( return SubstitutionArgumentMappings::error (); } - SubstitutionArg subst_arg (¶m, resolved); - mappings.push_back (std::move (subst_arg)); + mappings.emplace_back (¶m, resolved); } } @@ -892,30 +929,24 @@ SubstitutionRef::infer_substitions (location_t locus) if (have_mapping) { - args.push_back (SubstitutionArg (&p, it->second)); + args.emplace_back (&p, it->second); } else if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE) { TyVar infer_var = TyVar::get_implicit_infer_var (locus); - args.push_back (SubstitutionArg (&p, infer_var.get_tyty ())); + args.emplace_back (&p, infer_var.get_tyty ()); argument_mappings[symbol] = infer_var.get_tyty (); } else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST) { - const auto const_param = p.get_param_ty (); - rust_assert (const_param->is<TyTy::ConstType> ()); - const auto &const_type - = *static_cast<const TyTy::ConstType *> (const_param); - - TyVar infer_var - = TyVar::get_implicit_const_infer_var (const_type, locus); - args.push_back (SubstitutionArg (&p, infer_var.get_tyty ())); + TyVar infer_var = TyVar::get_implicit_const_infer_var (locus); + args.emplace_back (&p, infer_var.get_tyty ()); argument_mappings[symbol] = infer_var.get_tyty (); } } else { - args.push_back (SubstitutionArg (&p, p.get_param_ty ()->resolve ())); + args.emplace_back (&p, p.get_param_ty ()->resolve ()); } } @@ -961,10 +992,7 @@ SubstitutionRef::adjust_mappings_for_this ( bool ok = !arg.is_error (); if (ok || (trait_mode && i == 0)) - { - SubstitutionArg adjusted (&subst, arg.get_tyty ()); - resolved_mappings.push_back (std::move (adjusted)); - } + resolved_mappings.emplace_back (&subst, arg.get_tyty ()); } if (resolved_mappings.empty ()) @@ -1008,10 +1036,7 @@ SubstitutionRef::are_mappings_bound (SubstitutionArgumentMappings &mappings) bool ok = !arg.is_error (); if (ok) - { - SubstitutionArg adjusted (&subst, arg.get_tyty ()); - resolved_mappings.push_back (std::move (adjusted)); - } + resolved_mappings.emplace_back (&subst, arg.get_tyty ()); } return !resolved_mappings.empty (); @@ -1032,10 +1057,7 @@ SubstitutionRef::solve_mappings_from_receiver_for_self ( SubstitutionArg &arg = mappings.get_mappings ().at (i); if (param_mapping.needs_substitution ()) - { - SubstitutionArg adjusted (¶m_mapping, arg.get_tyty ()); - resolved_mappings.push_back (std::move (adjusted)); - } + resolved_mappings.emplace_back (¶m_mapping, arg.get_tyty ()); } return SubstitutionArgumentMappings (resolved_mappings, @@ -1067,7 +1089,7 @@ SubstitutionRef::monomorphize () if (!pty->can_resolve ()) continue; - const TyTy::BaseType *binding = pty->resolve (); + TyTy::BaseType *binding = pty->resolve (); if (binding->get_kind () == TyTy::TypeKind::PARAM) continue; diff --git a/gcc/rust/typecheck/rust-tyty-util.cc b/gcc/rust/typecheck/rust-tyty-util.cc index 4bc1723..72761d9 100644 --- a/gcc/rust/typecheck/rust-tyty-util.cc +++ b/gcc/rust/typecheck/rust-tyty-util.cc @@ -30,7 +30,8 @@ TyVar::TyVar (HirId ref) : ref (ref) auto context = Resolver::TypeCheckContext::get (); BaseType *lookup = nullptr; bool ok = context->lookup_type (ref, &lookup); - rust_assert (ok); + if (!ok || lookup == nullptr || lookup->get_kind () == TypeKind::ERROR) + return; } BaseType * @@ -39,7 +40,8 @@ TyVar::get_tyty () const auto context = Resolver::TypeCheckContext::get (); BaseType *lookup = nullptr; bool ok = context->lookup_type (ref, &lookup); - rust_assert (ok); + if (!ok || lookup == nullptr) + return nullptr; return lookup; } @@ -60,17 +62,14 @@ TyVar::get_implicit_infer_var (location_t locus) } TyVar -TyVar::get_implicit_const_infer_var (const ConstType &const_type, - location_t locus) +TyVar::get_implicit_const_infer_var (location_t locus) { auto &mappings = Analysis::Mappings::get (); auto context = Resolver::TypeCheckContext::get (); + TyVar ty_infer = get_implicit_infer_var (locus); HirId next = mappings.get_next_hir_id (); - auto infer - = new ConstType (ConstType::ConstKind::Infer, const_type.get_symbol (), - const_type.get_ty (), error_mark_node, - const_type.get_specified_bounds (), locus, next, next, {}); + auto infer = new ConstInferType (ty_infer.get_tyty (), next, next, {}); context->insert_implicit_type (infer->get_ref (), infer); mappings.insert_location (infer->get_ref (), locus); @@ -98,7 +97,10 @@ TyVar::subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst) TyVar TyVar::clone () const { - TyTy::BaseType *c = get_tyty ()->clone (); + TyTy::BaseType *base = get_tyty (); + if (base == nullptr || base->get_kind () == TypeKind::ERROR) + return TyVar::get_implicit_infer_var (UNKNOWN_LOCATION); + TyTy::BaseType *c = base->clone (); return TyVar (c->get_ref ()); } @@ -108,6 +110,10 @@ TyVar::monomorphized_clone () const auto &mappings = Analysis::Mappings::get (); auto context = Resolver::TypeCheckContext::get (); + TyTy::BaseType *base = get_tyty (); + if (base == nullptr || base->get_kind () == TypeKind::ERROR) + return TyVar::get_implicit_infer_var (UNKNOWN_LOCATION); + // this needs a new hirid TyTy::BaseType *c = get_tyty ()->monomorphized_clone (); c->set_ref (mappings.get_next_hir_id ()); diff --git a/gcc/rust/typecheck/rust-tyty-util.h b/gcc/rust/typecheck/rust-tyty-util.h index 1c8fd72..26101fd 100644 --- a/gcc/rust/typecheck/rust-tyty-util.h +++ b/gcc/rust/typecheck/rust-tyty-util.h @@ -43,8 +43,7 @@ public: static TyVar get_implicit_infer_var (location_t locus); - static TyVar get_implicit_const_infer_var (const TyTy::ConstType &const_type, - location_t locus); + static TyVar get_implicit_const_infer_var (location_t locus); static TyVar subst_covariant_var (TyTy::BaseType *orig, TyTy::BaseType *subst); diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h index deb76a7..b7ca5e1 100644 --- a/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h +++ b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h @@ -47,6 +47,10 @@ struct Term /** Variance constraint of a type parameter. */ struct Constraint { + Constraint (SolutionIndex target_index, Term *term) + : target_index (target_index), term (term) + {} + SolutionIndex target_index; Term *term; }; @@ -171,7 +175,10 @@ public: void visit (OpaqueType &type) override {} - void visit (ConstType &type) override {} + void visit (TyTy::ConstParamType &) override {} + void visit (TyTy::ConstValueType &) override {} + void visit (TyTy::ConstInferType &) override {} + void visit (TyTy::ConstErrorType &) override {} }; /** Per crate context for generic type variance analysis. */ diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc index 7971ccf..d640d55 100644 --- a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc +++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc @@ -321,6 +321,8 @@ GenericTyPerCrateCtx::query_generic_variance (const ADTType &type) auto num_types = type.get_num_type_params (); std::vector<Variance> result; + result.reserve (num_lifetimes + num_types); + for (size_t i = 0; i < num_lifetimes + num_types; ++i) { result.push_back (solutions[solution_index.value () + i]); @@ -410,7 +412,7 @@ GenericTyVisitorCtx::add_constraint (SolutionIndex index, Term term) } else { - ctx.constraints.push_back ({index, new Term (term)}); + ctx.constraints.emplace_back (index, new Term (term)); } } diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h index 7783075..f7f3665e 100644 --- a/gcc/rust/typecheck/rust-tyty-visitor.h +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -45,7 +45,10 @@ public: virtual void visit (ReferenceType &type) = 0; virtual void visit (PointerType &type) = 0; virtual void visit (ParamType &type) = 0; - virtual void visit (ConstType &type) = 0; + virtual void visit (ConstParamType &type) = 0; + virtual void visit (ConstValueType &type) = 0; + virtual void visit (ConstInferType &type) = 0; + virtual void visit (ConstErrorType &type) = 0; virtual void visit (StrType &type) = 0; virtual void visit (NeverType &type) = 0; virtual void visit (PlaceholderType &type) = 0; @@ -76,7 +79,10 @@ public: virtual void visit (const ReferenceType &type) = 0; virtual void visit (const PointerType &type) = 0; virtual void visit (const ParamType &type) = 0; - virtual void visit (const ConstType &type) = 0; + virtual void visit (const ConstParamType &type) = 0; + virtual void visit (const ConstValueType &type) = 0; + virtual void visit (const ConstInferType &type) = 0; + virtual void visit (const ConstErrorType &type) = 0; virtual void visit (const StrType &type) = 0; virtual void visit (const NeverType &type) = 0; virtual void visit (const PlaceholderType &type) = 0; diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index db96773..da5c350 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -16,29 +16,23 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +#include "rust-system.h" #include "rust-tyty.h" - -#include "optional.h" #include "rust-tyty-subst.h" #include "rust-tyty-visitor.h" #include "rust-hir-map.h" #include "rust-location.h" -#include "rust-linemap.h" - +#include "rust-type-util.h" +#include "rust-hir-type-bounds.h" #include "rust-substitution-mapper.h" #include "rust-hir-trait-reference.h" #include "rust-hir-trait-resolve.h" -#include "rust-tyty-cmp.h" -#include "rust-type-util.h" -#include "rust-hir-type-bounds.h" -#include "print-tree.h" #include "tree-pretty-print.h" +#include "optional.h" #include "options.h" -#include "rust-system.h" #include "tree.h" #include "fold-const.h" -#include <string> namespace Rust { namespace TyTy { @@ -295,8 +289,7 @@ BaseType::get_locus () const // FIXME this is missing locus bool -BaseType::satisfies_bound (const TypeBoundPredicate &predicate, - bool emit_error) const +BaseType::satisfies_bound (const TypeBoundPredicate &predicate, bool emit_error) { const Resolver::TraitReference *query = predicate.get (); for (const auto &bound : specified_bounds) @@ -351,41 +344,20 @@ BaseType::satisfies_bound (const TypeBoundPredicate &predicate, return false; std::string item_name = item->get_impl_item_name (); - TypeBoundPredicateItem lookup + tl::optional<TypeBoundPredicateItem> lookup = predicate.lookup_associated_item (item_name); - if (lookup.is_error ()) + if (!lookup.has_value ()) return false; - const auto *item_ref = lookup.get_raw_item (); + const auto *item_ref = lookup->get_raw_item (); TyTy::BaseType *bound_ty = item_ref->get_tyty (); - // compare the types - if (!bound_ty->can_eq (impl_item_ty, false)) - { - if (!impl_item_ty->can_eq (bound_ty, false)) - { - if (emit_error) - { - rich_location r (line_table, - mappings.lookup_location (get_ref ())); - r.add_range (predicate.get_locus ()); - r.add_range (mappings.lookup_location (i.get_hirid ())); - - std::string rich_msg - = "expected " + bound_ty->destructure ()->get_name () - + ", found " - + impl_item_ty->destructure ()->get_name (); - r.add_fixit_replace (rich_msg.c_str ()); - - rust_error_at ( - r, ErrorCode::E0271, - "type mismatch, expected %qs but got %qs", - bound_ty->destructure ()->get_name ().c_str (), - impl_item_ty->destructure ()->get_name ().c_str ()); - } - return false; - } - } + if (!Resolver::types_compatable ( + TyTy::TyWithLocation (bound_ty, predicate.get_locus ()), + TyTy::TyWithLocation (impl_item_ty, item->get_locus ()), + mappings.lookup_location (get_ref ()), false /*emit-error*/, + false /*check-bounds*/)) + return false; } return true; @@ -395,8 +367,7 @@ BaseType::satisfies_bound (const TypeBoundPredicate &predicate, } bool -BaseType::bounds_compatible (const BaseType &other, location_t locus, - bool emit_error) const +BaseType::bounds_compatible (BaseType &other, location_t locus, bool emit_error) { std::vector<std::reference_wrapper<const TypeBoundPredicate>> unsatisfied_bounds; @@ -501,6 +472,23 @@ BaseType::destructure () x = pr; } + else if (x->get_kind () == TypeKind::CONST) + { + auto p = x->as_const_type (); + if (p->const_kind () == BaseConstType::ConstKind::Decl) + { + auto decl = static_cast<ConstParamType *> (p); + auto pr = decl->resolve (); + if (pr == x) + return pr; + + x = pr; + } + else + { + return x; + } + } else if (auto p = x->try_as<PlaceholderType> ()) { if (!p->can_resolve ()) @@ -546,6 +534,23 @@ BaseType::destructure () const x = pr; } + else if (x->get_kind () == TypeKind::CONST) + { + auto p = x->as_const_type (); + if (p->const_kind () == BaseConstType::ConstKind::Decl) + { + auto decl = static_cast<const ConstParamType *> (p); + auto pr = decl->resolve (); + if (pr == x) + return pr; + + x = pr; + } + else + { + return x; + } + } else if (auto p = x->try_as<const PlaceholderType> ()) { if (!p->can_resolve ()) @@ -583,7 +588,7 @@ BaseType::monomorphized_clone () const { TyVar elm = arr->get_var_element_type ().monomorphized_clone (); return new ArrayType (arr->get_ref (), arr->get_ty_ref (), ident.locus, - arr->get_capacity (), elm, + arr->get_capacity_var (), elm, arr->get_combined_refs ()); } else if (auto slice = x->try_as<const SliceType> ()) @@ -637,8 +642,8 @@ BaseType::monomorphized_clone () const TyVar retty = fn->get_var_return_type ().monomorphized_clone (); return new FnPtr (fn->get_ref (), fn->get_ty_ref (), ident.locus, - std::move (cloned_params), retty, - fn->get_combined_refs ()); + std::move (cloned_params), retty, fn->get_abi (), + fn->get_unsafety (), fn->get_combined_refs ()); } else if (auto adt = x->try_as<const ADTType> ()) { @@ -780,7 +785,8 @@ BaseType::is_concrete () const { const TyTy::BaseType *x = destructure (); - if (x->is<ParamType> () || x->is<ProjectionType> ()) + if (x->is<ParamType> () || x->is<ProjectionType> () + || x->is<ConstParamType> ()) { return false; } @@ -862,10 +868,6 @@ BaseType::is_concrete () const return false; return closure->get_result_type ().is_concrete (); } - else if (auto const_type = x->try_as<const ConstType> ()) - { - return const_type->get_value () != error_mark_node; - } else if (x->is<InferType> () || x->is<BoolType> () || x->is<CharType> () || x->is<IntType> () || x->is<UintType> () || x->is<FloatType> () || x->is<USizeType> () || x->is<ISizeType> () || x->is<NeverType> () @@ -1113,13 +1115,6 @@ InferType::as_string () const return "<infer::error>"; } -bool -InferType::can_eq (const BaseType *other, bool emit_errors) const -{ - InferCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * InferType::clone () const { @@ -1410,12 +1405,6 @@ ErrorType::as_string () const return "<tyty::error>"; } -bool -ErrorType::can_eq (const BaseType *other, bool emit_errors) const -{ - return get_kind () == other->get_kind (); -} - BaseType * ErrorType::clone () const { @@ -1800,13 +1789,6 @@ ADTType::as_string () const } bool -ADTType::can_eq (const BaseType *other, bool emit_errors) const -{ - ADTCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool ADTType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) @@ -2037,13 +2019,6 @@ TupleType::get_field (size_t index) const } bool -TupleType::can_eq (const BaseType *other, bool emit_errors) const -{ - TupleCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool TupleType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) @@ -2126,13 +2101,6 @@ FnType::as_string () const } bool -FnType::can_eq (const BaseType *other, bool emit_errors) const -{ - FnCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool FnType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) @@ -2331,14 +2299,13 @@ FnPtr::as_string () const params_str += p.get_tyty ()->as_string () + " ,"; } - return "fnptr (" + params_str + ") -> " + get_return_type ()->as_string (); -} + std::string unsafety = ""; + if (get_unsafety () == Unsafety::Unsafe) + unsafety = "unsafe "; -bool -FnPtr::can_eq (const BaseType *other, bool emit_errors) const -{ - FnptrCmp r (this, emit_errors); - return r.can_eq (other); + std::string abi = get_string_from_abi (get_abi ()); + return unsafety + "abi:" + abi + " " + "fnptr (" + params_str + ") -> " + + get_return_type ()->as_string (); } bool @@ -2368,12 +2335,48 @@ BaseType * FnPtr::clone () const { std::vector<TyVar> cloned_params; + cloned_params.reserve (params.size ()); + for (auto &p : params) - cloned_params.push_back (TyVar (p.get_ref ())); + cloned_params.emplace_back (p.get_ref ()); return new FnPtr (get_ref (), get_ty_ref (), ident.locus, - std::move (cloned_params), result_type, - get_combined_refs ()); + std::move (cloned_params), result_type, get_abi (), + get_unsafety (), get_combined_refs ()); +} + +FnPtr * +FnPtr::handle_substitions (SubstitutionArgumentMappings &mappings) +{ + auto &mappings_table = Analysis::Mappings::get (); + + auto fn = clone ()->as<FnPtr> (); + fn->set_ref (mappings_table.get_next_hir_id ()); + fn->set_ty_ref (mappings_table.get_next_hir_id ()); + + if (!fn->result_type.get_tyty ()->is_concrete ()) + { + BaseType *concrete + = Resolver::SubstMapperInternal::Resolve (fn->result_type.get_tyty (), + mappings); + fn->result_type + = TyVar::subst_covariant_var (fn->result_type.get_tyty (), concrete); + } + + for (size_t i = 0; i < fn->params.size (); i++) + { + TyVar &field = fn->params.at (i); + if (!field.get_tyty ()->is_concrete ()) + { + BaseType *concrete + = Resolver::SubstMapperInternal::Resolve (field.get_tyty (), + mappings); + fn->params[i] + = TyVar::subst_covariant_var (field.get_tyty (), concrete); + } + } + + return fn; } void @@ -2396,13 +2399,6 @@ ClosureType::as_string () const } bool -ClosureType::can_eq (const BaseType *other, bool emit_errors) const -{ - ClosureCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool ClosureType::is_equal (const BaseType &other) const { if (other.get_kind () != TypeKind::CLOSURE) @@ -2499,15 +2495,10 @@ ArrayType::accept_vis (TyConstVisitor &vis) const std::string ArrayType::as_string () const { - return "[" + get_element_type ()->as_string () + "; " + capacity->as_string () - + "]"; -} + auto cap = get_capacity (); + std::string capacity_str = cap->as_string (); -bool -ArrayType::can_eq (const BaseType *other, bool emit_errors) const -{ - ArrayCmp r (this, emit_errors); - return r.can_eq (other); + return "[" + get_element_type ()->as_string () + "; " + capacity_str + "]"; } bool @@ -2537,6 +2528,12 @@ ArrayType::get_var_element_type () const } BaseType * +ArrayType::get_capacity () const +{ + return capacity.get_tyty (); +} + +BaseType * ArrayType::clone () const { return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity, @@ -2561,7 +2558,7 @@ ArrayType::handle_substitions (SubstitutionArgumentMappings &mappings) BaseType *concrete_cap = Resolver::SubstMapperInternal::Resolve (cap, mappings); rust_assert (concrete_cap->get_kind () == TyTy::TypeKind::CONST); - ref->capacity = static_cast<TyTy::ConstType *> (concrete_cap); + ref->capacity = TyVar::subst_covariant_var (cap, concrete_cap); return ref; } @@ -2585,13 +2582,6 @@ SliceType::as_string () const } bool -SliceType::can_eq (const BaseType *other, bool emit_errors) const -{ - SliceCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool SliceType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) @@ -2678,13 +2668,6 @@ BoolType::as_string () const return "bool"; } -bool -BoolType::can_eq (const BaseType *other, bool emit_errors) const -{ - BoolCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * BoolType::clone () const { @@ -2751,13 +2734,6 @@ IntType::as_string () const return "__unknown_int_type"; } -bool -IntType::can_eq (const BaseType *other, bool emit_errors) const -{ - IntCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * IntType::clone () const { @@ -2836,13 +2812,6 @@ UintType::as_string () const return "__unknown_uint_type"; } -bool -UintType::can_eq (const BaseType *other, bool emit_errors) const -{ - UintCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * UintType::clone () const { @@ -2915,13 +2884,6 @@ FloatType::as_string () const return "__unknown_float_type"; } -bool -FloatType::can_eq (const BaseType *other, bool emit_errors) const -{ - FloatCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * FloatType::clone () const { @@ -2977,13 +2939,6 @@ USizeType::as_string () const return "usize"; } -bool -USizeType::can_eq (const BaseType *other, bool emit_errors) const -{ - USizeCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * USizeType::clone () const { @@ -3028,13 +2983,6 @@ ISizeType::as_string () const return "isize"; } -bool -ISizeType::can_eq (const BaseType *other, bool emit_errors) const -{ - ISizeCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * ISizeType::clone () const { @@ -3079,13 +3027,6 @@ CharType::as_string () const return "char"; } -bool -CharType::can_eq (const BaseType *other, bool emit_errors) const -{ - CharCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * CharType::clone () const { @@ -3200,13 +3141,6 @@ ReferenceType::get_name () const } bool -ReferenceType::can_eq (const BaseType *other, bool emit_errors) const -{ - ReferenceCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool ReferenceType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) @@ -3362,13 +3296,6 @@ PointerType::get_name () const } bool -PointerType::can_eq (const BaseType *other, bool emit_errors) const -{ - PointerCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool PointerType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) @@ -3478,13 +3405,6 @@ ParamType::get_name () const return destructure ()->get_name (); } -bool -ParamType::can_eq (const BaseType *other, bool emit_errors) const -{ - ParamCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * ParamType::clone () const { @@ -3543,7 +3463,9 @@ ParamType::is_equal (const BaseType &other) const return false; if (can_resolve ()) - return resolve ()->can_eq (other2.resolve (), false); + return Resolver::types_compatable (TyTy::TyWithLocation (resolve ()), + TyTy::TyWithLocation (other2.resolve ()), + UNKNOWN_LOCATION, false, false); return get_symbol ().compare (other2.get_symbol ()) == 0; } @@ -3564,7 +3486,7 @@ ParamType::handle_substitions (SubstitutionArgumentMappings &subst_mappings) { const ParamType &pp = *static_cast<const ParamType *> (resolved); if (pp.can_resolve ()) - resolved = pp.resolve (); + pp.resolve (); } // this is the new subst that this needs to pass @@ -3586,155 +3508,382 @@ ParamType::is_implicit_self_trait () const return is_trait_self; } -// ConstType +static std::string +generate_tree_str (tree value) +{ + char *buf = nullptr; + size_t size = 0; -ConstType::ConstType (ConstKind kind, std::string symbol, TyTy::BaseType *ty, - tree value, - std::vector<TypeBoundPredicate> specified_bounds, - location_t locus, HirId ref, HirId ty_ref, - std::set<HirId> refs) - : BaseGeneric (ref, ty_ref, KIND, - {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, - symbol.empty () ? "<n/a>" - : symbol), + FILE *stream = open_memstream (&buf, &size); + if (!stream) + return "<error>"; + + print_generic_stmt (stream, value, TDF_NONE); + fclose (stream); + + std::string result = (buf ? std::string (buf, size) : "<error>"); + free (buf); + + if (!result.empty () && result.back () == '\n') + result.pop_back (); + + return result; +} + +// --- + +ConstParamType::ConstParamType (std::string symbol, location_t locus, + BaseType *type, HirId ref, HirId ty_ref, + std::set<HirId> refs) + : BaseConstType (type), + BaseGeneric (ref, ty_ref, KIND, + {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol), locus}, - specified_bounds, refs), - const_kind (kind), ty (ty), value (value), symbol (symbol) + {}, refs), + symbol (symbol) {} +BaseConstType::ConstKind +ConstParamType::const_kind () const +{ + return BaseConstType::ConstKind::Decl; +} + +std::string +ConstParamType::get_symbol () const +{ + return symbol; +} + +bool +ConstParamType::can_resolve () const +{ + return get_ref () != get_ty_ref (); +} + +BaseType * +ConstParamType::resolve () const +{ + TyVar var (get_ty_ref ()); + BaseType *r = var.get_tyty (); + + while (r->get_kind () == TypeKind::CONST) + { + TyVar v (r->get_ty_ref ()); + BaseType *n = v.get_tyty (); + + // fix infinite loop + if (r == n) + break; + + r = n; + } + + if (r->get_kind () == TypeKind::CONST && (r->get_ref () == r->get_ty_ref ())) + { + auto *const_type = r->as_const_type (); + if (const_type->const_kind () != BaseConstType::ConstKind::Value) + return TyVar (r->get_ty_ref ()).get_tyty (); + } + + return r; +} + void -ConstType::accept_vis (TyVisitor &vis) +ConstParamType::accept_vis (TyVisitor &vis) { vis.visit (*this); } void -ConstType::accept_vis (TyConstVisitor &vis) const +ConstParamType::accept_vis (TyConstVisitor &vis) const { vis.visit (*this); } -void -ConstType::set_value (tree v) +std::string +ConstParamType::as_string () const +{ + if (!can_resolve ()) + { + return get_symbol () + " CONST_REF: " + std::to_string (get_ref ()); + } + + BaseType *lookup = resolve (); + // Avoid infinite recursion if resolve() returns this same type + if (lookup == this->as_base_type ()) + { + return get_symbol () + " CONST_REF: " + std::to_string (get_ref ()); + } + + return get_symbol () + "=" + lookup->as_string (); +} + +BaseType * +ConstParamType::clone () const { - value = v; - const_kind = ConstType::ConstKind::Value; + return new ConstParamType (get_symbol (), ident.locus, specified_type, + get_ref (), get_ty_ref (), get_combined_refs ()); } std::string -ConstType::as_string () const +ConstParamType::get_name () const { - return get_name (); + if (!can_resolve ()) + return get_symbol (); + + BaseType *lookup = resolve (); + // Avoid infinite recursion if resolve() returns this same type + if (lookup == this->as_base_type ()) + return get_symbol (); + + return lookup->get_name (); } bool -ConstType::can_eq (const BaseType *other, bool emit_errors) const +ConstParamType::is_equal (const BaseType &other) const { - ConstCmp r (this, emit_errors); - return r.can_eq (other); + if (get_kind () != other.get_kind ()) + { + if (!can_resolve ()) + return false; + + return resolve ()->is_equal (other); + } + + auto other_const = other.as_const_type (); + if (other_const->const_kind () != BaseConstType::ConstKind::Decl) + return false; + + auto &other2 = static_cast<const ConstParamType &> (*other_const); + if (can_resolve () != other2.can_resolve ()) + return false; + + if (can_resolve ()) + return Resolver::types_compatable (TyTy::TyWithLocation (resolve ()), + TyTy::TyWithLocation (other2.resolve ()), + ident.locus, false); + + return get_symbol ().compare (other2.get_symbol ()) == 0; } BaseType * -ConstType::clone () const +ConstParamType::handle_substitions ( + SubstitutionArgumentMappings &subst_mappings) { - return new ConstType (const_kind, symbol, ty, value, get_specified_bounds (), - ident.locus, ref, ty_ref, get_combined_refs ()); + SubstitutionArg arg = SubstitutionArg::error (); + bool ok = subst_mappings.get_argument_for_symbol (this, &arg); + if (!ok || arg.is_error ()) + return this; + + ConstParamType *p = static_cast<ConstParamType *> (clone ()); + const BaseType *resolved = arg.get_tyty (); + + // this is the new subst that this needs to pass + p->set_ref (mappings.get_next_hir_id ()); + p->set_ty_ref (resolved->get_ref ()); + + return p; } -std::string -ConstType::get_symbol () const +// --- ConstValueType + +ConstValueType::ConstValueType (tree value, BaseType *type, HirId ref, + HirId ty_ref, std::set<HirId> refs) + : BaseType (ref, ty_ref, KIND, + {Resolver::CanonicalPath::create_empty (), UNKNOWN_LOCATION}, + refs), + BaseConstType (type), folded_val (value) +{} + +BaseConstType::ConstKind +ConstValueType::const_kind () const { - return symbol; + return BaseConstType::ConstKind::Value; } -bool -ConstType::can_resolve () const +void +ConstValueType::accept_vis (TyVisitor &vis) { - return false; + vis.visit (*this); +} + +void +ConstValueType::accept_vis (TyConstVisitor &vis) const +{ + vis.visit (*this); +} + +std::string +ConstValueType::as_string () const +{ + return generate_tree_str (folded_val); } BaseType * -ConstType::resolve () const +ConstValueType::clone () const { - rust_unreachable (); - return nullptr; + return new ConstValueType (folded_val, specified_type, get_ref (), + get_ty_ref (), get_combined_refs ()); } -static std::string -generate_tree_str (tree value) +std::string +ConstValueType::get_name () const { - char *buf = nullptr; - size_t size = 0; + return as_string (); +} - FILE *stream = open_memstream (&buf, &size); - if (!stream) - return "<error>"; +bool +ConstValueType::is_equal (const BaseType &other) const +{ + if (get_kind () != other.get_kind ()) + return false; - print_generic_stmt (stream, value, TDF_NONE); - fclose (stream); + auto other_const = other.as_const_type (); + if (other_const->const_kind () != BaseConstType::ConstKind::Value) + return false; - std::string result = (buf ? std::string (buf, size) : "<error>"); - free (buf); + auto &other2 = static_cast<const ConstValueType &> (*other_const); + return folded_val == other2.folded_val; +} - if (!result.empty () && result.back () == '\n') - result.pop_back (); +tree +ConstValueType::get_value () const +{ + return folded_val; +} - return result; +// --- ConstInferType + +ConstInferType::ConstInferType (BaseType *type, HirId ref, HirId ty_ref, + std::set<HirId> refs) + : BaseType (ref, ty_ref, KIND, + {Resolver::CanonicalPath::create_empty (), UNKNOWN_LOCATION}, + refs), + BaseConstType (type) +{} + +BaseConstType::ConstKind +ConstInferType::const_kind () const +{ + return BaseConstType::ConstKind::Infer; +} + +void +ConstInferType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstInferType::accept_vis (TyConstVisitor &vis) const +{ + vis.visit (*this); } std::string -ConstType::get_name () const +ConstInferType::as_string () const { - if (value == error_mark_node) - { - switch (get_const_kind ()) - { - case Rust::TyTy::ConstType::Decl: - return "ConstType:<" + get_ty ()->get_name () + " " + get_symbol () - + ">"; + return specified_type->get_name () + "-?"; +} - case Rust::TyTy::ConstType::Infer: - return "ConstType:<" + get_ty ()->get_name () + " ?" + ">"; +BaseType * +ConstInferType::clone () const +{ + auto &mappings = Analysis::Mappings::get (); + auto context = Resolver::TypeCheckContext::get (); - default: - return "ConstType:<" + get_ty ()->get_name () + " - <error>" + ">"; - } - } + ConstInferType *clone + = new ConstInferType (specified_type, mappings.get_next_hir_id (), + get_ty_ref (), get_combined_refs ()); + + context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (), + UNKNOWN_NODEID, + clone->get_ref (), + UNKNOWN_LOCAL_DEFID), + clone); + mappings.insert_location (clone->get_ref (), + mappings.lookup_location (get_ref ())); + + clone->append_reference (get_ref ()); - return generate_tree_str (value); + return clone; +} + +std::string +ConstInferType::get_name () const +{ + return as_string (); } bool -ConstType::is_equal (const BaseType &other) const +ConstInferType::is_equal (const BaseType &other) const { if (get_kind () != other.get_kind ()) - { - return false; - } + return false; - const ConstType &rhs = static_cast<const ConstType &> (other); - if (!get_ty ()->is_equal (*rhs.get_ty ())) + auto other_const = other.as_const_type (); + if (other_const->const_kind () != BaseConstType::ConstKind::Infer) return false; - tree lv = get_value (); - tree rv = rhs.get_value (); + return get_ref () == other.get_ref (); +} + +// --- ConstErrorType + +ConstErrorType::ConstErrorType (BaseType *type, HirId ref, HirId ty_ref, + std::set<HirId> refs) + : BaseType (ref, ty_ref, KIND, + {Resolver::CanonicalPath::create_empty (), UNKNOWN_LOCATION}, + refs), + BaseConstType (type) +{} - return operand_equal_p (lv, rv, 0); +BaseConstType::ConstKind +ConstErrorType::const_kind () const +{ + return BaseConstType::ConstKind::Error; } -ConstType * -ConstType::handle_substitions (SubstitutionArgumentMappings &mappings) +void +ConstErrorType::accept_vis (TyVisitor &vis) { - SubstitutionArg arg = SubstitutionArg::error (); - bool found = mappings.get_argument_for_symbol (this, &arg); - if (found && !arg.is_error ()) - { - TyTy::BaseType *subst = arg.get_tyty (); - rust_assert (subst->is<TyTy::ConstType> ()); - return static_cast<TyTy::ConstType *> (subst); - } + vis.visit (*this); +} + +void +ConstErrorType::accept_vis (TyConstVisitor &vis) const +{ + vis.visit (*this); +} + +std::string +ConstErrorType::as_string () const +{ + return "<const_error>"; +} + +BaseType * +ConstErrorType::clone () const +{ + return new ConstErrorType (specified_type, get_ref (), get_ty_ref (), + get_combined_refs ()); +} + +std::string +ConstErrorType::get_name () const +{ + return as_string (); +} + +bool +ConstErrorType::is_equal (const BaseType &other) const +{ + if (get_kind () != other.get_kind ()) + return false; - return this; + auto other_const = other.as_const_type (); + return other_const->const_kind () == BaseConstType::ConstKind::Error; } // OpaqueType @@ -3787,13 +3936,6 @@ OpaqueType::get_name () const return "impl " + raw_bounds_as_name (); } -bool -OpaqueType::can_eq (const BaseType *other, bool emit_errors) const -{ - OpaqueCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * OpaqueType::clone () const { @@ -3815,7 +3957,24 @@ OpaqueType::is_equal (const BaseType &other) const if (can_resolve () != other2.can_resolve ()) return false; - return bounds_compatible (other, UNDEF_LOCATION, false); + if (num_specified_bounds () != other.num_specified_bounds ()) + return false; + + for (const auto &pred : specified_bounds) + { + bool found = false; + for (const auto &opred : other.get_specified_bounds ()) + { + found = pred.is_equal (opred); + if (found) + break; + } + + if (!found) + return false; + } + + return true; } // StrType @@ -3863,13 +4022,6 @@ StrType::as_string () const } bool -StrType::can_eq (const BaseType *other, bool emit_errors) const -{ - StrCmp r (this, emit_errors); - return r.can_eq (other); -} - -bool StrType::is_equal (const BaseType &other) const { return get_kind () == other.get_kind (); @@ -3913,13 +4065,6 @@ NeverType::as_string () const return "!"; } -bool -NeverType::can_eq (const BaseType *other, bool emit_errors) const -{ - NeverCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * NeverType::clone () const { @@ -3975,13 +4120,6 @@ PlaceholderType::as_string () const + ">"; } -bool -PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const -{ - PlaceholderCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * PlaceholderType::clone () const { @@ -4118,12 +4256,6 @@ ProjectionType::as_string () const return "<Projection=" + subst_as_string () + "::" + base->as_string () + ">"; } -bool -ProjectionType::can_eq (const BaseType *other, bool emit_errors) const -{ - return base->can_eq (other, emit_errors); -} - BaseType * ProjectionType::clone () const { @@ -4237,13 +4369,6 @@ DynamicObjectType::as_string () const return "dyn [" + raw_bounds_as_string () + "]"; } -bool -DynamicObjectType::can_eq (const BaseType *other, bool emit_errors) const -{ - DynamicCmp r (this, emit_errors); - return r.can_eq (other); -} - BaseType * DynamicObjectType::clone () const { @@ -4266,7 +4391,21 @@ DynamicObjectType::is_equal (const BaseType &other) const if (num_specified_bounds () != other.num_specified_bounds ()) return false; - return bounds_compatible (other, UNDEF_LOCATION, false); + for (const auto &pred : specified_bounds) + { + bool found = false; + for (const auto &opred : other.get_specified_bounds ()) + { + found = pred.is_equal (opred); + if (found) + break; + } + + if (!found) + return false; + } + + return true; } const std::vector< @@ -4287,7 +4426,7 @@ DynamicObjectType::get_object_items () const if (item->get_trait_item_type () == Resolver::TraitItemReference::TraitItemType::FN && item->is_object_safe ()) - items.push_back ({item, &bound}); + items.emplace_back (item, &bound); } } return items; diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 49415ea..3236bf3 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -91,6 +91,7 @@ public: class TyVisitor; class TyConstVisitor; +class BaseConstType; class BaseType : public TypeBoundsMappings { public: @@ -110,29 +111,15 @@ public: virtual std::string as_string () const = 0; virtual std::string get_name () const = 0; - // similar to unify but does not actually perform type unification but - // determines whether they are compatible. Consider the following - // - // fn foo<T>() -> T { ... } - // fn foo() -> i32 { ... } - // - // when the function has been substituted they can be considered equal. - // - // It can also be used to optional emit errors for trait item compatibility - // checks - virtual bool can_eq (const BaseType *other, bool emit_errors) const = 0; - // Check value equality between two ty. Type inference rules are ignored. Two // ty are considered equal if they're of the same kind, and // 1. (For ADTs, arrays, tuples, refs) have the same underlying ty // 2. (For functions) have the same signature virtual bool is_equal (const BaseType &other) const; - bool satisfies_bound (const TypeBoundPredicate &predicate, - bool emit_error) const; + bool satisfies_bound (const TypeBoundPredicate &predicate, bool emit_error); - bool bounds_compatible (const BaseType &other, location_t locus, - bool emit_error) const; + bool bounds_compatible (BaseType &other, location_t locus, bool emit_error); void inherit_bounds (const BaseType &other); @@ -240,6 +227,11 @@ public: return static_cast<T *> (this); } + // Helper to get BaseConstType interface for CONST types + // Overridden by const types that also inherit from BaseConstType + virtual BaseConstType *as_const_type () { return nullptr; } + virtual const BaseConstType *as_const_type () const { return nullptr; } + protected: BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident, std::set<HirId> refs = std::set<HirId> ()); @@ -327,8 +319,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; InferTypeKind get_infer_kind () const; @@ -359,8 +349,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; std::string get_name () const override final; @@ -402,8 +390,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; std::string get_symbol () const override final; @@ -426,7 +412,7 @@ private: std::string symbol; }; -class ConstType : public BaseGeneric +class BaseConstType { public: static constexpr auto KIND = TypeKind::CONST; @@ -439,25 +425,30 @@ public: Error }; - ConstType (ConstKind kind, std::string symbol, TyTy::BaseType *ty, tree value, - std::vector<TypeBoundPredicate> specified_bounds, location_t locus, - HirId ref, HirId ty_ref, - std::set<HirId> refs = std::set<HirId> ()); + virtual ConstKind const_kind () const = 0; - void accept_vis (TyVisitor &vis) override; - void accept_vis (TyConstVisitor &vis) const override; + BaseType *get_specified_type () const { return specified_type; } - ConstKind get_const_kind () const { return const_kind; } - TyTy::BaseType *get_ty () const { return ty; } - tree get_value () const { return value; } + // Helper to get BaseType interface (all const types also inherit BaseType) + // This must be implemented by concrete classes since BaseConstType doesn't + // inherit from BaseType, but all concrete const types do. + virtual BaseType *as_base_type () = 0; + virtual const BaseType *as_base_type () const = 0; - void set_value (tree value); +protected: + BaseConstType (BaseType *type) : specified_type (type) {} - std::string as_string () const override; + BaseType *specified_type; +}; - bool can_eq (const BaseType *other, bool emit_errors) const override final; +class ConstParamType : public BaseConstType, public BaseGeneric +{ +public: + ConstParamType (std::string symbol, location_t locus, BaseType *type, + HirId ref, HirId ty_ref, + std::set<HirId> refs = std::set<HirId> ()); - BaseType *clone () const final override; + ConstKind const_kind () const override final; std::string get_symbol () const override final; @@ -465,19 +456,126 @@ public: BaseType *resolve () const override final; + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + BaseType *clone () const final override; std::string get_name () const override final; bool is_equal (const BaseType &other) const override; - ConstType *handle_substitions (SubstitutionArgumentMappings &mappings); + BaseType *handle_substitions (SubstitutionArgumentMappings &mappings); + + BaseType *as_base_type () override { return static_cast<BaseType *> (this); } + const BaseType *as_base_type () const override + { + return static_cast<const BaseType *> (this); + } + + BaseConstType *as_const_type () override { return this; } + const BaseConstType *as_const_type () const override { return this; } private: - ConstKind const_kind; - TyTy::BaseType *ty; - tree value; std::string symbol; }; +class ConstValueType : public BaseType, public BaseConstType +{ +public: + static constexpr auto KIND = TypeKind::CONST; + + ConstValueType (tree value, BaseType *type, HirId ref, HirId ty_ref, + std::set<HirId> refs = std::set<HirId> ()); + + ConstKind const_kind () const override final; + + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + BaseType *clone () const final override; + std::string get_name () const override final; + + bool is_equal (const BaseType &other) const override; + + tree get_value () const; + + BaseType *as_base_type () override { return static_cast<BaseType *> (this); } + const BaseType *as_base_type () const override + { + return static_cast<const BaseType *> (this); + } + + BaseConstType *as_const_type () override { return this; } + const BaseConstType *as_const_type () const override { return this; } + +private: + tree folded_val; +}; + +class ConstInferType : public BaseType, public BaseConstType +{ +public: + static constexpr auto KIND = TypeKind::CONST; + + ConstInferType (BaseType *type, HirId ref, HirId ty_ref, + std::set<HirId> refs = std::set<HirId> ()); + + ConstKind const_kind () const override final; + + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + BaseType *clone () const final override; + std::string get_name () const override final; + + bool is_equal (const BaseType &other) const override; + + BaseType *as_base_type () override { return static_cast<BaseType *> (this); } + const BaseType *as_base_type () const override + { + return static_cast<const BaseType *> (this); + } + + BaseConstType *as_const_type () override { return this; } + const BaseConstType *as_const_type () const override { return this; } +}; + +class ConstErrorType : public BaseType, public BaseConstType +{ +public: + static constexpr auto KIND = TypeKind::CONST; + + ConstErrorType (BaseType *type, HirId ref, HirId ty_ref, + std::set<HirId> refs = std::set<HirId> ()); + + ConstKind const_kind () const override final; + + void accept_vis (TyVisitor &vis) override; + void accept_vis (TyConstVisitor &vis) const override; + + std::string as_string () const override; + + BaseType *clone () const final override; + std::string get_name () const override final; + + bool is_equal (const BaseType &other) const override; + + BaseType *as_base_type () override { return static_cast<BaseType *> (this); } + const BaseType *as_base_type () const override + { + return static_cast<const BaseType *> (this); + } + + BaseConstType *as_const_type () override { return this; } + const BaseConstType *as_const_type () const override { return this; } +}; + class OpaqueType : public BaseType { public: @@ -496,8 +594,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; bool can_resolve () const; @@ -557,8 +653,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; size_t num_fields () const; @@ -589,7 +683,7 @@ public: TypeBoundPredicate (const TypeBoundPredicate &other); - virtual ~TypeBoundPredicate (){}; + virtual ~TypeBoundPredicate () {} TypeBoundPredicate &operator= (const TypeBoundPredicate &other); @@ -617,10 +711,10 @@ public: bool contains_item (const std::string &search) const; - TypeBoundPredicateItem + tl::optional<TypeBoundPredicateItem> lookup_associated_item (const std::string &search) const; - TypeBoundPredicateItem + tl::optional<TypeBoundPredicateItem> lookup_associated_item (const Resolver::TraitItemReference *ref) const; // WARNING THIS WILL ALWAYS RETURN NULLPTR @@ -851,8 +945,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; std::string get_identifier () const { return identifier; } @@ -1003,8 +1095,6 @@ public: std::string get_identifier () const { return identifier; } - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; size_t num_params () const { return params.size (); } @@ -1076,19 +1166,22 @@ public: static constexpr auto KIND = TypeKind::FNPTR; FnPtr (HirId ref, location_t locus, std::vector<TyVar> params, - TyVar result_type, std::set<HirId> refs = std::set<HirId> ()) + TyVar result_type, ABI abi, Unsafety unsafety, + std::set<HirId> refs = std::set<HirId> ()) : CallableTypeInterface (ref, ref, TypeKind::FNPTR, {Resolver::CanonicalPath::create_empty (), locus}, refs), - params (std::move (params)), result_type (result_type) + params (std::move (params)), result_type (result_type), abi (abi), + unsafety (unsafety) {} FnPtr (HirId ref, HirId ty_ref, location_t locus, std::vector<TyVar> params, - TyVar result_type, std::set<HirId> refs = std::set<HirId> ()) + TyVar result_type, ABI abi, Unsafety unsafety, + std::set<HirId> refs = std::set<HirId> ()) : CallableTypeInterface (ref, ty_ref, TypeKind::FNPTR, {Resolver::CanonicalPath::create_empty (), locus}, refs), - params (params), result_type (result_type) + params (params), result_type (result_type), abi (abi), unsafety (unsafety) {} std::string get_name () const override final { return as_string (); } @@ -1117,8 +1210,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; @@ -1126,9 +1217,17 @@ public: std::vector<TyVar> &get_params () { return params; } const std::vector<TyVar> &get_params () const { return params; } + ABI get_abi () const { return abi; } + + Unsafety get_unsafety () const { return unsafety; } + + FnPtr *handle_substitions (SubstitutionArgumentMappings &mappings); + private: std::vector<TyVar> params; TyVar result_type; + ABI abi; + Unsafety unsafety; }; class ClosureType : public CallableTypeInterface, public SubstitutionRef @@ -1194,8 +1293,6 @@ public: std::string as_string () const override; std::string get_name () const override final { return as_string (); } - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; @@ -1224,14 +1321,14 @@ class ArrayType : public BaseType public: static constexpr auto KIND = TypeKind::ARRAY; - ArrayType (HirId ref, location_t locus, ConstType *capacity, TyVar base, + ArrayType (HirId ref, location_t locus, TyVar capacity, TyVar base, std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ref, TypeKind::ARRAY, {Resolver::CanonicalPath::create_empty (), locus}, refs), element_type (base), capacity (capacity) {} - ArrayType (HirId ref, HirId ty_ref, location_t locus, ConstType *capacity, + ArrayType (HirId ref, HirId ty_ref, location_t locus, TyVar capacity, TyVar base, std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ty_ref, TypeKind::ARRAY, {Resolver::CanonicalPath::create_empty (), locus}, refs), @@ -1245,8 +1342,6 @@ public: std::string get_name () const override final { return as_string (); } - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *get_element_type () const; @@ -1254,13 +1349,14 @@ public: BaseType *clone () const final override; - ConstType *get_capacity () const { return capacity; } + BaseType *get_capacity () const; + const TyVar &get_capacity_var () const { return capacity; } ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings); private: TyVar element_type; - ConstType *capacity; + TyVar capacity; }; class SliceType : public BaseType @@ -1289,8 +1385,6 @@ public: std::string get_name () const override final { return as_string (); } - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *get_element_type () const; @@ -1319,8 +1413,6 @@ public: std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; }; @@ -1349,8 +1441,6 @@ public: std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - IntKind get_int_kind () const; BaseType *clone () const final override; @@ -1387,8 +1477,6 @@ public: std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - UintKind get_uint_kind () const; BaseType *clone () const final override; @@ -1421,8 +1509,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - FloatKind get_float_kind () const; BaseType *clone () const final override; @@ -1448,8 +1534,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; }; @@ -1468,8 +1552,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; }; @@ -1487,8 +1569,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; }; @@ -1507,8 +1587,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; @@ -1532,8 +1610,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; @@ -1568,8 +1644,6 @@ public: std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; @@ -1612,8 +1686,6 @@ public: std::string as_string () const override; std::string get_name () const override final; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - bool is_equal (const BaseType &other) const override; BaseType *clone () const final override; @@ -1659,8 +1731,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; std::string get_name () const override final; @@ -1683,8 +1753,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; std::string get_name () const override final; @@ -1734,8 +1802,6 @@ public: std::string as_string () const override; - bool can_eq (const BaseType *other, bool emit_errors) const override final; - BaseType *clone () const final override; std::string get_name () const override final; diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 30ead5b..43dd6dc 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -24,31 +24,46 @@ namespace Rust { namespace Resolver { +static TyTy::BaseType * +unify_error_type_node () +{ + static TyTy::BaseType *error = nullptr; + if (error == nullptr) + error = new TyTy::ErrorType (0); + return error; +} + UnifyRules::UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, location_t locus, bool commit_flag, bool emit_error, - bool infer, std::vector<CommitSite> &commits, + bool check_bounds, bool infer, + std::vector<CommitSite> &commits, std::vector<InferenceSite> &infers) : lhs (lhs), rhs (rhs), locus (locus), commit_flag (commit_flag), - emit_error (emit_error), infer_flag (infer), commits (commits), - infers (infers), mappings (Analysis::Mappings::get ()), - context (*TypeCheckContext::get ()) + emit_error (emit_error), infer_flag (infer), + check_bounds_flag (check_bounds), commits (commits), infers (infers), + mappings (Analysis::Mappings::get ()), context (*TypeCheckContext::get ()) {} TyTy::BaseType * UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, location_t locus, bool commit_flag, bool emit_error, - bool infer, std::vector<CommitSite> &commits, + bool check_bounds, bool infer, + std::vector<CommitSite> &commits, std::vector<InferenceSite> &infers) { - UnifyRules r (lhs, rhs, locus, commit_flag, emit_error, infer, commits, - infers); + UnifyRules r (lhs, rhs, locus, commit_flag, emit_error, infer, check_bounds, + commits, infers); TyTy::BaseType *result = r.go (); - commits.push_back ({lhs.get_ty (), rhs.get_ty (), result}); - if (r.commit_flag) - UnifyRules::commit (lhs.get_ty (), rhs.get_ty (), result); - bool failed = result->get_kind () == TyTy::TypeKind::ERROR; + + commits.emplace_back (lhs.get_ty (), rhs.get_ty (), result); + if (r.commit_flag && !failed) + { + result = result->clone (); + UnifyRules::commit (lhs.get_ty (), rhs.get_ty (), result); + } + if (failed && r.emit_error) r.emit_type_mismatch (); @@ -60,7 +75,7 @@ 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); + check_bounds_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 @@ -104,24 +119,59 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other, b->append_reference (resolved->get_ref ()); b->append_reference (o->get_ref ()); - bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER; - bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER; - bool results_is_non_general_infer_var - = (result_is_infer_var - && (static_cast<TyTy::InferType *> (resolved))->get_infer_kind () - != TyTy::InferType::GENERAL); - if (result_resolved || results_is_non_general_infer_var) + if (resolved->get_kind () != TyTy::TypeKind::CONST) { - for (auto &ref : resolved->get_combined_refs ()) + bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER; + bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER; + bool results_is_non_general_infer_var + = (result_is_infer_var + && (static_cast<TyTy::InferType *> (resolved))->get_infer_kind () + != TyTy::InferType::GENERAL); + if (result_resolved || results_is_non_general_infer_var) { - TyTy::BaseType *ref_tyty = nullptr; - bool ok = context.lookup_type (ref, &ref_tyty); - if (!ok) - continue; - - // if any of the types are inference variables lets fix them - if (ref_tyty->is<TyTy::InferType> ()) - context.insert_implicit_type (ref, resolved); + for (auto &ref : resolved->get_combined_refs ()) + { + TyTy::BaseType *ref_tyty = nullptr; + bool ok = context.lookup_type (ref, &ref_tyty); + if (!ok) + continue; + + // if any of the types are inference variables lets fix them + if (ref_tyty->is<TyTy::InferType> ()) + context.insert_implicit_type (ref, resolved); + } + } + } + else + { + auto base_const = resolved->as_const_type (); + if (base_const->const_kind () == TyTy::BaseConstType::ConstKind::Value) + { + rust_debug ("UnifyRules::commit const value, resolved_ref=%u " + "resolved_ty_ref=%u combined_refs.size=%zu", + resolved->get_ref (), resolved->get_ty_ref (), + resolved->get_combined_refs ().size ()); + + for (auto &ref : resolved->get_combined_refs ()) + { + TyTy::BaseType *ref_tyty = nullptr; + bool ok = context.lookup_type (ref, &ref_tyty); + if (!ok) + continue; + if (ref_tyty->get_kind () != TyTy::TypeKind::CONST) + continue; + + auto ref_base_const = ref_tyty->as_const_type (); + if (ref_base_const->const_kind () + == TyTy::BaseConstType::ConstKind::Infer + || ref_base_const->const_kind () + == TyTy::BaseConstType::ConstKind::Decl) + { + rust_debug (" committing to ref=%u kind=%d", ref, + (int) ref_base_const->const_kind ()); + context.insert_implicit_type (ref, resolved); + } + } } } } @@ -155,39 +205,40 @@ UnifyRules::emit_abi_mismatch (const TyTy::FnType &expected, TyTy::BaseType * UnifyRules::go () { - TyTy::BaseType *ltype = lhs.get_ty (); - TyTy::BaseType *rtype = rhs.get_ty (); - - ltype = lhs.get_ty ()->destructure (); - rtype = rhs.get_ty ()->destructure (); + TyTy::BaseType *ltype = lhs.get_ty ()->destructure (); + TyTy::BaseType *rtype = rhs.get_ty ()->destructure (); rust_debug ("unify::go ltype={%s} rtype={%s}", ltype->debug_str ().c_str (), rtype->debug_str ().c_str ()); - // check bounds - bool ltype_is_placeholder = ltype->get_kind () == TyTy::TypeKind::PLACEHOLDER; - bool rtype_is_placeholder = rtype->get_kind () == TyTy::TypeKind::PLACEHOLDER; - bool types_equal = ltype->is_equal (*rtype); - bool should_check_bounds - = !types_equal && !(ltype_is_placeholder || rtype_is_placeholder); - if (should_check_bounds) + if (check_bounds_flag) { - if (ltype->num_specified_bounds () > 0) + bool ltype_is_placeholder + = ltype->get_kind () == TyTy::TypeKind::PLACEHOLDER; + bool rtype_is_placeholder + = rtype->get_kind () == TyTy::TypeKind::PLACEHOLDER; + bool types_equal = ltype->is_equal (*rtype); + bool should_check_bounds + = !types_equal && !(ltype_is_placeholder || rtype_is_placeholder); + if (should_check_bounds) { - if (!ltype->bounds_compatible (*rtype, locus, emit_error)) + if (ltype->num_specified_bounds () > 0) { - // already emitted an error - emit_error = false; - return new TyTy::ErrorType (0); + if (!ltype->bounds_compatible (*rtype, locus, emit_error)) + { + // already emitted an error + emit_error = false; + return unify_error_type_node (); + } } - } - else if (rtype->num_specified_bounds () > 0) - { - if (!rtype->bounds_compatible (*ltype, locus, emit_error)) + else if (rtype->num_specified_bounds () > 0) { - // already emitted an error - emit_error = false; - return new TyTy::ErrorType (0); + if (!rtype->bounds_compatible (*ltype, locus, emit_error)) + { + // already emitted an error + emit_error = false; + return unify_error_type_node (); + } } } } @@ -222,7 +273,7 @@ UnifyRules::go () rust_assert (iv.get_tyty ()->get_kind () == TyTy::TypeKind::INFER); TyTy::InferType *i = static_cast<TyTy::InferType *> (iv.get_tyty ()); - infers.push_back ({p->get_ref (), p->get_ty_ref (), p, i}); + infers.emplace_back (p->get_ref (), p->get_ty_ref (), p, i); // FIXME // this is hacky to set the implicit param lets make this a function @@ -239,7 +290,7 @@ UnifyRules::go () rust_assert (iv.get_tyty ()->get_kind () == TyTy::TypeKind::INFER); TyTy::InferType *i = static_cast<TyTy::InferType *> (iv.get_tyty ()); - infers.push_back ({p->get_ref (), p->get_ty_ref (), p, i}); + infers.emplace_back (p->get_ref (), p->get_ty_ref (), p, i); // FIXME // this is hacky to set the implicit param lets make this a function @@ -248,6 +299,36 @@ UnifyRules::go () // set the rtype now to the new inference var ltype = i; } + else if (ltype->get_kind () == TyTy::TypeKind::CONST + && rtype->get_kind () == TyTy::TypeKind::CONST) + { + const auto &lhs = *ltype->as_const_type (); + const auto &rhs = *rtype->as_const_type (); + + bool both_are_decls + = lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl + && rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl; + bool have_decls + = lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl + || rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl; + + if (have_decls && !both_are_decls) + { + if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl) + { + TyTy::TyVar iv = TyTy::TyVar::get_implicit_const_infer_var ( + lhs.as_base_type ()->get_locus ()); + ltype = iv.get_tyty (); + } + else if (rhs.const_kind () + == TyTy::BaseConstType::ConstKind::Decl) + { + TyTy::TyVar iv = TyTy::TyVar::get_implicit_const_infer_var ( + rhs.as_base_type ()->get_locus ()); + rtype = iv.get_tyty (); + } + } + } } switch (ltype->get_kind ()) @@ -329,13 +410,13 @@ UnifyRules::go () return expect_opaque (static_cast<TyTy::OpaqueType *> (ltype), rtype); case TyTy::CONST: - return expect_const (static_cast<TyTy::ConstType *> (ltype), rtype); + return expect_const (ltype->as_const_type (), rtype); case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -350,7 +431,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, switch (ltype->get_infer_kind ()) { case TyTy::InferType::InferTypeKind::GENERAL: - return rtype->clone (); + return rtype; case TyTy::InferType::InferTypeKind::INTEGRAL: { @@ -388,7 +469,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, == TyTy::InferType::InferTypeKind::INTEGRAL); if (is_valid) { - ltype->apply_primitive_type_hint (*rtype); + if (commit_flag) + ltype->apply_primitive_type_hint (*rtype); return rtype; } } @@ -402,7 +484,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, == TyTy::InferType::InferTypeKind::FLOAT); if (is_valid) { - ltype->apply_primitive_type_hint (*rtype); + if (commit_flag) + ltype->apply_primitive_type_hint (*rtype); return rtype; } } @@ -431,15 +514,15 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype, bool is_valid = (ltype->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL); if (is_valid) - return rtype->clone (); + return rtype; } break; case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -453,7 +536,7 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -462,17 +545,17 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) TyTy::ADTType &type = *static_cast<TyTy::ADTType *> (rtype); if (ltype->get_adt_kind () != type.get_adt_kind ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } if (ltype->get_identifier ().compare (type.get_identifier ()) != 0) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } if (ltype->number_of_variants () != type.number_of_variants ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } for (size_t i = 0; i < type.number_of_variants (); ++i) @@ -482,7 +565,7 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) if (a->num_fields () != b->num_fields ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } for (size_t j = 0; j < a->num_fields (); j++) @@ -498,7 +581,7 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (other_field_ty)); if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } } @@ -521,12 +604,12 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (pb)); if (res->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } } - return type.clone (); + return ltype; } break; @@ -554,9 +637,9 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -570,12 +653,12 @@ UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; case TyTy::STR: - return rtype->clone (); + return rtype; case TyTy::ADT: case TyTy::REF: @@ -601,9 +684,9 @@ UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -617,7 +700,7 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -632,7 +715,7 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (other_base_type)); if (base_resolved->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } // rust is permissive about mutablity here you can always go from @@ -640,12 +723,10 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true; if (!mutability_ok) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ReferenceType (ltype->get_ref (), ltype->get_ty_ref (), - TyTy::TyVar (base_resolved->get_ref ()), - ltype->mutability ()); + return ltype; } break; @@ -673,9 +754,9 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -689,7 +770,7 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -704,7 +785,7 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (other_base_type)); if (base_resolved->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } // rust is permissive about mutablity here you can always go from @@ -712,12 +793,10 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) bool mutability_ok = ltype->is_mutable () ? type.is_mutable () : true; if (!mutability_ok) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::PointerType (ltype->get_ref (), ltype->get_ty_ref (), - TyTy::TyVar (base_resolved->get_ref ()), - ltype->mutability ()); + return ltype; } break; @@ -745,9 +824,9 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -761,7 +840,7 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -810,9 +889,9 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -826,7 +905,7 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -838,24 +917,35 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (type.get_element_type ())); if (element_unify->get_kind () == TyTy::TypeKind::ERROR) - return new TyTy::ErrorType (0); + return unify_error_type_node (); + + auto ltype_cap = ltype->get_capacity (); + auto rtype_cap = type.get_capacity (); + + // If either capacity is not a const type, return error + if (ltype_cap->get_kind () != TyTy::TypeKind::CONST + || rtype_cap->get_kind () != TyTy::TypeKind::CONST) + return unify_error_type_node (); bool save_emit_error = emit_error; emit_error = false; TyTy::BaseType *capacity_unify - = resolve_subtype (TyTy::TyWithLocation (ltype->get_capacity ()), - TyTy::TyWithLocation (type.get_capacity ())); + = resolve_subtype (TyTy::TyWithLocation (ltype_cap), + TyTy::TyWithLocation (rtype_cap)); emit_error = save_emit_error; if (capacity_unify->get_kind () != TyTy::TypeKind::CONST) - return new TyTy::ErrorType (0); - - TyTy::ConstType *capacity_type_unify - = static_cast<TyTy::ConstType *> (capacity_unify); - return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (), - type.get_ident ().locus, - capacity_type_unify, - TyTy::TyVar (element_unify->get_ref ())); + return unify_error_type_node (); + + auto capacity_type_unify = capacity_unify->as_const_type (); + if (capacity_type_unify->const_kind () + == TyTy::BaseConstType::ConstKind::Error) + return unify_error_type_node (); + + return new TyTy::ArrayType ( + type.get_ref (), type.get_ty_ref (), type.get_ident ().locus, + TyTy::TyVar (capacity_type_unify->as_base_type ()->get_ref ()), + TyTy::TyVar (element_unify->get_ref ())); } break; @@ -883,9 +973,9 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -899,7 +989,7 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -911,12 +1001,7 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (type.get_element_type ())); if (element_unify->get_kind () != TyTy::TypeKind::ERROR) - { - return new TyTy::SliceType (type.get_ref (), type.get_ty_ref (), - type.get_ident ().locus, - TyTy::TyVar ( - element_unify->get_ref ())); - } + return ltype; } break; @@ -944,9 +1029,9 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -960,7 +1045,7 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -969,7 +1054,7 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype); if (ltype->num_params () != type.num_params ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } for (size_t i = 0; i < ltype->num_params (); i++) @@ -981,7 +1066,7 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (b)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } @@ -990,7 +1075,7 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (type.get_return_type ())); if (unified_return->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } // ABI match? see @@ -1001,12 +1086,12 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) { emit_abi_mismatch (*ltype, type); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } // DEF Id match? see https://github.com/Rust-GCC/gccrs/issues/2053 - return ltype->clone (); + return ltype; } break; @@ -1034,9 +1119,9 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1050,7 +1135,7 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -1059,7 +1144,7 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) TyTy::FnPtr &type = *static_cast<TyTy::FnPtr *> (rtype); if (ltype->num_params () != type.num_params ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } for (size_t i = 0; i < ltype->num_params (); i++) @@ -1071,7 +1156,7 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (b)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } @@ -1080,10 +1165,20 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (type.get_return_type ())); if (unified_return->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return ltype->clone (); + if (ltype->get_abi () != type.get_abi ()) + { + return unify_error_type_node (); + } + + if (ltype->get_unsafety () != type.get_unsafety ()) + { + return unify_error_type_node (); + } + + return ltype; } break; @@ -1098,12 +1193,12 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (other_ret_type)); if (unified_result->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } if (ltype->num_params () != type.num_params ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } for (size_t i = 0; i < ltype->num_params (); i++) @@ -1116,11 +1211,30 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (other_param)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } - return ltype->clone (); + // FIXME + // + // there is a bug in: + // testsuite/rust/compile/try-catch-unwind-{new,old}.rs I think the test + // + // case is wrong because it should be taking an FnOnce which probably + // didnt exist at the time in gccrs + // + // if (ltype->get_abi () != type.get_abi ()) + // { + // return unify_error_type_node (); + // } + + // FIXME fntype needs to track unsafe or not + // if (ltype->get_unsafety () != type.get_unsafety ()) + // { + // return unify_error_type_node (); + // } + + return ltype; } break; @@ -1135,12 +1249,12 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (other_ret_type)); if (unified_result->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } if (ltype->num_params () != type.get_num_params ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } for (size_t i = 0; i < ltype->num_params (); i++) @@ -1153,11 +1267,11 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (other_param)); if (unified_param->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } - return ltype->clone (); + return ltype; } break; @@ -1183,9 +1297,9 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1199,7 +1313,7 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -1208,7 +1322,7 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) TyTy::TupleType &type = *static_cast<TyTy::TupleType *> (rtype); if (ltype->num_fields () != type.num_fields ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } std::vector<TyTy::TyVar> fields; @@ -1221,13 +1335,12 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) = resolve_subtype (TyTy::TyWithLocation (bo), TyTy::TyWithLocation (fo)); if (unified_ty->get_kind () == TyTy::TypeKind::ERROR) - return new TyTy::ErrorType (0); + return unify_error_type_node (); - fields.push_back (TyTy::TyVar (unified_ty->get_ref ())); + fields.emplace_back (unified_ty->get_ref ()); } - return new TyTy::TupleType (type.get_ref (), type.get_ty_ref (), - type.get_ident ().locus, fields); + return ltype; } break; @@ -1255,9 +1368,9 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1272,14 +1385,15 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype) = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; case TyTy::BOOL: - return rtype->clone (); + return rtype; case TyTy::CHAR: case TyTy::INT: @@ -1305,9 +1419,9 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1322,14 +1436,15 @@ UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype) = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; case TyTy::CHAR: - return rtype->clone (); + return rtype; case TyTy::INT: case TyTy::FLOAT: @@ -1355,9 +1470,9 @@ UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1373,8 +1488,9 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) || r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; @@ -1384,8 +1500,7 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) TyTy::IntType &type = *static_cast<TyTy::IntType *> (rtype); bool is_valid = ltype->get_int_kind () == type.get_int_kind (); if (is_valid) - return new TyTy::IntType (type.get_ref (), type.get_ty_ref (), - type.get_int_kind ()); + return ltype; } break; @@ -1413,9 +1528,9 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1431,8 +1546,9 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) || r->get_infer_kind () == TyTy::InferType::InferTypeKind::INTEGRAL; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; @@ -1442,8 +1558,7 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) TyTy::UintType &type = *static_cast<TyTy::UintType *> (rtype); bool is_valid = ltype->get_uint_kind () == type.get_uint_kind (); if (is_valid) - return new TyTy::UintType (type.get_ref (), type.get_ty_ref (), - type.get_uint_kind ()); + return ltype; } break; @@ -1471,9 +1586,9 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1489,8 +1604,9 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) || r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; @@ -1500,8 +1616,7 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) TyTy::FloatType &type = *static_cast<TyTy::FloatType *> (rtype); bool is_valid = ltype->get_float_kind () == type.get_float_kind (); if (is_valid) - return new TyTy::FloatType (type.get_ref (), type.get_ty_ref (), - type.get_float_kind ()); + return ltype; } break; @@ -1529,9 +1644,9 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1546,14 +1661,15 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype) = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; case TyTy::ISIZE: - return rtype->clone (); + return rtype; case TyTy::ADT: case TyTy::STR: @@ -1579,9 +1695,9 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1596,14 +1712,15 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype) = r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT; if (is_valid) { - r->apply_primitive_type_hint (*ltype); - return ltype->clone (); + if (commit_flag) + r->apply_primitive_type_hint (*ltype); + return ltype; } } break; case TyTy::USIZE: - return rtype->clone (); + return rtype; case TyTy::ADT: case TyTy::STR: @@ -1629,9 +1746,9 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1645,14 +1762,14 @@ UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; default: - return rtype->clone (); + return rtype; } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1667,12 +1784,12 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype, bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; case TyTy::PLACEHOLDER: - return ltype->clone (); + return ltype; case TyTy::PROJECTION: case TyTy::DYNAMIC: @@ -1697,14 +1814,14 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype, case TyTy::NEVER: case TyTy::OPAQUE: if (infer_flag) - return rtype->clone (); + return rtype; gcc_fallthrough (); case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1719,7 +1836,7 @@ UnifyRules::expect_projection (TyTy::ProjectionType *ltype, bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -1752,9 +1869,9 @@ UnifyRules::expect_projection (TyTy::ProjectionType *ltype, case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1768,7 +1885,7 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -1778,15 +1895,15 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) = *static_cast<TyTy::DynamicObjectType *> (rtype); if (ltype->num_specified_bounds () != type.num_specified_bounds ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } if (!ltype->bounds_compatible (type, locus, true)) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return ltype->clone (); + return ltype; } break; @@ -1814,9 +1931,9 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1830,7 +1947,7 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) bool is_valid = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL; if (is_valid) - return ltype->clone (); + return ltype; } break; @@ -1839,7 +1956,7 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) TyTy::ClosureType &type = *static_cast<TyTy::ClosureType *> (rtype); if (ltype->get_def_id () != type.get_def_id ()) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType *args_res @@ -1847,7 +1964,7 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (&type.get_parameters ())); if (args_res->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType *res @@ -1855,10 +1972,10 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) TyTy::TyWithLocation (&type.get_result_type ())); if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR) { - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return ltype->clone (); + return ltype; } break; @@ -1886,9 +2003,9 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype) case TyTy::OPAQUE: case TyTy::CONST: case TyTy::ERROR: - return new TyTy::ErrorType (0); + return unify_error_type_node (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } TyTy::BaseType * @@ -1898,7 +2015,7 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) { TyTy::OpaqueType *ro = rtype->as<TyTy::OpaqueType> (); if (!ltype->is_equal (*ro)) - return new TyTy::ErrorType (0); + return unify_error_type_node (); if (ltype->can_resolve () && ro->can_resolve ()) { @@ -1908,7 +2025,7 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) auto res = resolve_subtype (TyTy::TyWithLocation (lr), TyTy::TyWithLocation (rr)); if (res->get_kind () == TyTy::TypeKind::ERROR) - return new TyTy::ErrorType (0); + return unify_error_type_node (); } else if (ltype->can_resolve ()) { @@ -1927,7 +2044,7 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) auto res = resolve_subtype (TyTy::TyWithLocation (underly), TyTy::TyWithLocation (rtype)); if (res->get_kind () == TyTy::TypeKind::ERROR) - return new TyTy::ErrorType (0); + return unify_error_type_node (); } else { @@ -1938,70 +2055,108 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype) } TyTy::BaseType * -UnifyRules::expect_const (TyTy::ConstType *ltype, TyTy::BaseType *rtype) +UnifyRules::expect_const (TyTy::BaseConstType *ltype, TyTy::BaseType *rtype) { if (rtype->get_kind () != TyTy::TypeKind::CONST) - return new TyTy::ErrorType (0); + return unify_error_type_node (); - TyTy::ConstType &lhs = *ltype; - TyTy::ConstType &rhs = *static_cast<TyTy::ConstType *> (rtype); + auto &lhs = *ltype; + auto &rhs = *rtype->as_const_type (); - auto res = resolve_subtype (TyTy::TyWithLocation (lhs.get_ty ()), - TyTy::TyWithLocation (rhs.get_ty ())); - if (res->get_kind () == TyTy::TypeKind::ERROR) - return new TyTy::ErrorType (0); + // Handle error types early + if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Error + || rhs.const_kind () == TyTy::BaseConstType::ConstKind::Error) + { + auto lhs_base = ltype->as_base_type (); + return new TyTy::ConstErrorType (lhs.get_specified_type (), + lhs_base->get_ref (), + lhs_base->get_ty_ref (), + lhs_base->get_combined_refs ()); + } - tree lv = lhs.get_value (); - tree rv = rhs.get_value (); + // Try to resolve Decl types (ConstParamType) + TyTy::BaseConstType *resolved_lhs = &lhs; + TyTy::BaseConstType *resolved_rhs = &rhs; - if (error_operand_p (lv) && error_operand_p (rv)) + if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl) { - // this is only allowed for some silly senarios like: - // gcc/testsuite/rust/compile/issue-const_generics_5.rs - if (lhs.get_const_kind () == rhs.get_const_kind ()) + auto *param = static_cast<TyTy::ConstParamType *> (&lhs); + if (param->can_resolve ()) { - return new TyTy::ConstType (lhs.get_const_kind (), lhs.get_symbol (), - res, error_mark_node, - lhs.get_specified_bounds (), - lhs.get_locus (), lhs.get_ref (), - lhs.get_ty_ref (), - lhs.get_combined_refs ()); + auto *resolved = param->resolve (); + if (resolved->get_kind () == TyTy::TypeKind::CONST) + resolved_lhs = resolved->as_const_type (); } - - return new TyTy::ErrorType (0); } - bool equal = operand_equal_p (lv, rv, 0); - if (equal) + if (rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl) { - return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - lhs.get_symbol (), res, lv, - lhs.get_specified_bounds (), lhs.get_locus (), - lhs.get_ref (), lhs.get_ty_ref (), - lhs.get_combined_refs ()); + auto *param = static_cast<TyTy::ConstParamType *> (&rhs); + if (param->can_resolve ()) + { + auto *resolved = param->resolve (); + if (resolved->get_kind () == TyTy::TypeKind::CONST) + resolved_rhs = resolved->as_const_type (); + } } - if (lhs.get_const_kind () == TyTy::ConstType::Infer && !error_operand_p (rv)) + auto res = resolve_subtype ( + TyTy::TyWithLocation (resolved_lhs->get_specified_type ()), + TyTy::TyWithLocation (resolved_rhs->get_specified_type ())); + if (res->get_kind () == TyTy::TypeKind::ERROR) + return unify_error_type_node (); + + if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Value + && resolved_rhs->const_kind () == TyTy::BaseConstType::ConstKind::Value) { - lhs.set_value (rv); - return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - lhs.get_symbol (), res, rv, - lhs.get_specified_bounds (), lhs.get_locus (), - lhs.get_ref (), lhs.get_ty_ref (), - lhs.get_combined_refs ()); + auto vlhs = static_cast<TyTy::ConstValueType &> (*resolved_lhs); + auto vrhs = static_cast<TyTy::ConstValueType &> (*resolved_rhs); + tree lv = vlhs.get_value (); + tree rv = vrhs.get_value (); + + bool ok = operand_equal_p (lv, rv, 0); + if (!ok) + return unify_error_type_node (); + else + { + auto lhs_base = resolved_lhs->as_base_type (); + return new TyTy::ConstValueType (lv, res, lhs_base->get_ref (), + lhs_base->get_ty_ref (), + lhs_base->get_combined_refs ()); + } } - else if (rhs.get_const_kind () == TyTy::ConstType::Infer - && !error_operand_p (lv)) + else if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Infer + && resolved_rhs->const_kind () + == TyTy::BaseConstType::ConstKind::Value) + return resolved_rhs->as_base_type (); + else if (resolved_rhs->const_kind () == TyTy::BaseConstType::ConstKind::Infer + && resolved_lhs->const_kind () + == TyTy::BaseConstType::ConstKind::Value) + return resolved_lhs->as_base_type (); + else if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Infer + && resolved_rhs->const_kind () + == TyTy::BaseConstType::ConstKind::Infer) + return resolved_lhs->as_base_type (); + else if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl + || resolved_rhs->const_kind () + == TyTy::BaseConstType::ConstKind::Decl) { - rhs.set_value (lv); - return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, - rhs.get_symbol (), res, lv, - rhs.get_specified_bounds (), rhs.get_locus (), - rhs.get_ref (), rhs.get_ty_ref (), - rhs.get_combined_refs ()); + // If we still have unresolved Decl after trying to resolve, unify with it + // This allows const inference to work + if (resolved_lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl + && resolved_rhs->const_kind () + != TyTy::BaseConstType::ConstKind::Decl) + return resolved_rhs->as_base_type (); + else if (resolved_rhs->const_kind () + == TyTy::BaseConstType::ConstKind::Decl + && resolved_lhs->const_kind () + != TyTy::BaseConstType::ConstKind::Decl) + return resolved_lhs->as_base_type (); + // Both are Decl - return lhs + return resolved_lhs->as_base_type (); } - return new TyTy::ErrorType (0); + return unify_error_type_node (); } } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h index b8c9cbc..4bed24c 100644 --- a/gcc/rust/typecheck/rust-unify.h +++ b/gcc/rust/typecheck/rust-unify.h @@ -30,6 +30,11 @@ class UnifyRules public: struct InferenceSite { + InferenceSite (HirId pref, HirId ptyref, TyTy::ParamType *param, + TyTy::InferType *infer) + : pref (pref), ptyref (ptyref), param (param), infer (infer) + {} + HirId pref; HirId ptyref; TyTy::ParamType *param; @@ -37,6 +42,11 @@ public: }; struct CommitSite { + CommitSite (TyTy::BaseType *lhs, TyTy::BaseType *rhs, + TyTy::BaseType *resolved) + : lhs (lhs), rhs (rhs), resolved (resolved) + {} + TyTy::BaseType *lhs; TyTy::BaseType *rhs; TyTy::BaseType *resolved; @@ -45,6 +55,7 @@ public: static TyTy::BaseType *Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, location_t locus, bool commit_flag, bool emit_error, bool infer, + bool check_bounds, std::vector<CommitSite> &commits, std::vector<InferenceSite> &infers); @@ -84,12 +95,13 @@ protected: TyTy::BaseType *rtype); TyTy::BaseType *expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype); - TyTy::BaseType *expect_const (TyTy::ConstType *ltype, TyTy::BaseType *rtype); + TyTy::BaseType *expect_const (TyTy::BaseConstType *ltype, + TyTy::BaseType *rtype); private: UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs, location_t locus, bool commit_flag, bool emit_error, bool infer, - std::vector<CommitSite> &commits, + bool check_bounds, std::vector<CommitSite> &commits, std::vector<InferenceSite> &infers); TyTy::BaseType *resolve_subtype (TyTy::TyWithLocation lhs, @@ -110,6 +122,7 @@ private: bool commit_flag; bool emit_error; bool infer_flag; + bool check_bounds_flag; std::vector<CommitSite> &commits; std::vector<InferenceSite> &infers; diff --git a/gcc/rust/util/bi-map.h b/gcc/rust/util/bi-map.h index 54870f7..4af157f 100644 --- a/gcc/rust/util/bi-map.h +++ b/gcc/rust/util/bi-map.h @@ -17,6 +17,7 @@ // <http://www.gnu.org/licenses/>. #include "rust-system.h" +#include "optional.h" #ifndef BIMAP_H #define BIMAP_H diff --git a/gcc/rust/util/fnv-hash.h b/gcc/rust/util/fnv-hash.h index 6d2ec01..e51b66a 100644 --- a/gcc/rust/util/fnv-hash.h +++ b/gcc/rust/util/fnv-hash.h @@ -15,6 +15,7 @@ // 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-system.h" #ifndef RUST_FNV_HASH_H #define RUST_FNV_HASH_H diff --git a/gcc/rust/util/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h index 367044a..a22664a 100644 --- a/gcc/rust/util/rust-attribute-values.h +++ b/gcc/rust/util/rust-attribute-values.h @@ -36,6 +36,7 @@ public: static constexpr auto &DOC = "doc"; static constexpr auto &MUST_USE = "must_use"; static constexpr auto &LANG = "lang"; + static constexpr auto &LINK_NAME = "link_name"; static constexpr auto &LINK_SECTION = "link_section"; static constexpr auto &NO_MANGLE = "no_mangle"; static constexpr auto &REPR = "repr"; @@ -48,6 +49,8 @@ public: static constexpr auto &PROC_MACRO_DERIVE = "proc_macro_derive"; static constexpr auto &PROC_MACRO_ATTRIBUTE = "proc_macro_attribute"; + static constexpr auto &DERIVE = "derive"; + static constexpr auto &TARGET_FEATURE = "target_feature"; // From now on, these are reserved by the compiler and gated through // #![feature(rustc_attrs)] @@ -60,6 +63,8 @@ public: static constexpr auto &RUSTC_PROMOTABLE = "rustc_promotable"; static constexpr auto &RUSTC_CONST_STABLE = "rustc_const_stable"; static constexpr auto &RUSTC_CONST_UNSTABLE = "rustc_const_unstable"; + static constexpr auto &RUSTC_ALLOW_CONST_FN_UNSTABLE + = "rustc_allow_const_fn_unstable"; static constexpr auto &RUSTC_SPECIALIZATION_TRAIT = "rustc_specialization_trait"; @@ -88,8 +93,6 @@ public: static constexpr auto &TEST = "test"; - static constexpr auto &SIMD_TEST = "simd_test"; - static constexpr auto &RUSTC_ARGS_REQUIRED_CONST = "rustc_args_required_const"; }; diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index c846c2d..9621100 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -38,6 +38,31 @@ Attributes::is_known (const std::string &attribute_path) return !lookup.is_error (); } +tl::optional<std::string> +Attributes::extract_string_literal (const AST::Attribute &attr) +{ + if (!attr.has_attr_input ()) + return tl::nullopt; + + auto &attr_input = attr.get_attr_input (); + + if (attr_input.get_attr_input_type () + != AST::AttrInput::AttrInputType::LITERAL) + return tl::nullopt; + + auto &literal_expr + = static_cast<AST::AttrInputLiteral &> (attr_input).get_literal (); + + auto lit_type = literal_expr.get_lit_type (); + + // TODO: bring escape sequence handling out of lexing? + if (lit_type != AST::Literal::LitType::STRING + && lit_type != AST::Literal::LitType::RAW_STRING) + return tl::nullopt; + + return literal_expr.as_string (); +} + using Attrs = Values::Attributes; // https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_feature/builtin_attrs.rs.html#248 @@ -53,6 +78,7 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::DOC, HIR_LOWERING}, {Attrs::MUST_USE, STATIC_ANALYSIS}, {Attrs::LANG, HIR_LOWERING}, + {Attrs::LINK_NAME, CODE_GENERATION}, {Attrs::LINK_SECTION, CODE_GENERATION}, {Attrs::NO_MANGLE, CODE_GENERATION}, {Attrs::REPR, CODE_GENERATION}, @@ -64,6 +90,8 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::PROC_MACRO, EXPANSION}, {Attrs::PROC_MACRO_DERIVE, EXPANSION}, {Attrs::PROC_MACRO_ATTRIBUTE, EXPANSION}, + + {Attrs::DERIVE, EXPANSION}, // FIXME: This is not implemented yet, see // https://github.com/Rust-GCC/gccrs/issues/1475 {Attrs::TARGET_FEATURE, CODE_GENERATION}, @@ -78,6 +106,7 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION}, {Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS}, {Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS}, + {Attrs::RUSTC_ALLOW_CONST_FN_UNSTABLE, STATIC_ANALYSIS}, {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION}, {Attrs::TRACK_CALLER, CODE_GENERATION}, {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK}, @@ -100,8 +129,7 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::NON_EXHAUSTIVE, TYPE_CHECK}, {Attrs::RUSTFMT, EXTERNAL}, - {Attrs::TEST, CODE_GENERATION}, - {Attrs::SIMD_TEST, CODE_GENERATION}}; + {Attrs::TEST, CODE_GENERATION}}; BuiltinAttributeMappings * BuiltinAttributeMappings::get () @@ -144,6 +172,7 @@ AttributeChecker::go (AST::Crate &crate) void AttributeChecker::visit (AST::Crate &crate) { + check_inner_attributes (crate.get_inner_attrs ()); check_attributes (crate.get_inner_attrs ()); for (auto &item : crate.items) @@ -214,8 +243,8 @@ check_doc_attribute (const AST::Attribute &attribute) { rust_error_at ( attribute.get_locus (), - // FIXME: Improve error message here. Rustc has a very good one - "%<#[doc]%> cannot be an empty attribute"); + "valid forms for the attribute are " + "%<#[doc(hidden|inline|...)]%> and %<#[doc = \" string \"]%>"); return; } @@ -300,6 +329,20 @@ check_proc_macro_non_root (AST::AttrVec attributes, location_t loc) void AttributeChecker::check_attribute (const AST::Attribute &attribute) { + if (!attribute.empty_input ()) + { + const auto &attr_input = attribute.get_attr_input (); + auto type = attr_input.get_attr_input_type (); + if (type == AST::AttrInput::AttrInputType::TOKEN_TREE) + { + const auto &option = static_cast<const AST::DelimTokenTree &> ( + attribute.get_attr_input ()); + std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item ( + option.parse_to_meta_item ()); + AST::DefaultASTVisitor::visit (meta_item); + } + } + BuiltinAttrDefinition result; // This checker does not check non-builtin attributes @@ -314,6 +357,15 @@ AttributeChecker::check_attribute (const AST::Attribute &attribute) } void +AttributeChecker::check_inner_attributes (const AST::AttrVec &attributes) +{ + for (auto &attr : attributes) + if (attr.is_derive ()) + rust_error_at (attr.get_locus (), + "derive attribute cannot be used at crate level"); +} + +void AttributeChecker::check_attributes (const AST::AttrVec &attributes) { for (auto &attr : attributes) @@ -329,10 +381,6 @@ AttributeChecker::visit (AST::DelimTokenTree &) {} void -AttributeChecker::visit (AST::AttrInputMetaItemContainer &) -{} - -void AttributeChecker::visit (AST::IdentifierExpr &) {} @@ -395,8 +443,16 @@ AttributeChecker::visit (AST::MetaItemLitExpr &) {} void -AttributeChecker::visit (AST::MetaItemPathExpr &) -{} +AttributeChecker::visit (AST::MetaItemPathExpr &attribute) +{ + if (!attribute.get_expr ().is_literal ()) + { + rust_error_at (attribute.get_expr ().get_locus (), + "malformed %<path%> attribute input"); + rust_inform (attribute.get_expr ().get_locus (), + "must be of the form: %<#[path = \"file\"]%>"); + } +} void AttributeChecker::visit (AST::BorrowExpr &) @@ -622,6 +678,7 @@ AttributeChecker::visit (AST::TypeBoundWhereClauseItem &) void AttributeChecker::visit (AST::Module &module) { + check_attributes (module.get_outer_attrs ()); check_proc_macro_non_function (module.get_outer_attrs ()); for (auto &item : module.get_items ()) { @@ -774,10 +831,6 @@ AttributeChecker::visit (AST::StaticItem &item) } void -AttributeChecker::visit (AST::TraitItemConst &) -{} - -void AttributeChecker::visit (AST::TraitItemType &) {} @@ -785,6 +838,7 @@ void AttributeChecker::visit (AST::Trait &trait) { check_proc_macro_non_function (trait.get_outer_attrs ()); + check_attributes (trait.get_outer_attrs ()); } void @@ -841,10 +895,6 @@ AttributeChecker::visit (AST::MetaItemPath &) {} void -AttributeChecker::visit (AST::MetaItemSeq &) -{} - -void AttributeChecker::visit (AST::MetaWord &) {} @@ -920,11 +970,11 @@ AttributeChecker::visit (AST::StructPattern &) // void AttributeChecker::visit(TupleStructItems& ){} void -AttributeChecker::visit (AST::TupleStructItemsNoRange &) +AttributeChecker::visit (AST::TupleStructItemsNoRest &) {} void -AttributeChecker::visit (AST::TupleStructItemsRange &) +AttributeChecker::visit (AST::TupleStructItemsHasRest &) {} void @@ -934,11 +984,11 @@ AttributeChecker::visit (AST::TupleStructPattern &) // void AttributeChecker::visit(TuplePatternItems& ){} void -AttributeChecker::visit (AST::TuplePatternItemsMultiple &) +AttributeChecker::visit (AST::TuplePatternItemsNoRest &) {} void -AttributeChecker::visit (AST::TuplePatternItemsRanged &) +AttributeChecker::visit (AST::TuplePatternItemsHasRest &) {} void diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h index db8fe23..b10a080 100644 --- a/gcc/rust/util/rust-attributes.h +++ b/gcc/rust/util/rust-attributes.h @@ -29,6 +29,8 @@ class Attributes { public: static bool is_known (const std::string &attribute_path); + static tl::optional<std::string> + extract_string_literal (const AST::Attribute &attr); }; enum CompilerPass @@ -104,13 +106,14 @@ private: void check_attribute (const AST::Attribute &attribute); /* Check the validity of all given attributes */ + + void check_inner_attributes (const AST::AttrVec &attributes); void check_attributes (const AST::AttrVec &attributes); // rust-ast.h void visit (AST::Crate &crate) override; void visit (AST::Token &tok) override; void visit (AST::DelimTokenTree &delim_tok_tree) override; - void visit (AST::AttrInputMetaItemContainer &input) override; void visit (AST::IdentifierExpr &ident_expr) override; void visit (AST::Lifetime &lifetime) override; void visit (AST::LifetimeParam &lifetime_param) override; @@ -203,7 +206,6 @@ private: void visit (AST::Union &union_item) override; void visit (AST::ConstantItem &const_item) override; void visit (AST::StaticItem &static_item) override; - void visit (AST::TraitItemConst &item) override; void visit (AST::TraitItemType &item) override; void visit (AST::Trait &trait) override; void visit (AST::InherentImpl &impl) override; @@ -219,7 +221,6 @@ private: void visit (AST::MacroRulesDefinition &rules_def) override; void visit (AST::MacroInvocation ¯o_invoc) override; void visit (AST::MetaItemPath &meta_item) override; - void visit (AST::MetaItemSeq &meta_item) override; void visit (AST::MetaWord &meta_item) override; void visit (AST::MetaNameValueStr &meta_item) override; void visit (AST::MetaListPaths &meta_item) override; @@ -242,12 +243,12 @@ private: void visit (AST::StructPatternFieldIdent &field) override; void visit (AST::StructPattern &pattern) override; // void visit(TupleStructItems& tuple_items) override; - void visit (AST::TupleStructItemsNoRange &tuple_items) override; - void visit (AST::TupleStructItemsRange &tuple_items) override; + void visit (AST::TupleStructItemsNoRest &tuple_items) override; + void visit (AST::TupleStructItemsHasRest &tuple_items) override; void visit (AST::TupleStructPattern &pattern) override; // void visit(TuplePatternItems& tuple_items) override; - void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - void visit (AST::TuplePatternItemsRanged &tuple_items) override; + void visit (AST::TuplePatternItemsNoRest &tuple_items) override; + void visit (AST::TuplePatternItemsHasRest &tuple_items) override; void visit (AST::TuplePattern &pattern) override; void visit (AST::GroupedPattern &pattern) override; void visit (AST::SlicePattern &pattern) override; diff --git a/gcc/rust/util/rust-canonical-path.h b/gcc/rust/util/rust-canonical-path.h index 079ae76..4c4d9df 100644 --- a/gcc/rust/util/rust-canonical-path.h +++ b/gcc/rust/util/rust-canonical-path.h @@ -114,6 +114,8 @@ public: return CanonicalPath (other.segs, crate_num); std::vector<std::pair<NodeId, std::string>> copy (segs); + copy.reserve (other.segs.size ()); + for (auto &s : other.segs) copy.push_back (s); diff --git a/gcc/rust/util/rust-dump.h b/gcc/rust/util/rust-dump.h index c2d9c4d..111174b 100644 --- a/gcc/rust/util/rust-dump.h +++ b/gcc/rust/util/rust-dump.h @@ -16,6 +16,8 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +#include "rust-system.h" + // Common definitions useful for textual dump of IRs (AST and HIR). #ifndef RUST_DUMP_H diff --git a/gcc/rust/util/rust-ggc.cc b/gcc/rust/util/rust-ggc.cc index 0722af2..46220a2 100644 --- a/gcc/rust/util/rust-ggc.cc +++ b/gcc/rust/util/rust-ggc.cc @@ -17,6 +17,7 @@ // <http://www.gnu.org/licenses/>. #include "rust-ggc.h" +#include "rust-ast.h" #include "stringpool.h" namespace Rust { @@ -29,6 +30,8 @@ Ident::Ident (const std::string &str) : inner (get_identifier_with_length (str.c_str (), str.length ())) {} +Ident::Ident (const Rust::Identifier &ident) : Ident (ident.as_string ()) {} + bool Ident::operator== (const std::string &other) const { diff --git a/gcc/rust/util/rust-ggc.h b/gcc/rust/util/rust-ggc.h index da28ede..da4ede1 100644 --- a/gcc/rust/util/rust-ggc.h +++ b/gcc/rust/util/rust-ggc.h @@ -24,6 +24,9 @@ namespace Rust { +// forward declare +class Identifier; + namespace GGC { class Ident @@ -33,6 +36,7 @@ class Ident public: Ident (const char *str); Ident (const std::string &str); + Ident (const Rust::Identifier &ident); bool operator== (const Ident &other) const { return inner == other.inner; } bool operator== (const std::string &other) const; diff --git a/gcc/rust/util/rust-inline-visitor.h b/gcc/rust/util/rust-inline-visitor.h index 2a35aa6..a00cd2c 100644 --- a/gcc/rust/util/rust-inline-visitor.h +++ b/gcc/rust/util/rust-inline-visitor.h @@ -15,6 +15,7 @@ // 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-system.h" // An improved implementation of the inline visitor. // Original idea from https://members.accu.org/index.php/articles/2021 diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h index 67a5d9c..7b9f498 100644 --- a/gcc/rust/util/rust-lang-item.h +++ b/gcc/rust/util/rust-lang-item.h @@ -21,6 +21,9 @@ #include "optional.h" #include "bi-map.h" +#ifndef RUST_LANG_ITEM_H +#define RUST_LANG_ITEM_H + namespace Rust { class LangItem @@ -185,3 +188,5 @@ template <> struct hash<Rust::LangItem::Kind> } }; } // namespace std + +#endif // RUST_LANG_ITEM_H diff --git a/gcc/rust/util/rust-token-converter.cc b/gcc/rust/util/rust-token-converter.cc index 52172f4..0865bf9 100644 --- a/gcc/rust/util/rust-token-converter.cc +++ b/gcc/rust/util/rust-token-converter.cc @@ -102,7 +102,9 @@ ProcMacro::TokenStream convert (const std::vector<const_TokenPtr> &tokens) { std::vector<ProcMacro::TokenStream> trees; - trees.push_back (ProcMacro::TokenStream::make_tokenstream ()); + trees.reserve (tokens.size ()); + + trees.emplace_back (ProcMacro::TokenStream::make_tokenstream ()); for (auto &token : tokens) { auto loc = convert (token->get_locus ()); diff --git a/gcc/rust/util/rust-unwrap-segment.h b/gcc/rust/util/rust-unwrap-segment.h index af3a237..ccc1e61 100644 --- a/gcc/rust/util/rust-unwrap-segment.h +++ b/gcc/rust/util/rust-unwrap-segment.h @@ -16,6 +16,10 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +#include "rust-system.h" +#include "optional.h" +#include "rust-lang-item.h" +#include "rust-mapping-common.h" #include <ast/rust-ast-full-decls.h> namespace Rust { @@ -115,4 +119,20 @@ unwrap_segment_get_lang_item (const std::unique_ptr<T> &ptr) return unwrap_segment_get_lang_item (*ptr); } +/** + * Used to output a path in error messages + */ + +inline static std::string +unwrap_segment_error_string (const AST::TypePath &path) +{ + return path.make_debug_string (); +} + +inline static std::string +unwrap_segment_error_string (const AST::PathInExpression &path) +{ + return path.as_simple_path ().as_string (); +} + } // namespace Rust diff --git a/gcc/symtab.cc b/gcc/symtab.cc index 20dfe09..fb2aca5 100644 --- a/gcc/symtab.cc +++ b/gcc/symtab.cc @@ -873,7 +873,16 @@ symtab_node::dump_referring (FILE *file) fprintf (file, "\n"); } -static const char * const symtab_type_names[] = {"symbol", "function", "variable"}; +static const char * const toplevel_type_names[] = +{ + "base", + "asm", + "symbol", + "function", + "variable", +}; + +static_assert (ARRAY_SIZE(toplevel_type_names)==TOPLEVEL_MAX); /* Dump the visibility of the symbol. */ @@ -889,7 +898,7 @@ symtab_node::get_visibility_string () const const char * symtab_node::get_symtab_type_string () const { - return symtab_type_names[type]; + return toplevel_type_names[type]; } /* Dump base fields of symtab nodes to F. Not to be used directly. */ @@ -904,7 +913,7 @@ symtab_node::dump_base (FILE *f) fprintf (f, "%s (%s)", dump_asm_name (), name ()); if (dump_flags & TDF_ADDRESS) dump_addr (f, " @", (void *)this); - fprintf (f, "\n Type: %s", symtab_type_names[type]); + fprintf (f, "\n Type: %s", toplevel_type_names[type]); if (definition) fprintf (f, " definition"); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e13b07d..013121d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,451 @@ +2025-10-31 Tamar Christina <tamar.christina@arm.com> + + PR target/121853 + * gcc.target/aarch64/pr121853_1.c: New test. + * gcc.target/aarch64/pr121853_2.c: New test. + +2025-10-31 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/122452 + * gfortran.dg/pdt_65.f03: New test. + +2025-10-31 Richard Biener <rguenther@suse.de> + + PR tree-optimization/122502 + * gcc.dg/torture/pr122502.c: New testcase. + +2025-10-31 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + * gcc.dg/tree-ssa/pr122478.c: Swap `1` and `"optimized"`. + +2025-10-31 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR tree-optimization/122497 + * gcc.dg/torture/pr122497-1.c: New test. + +2025-10-31 Lulu Cheng <chenglulu@loongson.cn> + + * gcc.dg/vect/slp-widen-mult-half.c: Remove '-mlasx'. + * gcc.dg/vect/tree-vect.h: Check whether the runtime + environment supports LSX instructions. + * gcc.dg/vect/vect-widen-mult-const-s16.c: Dito. + * gcc.dg/vect/vect-widen-mult-const-u16.c: Dito. + * gcc.dg/vect/vect-widen-mult-half-u8.c: Dito. + * gcc.dg/vect/vect-widen-mult-half.c: Dito. + * gcc.dg/vect/vect-widen-mult-u16.c: Dito. + * gcc.dg/vect/vect-widen-mult-u8-s16-s32.c: Dito. + * gcc.dg/vect/vect-widen-mult-u8-u32.c: Dito. + * gcc.dg/vect/vect-widen-mult-u8.c: Dito. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * rust/compile/tuplepattern-restpattern-typecheck-err.rs: New file. + +2025-10-30 Ryo Yoshida <low.ryoshida@gmail.com> + + * rust/compile/match-tuplestructpattern-non-variant.rs: New test. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * rust/compile/issue-4231.rs: New file. + +2025-10-30 Lucas Ly Ba <lucas.ly-ba@outlook.fr> + + * rust/compile/issue-4212.rs: New test. + +2025-10-30 lishin <lishin1008@gmail.com> + + * rust/compile/issue-3556.rs: New test. + +2025-10-30 Ryo Yoshida <low.ryoshida@gmail.com> + + * rust/compile/tuple_index_on_non_tuple.rs: New test. + +2025-10-30 0xllx0 <github+elle@weathered-steel.dev> + + * rust/compile/issue-4145.rs: New test. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust/compile/attr_malformed_doc.rs: New test. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust/compile/attr_malformed_path.rs: New test. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * rust/compile/match-tuplestructpattern-err.rs: New file. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * rust/compile/match-tuplestructpattern-rest.rs: New file. + * rust/execute/torture/match-tuplestructpattern-rest-1.rs: New file. + * rust/execute/torture/match-tuplestructpattern-rest-2.rs: New file. + +2025-10-30 0xllx0 <github+elle@weathered-steel.dev> + + * rust/compile/issue-4148.rs: New test. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/core/core.exp: New test. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * rust/compile/issue-3929-1.rs: New file. + * rust/compile/issue-3929-2.rs: New file. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/execute/torture/link-name.rs: New test. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust/compile/macros/mbe/macro58.rs: New test. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * rust/compile/issue-3538.rs: New test. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * rust/compile/issue-3592.rs: New test. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * rust/compile/issue-4165.rs: New test. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * rust/compile/issue-4090-1.rs: New test. + * rust/compile/issue-4090-2.rs: New test. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * rust/compile/issue-4168.rs: New test. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * rust/compile/issue-2394.rs: Update test case + * rust/compile/issue-4146.rs: New test. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * rust/compile/issue-4139.rs: New test. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/compile/issue-4155.rs: New test. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust/compile/issue-3922.rs: New test. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust/compile/issue-3924.rs: New test. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * rust/compile/issue-3969.rs: New test. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * rust/compile/issue-3965-1.rs: New test. + * rust/compile/issue-3965-2.rs: New test. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * rust/compile/tuplepattern-rest-readonly.rs: New file. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * rust/compile/issue-3930.rs: New file. + +2025-10-30 Philip Herron <herron.philip@googlemail.com> + + * rust/compile/issue-1725-2.rs: remove bad error message + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust/compile/use_self_alone_in_list.rs: New test. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust/compile/use_self_alone.rs: New test. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/compile/primitive-import.rs: New test. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/compile/parse_float_dot.rs: New test. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/compile/format_args_concat.rs: New test. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/compile/global-path-array.rs: New test. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust/compile/impl_fnptr.rs: New test. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/compile/parse_closure_bind.rs: New test. + +2025-10-30 lishin <lishin1008@gmail.com> + + * rust/compile/issue-3645.rs: New test. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * rust/compile/slice_rest_pattern.rs: Removed -fsyntax-only. + * rust/execute/torture/match-slicepattern-array-2.rs: New file. + * rust/execute/torture/match-slicepattern-slice-2.rs: New file. + +2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com> + + * rust/execute/torture/let-identifierpattern-subpattern.rs: New file. + +2025-10-30 lishin <lishin1008@gmail.com> + + * rust/compile/issue-3958.rs: New test. + +2025-10-30 lishin <lishin1008@gmail.com> + + * rust/compile/issue-3947.rs: New test. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust/compile/issue-3966.rs: New test. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/compile/use_3.rs: New test. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust/compile/issue-3974.rs: New test. + +2025-10-30 Arthur Cohen <arthur.cohen@embecosm.com> + + * rust/compile/issue-3726.rs: New test. + * rust/compile/issue-3898.rs: New test. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/compile/macros/mbe/macro-issue4054.rs: New test. + +2025-10-30 Ryutaro Okada <1015ryu88@gmail.com> + + * rust/compile/enum_discriminant3.rs: New test. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/compile/cfg-test.rs: New test. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust/compile/import_wildcards.rs: New test. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/compile/macros/mbe/macro49.rs: Add missing lang items. + +2025-10-30 lishin <lishin1008@gmail.com> + + * rust/compile/issue-3928.rs: New test. + +2025-10-30 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> + + * rust/execute/inline_asm_inout_ident.rs: Add arch filter on test. + * rust/execute/inline_asm_inout_var.rs: Likewise. + +2025-10-30 Owen Avery <powerboat9.gamer@gmail.com> + + * rust/compile/attr-macro.rs: New test. + +2025-10-30 David Faust <david.faust@oracle.com> + + PR debug/122248 + * gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c: New. + * gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c: New. + * gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c: New. + +2025-10-30 David Faust <david.faust@oracle.com> + + * gcc.dg/debug/btf/btf-prune-4.c: New. + +2025-10-30 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.dg/cpp/escape-3.i: Remove parentheses in dg-scan directive. + +2025-10-30 Qing Zhao <qing.zhao@oracle.com> + + * gcc.dg/pointer-counted-by.c: Update for void pointers. + * gcc.dg/pointer-counted-by-10.c: New test. + * gcc.dg/pointer-counted-by-4-void.c: New test. + +2025-10-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR target/116075 + * gcc.target/aarch64/sve/dup-insr-1.c: New test. + * gcc.target/aarch64/sve/dup-insr-2.c: New test. + +2025-10-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR tree-optimization/122247 + * g++.dg/tree-ssa/copy-prop-aggregate-sra-2.C: New test. + +2025-10-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR tree-optimization/122247 + * g++.dg/tree-ssa/copy-prop-aggregate-sra-1.C: New test. + +2025-10-30 Robin Dapp <rdapp@ventanamicro.com> + + * gcc.dg/tree-ssa/ctz-char.c: Remove -fno-tree-ch. + * gcc.dg/tree-ssa/ctz-complement-char.c: Ditto. + * gcc.dg/tree-ssa/ctz-complement-int.c: Ditto. + * gcc.dg/tree-ssa/ctz-complement-long-long.c: Ditto. + * gcc.dg/tree-ssa/ctz-complement-long.c: Ditto. + * gcc.dg/tree-ssa/ctz-int.c: Ditto. + * gcc.dg/tree-ssa/ctz-long-long.c: Ditto. + * gcc.dg/tree-ssa/ctz-long.c: Ditto. + * gcc.dg/tree-ssa/ctz-ch.c: New test. + * gcc.dg/pr41488.c: Add -fno-tree-scev-cprop. + +2025-10-30 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/specs/generic_inst7.ads: New test. + * gnat.dg/specs/generic_inst8.ads: New test. + +2025-10-30 Robin Dapp <rdapp.gcc@gmail.com> + + PR target/122445 + * gcc.target/riscv/rvv/autovec/pr122445.c: New test. + +2025-10-30 Artemiy Volkov <artemiy.volkov@arm.com> + + PR tree-optimization/122478 + * gcc.dg/tree-ssa/pr122478.c: New test. + +2025-10-30 Richard Biener <rguenther@suse.de> + + * gcc.dg/tree-ssa/pr92834.c: Scan phiopt1 instead of optimized. + +2025-10-30 Stefan Schulze Frielinghaus <stefansf@gcc.gnu.org> + + PR rtl-optimization/121198 + * gcc.target/avr/pr121198.c: New test. + +2025-10-30 Gaius Mulley <gaiusmod2@gmail.com> + + PR modula2/122485 + * gm2.dg/spell/iso/fail/badimport.mod: New test. + +2025-10-30 Richard Biener <rguenther@suse.de> + Eric Botcazou <ebotcazou@adacore.com> + + * gcc.dg/vect/slp-reduc-13.c: New testcase. + +2025-10-30 Uros Bizjak <ubizjak@gmail.com> + + PR target/116815 + * gcc.dg/pr116815.c: New test. + * gcc.target/i386/pr116815.c: New test. + +2025-10-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + * c-c++-common/ubsan/align-5.c: Xfail. + * gcc.dg/pr107389.c: Move to... + * gcc.dg/torture/pr107389.c: ...here. Skip for lto. + * gcc.dg/builtin-assume-aligned-1.c: Instead of + testing for deleting of assume-align, test for + the alignment/misalignment. Also disable the + vectorizer. + +2025-10-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + Revert: + 2025-10-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR middle-end/107389 + PR tree-optimization/122086 + * gcc.dg/pr107389.c: Move to... + * gcc.dg/torture/pr107389.c: ...here. Skip for lto. + Use dg-additional-options rather than dg-options. + * c-c++-common/ubsan/align-5.c: xfail. + +2025-10-30 liuhongt <hongtao.liu@intel.com> + + * gcc.target/i386/pr122457.c: New test. + +2025-10-30 Guo Jie <guojie@loongson.cn> + + * gcc.target/loongarch/fnmam4-vec.c: New test. + +2025-10-30 Jinyang He <hejinyang@loongson.cn> + Peng Fan <fanpeng@loongson.cn> + + * gcc.target/loongarch/conditional-move-opt-1.c: Remove mul. + * gcc.target/loongarch/conditional-move-opt-2.c: Remove and. + * gcc.target/loongarch/conditional-move-opt-3.c: New test. + +2025-10-30 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/aggr32.adb: New test. + * gnat.dg/aggr32_pkg.ads: New helper. + * gnat.dg/aggr32_pkg-child.ads: Likewise. + +2025-10-30 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/specs/generic_inst6.ads: New test. + * gnat.dg/specs/generic_inst6_pkg1-child.ads: New helper. + * gnat.dg/specs/generic_inst6_pkg1-child-grand1.ads: Likewise. + * gnat.dg/specs/generic_inst6_pkg1-child-grand2.ads: Likewise. + * gnat.dg/specs/generic_inst6_pkg1.ads: Likewise. + * gnat.dg/specs/generic_inst6_pkg2.ads: Likewise. + * gnat.dg/specs/generic_inst6_pkg3.ads: Likewise. + +2025-10-29 Andrew MacLeod <amacleod@redhat.com> + + PR tree-optimization/91191 + * gcc.dg/pr91191.c: New. + +2025-10-29 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/122165 + * gfortran.dg/pdt_64.f03: New test. + +2025-10-29 Richard Biener <rguenther@suse.de> + + PR tree-optimization/70102 + * gfortran.dg/vect/pr70102.f: New testcase. + +2025-10-29 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/122433 + PR fortran/122434 + * gfortran.dg/pdt_62.f03: New test. + * gfortran.dg/pdt_63.f03: New test. + +2025-10-29 Lulu Cheng <chenglulu@loongson.cn> + + PR target/122097 + * gcc.target/loongarch/pr122097.c: New test. + +2025-10-29 Xi Ruoyao <xry111@xry111.site> + + * gcc.target/loongarch/trap-default.c: New test. + * gcc.target/loongarch/trap-1.c: New test. + 2025-10-28 Yuao Ma <c8ef@outlook.com> PR fortran/122342 diff --git a/gcc/testsuite/g++.dg/tree-ssa/copy-prop-aggregate-sra-1.C b/gcc/testsuite/g++.dg/tree-ssa/copy-prop-aggregate-sra-1.C new file mode 100644 index 0000000..52f1779 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/copy-prop-aggregate-sra-1.C @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-forwprop1-details -fdump-tree-esra-details -fexceptions" } */ + +/* PR tree-optimization/122247 */ + +struct s1 +{ + int t[1024]; +}; + +struct s1 f(void); + +void g(int a, int b, int ); +void p(struct s1); +void h(struct s1 outer) +{ + { + struct s1 inner = outer; + p(inner); + } + g(outer.t[0], outer.t[1], outer.t[2]); +} +/* Forwprop should be able to copy prop the copy of `inner = outer` to the call of p. + Also remove this copy. */ + +/* { dg-final { scan-tree-dump-times "after previous" 1 "forwprop1" } } */ +/* { dg-final { scan-tree-dump-times "Removing dead store stmt inner = outer" 1 "forwprop1" } } */ + +/* The extra copy that was done by inlining is removed so SRA should not decide to cause + inner nor outer to be scalarized even for the 3 elements accessed afterwards. */ +/* { dg-final { scan-tree-dump-times "Disqualifying inner" 1 "esra" } } */ +/* { dg-final { scan-tree-dump-times "Disqualifying outer" 1 "esra" } } */ + diff --git a/gcc/testsuite/g++.dg/tree-ssa/copy-prop-aggregate-sra-2.C b/gcc/testsuite/g++.dg/tree-ssa/copy-prop-aggregate-sra-2.C new file mode 100644 index 0000000..0b05d5d --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/copy-prop-aggregate-sra-2.C @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop1-details -fdump-tree-esra-details -fexceptions" } */ + +/* PR tree-optimization/122247 */ + +struct s1 +{ + int t[1024]; +}; + +struct s1 f(void); + +void g(int a, int b, int ); +void p(struct s1); +void h(struct s1 outer) +{ + struct s1 inner = outer; + p(inner); + g(outer.t[0], outer.t[1], outer.t[2]); +} +/* Forwprop should be able to copy prop the copy of `inner = outer` to the call of p. + Also remove this copy. */ + +/* { dg-final { scan-tree-dump-times "after previous" 1 "forwprop1" } } */ +/* { dg-final { scan-tree-dump-times "Removing dead store stmt inner = outer" 1 "forwprop1" } } */ + +/* The extra copy that was done by inlining is removed so SRA should not decide to cause + inner nor outer to be scalarized even for the 3 elements accessed afterwards. */ +/* { dg-final { scan-tree-dump-times "Disqualifying inner" 1 "esra" } } */ +/* { dg-final { scan-tree-dump-times "Disqualifying outer" 1 "esra" } } */ + diff --git a/gcc/testsuite/gcc.dg/builtin-assume-aligned-1.c b/gcc/testsuite/gcc.dg/builtin-assume-aligned-1.c index a74ecce..01aa884 100644 --- a/gcc/testsuite/gcc.dg/builtin-assume-aligned-1.c +++ b/gcc/testsuite/gcc.dg/builtin-assume-aligned-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -fdump-tree-optimized" } */ +/* { dg-options "-O3 -fno-tree-vectorize -fdump-tree-optimized-alias" } */ void test1 (double *out1, double *out2, double *out3, double *in1, @@ -19,6 +19,8 @@ test1 (double *out1, double *out2, double *out3, double *in1, } } +/* { dg-final { scan-tree-dump-times " ALIGN = 16, MISALIGN = 0" 5 "optimized" } } */ + void test2 (double *out1, double *out2, double *out3, double *in1, double *in2, int len) @@ -37,4 +39,8 @@ test2 (double *out1, double *out2, double *out3, double *in1, } } -/* { dg-final { scan-tree-dump-not "__builtin_assume_aligned" "optimized" } } */ + +/* { dg-final { scan-tree-dump-times " ALIGN = 32" 5 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " ALIGN = 32, MISALIGN = 16" 4 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " ALIGN = 32, MISALIGN = 0" 1 "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/cpp/escape-3.i b/gcc/testsuite/gcc.dg/cpp/escape-3.i index 6eb7dc4..cb47581 100644 --- a/gcc/testsuite/gcc.dg/cpp/escape-3.i +++ b/gcc/testsuite/gcc.dg/cpp/escape-3.i @@ -13,4 +13,4 @@ int foo (int a, int b) } /* Test for "/some\\directory" instead of "/some\\\\directory" */ -/* { dg-final { scan-assembler { "/some\\\\directory" } } } */ +/* { dg-final { scan-assembler "/some\\\\\\\\directory" } } */ diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-prune-4.c b/gcc/testsuite/gcc.dg/debug/btf/btf-prune-4.c new file mode 100644 index 0000000..3f19559 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-prune-4.c @@ -0,0 +1,61 @@ +/* Test that -gprune-btf does not prune at typedefs. */ + +/* { dg-do compile } */ +/* { dg-options "-gbtf -gprune-btf -dA" } */ + +/* We must have the full definitions of td1 and td3. Neither are pruned. + td2 will be skipped entirely, only because the only reference to + it is through struct inner, which is pruned because inner itself + is only used as a pointer member. + + In general, we must never get an anonymous FWD; the only FWD in this + case will be for 'inner' */ + +/* Exactly 1 FWD for inner and no anonymous FWD. */ +/* { dg-final { scan-assembler-times "TYPE \[0-9\]+ BTF_KIND_FWD" 1 } } */ +/* { dg-final { scan-assembler-not "TYPE \[0-9\]+ BTF_KIND_FWD ''" } } */ +/* { dg-final { scan-assembler " BTF_KIND_FWD 'inner'" } } */ + +/* One anonymous struct for td1 and one anonymous union for td3. */ +/* { dg-final { scan-assembler-times "TYPE \[0-9\]+ BTF_KIND_STRUCT ''" 1 } } */ +/* { dg-final { scan-assembler-times "TYPE \[0-9\]+ BTF_KIND_UNION ''" 1 } } */ + +/* The two remaining typedefs. */ +/* { dg-final { scan-assembler " BTF_KIND_TYPEDEF 'td1'" } } */ +/* { dg-final { scan-assembler " BTF_KIND_TYPEDEF 'td3'" } } */ + +typedef struct { + int x; + char c; +} td1; + +typedef struct { + long l; + char b[4]; +} td2; + +typedef union { + long l; + unsigned short s[2]; +} td3; + +struct inner { + char a; + td2 *ptd; + long z; +}; + +struct A { + td1 *pt; + struct inner *in; + unsigned long l[4]; +}; + +struct A foo; + +struct B { + int x; + td3 **ppptd3; +}; + +struct B bar; diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c new file mode 100644 index 0000000..6fdcdc6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-4.c @@ -0,0 +1,28 @@ +/* Test DWARF generation for decl_tags on global decls appearing multiple + times with different decl_tags. PR122248. */ +/* { dg-do compile } */ +/* { dg-options "-gdwarf -dA" } */ + +#define __tag1 __attribute__((btf_decl_tag ("tag1"))) +#define __tag2 __attribute__((btf_decl_tag ("tag2"))) +#define __tag3 __attribute__((btf_decl_tag ("tag3"))) +#define __tag4 __attribute__((btf_decl_tag ("tag4"))) + +int foo __tag1; +int foo __tag2; + +/* Result: foo has __tag1 and __tag2. */ + +int bar __tag3; +int bar; + +/* Result: bar has __tag3. */ + +int baz; +int baz __tag4; + +/* Result: baz has __tag4. */ + +/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_GNU_annotation" 4 } } */ +/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 4 } } */ + diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c new file mode 100644 index 0000000..c7cb60c --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-5.c @@ -0,0 +1,35 @@ +/* Test DWARF generation for decl_tags on global decls appearing multiple + times with different decl_tags. PR122248. */ +/* { dg-do compile } */ +/* { dg-options "-gdwarf -dA" } */ + +#define __tag1 __attribute__((btf_decl_tag ("tag1"))) +#define __tag2 __attribute__((btf_decl_tag ("tag2"))) +#define __tag3 __attribute__((btf_decl_tag ("tag3"))) + +struct S +{ + int x; + char c; +}; + +extern struct S foo __tag1; +struct S foo __tag2; + +/* Result: non-completing variable DIE for 'foo' has tag1, and the + completing DIE (with AT_specification) for 'foo' has tag2 -> tag1. */ + +extern int a __tag3; +int a; + +/* Result: non-completing variable DIE for a has tag3, and the + completing DIE (with AT_specification) for 'a' also refers to tag3. */ + +/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_GNU_annotation" 3 } } */ + +/* 5 AT_GNU annotations: + - foo -> tag1 + - foo -> tag2 -> tag1 + - a -> tag3 + - a -> tag3 */ +/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 5 } } */ diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c new file mode 100644 index 0000000..dd89d11 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf-btf-decl-tag-6.c @@ -0,0 +1,24 @@ +/* Test DWARF generation for decl_tags on global decls appearing multiple + times with different decl_tags. PR122248. */ +/* { dg-do compile } */ +/* { dg-options "-gdwarf -dA" } */ + +#define __tag1 __attribute__((btf_decl_tag ("tag1"))) +#define __tag2 __attribute__((btf_decl_tag ("tag2"))) +#define __tag3 __attribute__((btf_decl_tag ("tag3"))) + +__tag1 +extern int +do_thing (int); + +__tag2 +__tag3 +int +do_thing (int x) +{ + return x * x; +} + +/* Result: do_thing has all 3 tags. */ +/* { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_GNU_annotation" 3 } } */ +/* { dg-final { scan-assembler-times " DW_AT_GNU_annotation" 3 } } */ diff --git a/gcc/testsuite/gcc.dg/fold-vecperm-1.c b/gcc/testsuite/gcc.dg/fold-vecperm-1.c index 5d4456b..878d392 100644 --- a/gcc/testsuite/gcc.dg/fold-vecperm-1.c +++ b/gcc/testsuite/gcc.dg/fold-vecperm-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-forwprop3" } */ typedef int v4si __attribute__((vector_size(16))); typedef short v8hi __attribute__((vector_size(16))); @@ -20,4 +20,4 @@ int128 concat (int128 a, int128 b) { return res; } -/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 1 "forwprop3" } } */ diff --git a/gcc/testsuite/gcc.dg/gnu-compoundlit-1.c b/gcc/testsuite/gcc.dg/gnu-compoundlit-1.c new file mode 100644 index 0000000..a7f3496 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu-compoundlit-1.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-std=gnu23" } */ + +int g(int n, int (*p)[n]); +int f(int n) +{ + return g(n, &(int[n]){ }); +} + +void h(int n) +{ + (int[n]){ 1 }; /* { dg-error "empty initializer" } */ +} + +void i(int n) +{ + (static int[3]){ }; + (static int[n]){ }; /* { dg-error "storage size" } */ + (constexpr int[3]){ }; + (constexpr int[n]){ }; /* { dg-error "storage size" } */ + (register int[3]){ }; /* { dg-error "register" } */ + (register int[n]){ }; /* { dg-error "register" } */ + (_Thread_local int[3]){ }; /* { dg-error "_Thread_local" } */ + (_Thread_local int[n]){ }; /* { dg-error "_Thread_local" } */ +} + diff --git a/gcc/testsuite/gcc.dg/gnu-compoundlit-2.c b/gcc/testsuite/gcc.dg/gnu-compoundlit-2.c new file mode 100644 index 0000000..dcc5775 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu-compoundlit-2.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu23 -Wall" } */ + +[[gnu::noinline,gnu::noipa]] +static bool f(int n) +{ + struct foo { char a[n]; }; + struct foo x = { }; + + return 0 == __builtin_memcmp(&x, &(struct foo){ }, sizeof x); +} + +int main() +{ + if (!f(7)) + __builtin_abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-10.c b/gcc/testsuite/gcc.dg/pointer-counted-by-10.c new file mode 100644 index 0000000..e2bd018 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-10.c @@ -0,0 +1,8 @@ +/* Testing the correct usage of attribute counted_by for pointer to void. */ +/* { dg-do compile } */ +/* { dg-options "-O0 -Wpointer-arith" } */ + +struct pointer_array { + int count; + void *array __attribute__ ((counted_by (count))); /* { dg-warning "attribute is used for a pointer to void" } */ +}; diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-void.c b/gcc/testsuite/gcc.dg/pointer-counted-by-4-void.c new file mode 100644 index 0000000..71bac95 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4-void.c @@ -0,0 +1,6 @@ +/* Test the attribute counted_by for pointer field and its usage in + * __builtin_dynamic_object_size. */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +#define PTR_TYPE void +#include "pointer-counted-by-4.c" diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by.c b/gcc/testsuite/gcc.dg/pointer-counted-by.c index 0f18828..5e9ebef 100644 --- a/gcc/testsuite/gcc.dg/pointer-counted-by.c +++ b/gcc/testsuite/gcc.dg/pointer-counted-by.c @@ -49,9 +49,10 @@ struct pointer_array_6 { int *array_6 __attribute__ ((counted_by (days))); }; +/* counted_by is allowed for pointer to void when GNU extension is enabled. */ struct pointer_array_7 { int count; - void *array_7 __attribute__ ((counted_by (count))); /* { dg-error "attribute is not allowed for a pointer to void" } */ + void *array_7 __attribute__ ((counted_by (count))); }; struct pointer_array_8 { diff --git a/gcc/testsuite/gcc.dg/pr116815.c b/gcc/testsuite/gcc.dg/pr116815.c new file mode 100644 index 0000000..b5f1330 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr116815.c @@ -0,0 +1,57 @@ +/* PR target/116815 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +[[gnu::always_inline]] +inline unsigned min (unsigned a, unsigned b) +{ + return (a < b) ? a : b; +} + +[[gnu::always_inline]] +inline unsigned max (unsigned a, unsigned b) +{ + return (a > b) ? a : b; +} + +[[gnu::noipa]] unsigned +umaxadd (unsigned a, unsigned b) +{ + return max (a + b, a); +} + +[[gnu::noipa]] unsigned +umaxsub (unsigned a, unsigned b) +{ + return max (a - b, a); +} + +[[gnu::noipa]] unsigned +uminadd (unsigned a, unsigned b) +{ + return min (a + b, a); +} + +[[gnu::noipa]] unsigned +uminsub (unsigned a, unsigned b) +{ + return min (a - b, a); +} + +int +main () +{ + /* Overflows to 0x30000000. */ + if (umaxadd (0x90000000, 0xa0000000) != 0x90000000) + __builtin_abort (); + + if (uminadd (0x90000000, 0xa0000000) != 0x30000000) + __builtin_abort (); + + /* Underflows to 0x60000000. */ + if (umaxsub (0x00000000, 0xa0000000) != 0x60000000) + __builtin_abort (); + + if (uminsub (0x00000000, 0xa0000000) != 0x00000000) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/pr41488.c b/gcc/testsuite/gcc.dg/pr41488.c index 1e4bf19..a7ba367 100644 --- a/gcc/testsuite/gcc.dg/pr41488.c +++ b/gcc/testsuite/gcc.dg/pr41488.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-ivcanon-scev" } */ +/* { dg-options "-O2 -fno-tree-scev-cprop -fdump-tree-ivcanon-scev" } */ struct struct_t { diff --git a/gcc/testsuite/gcc.dg/pr68090.c b/gcc/testsuite/gcc.dg/pr68090.c index 87b3b93..84e0ca4 100644 --- a/gcc/testsuite/gcc.dg/pr68090.c +++ b/gcc/testsuite/gcc.dg/pr68090.c @@ -1,13 +1,18 @@ /* PR c/68090 */ /* { dg-do compile } */ -/* { dg-options "" } */ +/* { dg-options "--pedantic-error" } */ void fn (int i) { (int[(0, 1)]) { 0 }; /* { dg-error "compound literal has variable size" } */ + /* { dg-error "variable-size" "" { target *-*-* } .-1 } */ (int[i]) { 0 }; /* { dg-error "compound literal has variable size" } */ + /* { dg-error "variable-size" "" { target *-*-* } .-1 } */ (int[(0, i)]) { 0 }; /* { dg-error "compound literal has variable size" } */ + /* { dg-error "variable-size" "" { target *-*-* } .-1 } */ (int [][i]){ 0 }; /* { dg-error "compound literal has variable size" } */ + /* { dg-error "variable-size" "" { target *-*-* } .-1 } */ (int [][(1, 2)]){ 0 }; /* { dg-error "compound literal has variable size" } */ + /* { dg-error "variable-size" "" { target *-*-* } .-1 } */ } diff --git a/gcc/testsuite/gcc.dg/pr91191.c b/gcc/testsuite/gcc.dg/pr91191.c new file mode 100644 index 0000000..7bf727e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr91191.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +unsigned char reg(_Bool b) { + union U { + unsigned char f0; + _Bool f1; + }; + union U u; + u.f1 = b; + if (u.f0 > 1) { + // This cannot happen + // if b is only allowed + // to be 0 or 1: + return 42; + } + return 13; +} + +/* { dg-final { scan-tree-dump "return 13" "evrp" } } */ diff --git a/gcc/testsuite/gcc.dg/pr97986-1.c b/gcc/testsuite/gcc.dg/pr97986-1.c new file mode 100644 index 0000000..87ee3d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97986-1.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu23" } */ + +#include <stdarg.h> + +int f(int n, ...) +{ + __label__ b, d; + va_list ap; + va_start(ap, n); + _Static_assert(5 == sizeof(va_arg(ap, char[5]))); /* { dg-warning "array type" } */ + void g(void) { n++; goto b; } + int *a = va_arg((g(), ap), int[n]); /* { dg-warning "array type" } */ +b: + void h(void) { n++; goto d; } + typeof(va_arg(ap, int[(h(), n)])) c; /* { dg-warning "array type" } */ +d: + return n; +} + +int main() +{ + if (9 != f(7)) + __builtin_abort(); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/pr97986-2.c b/gcc/testsuite/gcc.dg/pr97986-2.c new file mode 100644 index 0000000..fc23a57 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97986-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c90" } */ + +#include <stdarg.h> + + +int f(int n, ...) +{ + va_list ap; + va_start(ap, n); + _Static_assert(5 == sizeof(va_arg(ap, char[5]))); + va_arg(ap, int[n]); /* { dg-error "array type" } */ + int * a = va_arg(ap, int[3]); /* { dg-error "invalid use of non-lvalue array" } */ +} + diff --git a/gcc/testsuite/gcc.dg/torture/pr122497-1.c b/gcc/testsuite/gcc.dg/torture/pr122497-1.c new file mode 100644 index 0000000..8b027ca --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr122497-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* PR tree-optimization/122497 */ + +/* This was ICEing during SCCP + trying to simplify a reference back to the phi + which was removed. */ + +char g_2[1][2]; +int g_4, g_5; +void main() { + for (; g_4; g_4 -= 1) + g_5 = g_2[g_4 + 2][g_4]; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr122502.c b/gcc/testsuite/gcc.dg/torture/pr122502.c new file mode 100644 index 0000000..5e2cb2e --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr122502.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ + +short int *ts; + +void +c2 (unsigned long long int s4, int ns) +{ + short int *b2 = (short int *)&ns; + + while (ns != 0) + { + int xn; + + for (xn = 0; xn < 3; ++xn) + for (*b2 = 0; *b2 < 2; ++*b2) + s4 += xn; + if (s4 != 0) + b2 = ts; + ++ns; + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ctz-ch.c b/gcc/testsuite/gcc.dg/tree-ssa/ctz-ch.c new file mode 100644 index 0000000..5d72597 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ctz-ch.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +typedef unsigned long BITMAP_WORD; + +bool +bmp_iter_set (BITMAP_WORD bits, unsigned *bit_no) +{ + /* If our current word is nonzero, it contains the bit we want. */ + if (bits) + { + while (!(bits & 1)) + { + bits >>= 1; + *bit_no += 1; + } + return true; + } + + return false; +} + +/* { dg-final { scan-tree-dump-times "__builtin_ctz|\\.CTZ" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ctz-char.c b/gcc/testsuite/gcc.dg/tree-ssa/ctz-char.c index 3cd166a..fa8b7f3 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ctz-char.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ctz-char.c @@ -1,6 +1,6 @@ /* { dg-do run } */ /* { dg-require-effective-target ctz } */ -/* { dg-options "-O2 -fno-tree-ch -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ #define PREC (__CHAR_BIT__) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-char.c b/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-char.c index b9afe88..5ebc321 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-char.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-char.c @@ -1,6 +1,6 @@ /* { dg-do run } */ /* { dg-require-effective-target ctz } */ -/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fno-tree-ch -fdump-tree-optimized" } */ #define PREC (__CHAR_BIT__) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-int.c b/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-int.c index d2702a6..0ce4b6b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-int.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-int.c @@ -1,6 +1,6 @@ /* { dg-do run } */ /* { dg-require-effective-target ctz } */ -/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fno-tree-ch -fdump-tree-optimized" } */ #define PREC (__CHAR_BIT__ * __SIZEOF_INT__) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-long-long.c b/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-long-long.c index 1ea0d5d..f98bec0 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-long-long.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-long-long.c @@ -1,6 +1,6 @@ /* { dg-do run } */ /* { dg-require-effective-target ctzll } */ -/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fno-tree-ch -fdump-tree-optimized" } */ #define PREC (__CHAR_BIT__ * __SIZEOF_LONG_LONG__) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-long.c b/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-long.c index 80fb02d..8edb372 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-long.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ctz-complement-long.c @@ -1,6 +1,6 @@ /* { dg-do run } */ /* { dg-require-effective-target ctzl } */ -/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fno-tree-ch -fdump-tree-optimized" } */ #define PREC (__CHAR_BIT__ * __SIZEOF_LONG__) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ctz-int.c b/gcc/testsuite/gcc.dg/tree-ssa/ctz-int.c index 7f63493..2bf3ae6 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ctz-int.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ctz-int.c @@ -1,6 +1,6 @@ /* { dg-do run } */ /* { dg-require-effective-target ctz } */ -/* { dg-options "-O2 -fno-tree-ch -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ #define PREC (__CHAR_BIT__ * __SIZEOF_INT__) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ctz-long-long.c b/gcc/testsuite/gcc.dg/tree-ssa/ctz-long-long.c index 924f61b..2e15948 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ctz-long-long.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ctz-long-long.c @@ -1,6 +1,6 @@ /* { dg-do run } */ /* { dg-require-effective-target ctzll } */ -/* { dg-options "-O2 -fno-tree-ch -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ #define PREC (__CHAR_BIT__ * __SIZEOF_LONG_LONG__) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ctz-long.c b/gcc/testsuite/gcc.dg/tree-ssa/ctz-long.c index 178945d..2e3be65 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ctz-long.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ctz-long.c @@ -1,6 +1,6 @@ /* { dg-do run } */ /* { dg-require-effective-target ctzl } */ -/* { dg-options "-O2 -fno-tree-ch -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ #define PREC (__CHAR_BIT__ * __SIZEOF_LONG__) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr122478.c b/gcc/testsuite/gcc.dg/tree-ssa/pr122478.c new file mode 100644 index 0000000..a39c91b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr122478.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-additional-options "-fgimple" } */ + +unsigned char __GIMPLE (ssa) +foo (unsigned short mask__701) +{ + _Bool _19; + unsigned char _180; + +__BB(2): + _19 = __BIT_FIELD_REF <_Bool> (mask__701, 1, 12); + _180 = __VIEW_CONVERT<unsigned char>(_19); + return _180; +} + +/* { dg-final { scan-tree-dump-times "VIEW_CONVERT_EXPR" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr92834.c b/gcc/testsuite/gcc.dg/tree-ssa/pr92834.c index 889048d..70acf74 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr92834.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr92834.c @@ -1,8 +1,8 @@ /* PR tree-optimization/92834 */ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-optimized" } */ -/* { dg-final { scan-tree-dump-times "MIN_EXPR <" 8 "optimized" } } */ -/* { dg-final { scan-tree-dump-times "MAX_EXPR <" 8 "optimized" } } */ +/* { dg-options "-O2 -fdump-tree-phiopt1" } */ +/* { dg-final { scan-tree-dump-times "MIN_EXPR <" 16 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR <" 16 "phiopt1" } } */ static inline unsigned umax1 (unsigned a, unsigned b) diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-13.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-13.c new file mode 100644 index 0000000..00e91fc --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-13.c @@ -0,0 +1,66 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ +/* { dg-additional-options "-fgimple" } */ + +int q[2]; + +void __GIMPLE (ssa,guessed_local(16535624),startwith("loop")) +foo (int * r) +{ + int i; + int sum2; + int sum1; + int _1; + long unsigned int _2; + long unsigned int _3; + int * _4; + int _24; + __SIZETYPE__ _6; + __SIZETYPE__ _7; + int * _8; + int _9; + int _13; + unsigned int _30; + unsigned int _31; + + __BB(2,guessed_local(16535624)): + goto __BB3(precise(134217728)); + + __BB(3,loop_header(1),guessed_local(1057206200)): + sum1_5 = __PHI (__BB5: sum1_18, __BB2: 0); + sum2_26 = __PHI (__BB5: sum2_19, __BB2: 0); + i_28 = __PHI (__BB5: i_20, __BB2: 0); + _31 = __PHI (__BB5: _30, __BB2: 64u); + _1 = i_28 * 2; + _2 = (long unsigned int) _1; + _3 = _2 * 4ul; + _4 = r_17(D) + _3; + _24 = __MEM <int> (_4); + /* Deliberately have swapped operands here */ + sum1_18 = sum1_5 + _24; + _13 = _1 + 1; + _6 = (__SIZETYPE__) _13; + _7 = _6 * 4ul; + _8 = r_17(D) + _7; + _9 = __MEM <int> (_8); + /* versus here. */ + sum2_19 = _9 + sum2_26; + i_20 = i_28 + 1; + _30 = _31 - 1u; + if (_30 != 0u) + goto __BB5(guessed(132118446)); + else + goto __BB4(guessed(2099282)); + + __BB(5,guessed_local(1040670576)): + goto __BB3(precise(134217728)); + + __BB(4,guessed_local(16535624)): + sum1_33 = __PHI (__BB3: sum1_18); + sum2_32 = __PHI (__BB3: sum2_19); + q[0] = sum1_33; + q[1] = sum2_32; + return; +} + +/* { dg-final { scan-tree-dump "SLP discovery of size 2 reduction group succeeded" "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-widen-mult-half.c b/gcc/testsuite/gcc.dg/vect/slp-widen-mult-half.c index b69ade3..72811eb 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-widen-mult-half.c +++ b/gcc/testsuite/gcc.dg/vect/slp-widen-mult-half.c @@ -1,7 +1,6 @@ /* Disabling epilogues until we find a better way to deal with scans. */ /* { dg-additional-options "--param vect-epilogues-nomask=0" } */ /* { dg-require-effective-target vect_int } */ -/* { dg-additional-options "-mlasx" { target loongarch*-*-* } } */ #include "tree-vect.h" diff --git a/gcc/testsuite/gcc.dg/vect/tree-vect.h b/gcc/testsuite/gcc.dg/vect/tree-vect.h index 1e4b56e..37908c9 100644 --- a/gcc/testsuite/gcc.dg/vect/tree-vect.h +++ b/gcc/testsuite/gcc.dg/vect/tree-vect.h @@ -76,6 +76,8 @@ check_vect (void) } #elif defined(__mips_msa) asm volatile ("or.v $w0,$w0,$w0"); +#elif defined(__loongarch__) + asm volatile ("vor.v\t$vr0,$vr0,$vr0"); #endif signal (SIGILL, SIG_DFL); } diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-const-s16.c b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-const-s16.c index 53c9b84..dfbb217 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-const-s16.c +++ b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-const-s16.c @@ -2,7 +2,6 @@ /* { dg-additional-options "--param vect-epilogues-nomask=0" } */ /* { dg-require-effective-target vect_int } */ /* { dg-additional-options "-fno-ipa-icf" } */ -/* { dg-additional-options "-mlasx" { target loongarch*-*-*} } */ #include "tree-vect.h" diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-const-u16.c b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-const-u16.c index e9db828..c2ad58f 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-const-u16.c +++ b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-const-u16.c @@ -2,7 +2,6 @@ /* { dg-additional-options "--param vect-epilogues-nomask=0" } */ /* { dg-require-effective-target vect_int } */ /* { dg-additional-options "-fno-ipa-icf" } */ -/* { dg-additional-options "-mlasx" { target loongarch*-*-*} } */ #include "tree-vect.h" diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-half-u8.c b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-half-u8.c index 607f317..bfdcbaa 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-half-u8.c +++ b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-half-u8.c @@ -2,7 +2,6 @@ /* { dg-additional-options "--param vect-epilogues-nomask=0" } */ /* { dg-require-effective-target vect_int } */ /* { dg-additional-options "-fno-ipa-icf" } */ -/* { dg-additional-options "-mlasx" { target loongarch*-*-*} } */ #include "tree-vect.h" diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-half.c b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-half.c index cd13d82..e46b0cc 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-half.c +++ b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-half.c @@ -1,7 +1,6 @@ /* Disabling epilogues until we find a better way to deal with scans. */ /* { dg-additional-options "--param vect-epilogues-nomask=0" } */ /* { dg-require-effective-target vect_int } */ -/* { dg-additional-options "-mlasx" { target loongarch*-*-*} } */ #include "tree-vect.h" diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u16.c b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u16.c index 258d253..14411ef 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u16.c +++ b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u16.c @@ -1,7 +1,6 @@ /* Disabling epilogues until we find a better way to deal with scans. */ /* { dg-additional-options "--param vect-epilogues-nomask=0" } */ /* { dg-require-effective-target vect_int } */ -/* { dg-additional-options "-mlasx" { target loongarch*-*-*} } */ #include <stdarg.h> #include "tree-vect.h" diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-s16-s32.c b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-s16-s32.c index 3baafca..f40def5 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-s16-s32.c +++ b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-s16-s32.c @@ -1,7 +1,6 @@ /* Disabling epilogues until we find a better way to deal with scans. */ /* { dg-additional-options "--param vect-epilogues-nomask=0" } */ /* { dg-require-effective-target vect_int } */ -/* { dg-additional-options "-mlasx" { target loongarch*-*-*} } */ #include <stdarg.h> #include "tree-vect.h" diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-u32.c b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-u32.c index bcfbe19..6386639 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-u32.c +++ b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8-u32.c @@ -1,6 +1,5 @@ /* { dg-additional-options "--param vect-epilogues-nomask=0" } */ /* { dg-require-effective-target vect_int } */ -/* { dg-additional-options "-mlasx" { target loongarch*-*-* } } */ #include <stdarg.h> #include "tree-vect.h" diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8.c b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8.c index e3bf13b..78ad74b 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8.c +++ b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u8.c @@ -1,6 +1,5 @@ /* { dg-additional-options "--param vect-epilogues-nomask=0" } */ /* { dg-require-effective-target vect_int } */ -/* { dg-additional-options "-mlasx" { target loongarch*-*-*} } */ #include <stdarg.h> #include "tree-vect.h" diff --git a/gcc/testsuite/gcc.dg/vla-init-4.c b/gcc/testsuite/gcc.dg/vla-init-4.c index 06351d0..7d1aa5b 100644 --- a/gcc/testsuite/gcc.dg/vla-init-4.c +++ b/gcc/testsuite/gcc.dg/vla-init-4.c @@ -4,4 +4,4 @@ /* { dg-options "" } */ const int i = 1; -void foo() { char *p = (char [i]){ "" }; } /* { dg-error "compound literal has variable size" } */ +void foo() { char *p = (char [i]){ "" }; } /* { dg-error "variable-sized object" } */ diff --git a/gcc/testsuite/gcc.dg/vla-init-5.c b/gcc/testsuite/gcc.dg/vla-init-5.c index aa9f491..2c249ec 100644 --- a/gcc/testsuite/gcc.dg/vla-init-5.c +++ b/gcc/testsuite/gcc.dg/vla-init-5.c @@ -4,4 +4,4 @@ /* { dg-options "" } */ const int i = 1; -void foo() { void *p = (char [][i]){ "" }; } /* { dg-error "compound literal has variable size" } */ +void foo() { void *p = (char [][i]){ "" }; } /* { dg-error "variable-sized object" } */ diff --git a/gcc/testsuite/gcc.target/aarch64/pr121853_1.c b/gcc/testsuite/gcc.target/aarch64/pr121853_1.c new file mode 100644 index 0000000..24b2fdc --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr121853_1.c @@ -0,0 +1,64 @@ +/* { dg-do run } */ +/* { dg-additional-options "-O2 -std=c99" } */ + +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +__attribute__ ((noipa)) +float convert(__bf16 value) { + return (float)value; +} + +static inline uint32_t f32_bits(float f) { + uint32_t u; memcpy(&u, &f, sizeof u); return u; +} +static inline __bf16 bf16_from_bits(uint16_t u) { + __bf16 b; memcpy(&b, &u, sizeof b); return b; +} + +/* Fixed bf16 inputs (as raw 16-bit payloads) covering edge cases. */ +static const uint16_t inputs[] = { + 0x0000, // +0 + 0x8000, // -0 + 0x7F80, // +inf + 0xFF80, // -inf + 0x7FC0, // qNaN (+) (quiet bit set in bf16) + 0xFFC0, // qNaN (-) + 0x7F01, // sNaN (+) (will be quieted by conversion) + 0xFF01, // sNaN (-) + 0x0001, // smallest +subnormal + 0x007F, // largest +subnormal + 0x8001, // smallest -subnormal + 0x807F, // largest -subnormal + 0x0080, // smallest +normal + 0x3F80, // +1.0 + 0xBF80, // -1.0 + 0x3F00, // +0.5 + 0xBF00, // -0.5 + 0x3FC0, // +1.5 + 0x7F7F, // max finite + + 0xFF7F, // max finite - +}; + +int main(void) { + const size_t N = sizeof(inputs)/sizeof(inputs[0]); + size_t fails = 0; + + for (size_t i = 0; i < N; ++i) { + __bf16 in = bf16_from_bits(inputs[i]); + float out = convert(in); + uint32_t got = f32_bits(out); + uint32_t exp = inputs[i] << 16; + + if (got != exp) { + printf("FAIL[%zu]: in_bf16=0x%04X exp_f32=0x%08X got_f32=0x%08X\n", + i, inputs[i], exp, got); + ++fails; + } + } + + if (fails != 0) + __builtin_abort (); +} + diff --git a/gcc/testsuite/gcc.target/aarch64/pr121853_2.c b/gcc/testsuite/gcc.target/aarch64/pr121853_2.c new file mode 100644 index 0000000..e9fb401 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr121853_2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O1" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +float convert(__bf16 value) { + return (float)value; +} + +/* +** convert: +** movi v[0-9]+.4s, 0 +** ext v[0-9]+.16b, v[0-9]+.16b, v[0-9]+.16b, #14 +** ret +*/ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/dup-insr-1.c b/gcc/testsuite/gcc.target/aarch64/sve/dup-insr-1.c new file mode 100644 index 0000000..41dcbba --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/dup-insr-1.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ +/* PR target/116075 */ + +#include <arm_sve.h> + +svint8_t f(void) +{ + svint8_t tt; + tt = svdup_s8 (0); + tt = svinsr (tt, 0); + return tt; +} + +svint8_t f1(int8_t t) +{ + svint8_t tt; + tt = svdup_s8 (t); + tt = svinsr (tt, t); + return tt; +} + +/* The above 2 functions should have removed the VEC_SHL_INSERT. */ + +/* { dg-final { scan-tree-dump-not ".VEC_SHL_INSERT " "optimized" } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/sve/dup-insr-2.c b/gcc/testsuite/gcc.target/aarch64/sve/dup-insr-2.c new file mode 100644 index 0000000..8eafe97 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/dup-insr-2.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ +/* PR target/116075 */ + +#include <arm_sve.h> + +svint8_t f(int8_t t) +{ + svint8_t tt; + tt = svdup_s8 (0); + tt = svinsr (tt, t); + return tt; +} + +svint8_t f1(int8_t t) +{ + svint8_t tt; + tt = svdup_s8 (t); + tt = svinsr (tt, 0); + return tt; +} + +/* The above 2 functions should not have removed the VEC_SHL_INSERT. */ + +/* { dg-final { scan-tree-dump-times ".VEC_SHL_INSERT " 2 "optimized" } } */ + diff --git a/gcc/testsuite/gcc.target/avr/pr121198.c b/gcc/testsuite/gcc.target/avr/pr121198.c new file mode 100644 index 0000000..551247e --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/pr121198.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -mmcu=atmega8" } */ + +long +test (void) +{ + long x; + __asm__ ("" : "={r22}" (x)); + return x; +} diff --git a/gcc/testsuite/gcc.target/i386/pr116815.c b/gcc/testsuite/gcc.target/i386/pr116815.c new file mode 100644 index 0000000..1cd2f72 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr116815.c @@ -0,0 +1,31 @@ +/* PR target/116815 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-march=pentiumpro" { target ia32 } } */ + +static inline __attribute__ ((always_inline)) +unsigned max (unsigned a, unsigned b) { return a > b ? a : b; } + +static inline __attribute__ ((always_inline)) +unsigned min (unsigned a, unsigned b) { return a < b ? a : b; } + +#define OPERATION(op, type, N, exp1, exp2) \ + unsigned u##op##type##N (unsigned a, unsigned b) { return op (exp1, exp2); } + +OPERATION (max, add, 1, a, a + b) +OPERATION (max, add, 2, a, b + a) +OPERATION (max, add, 3, a + b, a) +OPERATION (max, add, 4, b + a, a) + +OPERATION (min, add, 1, a, a + b) +OPERATION (min, add, 2, a, b + a) +OPERATION (min, add, 3, a + b, a) +OPERATION (min, add, 4, b + a, a) + +OPERATION (max, sub, 1, a, a - b) +OPERATION (max, sub, 2, a - b, a) + +OPERATION (min, sub, 1, a, a - b) +OPERATION (min, sub, 2, a - b, a) + +/* { dg-final { scan-assembler-not "cmp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr122457.c b/gcc/testsuite/gcc.target/i386/pr122457.c new file mode 100644 index 0000000..dc57fb2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr122457.c @@ -0,0 +1,4 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64-v4 -mavxvnniint16" } */ + +#include "vnniint16-auto-vectorize-2.c" diff --git a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-1.c b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-1.c index ed13471..47802aa 100644 --- a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-1.c +++ b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-1.c @@ -27,7 +27,7 @@ void test_lt () { if (lm < ln) - lr *= (1 << 16); + lr += (1 << 16); lr += lm; } @@ -35,7 +35,7 @@ void test_le () { if (lm <= ln) - lr = lm * ((long)1 << 32); + lr = lm + ((long)1 << 32); else lr = lm; lr += lm; diff --git a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-2.c b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-2.c index ac72d4d..743fd5e 100644 --- a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-2.c +++ b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-2.c @@ -29,7 +29,7 @@ void test_lez () { if (lm <= 0) - lr &= (1 << 16); + lr |= (1 << 16); lr += lm; } diff --git a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-3.c b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-3.c new file mode 100644 index 0000000..9588798 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler "maskeqz" } } */ +/* { dg-final { scan-assembler "masknez" } } */ + +extern long lm, ln, lr; + +void +test_and () +{ + if (lm < 0) + lr &= (1 << 16); + lr += lm; +} diff --git a/gcc/testsuite/gcc.target/loongarch/fnmam4-vec.c b/gcc/testsuite/gcc.target/loongarch/fnmam4-vec.c new file mode 100644 index 0000000..0969303 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/fnmam4-vec.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-Ofast -mlasx -ftree-vectorize" } */ +/* { dg-require-effective-target loongarch_asx } */ + +void +foo (float *u, float x, float *y, float z) +{ + int i; + for (i = 0; i < 1024; i++) + *(u++) = (x - y[i] * z); +} + +/* { dg-final { scan-assembler-not "\tvori.b"} } */ +/* { dg-final { scan-assembler-not "\txvori.b"} } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122445.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122445.c new file mode 100644 index 0000000..4736868 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122445.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcbv_zvl256b -mabi=lp64d -O3 -mrvv-vector-bits=zvl --param=riscv-autovec-mode=V4QI -mtune=generic-ooo -fdump-rtl-avlprop-all" } */ + +typedef unsigned char uint8_t; +typedef short int16_t; + +#define FDEC_STRIDE 32 + +static inline uint8_t x264_clip_uint8( int x ) +{ + return x; +} + +void +x264_add4x4_idct (uint8_t *p_dst, int16_t d[16]) +{ + for( int y = 0; y < 4; y++ ) + { + for( int x = 0; x < 4; x++ ) + p_dst[x] = x264_clip_uint8( p_dst[x] + d[y*4+x] ); + p_dst += FDEC_STRIDE; + } +} + +/* { dg-final { scan-rtl-dump "Propagating AVL: \\(const_int 4" "avlprop" } } */ +/* { dg-final { scan-rtl-dump-not "Propagating AVL: \\(const_int 1" "avlprop" } } */ diff --git a/gcc/testsuite/gfortran.dg/pdt_65.f03 b/gcc/testsuite/gfortran.dg/pdt_65.f03 new file mode 100644 index 0000000..d5e45c2 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pdt_65.f03 @@ -0,0 +1,135 @@ +! { dg-do compile } +! { dg-options "-fdump-tree-original" } +! +! Test fix for PR122452 +! +! Contributed by Damian Rouson <damian@archaeologic.codes> +! +module kind_parameters_m + integer, parameter :: default_real = kind(1e0) + integer, parameter :: double_precision = kind(1d0) +end module + +module tensor_m + use kind_parameters_m, only : default_real, double_precision + implicit none + + private + public :: tensor_t + + type tensor_t(k) + integer, kind :: k = default_real + real(k), allocatable, private :: values_(:) + contains + generic :: values => default_real_values, double_precision_values + procedure, private, non_overridable :: default_real_values, double_precision_values + generic :: num_components => default_real_num_components, double_precision_num_components + procedure, private :: default_real_num_components, double_precision_num_components + end type + + interface tensor_t + + pure module function construct_default_real(values) result(tensor) + implicit none + real, intent(in) :: values(:) + type(tensor_t) tensor + end function + + pure module function construct_double_precision(values) result(tensor) + implicit none + double precision, intent(in) :: values(:) + type(tensor_t(double_precision)) tensor + end function + + end interface + + interface + + pure module function default_real_values(self) result(tensor_values) + implicit none + class(tensor_t), intent(in) :: self + real, allocatable :: tensor_values(:) + end function + + pure module function double_precision_values(self) result(tensor_values) + implicit none + class(tensor_t(double_precision)), intent(in) :: self + double precision, allocatable :: tensor_values(:) + end function + + pure module function default_real_num_components(self) result(n) + implicit none + class(tensor_t), intent(in) :: self + integer n + end function + + pure module function double_precision_num_components(self) result(n) + implicit none + class(tensor_t(double_precision)), intent(in) :: self + integer n + end function + + end interface + +end module tensor_m + +submodule(tensor_m) tensor_s +contains + + pure module function construct_default_real(values) result(tensor) + implicit none + real, intent(in) :: values(:) + type(tensor_t) tensor + tensor = tensor_t ()(values) + end function + + pure module function construct_double_precision(values) result(tensor) + implicit none + double precision, intent(in) :: values(:) + type(tensor_t(double_precision)) tensor + tensor = tensor_t (double_precision)(values) + end function + + pure module function default_real_values(self) result(tensor_values) + implicit none + class(tensor_t), intent(in) :: self + real, allocatable :: tensor_values(:) + tensor_values = self%values_ + end function + + pure module function double_precision_values(self) result(tensor_values) + implicit none + class(tensor_t(double_precision)), intent(in) :: self + double precision, allocatable :: tensor_values(:) + tensor_values = self%values_ + end function + + + pure module function default_real_num_components(self) result(n) + implicit none + class(tensor_t), intent(in) :: self + integer n + n = default_real + end function + + pure module function double_precision_num_components(self) result(n) + implicit none + class(tensor_t(double_precision)), intent(in) :: self + integer n + n = double_precision + end function + +end submodule tensor_s + + + use tensor_m + type(tensor_t(kind(0e0))) :: a + type(tensor_t(kind(0D0))) :: b + a = tensor_t ([1e0,2e0]) + print *, a%num_components (), a%values () + b = tensor_t ([3d0,4d0]) + print *, b%num_components (), b%values () +end +! { dg-final { scan-tree-dump-times "construct_" 4 "original" } } +! { dg-final { scan-tree-dump-times "_components" 4 "original" } } +! { dg-final { scan-tree-dump-times "_values" 4 "original" } } diff --git a/gcc/testsuite/gm2.dg/spell/iso/fail/badimport.mod b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport.mod new file mode 100644 index 0000000..337cf34 --- /dev/null +++ b/gcc/testsuite/gm2.dg/spell/iso/fail/badimport.mod @@ -0,0 +1,14 @@ + +(* { dg-do compile } *) +(* { dg-options "-g -c" } *) + +MODULE badimport ; + +IMPORT ASCII ; +FROM StrIO IMPORT WriteString ; +FROM ASCIi IMPORT nul ; + (* { dg-error "error: the file containing the definition module 'ASCIi' cannot be found, did you mean ASCII" "ASCIi" { target *-*-* } 9 } *) + +BEGIN + +END badimport. diff --git a/gcc/testsuite/gnat.dg/aggr32.adb b/gcc/testsuite/gnat.dg/aggr32.adb new file mode 100644 index 0000000..e5b0887 --- /dev/null +++ b/gcc/testsuite/gnat.dg/aggr32.adb @@ -0,0 +1,15 @@ +-- { dg-do compile } + +with Aggr32_Pkg.Child; + +procedure Aggr32 (W, H : Positive) is + + use Aggr32_Pkg; + + package Test_1 is new Child (Frame => (Width => W, Height => H)); + + package Test_2 is new Child (Frame => Rec'(Width => W, Height => H)); + +begin + null; +end; diff --git a/gcc/testsuite/gnat.dg/aggr32_pkg-child.ads b/gcc/testsuite/gnat.dg/aggr32_pkg-child.ads new file mode 100644 index 0000000..352e2b5 --- /dev/null +++ b/gcc/testsuite/gnat.dg/aggr32_pkg-child.ads @@ -0,0 +1,6 @@ +generic + + Frame : Rec; + +package Aggr32_Pkg.Child is +end Aggr32_Pkg.Child; diff --git a/gcc/testsuite/gnat.dg/aggr32_pkg.ads b/gcc/testsuite/gnat.dg/aggr32_pkg.ads new file mode 100644 index 0000000..e0e8bef --- /dev/null +++ b/gcc/testsuite/gnat.dg/aggr32_pkg.ads @@ -0,0 +1,8 @@ +package Aggr32_Pkg is + + type Rec is record + Width : Positive; + Height : Positive; + end record; + +end Aggr32_Pkg; diff --git a/gcc/testsuite/gnat.dg/specs/generic_inst6.ads b/gcc/testsuite/gnat.dg/specs/generic_inst6.ads new file mode 100644 index 0000000..0f15207 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/generic_inst6.ads @@ -0,0 +1,6 @@ +-- { dg-do compile } + +with Generic_Inst6_Pkg1.Child.Grand2; +with Generic_Inst6_Pkg3; + +package Generic_Inst6 is new Generic_Inst6_Pkg3.Grand2; diff --git a/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg1-child-grand1.ads b/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg1-child-grand1.ads new file mode 100644 index 0000000..4d8e7ce --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg1-child-grand1.ads @@ -0,0 +1,3 @@ +generic +package Generic_Inst6_Pkg1.Child.Grand1 is +end Generic_Inst6_Pkg1.Child.Grand1; diff --git a/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg1-child-grand2.ads b/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg1-child-grand2.ads new file mode 100644 index 0000000..326a3e0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg1-child-grand2.ads @@ -0,0 +1,6 @@ +with Generic_Inst6_Pkg1.Child.Grand1; + +generic +package Generic_Inst6_Pkg1.Child.Grand2 is + package My_Grand1 is new Generic_Inst6_Pkg1.Child.Grand1; +end Generic_Inst6_Pkg1.Child.Grand2; diff --git a/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg1-child.ads b/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg1-child.ads new file mode 100644 index 0000000..3676052 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg1-child.ads @@ -0,0 +1,3 @@ +generic +package Generic_Inst6_Pkg1.Child is +end Generic_Inst6_Pkg1.Child; diff --git a/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg1.ads b/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg1.ads new file mode 100644 index 0000000..a480bbd --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg1.ads @@ -0,0 +1,3 @@ +generic +package Generic_Inst6_Pkg1 is +end Generic_Inst6_Pkg1; diff --git a/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg2.ads b/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg2.ads new file mode 100644 index 0000000..98b2011 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg2.ads @@ -0,0 +1,3 @@ +with Generic_Inst6_Pkg1; + +package Generic_Inst6_Pkg2 is new Generic_Inst6_Pkg1; diff --git a/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg3.ads b/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg3.ads new file mode 100644 index 0000000..395b9f0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/generic_inst6_pkg3.ads @@ -0,0 +1,4 @@ +with Generic_Inst6_Pkg1.Child; +with Generic_Inst6_Pkg2; + +package Generic_Inst6_Pkg3 is new Generic_Inst6_Pkg2.Child; diff --git a/gcc/testsuite/gnat.dg/specs/generic_inst7.ads b/gcc/testsuite/gnat.dg/specs/generic_inst7.ads new file mode 100644 index 0000000..3132525 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/generic_inst7.ads @@ -0,0 +1,17 @@ +-- { dg-do compile } + +package Generic_Inst7 is + + function F return Integer is (0); + + generic + with function Foo return Integer; + package P is + type Color is (Foo); + end P; + + package My_P is new P (F); + + I : Integer := My_P.Foo; -- { dg-error "expected type|found type" } + +end Generic_Inst7; diff --git a/gcc/testsuite/gnat.dg/specs/generic_inst8.ads b/gcc/testsuite/gnat.dg/specs/generic_inst8.ads new file mode 100644 index 0000000..0eac709 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/generic_inst8.ads @@ -0,0 +1,18 @@ +-- { dg-do compile } + +package Generic_Inst8 is + + function F return Integer is (0); + + generic + with function Foo return Integer; + package P is + type Color1 is (Foo); + type Color2 is (Foo); + end P; + + package My_P is new P (F); + + I : Integer := My_P.Foo; -- { dg-error "no visible interpretation|use" } + +end Generic_Inst8; diff --git a/gcc/testsuite/rust/compile/attr-macro.rs b/gcc/testsuite/rust/compile/attr-macro.rs new file mode 100644 index 0000000..de9fce1 --- /dev/null +++ b/gcc/testsuite/rust/compile/attr-macro.rs @@ -0,0 +1,7 @@ +macro_rules! foo { + () => { #[cfg(all())] 12 } +} + +fn main() -> i32 { + foo!() +} diff --git a/gcc/testsuite/rust/compile/attr_malformed_doc.rs b/gcc/testsuite/rust/compile/attr_malformed_doc.rs new file mode 100644 index 0000000..6b9ef61 --- /dev/null +++ b/gcc/testsuite/rust/compile/attr_malformed_doc.rs @@ -0,0 +1,3 @@ +// { dg-error "valid forms for the attribute are ...doc.hidden.inline....... and ...doc = . string ..." "" { target *-*-* } .+1 } +#[doc] +trait MyTrait {} diff --git a/gcc/testsuite/rust/compile/attr_malformed_path.rs b/gcc/testsuite/rust/compile/attr_malformed_path.rs new file mode 100644 index 0000000..2bccf37 --- /dev/null +++ b/gcc/testsuite/rust/compile/attr_malformed_path.rs @@ -0,0 +1,3 @@ +#[cfg_attr(target_arch = "x86_64", path = (target_arch = "x86", path = "x86.rs"))] +mod imp {} +// { dg-error "malformed .path. attribute input" "" { target *-*-* } .-2 } diff --git a/gcc/testsuite/rust/compile/cfg-test.rs b/gcc/testsuite/rust/compile/cfg-test.rs new file mode 100644 index 0000000..a2e870c --- /dev/null +++ b/gcc/testsuite/rust/compile/cfg-test.rs @@ -0,0 +1,4 @@ +#[test] +fn foo() { + some_function_which_doesnt_exist(); +} diff --git a/gcc/testsuite/rust/compile/enum_discriminant3.rs b/gcc/testsuite/rust/compile/enum_discriminant3.rs new file mode 100644 index 0000000..32c79a5 --- /dev/null +++ b/gcc/testsuite/rust/compile/enum_discriminant3.rs @@ -0,0 +1,8 @@ +const x: isize = 1; +// { dg-warning "unused name" "" { target *-*-* } .-1 } + +fn main() { + enum Foo { + Bar = x, + } +} diff --git a/gcc/testsuite/rust/compile/format_args_concat.rs b/gcc/testsuite/rust/compile/format_args_concat.rs new file mode 100644 index 0000000..b180667 --- /dev/null +++ b/gcc/testsuite/rust/compile/format_args_concat.rs @@ -0,0 +1,51 @@ +#![feature(rustc_attrs)] + +#[rustc_builtin_macro] +macro_rules! format_args { + () => {}; +} + +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} + +#[lang = "sized"] +trait Sized {} + +pub mod core { + pub mod fmt { + pub struct Formatter; + pub struct Result; + + pub struct Arguments<'a>; + + impl<'a> Arguments<'a> { + pub fn new_v1(_: &'a [&'static str], _: &'a [ArgumentV1<'a>]) -> Arguments<'a> { + Arguments + } + } + + pub struct ArgumentV1<'a>; + + impl<'a> ArgumentV1<'a> { + pub fn new<'b, T>(_: &'b T, _: fn(&T, &mut Formatter) -> Result) -> ArgumentV1 { + ArgumentV1 + } + } + + pub trait Display { + fn fmt(&self, _: &mut Formatter) -> Result; + } + + impl Display for i32 { + fn fmt(&self, _: &mut Formatter) -> Result { + Result + } + } + } +} + +fn main() { + let _formatted = format_args!(concat!("hello ", "{}"), 15); +} diff --git a/gcc/testsuite/rust/compile/global-path-array.rs b/gcc/testsuite/rust/compile/global-path-array.rs new file mode 100644 index 0000000..c3aa024 --- /dev/null +++ b/gcc/testsuite/rust/compile/global-path-array.rs @@ -0,0 +1,5 @@ +const X: i32 = 1; + +pub fn foo() -> [i32; 1] { + [::X] +} diff --git a/gcc/testsuite/rust/compile/impl_fnptr.rs b/gcc/testsuite/rust/compile/impl_fnptr.rs new file mode 100644 index 0000000..20c9d88 --- /dev/null +++ b/gcc/testsuite/rust/compile/impl_fnptr.rs @@ -0,0 +1,18 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "eq"] +pub trait PartialEq<Rhs: ?Sized = Self> { + fn eq(&self, other: &Rhs) -> bool; + + fn ne(&self, other: &Rhs) -> bool { + !self.eq(other) + } +} + +impl<Ret> PartialEq for extern "C" fn() -> Ret { + #[inline] + fn eq(&self, other: &Self) -> bool { + *self as usize == *other as usize + } +} diff --git a/gcc/testsuite/rust/compile/import_wildcards.rs b/gcc/testsuite/rust/compile/import_wildcards.rs new file mode 100644 index 0000000..3fc3658 --- /dev/null +++ b/gcc/testsuite/rust/compile/import_wildcards.rs @@ -0,0 +1,8 @@ +mod x {} + +mod y {} + +fn main() { + use x as _; + use y as _; +} diff --git a/gcc/testsuite/rust/compile/issue-1725-2.rs b/gcc/testsuite/rust/compile/issue-1725-2.rs index 726d967..d6a2d68 100644 --- a/gcc/testsuite/rust/compile/issue-1725-2.rs +++ b/gcc/testsuite/rust/compile/issue-1725-2.rs @@ -26,6 +26,5 @@ pub fn foo<T: core::ops::Add<Output = i32>>(a: T) -> i32 { pub fn main() { foo(123f32); - // { dg-error "type mismatch, expected .i32. but got .f32." "" { target *-*-* } .-1 } - // { dg-error "bounds not satisfied for f32 .Add. is not satisfied" "" { target *-*-* } .-2 } + // { dg-error "bounds not satisfied for f32 .Add. is not satisfied" "" { target *-*-* } .-1 } } diff --git a/gcc/testsuite/rust/compile/issue-2394.rs b/gcc/testsuite/rust/compile/issue-2394.rs index 92f7afc..b5b5394 100644 --- a/gcc/testsuite/rust/compile/issue-2394.rs +++ b/gcc/testsuite/rust/compile/issue-2394.rs @@ -1,5 +1,6 @@ const A: i32 = (1 / 0); // { dg-error "division by zero" "" { target *-*-* } .-1 } +// { dg-error "is not a constant expression" "" { target *-*-* } .-2 } fn main() { let a = 1 / 0; diff --git a/gcc/testsuite/rust/compile/issue-3538.rs b/gcc/testsuite/rust/compile/issue-3538.rs new file mode 100644 index 0000000..7269457 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3538.rs @@ -0,0 +1,9 @@ +enum A { + Value(()), +} + +fn main() { + let a = A::Value(()); + a == A::Value; + // { dg-error "variant expected constructor call" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust/compile/issue-3556.rs b/gcc/testsuite/rust/compile/issue-3556.rs new file mode 100644 index 0000000..be7d85a --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3556.rs @@ -0,0 +1,4 @@ +fn main() { + let ref mut a @ (ref mut b,); + // { dg-error "expected T\\?, found tuple" "" { target *-*-* } .-1 } +}
\ No newline at end of file diff --git a/gcc/testsuite/rust/compile/issue-3592.rs b/gcc/testsuite/rust/compile/issue-3592.rs new file mode 100644 index 0000000..34018d1 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3592.rs @@ -0,0 +1,7 @@ +pub trait X { + fn x() { + fn f(&mut self) {} + // { dg-error ".self. parameter is only allowed in associated functions" "" { target *-*-* } .-1 } + f(); + } +} diff --git a/gcc/testsuite/rust/compile/issue-3645.rs b/gcc/testsuite/rust/compile/issue-3645.rs new file mode 100644 index 0000000..91285f1 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3645.rs @@ -0,0 +1,6 @@ +// { dg-warning "unused name 'y'" "" { target *-*-* } 5 } +// { dg-warning "unused name 'z'" "" { target *-*-* } 5 } + +fn main() { + let (ref y,z) = (1i32, 2u32); +}
\ No newline at end of file diff --git a/gcc/testsuite/rust/compile/issue-3726.rs b/gcc/testsuite/rust/compile/issue-3726.rs new file mode 100644 index 0000000..ced87a5 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3726.rs @@ -0,0 +1,17 @@ +pub enum TypeCtor { + Slice, + Array, +} +pub struct ApplicationTy(TypeCtor); + +macro_rules! ty_app { + ($ctor:pat) => { + ApplicationTy($ctor) + }; +} + +pub fn foo(ty: ApplicationTy) { + match ty { + ty_app!(TypeCtor::Array) => {} + } +} diff --git a/gcc/testsuite/rust/compile/issue-3898.rs b/gcc/testsuite/rust/compile/issue-3898.rs new file mode 100644 index 0000000..114370c --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3898.rs @@ -0,0 +1,112 @@ +// { dg-additional-options "-frust-compile-until=lowering" } + +#[lang = "sized"] +trait Sized {} + +enum Result<T, E> { + Ok(T), + Err(E), +} + +use Result::{Err, Ok}; + +struct Utf8Error; + +const CONT_MASK: u8 = 15; +const TAG_CONT_U8: u8 = 15; + +#[inline(always)] +pub fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { + let mut index = 0; + let len = 64; + + let usize_bytes = 8; + let ascii_block_size = 2 * usize_bytes; + let blocks_end = if len >= ascii_block_size { + len - ascii_block_size + 1 + } else { + 0 + }; + + while index < len { + let old_offset = index; + macro_rules! err { + ($error_len: expr) => { + return Err(Utf8Error) + }; + } + + macro_rules! next { + () => {{ + index += 1; + // we needed data, but there was none: error! + if index >= len { + err!(None) + } + v[index] + }}; + } + + let first = v[index]; + if first >= 128 { + let w = 15; + // 2-byte encoding is for codepoints \u{0080} to \u{07ff} + // first C2 80 last DF BF + // 3-byte encoding is for codepoints \u{0800} to \u{ffff} + // first E0 A0 80 last EF BF BF + // excluding surrogates codepoints \u{d800} to \u{dfff} + // ED A0 80 to ED BF BF + // 4-byte encoding is for codepoints \u{1000}0 to \u{10ff}ff + // first F0 90 80 80 last F4 8F BF BF + // + // Use the UTF-8 syntax from the RFC + // + // https://tools.ietf.org/html/rfc3629 + // UTF8-1 = %x00-7F + // UTF8-2 = %xC2-DF UTF8-tail + // UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) / + // %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail ) + // UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) / + // %xF4 %x80-8F 2( UTF8-tail ) + match w { + 2 => { + if next!() & !CONT_MASK != TAG_CONT_U8 { + err!(Some(1)) + } + } + 3 => { + match (first, next!()) { + (0xE0, 0xA0..=0xBF) + | (0xE1..=0xEC, 0x80..=0xBF) + | (0xED, 0x80..=0x9F) + | (0xEE..=0xEF, 0x80..=0xBF) => {} + _ => err!(Some(1)), + } + if next!() & !CONT_MASK != TAG_CONT_U8 { + err!(Some(2)) + } + } + 4 => { + match (first, next!()) { + (0xF0, 0x90..=0xBF) | (0xF1..=0xF3, 0x80..=0xBF) | (0xF4, 0x80..=0x8F) => {} + _ => err!(Some(1)), + } + if next!() & !CONT_MASK != TAG_CONT_U8 { + err!(Some(2)) + } + if next!() & !CONT_MASK != TAG_CONT_U8 { + err!(Some(3)) + } + } + _ => err!(Some(1)), + } + index += 1; + } else { + index += 1; + } + } + + Ok(()) +} + +fn main() {} diff --git a/gcc/testsuite/rust/compile/issue-3922.rs b/gcc/testsuite/rust/compile/issue-3922.rs new file mode 100644 index 0000000..3c07f94 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3922.rs @@ -0,0 +1,12 @@ +struct S( + [u8; { + { + // { dg-error "mismatched types. expected .... but got ..integer.. .E0308." "" { target *-*-* } .-1 } + struct Z; + 0 + } + 0 + }], +); + +fn main() {} diff --git a/gcc/testsuite/rust/compile/issue-3924.rs b/gcc/testsuite/rust/compile/issue-3924.rs new file mode 100644 index 0000000..cc423ce --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3924.rs @@ -0,0 +1,6 @@ +pub fn main() { + const S: usize = 23 as i64; + // { dg-error {mismatched types, expected .usize. but got .i64.} "" { target *-*-* } .-1 } + [0; S]; + () +} diff --git a/gcc/testsuite/rust/compile/issue-3928.rs b/gcc/testsuite/rust/compile/issue-3928.rs new file mode 100644 index 0000000..639d4c8 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3928.rs @@ -0,0 +1,12 @@ +// { dg-do compile } +// { dg-options "-fsyntax-only" } + +#![feature(exclusive_range_pattern)] + +fn Foo() { + let x = 1u32; + + match x { + 3..-1 => 4, + }; +} diff --git a/gcc/testsuite/rust/compile/issue-3929-1.rs b/gcc/testsuite/rust/compile/issue-3929-1.rs new file mode 100644 index 0000000..3d7b056 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3929-1.rs @@ -0,0 +1,9 @@ +// { dg-options "-w" } +struct S(); + +fn main() { + let s = S{}; + match s { + S{..} => {} + } +} diff --git a/gcc/testsuite/rust/compile/issue-3929-2.rs b/gcc/testsuite/rust/compile/issue-3929-2.rs new file mode 100644 index 0000000..5f45a7c --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3929-2.rs @@ -0,0 +1,12 @@ +// { dg-options "-w" } +struct S { + x: i32, + y: i32, +} + +fn main() { + let s = S{x: 1, y: 2}; + match s { + S{x: 1, ..} => {} + } +} diff --git a/gcc/testsuite/rust/compile/issue-3930.rs b/gcc/testsuite/rust/compile/issue-3930.rs new file mode 100644 index 0000000..dfcd19a --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3930.rs @@ -0,0 +1,4 @@ +// { dg-additional-options "-w" } +fn main() { + let (a, .., b) = (2, 3); +} diff --git a/gcc/testsuite/rust/compile/issue-3947.rs b/gcc/testsuite/rust/compile/issue-3947.rs new file mode 100644 index 0000000..58ccde6 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3947.rs @@ -0,0 +1,10 @@ +enum _Enum { + A(), +} + +type _E = _Enum; + +// { dg-warning "function is never used: '_a'" "" { target *-*-* } .+1 } +const fn _a() -> _Enum { + _E::A() +} diff --git a/gcc/testsuite/rust/compile/issue-3958.rs b/gcc/testsuite/rust/compile/issue-3958.rs new file mode 100644 index 0000000..935b512 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3958.rs @@ -0,0 +1,11 @@ +// { dg-options "-fsyntax-only" } +trait A { + fn a(&self) -> <Self as A>::X; +} + +impl A for u32 {} + +fn main() { + let a: u32 = 0; + let b: u32 = a.a(); +} diff --git a/gcc/testsuite/rust/compile/issue-3965-1.rs b/gcc/testsuite/rust/compile/issue-3965-1.rs new file mode 100644 index 0000000..291a220 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3965-1.rs @@ -0,0 +1,4 @@ +fn main() { + [(); { continue }]; + // { dg-error ".continue. outside of a loop .E0268." "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust/compile/issue-3965-2.rs b/gcc/testsuite/rust/compile/issue-3965-2.rs new file mode 100644 index 0000000..d48503f --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3965-2.rs @@ -0,0 +1,7 @@ +fn main() { + loop { continue } + + [(); {while true {break}; 0}]; + + [(); {while true {break}; 0}]; +} diff --git a/gcc/testsuite/rust/compile/issue-3966.rs b/gcc/testsuite/rust/compile/issue-3966.rs new file mode 100644 index 0000000..20d3031 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3966.rs @@ -0,0 +1,5 @@ +struct S { + #[cfg_attr()] + field: u8, + // { dg-error "malformed .cfg_attr. attribute input" "" { target *-*-* } .-2 } +} diff --git a/gcc/testsuite/rust/compile/issue-3969.rs b/gcc/testsuite/rust/compile/issue-3969.rs new file mode 100644 index 0000000..9608589 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3969.rs @@ -0,0 +1,30 @@ +#[lang = "sized"] +pub trait Sized { + // Empty. +} + +#[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 main() { + [(); { + while true { + // { dg-error ".constexpr. loop iteration count exceeds limit" "" { target *-*-* } .-1 } + break 9; + // { dg-error "can only .break. with a value inside a .loop. block .E0571." "" { target *-*-* } .-1 } + } + 51 + }]; + + while true { + break (|| { + // { dg-error "can only .break. with a value inside a .loop. block .E0571." "" { target *-*-* } .-1 } + let while_true = 9; + }); + } +} diff --git a/gcc/testsuite/rust/compile/issue-3974.rs b/gcc/testsuite/rust/compile/issue-3974.rs new file mode 100644 index 0000000..dfd693a --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-3974.rs @@ -0,0 +1,8 @@ +impl<'a, F> RunUntil<'a, F> { + // { dg-error "could not resolve type path" "" { target *-*-* } .-1 } + fn project<'pin>() -> Projection<'pin, 'a, F> { + // { dg-error "could not resolve type path" "" { target *-*-* } .-1 } + Self!() + // { dg-error "could not resolve macro invocation" "" { target *-*-* } .-1 } + } +} diff --git a/gcc/testsuite/rust/compile/issue-4090-1.rs b/gcc/testsuite/rust/compile/issue-4090-1.rs new file mode 100644 index 0000000..9f83835 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4090-1.rs @@ -0,0 +1,68 @@ +mod core { + mod marker { + #[lang = "sized"] + pub trait Sized {} + + #[lang = "phantom_data"] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct PhantomData<T: ?Sized>; + + #[unstable(feature = "structural_match", issue = "31434")] + #[lang = "structural_teq"] + pub trait StructuralEq { + // Empty. + } + + #[unstable(feature = "structural_match", issue = "31434")] + #[lang = "structural_peq"] + pub trait StructuralPartialEq { + // Empty. + } + } + + pub mod cmp { + use super::marker::Sized; + + #[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) {} + } + } + + pub mod ptr { + + use super::cmp::{Eq, PartialEq}; + + macro_rules! fnptr_impls_safety_abi { + ($FnTy: ty, $($Arg: ident),*) => { + #[stable(feature = "fnptr_impls", since = "1.4.0")] + impl<Ret, $($Arg),*> PartialEq for $FnTy { + #[inline] + fn eq(&self, other: &Self) -> bool { + *self as usize == *other as usize + } + } + + #[stable(feature = "fnptr_impls", since = "1.4.0")] + impl<Ret, $($Arg),*> Eq for $FnTy {} + + } + } + + fnptr_impls_safety_abi! { extern "Rust" fn() -> Ret, } + } +} + +#[derive(PartialEq, Eq)] +struct AllowedBelow { + // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 } + f: fn(), +} diff --git a/gcc/testsuite/rust/compile/issue-4090-2.rs b/gcc/testsuite/rust/compile/issue-4090-2.rs new file mode 100644 index 0000000..75d6b7c --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4090-2.rs @@ -0,0 +1,71 @@ +mod core { + mod marker { + #[lang = "sized"] + pub trait Sized {} + + #[lang = "phantom_data"] + #[stable(feature = "rust1", since = "1.0.0")] + pub struct PhantomData<T: ?Sized>; + + #[unstable(feature = "structural_match", issue = "31434")] + #[lang = "structural_teq"] + pub trait StructuralEq { + // Empty. + } + + #[unstable(feature = "structural_match", issue = "31434")] + #[lang = "structural_peq"] + pub trait StructuralPartialEq { + // Empty. + } + } + + pub mod cmp { + use super::marker::Sized; + + #[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) {} + } + } + + pub mod ptr { + + use super::cmp::{Eq, PartialEq}; + + macro_rules! fnptr_impls_safety_abi { + ($FnTy: ty, $($Arg: ident),*) => { + #[stable(feature = "fnptr_impls", since = "1.4.0")] + impl<Ret, $($Arg),*> PartialEq for $FnTy { + #[inline] + fn eq(&self, other: &Self) -> bool { + *self as usize == *other as usize + } + } + + #[stable(feature = "fnptr_impls", since = "1.4.0")] + impl<Ret, $($Arg),*> Eq for $FnTy {} + + } + } + + fnptr_impls_safety_abi! { extern "Rust" fn() -> Ret, } + fnptr_impls_safety_abi! { extern "C" fn() -> Ret, } + fnptr_impls_safety_abi! { unsafe extern "Rust" fn() -> Ret, } + fnptr_impls_safety_abi! { unsafe extern "C" fn() -> Ret, } + } +} + +#[derive(PartialEq, Eq)] +struct AllowedBelow { + // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 } + f: fn(), +} diff --git a/gcc/testsuite/rust/compile/issue-4139.rs b/gcc/testsuite/rust/compile/issue-4139.rs new file mode 100644 index 0000000..dc62d1c --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4139.rs @@ -0,0 +1,7 @@ +// { dg-skip-if "" { *-*-* } { "-m32" } { "" } } +const X: i32 = const { + let a = 0x736f6d6570736575; + // { dg-error "integer overflows the respective type" "" { target *-*-* } .-1 } + let b = 14; + a + b +}; diff --git a/gcc/testsuite/rust/compile/issue-4145.rs b/gcc/testsuite/rust/compile/issue-4145.rs new file mode 100644 index 0000000..98b33ca --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4145.rs @@ -0,0 +1,13 @@ +// { dg-excess-errors "warnings" } + +struct S { + field: [u8; { + #[path = "outer/inner.rs"] + // { dg-warning "error handling module file for .inner." "#4145" { xfail *-*-* } .+1 } + mod inner; + // OK + 0 + }], +} + +fn main() {} diff --git a/gcc/testsuite/rust/compile/issue-4146.rs b/gcc/testsuite/rust/compile/issue-4146.rs new file mode 100644 index 0000000..efb3ee2 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4146.rs @@ -0,0 +1,3 @@ +const _NISIZE_DIV_P: &isize = &(1isize / 0); +// { dg-error "division by zero" "" { target *-*-* } .-1 } +// { dg-error "is not a constant expression" "" { target *-*-* } .-2 } diff --git a/gcc/testsuite/rust/compile/issue-4148.rs b/gcc/testsuite/rust/compile/issue-4148.rs new file mode 100644 index 0000000..599d739 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4148.rs @@ -0,0 +1,26 @@ +// { dg-excess-errors "warnings" } + +// TODO: all `xfail` conditions should be changed to `target` once the ICE in #4148 is resolved + +pub fn ret_parens(x: i32) -> i32 { + // { dg-warning "unnecessary parentheses around block return value" "#4148" { xfail *-*-* } .+1 } + ((x+1)) +} + +// { dg-warning "unnecessary parentheses around type" "#4148" { xfail *-*-* } .+1 } +// { dg-warning "unnecessary parentheses around pattern" "#4148" { xfail *-*-* } .+1 } +pub fn arg_ret_parens((x): (i32)) -> (i32) { + // { dg-warning "unnecessary parentheses around block return value" "#4148" { xfail *-*-* } .+1 } + ((x+1)) +} + +// { dg-warning "unnecessary parentheses around type" "#4148" { xfail *-*-* } .+1 } +pub fn ret_rpit_parens2(x: i32) -> (i32) { + // { dg-warning "unnecessary parentheses around block return value" "#4148" { xfail *-*-* } .+1 } + ((x+1)) +} + +pub fn ret_parens3(x: i32) -> i32 { + // { dg-warning "unnecessary parentheses around block return value" "#4148" { xfail *-*-* } .+1 } + ((x+1)) +} diff --git a/gcc/testsuite/rust/compile/issue-4155.rs b/gcc/testsuite/rust/compile/issue-4155.rs new file mode 100644 index 0000000..9fae613 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4155.rs @@ -0,0 +1,7 @@ +struct Bug { + inner: [(); match Vec::new { + f @ |n() => 1 +// { dg-error "failed to parse pattern to bind" "" { target *-*-* } .-1 } +// { dg-error "unexpected token .|. in pattern" "" { target *-*-* } .-2 } + }], +} diff --git a/gcc/testsuite/rust/compile/issue-4165.rs b/gcc/testsuite/rust/compile/issue-4165.rs new file mode 100644 index 0000000..bc513da --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4165.rs @@ -0,0 +1,12 @@ +const N: usize = 2; +const ARR: [i32; N] = [42; X]; +// { dg-error {cannot find value .X. in this scope \[E0425\]} "" { target *-*-* } .-1 } +// { dg-error {mismatched types, expected .\[i32; 2]. but got .<tyty::error>. \[E0308\]} "" { target *-*-* } .-2 } +// { dg-error {mismatched types, expected .usize. but got .bool. \[E0308\]} "" { target *-*-* } .-3 } +const X: bool = (N[0] == 99) && (ARR[0] == 0); +// { dg-error {the type .usize. cannot be indexed by .<integer>. \[E0277\]} "" { target *-*-* } .-1 } +// { dg-error {mismatched types, expected .<tyty::error>. but got .<integer>. \[E0308\]} "" { target *-*-* } .-2 } + +fn main() { + let _ = X; +} diff --git a/gcc/testsuite/rust/compile/issue-4168.rs b/gcc/testsuite/rust/compile/issue-4168.rs new file mode 100644 index 0000000..abb1190 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4168.rs @@ -0,0 +1,7 @@ +const fn add(x: usize, y: usize) -> i32 { + add + y + // { dg-error "cannot apply operator .+. to types fn .x usize,y usize,. -> i32 and usize" "" { target *-*-* } .-1 } +} +const ARR: [i32; add(1, 2)] = [5, 6, 1]; +// { dg-error "mismatched types, expected .usize. but got .i32. .E0308." "" { target *-*-* } .-1 } +// { dg-error "mismatched types" "" { target *-*-* } .-2 } diff --git a/gcc/testsuite/rust/compile/issue-4212.rs b/gcc/testsuite/rust/compile/issue-4212.rs new file mode 100644 index 0000000..e068e45 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4212.rs @@ -0,0 +1,5 @@ +#![derive(PartialOrd, PartialEq)] +// { dg-error "derive attribute cannot be used at crate level" "" { target *-*-* } .-1 } +pub fn check_ge(a: i32, b: i32) -> bool { + a >= b +} diff --git a/gcc/testsuite/rust/compile/issue-4231.rs b/gcc/testsuite/rust/compile/issue-4231.rs new file mode 100644 index 0000000..4629baa --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4231.rs @@ -0,0 +1,6 @@ +#[repr = ""] // { dg-error "malformed .repr. attribute" } +struct ThreeInts { + first: i16, + second: i8, + third: i32 +} diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro-issue4054.rs b/gcc/testsuite/rust/compile/macros/mbe/macro-issue4054.rs new file mode 100644 index 0000000..6dcab23 --- /dev/null +++ b/gcc/testsuite/rust/compile/macros/mbe/macro-issue4054.rs @@ -0,0 +1,14 @@ +#[allow(path_statements)] + +macro_rules! array_impl_default { + {$t:ident} => { + $t; + array_impl_default!{} + }; + {} => {} +} + +pub fn foo() { + let x = 12; + array_impl_default! {x} +} diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro49.rs b/gcc/testsuite/rust/compile/macros/mbe/macro49.rs index 0900f7c..9d63ff1 100644 --- a/gcc/testsuite/rust/compile/macros/mbe/macro49.rs +++ b/gcc/testsuite/rust/compile/macros/mbe/macro49.rs @@ -1,3 +1,14 @@ +#[lang = "sized"] +pub trait Sized {} + +#[lang = "fn_once"] +trait FnOnce<Args> { + #[lang = "fn_once_output"] + type Output; + + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + macro_rules! closure { () => {{ 14 + 15 diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro58.rs b/gcc/testsuite/rust/compile/macros/mbe/macro58.rs new file mode 100644 index 0000000..d8f7599 --- /dev/null +++ b/gcc/testsuite/rust/compile/macros/mbe/macro58.rs @@ -0,0 +1,12 @@ +pub fn print(a: *const u8) {} +#[macro_export] +macro_rules! pr_warn ( + ($($arg:tt)*) => ( + $($crate::print($arg))* + ) +); + +fn main() { + pr_warn!("test\0", "test\0"); + // { dg-error "expecting .;. but .identifier. found" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust/compile/match-tuplestructpattern-err.rs b/gcc/testsuite/rust/compile/match-tuplestructpattern-err.rs new file mode 100644 index 0000000..efd1a89 --- /dev/null +++ b/gcc/testsuite/rust/compile/match-tuplestructpattern-err.rs @@ -0,0 +1,14 @@ +fn main() { + struct A (i32, i32); + let a = A (0, 1); + + match a { + A (1, 2, 3, 4) => {}, + // { dg-error "this pattern has 4 fields but the corresponding tuple variant has 2 fields .E0023." "" { target *-*-* } .-1 } + A (1, 2, .., 3, 4) => {}, + // { dg-error "this pattern has 4 fields but the corresponding tuple variant has 2 fields .E0023." "" { target *-*-* } .-1 } + A (.., 3, 4, 5) => {}, + // { dg-error "this pattern has 3 fields but the corresponding tuple variant has 2 fields .E0023." "" { target *-*-* } .-1 } + _ => {} + } +}
\ No newline at end of file diff --git a/gcc/testsuite/rust/compile/match-tuplestructpattern-non-variant.rs b/gcc/testsuite/rust/compile/match-tuplestructpattern-non-variant.rs new file mode 100644 index 0000000..cf751cb --- /dev/null +++ b/gcc/testsuite/rust/compile/match-tuplestructpattern-non-variant.rs @@ -0,0 +1,20 @@ +enum Empty {} +enum NonEmpty { + Foo(i32), +} + +fn f(e: Empty) { + match e { + Empty(0) => {} // { dg-error "expected tuple struct or tuple variant, found enum 'Empty'" } + } + + match e { + Empty(Empty(..)) => {} // { dg-error "expected tuple struct or tuple variant, found enum 'Empty'" } + } +} + +fn g(e: NonEmpty) { + match e { + NonEmpty(0) => {} // { dg-error "expected tuple struct or tuple variant, found enum 'NonEmpty'" } + } +} diff --git a/gcc/testsuite/rust/compile/match-tuplestructpattern-rest.rs b/gcc/testsuite/rust/compile/match-tuplestructpattern-rest.rs new file mode 100644 index 0000000..4681acb --- /dev/null +++ b/gcc/testsuite/rust/compile/match-tuplestructpattern-rest.rs @@ -0,0 +1,9 @@ +fn main() { + struct A (i32, i32); + let a = A (0, 1); + + match a { + A (0, ..) => {}, + _ => {} + } +} diff --git a/gcc/testsuite/rust/compile/parse_closure_bind.rs b/gcc/testsuite/rust/compile/parse_closure_bind.rs new file mode 100644 index 0000000..1e08197 --- /dev/null +++ b/gcc/testsuite/rust/compile/parse_closure_bind.rs @@ -0,0 +1,19 @@ +// { dg-additional-options "-frust-compile-until=typecheck" } +// TODO: this should typecheck + +#[lang = "sized"] +trait Sized {} + +#[lang = "fn_once"] +pub trait FnOnce<Args> { + /// The returned type after the call operator is used. + #[lang = "fn_once_output"] + type Output; + + /// Performs the call operation. + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +pub fn foo() { + (|_a @ _b| {}) (1) +} diff --git a/gcc/testsuite/rust/compile/parse_float_dot.rs b/gcc/testsuite/rust/compile/parse_float_dot.rs new file mode 100644 index 0000000..bfe3da2 --- /dev/null +++ b/gcc/testsuite/rust/compile/parse_float_dot.rs @@ -0,0 +1,3 @@ +// floating point literals can't start with a '.' +// TODO: improve the error message emitted here +const X: f32 = .5; // { dg-error ".*" } diff --git a/gcc/testsuite/rust/compile/primitive-import.rs b/gcc/testsuite/rust/compile/primitive-import.rs new file mode 100644 index 0000000..cc750af --- /dev/null +++ b/gcc/testsuite/rust/compile/primitive-import.rs @@ -0,0 +1,7 @@ +mod primitive { + pub use i32; +} + +pub fn foo() -> primitive::i32 { + 1 +} diff --git a/gcc/testsuite/rust/compile/slice_rest_pattern.rs b/gcc/testsuite/rust/compile/slice_rest_pattern.rs index c27a8dd..bb3c414 100644 --- a/gcc/testsuite/rust/compile/slice_rest_pattern.rs +++ b/gcc/testsuite/rust/compile/slice_rest_pattern.rs @@ -1,5 +1,4 @@ -// { dg-options "-fsyntax-only" } -fn foo(a: &[u32]) { +pub fn foo(a: &[u32]) { match a { [first, ..] => {} [.., last] => {} diff --git a/gcc/testsuite/rust/compile/tuple_index_on_non_tuple.rs b/gcc/testsuite/rust/compile/tuple_index_on_non_tuple.rs new file mode 100644 index 0000000..f94b8c3 --- /dev/null +++ b/gcc/testsuite/rust/compile/tuple_index_on_non_tuple.rs @@ -0,0 +1,15 @@ +enum E { + V(usize), +} + +struct S { + field: i32, +} + +fn main() { + let e = E::V(0); + let _ = e.0; // { dg-error "expected tuple or tuple struct, found 'E'" } + + let s = S { field: 0 }; + let _ = s.0; // { dg-error "expected tuple or tuple struct, found 'S'" } +} diff --git a/gcc/testsuite/rust/compile/tuplepattern-rest-readonly.rs b/gcc/testsuite/rust/compile/tuplepattern-rest-readonly.rs new file mode 100644 index 0000000..db165ef --- /dev/null +++ b/gcc/testsuite/rust/compile/tuplepattern-rest-readonly.rs @@ -0,0 +1,5 @@ +fn main() { + let (a, .., b) = (1, 1); + a = 2; // { dg-error "assignment of read-only variable .a." } + b = 2; // { dg-error "assignment of read-only variable .b." } +}
\ No newline at end of file diff --git a/gcc/testsuite/rust/compile/tuplepattern-restpattern-typecheck-err.rs b/gcc/testsuite/rust/compile/tuplepattern-restpattern-typecheck-err.rs new file mode 100644 index 0000000..d9f7c18 --- /dev/null +++ b/gcc/testsuite/rust/compile/tuplepattern-restpattern-typecheck-err.rs @@ -0,0 +1,8 @@ +fn main() { + match (1, 2.2, "not 3") { + // { dg-error "expected a tuple with 3 elements, found one with 5 elements" "" { target *-*-* } .+1 } + (a, b, .., c, d, e) => { + let _ = b + c; // { dg-error "cannot apply operator .+. to types <float> and & str" } + } + } +}
\ No newline at end of file diff --git a/gcc/testsuite/rust/compile/use_3.rs b/gcc/testsuite/rust/compile/use_3.rs new file mode 100644 index 0000000..2cfe38f --- /dev/null +++ b/gcc/testsuite/rust/compile/use_3.rs @@ -0,0 +1,10 @@ +mod intrinsic { + pub fn foo() {} +} + +pub mod a { + pub fn b() { + use crate::intrinsic; + intrinsic::foo(); + } +} diff --git a/gcc/testsuite/rust/compile/use_self_alone.rs b/gcc/testsuite/rust/compile/use_self_alone.rs new file mode 100644 index 0000000..1df923c --- /dev/null +++ b/gcc/testsuite/rust/compile/use_self_alone.rs @@ -0,0 +1,2 @@ +use self; +// { dg-error ".self. imports are only allowed within a { } list" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/compile/use_self_alone_in_list.rs b/gcc/testsuite/rust/compile/use_self_alone_in_list.rs new file mode 100644 index 0000000..2e87227 --- /dev/null +++ b/gcc/testsuite/rust/compile/use_self_alone_in_list.rs @@ -0,0 +1,7 @@ +struct B; + +use {B as B2, self}; +// { dg-error ".self. import can only appear in an import list with a non-empty prefix" "" { target *-*-* } .-1 } + +use {self}; +// { dg-error ".self. import can only appear in an import list with a non-empty prefix" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/rust/core/core.exp b/gcc/testsuite/rust/core/core.exp new file mode 100644 index 0000000..330c6d5 --- /dev/null +++ b/gcc/testsuite/rust/core/core.exp @@ -0,0 +1,37 @@ +# Copyright (C) 2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program 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/>. + +# Compile test libcore, no torture testing. +# +# Skip torture testing for now, as it'd be slow + +# Load support procs. +load_lib rust-dg.exp + +# Initialize `dg'. +dg-init + +# Main loop. +set saved-dg-do-what-default ${dg-do-what-default} + +set dg-do-what-default "compile" +set individual_timeout 600 +dg-additional-files [lsort [glob -nocomplain $srcdir/../../libgrust/rustc-lib/*]] +dg-runtest $srcdir/../../libgrust/rustc-lib/core/src/lib.rs "-frust-edition=2018 -frust-crate=core -frust-compile-until=astvalidation -w" "" +set dg-do-what-default ${saved-dg-do-what-default} + +# All done. +dg-finish diff --git a/gcc/testsuite/rust/execute/inline_asm_inout_ident.rs b/gcc/testsuite/rust/execute/inline_asm_inout_ident.rs index b0a3d25..324b84d 100644 --- a/gcc/testsuite/rust/execute/inline_asm_inout_ident.rs +++ b/gcc/testsuite/rust/execute/inline_asm_inout_ident.rs @@ -1,3 +1,4 @@ +/* { dg-do run { target x86_64*-*-* } } */ /* { dg-output "Value is: 5\r*\n" } */ #![feature(rustc_attrs)] diff --git a/gcc/testsuite/rust/execute/inline_asm_inout_var.rs b/gcc/testsuite/rust/execute/inline_asm_inout_var.rs index ff101b8..fff432e 100644 --- a/gcc/testsuite/rust/execute/inline_asm_inout_var.rs +++ b/gcc/testsuite/rust/execute/inline_asm_inout_var.rs @@ -1,3 +1,4 @@ +/* { dg-do run { target x86_64*-*-* } } */ /* { dg-output "Value is: 5\r*\n" } */ #![feature(rustc_attrs)] diff --git a/gcc/testsuite/rust/execute/torture/let-identifierpattern-subpattern.rs b/gcc/testsuite/rust/execute/torture/let-identifierpattern-subpattern.rs new file mode 100644 index 0000000..fa1f56e --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/let-identifierpattern-subpattern.rs @@ -0,0 +1,11 @@ +fn main() -> i32 { + let foo @ (bar, _, _) = (0, 2, 3); + let mut ret = 1; + + match foo { + (0, 2, 3) => { ret = bar }, + _ => {} + } + + ret +}
\ No newline at end of file diff --git a/gcc/testsuite/rust/execute/torture/link-name.rs b/gcc/testsuite/rust/execute/torture/link-name.rs new file mode 100644 index 0000000..1ab1ac1 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/link-name.rs @@ -0,0 +1,16 @@ +// { dg-additional-options "-fdump-rtl-final" } +// { dg-final { scan-rtl-dump "printf" "final" } } +// { dg-output "gcc\r*\n" } + +extern "C" { + #[link_name = "printf"] + fn druckt(fmt: *const i8, ...); +} + +fn main() -> i32 { + let a = "gcc\0"; + + unsafe { druckt("%s\n\0" as *const str as *const i8, a as *const str as *const i8); } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/match-slicepattern-array-2.rs b/gcc/testsuite/rust/execute/torture/match-slicepattern-array-2.rs new file mode 100644 index 0000000..c6e7762 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/match-slicepattern-array-2.rs @@ -0,0 +1,27 @@ +// { dg-output "correct\r*" } +extern "C" { + fn puts(s: *const i8); +} + +fn main() -> i32 { + let a = [0, 4, 5, 6, 1]; + let mut ret = 1; + + match a { + [1, .., b] => { + /* should not take this path */ + unsafe { puts("wrong\0" as *const str as *const i8) } + } + [0, .., 0] => { + /* should not take this path */ + unsafe { puts("wrong\0" as *const str as *const i8) } + }, + [0, .., b] => { + ret -= b; + unsafe { puts("correct\0" as *const str as *const i8) } + }, + _ => {} + } + + ret +} diff --git a/gcc/testsuite/rust/execute/torture/match-slicepattern-slice-2.rs b/gcc/testsuite/rust/execute/torture/match-slicepattern-slice-2.rs new file mode 100644 index 0000000..2fdffbb --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/match-slicepattern-slice-2.rs @@ -0,0 +1,28 @@ +// { dg-output "correct\r*" } +extern "C" { + fn puts(s: *const i8); +} + +fn main() -> i32 { + let arr = [0, 4, 5, 6, 1]; + let a: &[i32] = &arr; + let mut ret = 1; + + match a { + [1, .., b] => { + /* should not take this path */ + unsafe { puts("wrong\0" as *const str as *const i8) } + } + [0, .., 0] => { + /* should not take this path */ + unsafe { puts("wrong\0" as *const str as *const i8) } + }, + [0, .., b] => { + ret -= b; + unsafe { puts("correct\0" as *const str as *const i8) } + }, + _ => {} + } + + ret +} diff --git a/gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-1.rs b/gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-1.rs new file mode 100644 index 0000000..8d7446d --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-1.rs @@ -0,0 +1,24 @@ +// { dg-output "correct\r*" } +extern "C" { + fn puts(s: *const i8); +} + +fn main() -> i32 { + struct A (i32, i32, i32); + let a = A (0, 1, 2); + let mut ret = 1; + + match a { + A (1, ..) => { + /* should not take this path */ + unsafe { puts("wrong\0" as *const str as *const i8) } + } + A (0, b, ..) => { + ret -= b; + unsafe { puts("correct\0" as *const str as *const i8) } + }, + _ => {} + } + + ret +} diff --git a/gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-2.rs b/gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-2.rs new file mode 100644 index 0000000..f433be9 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/match-tuplestructpattern-rest-2.rs @@ -0,0 +1,28 @@ +// { dg-output "correct\r*" } +extern "C" { + fn puts(s: *const i8); +} + +fn main() -> i32 { + struct A (i32, i32, i32); + let a = A (0, 3, 1); + let mut ret = 1; + + match a { + A (1, ..) => { + /* should not take this path */ + unsafe { puts("wrong\0" as *const str as *const i8) } + } + A (.., 3) => { + /* should not take this path */ + unsafe { puts("wrong\0" as *const str as *const i8) } + } + A (.., b) => { + ret -= b; + unsafe { puts("correct\0" as *const str as *const i8) } + }, + _ => {} + } + + ret +} diff --git a/gcc/tree-scalar-evolution.cc b/gcc/tree-scalar-evolution.cc index ecdef75..9f82abc 100644 --- a/gcc/tree-scalar-evolution.cc +++ b/gcc/tree-scalar-evolution.cc @@ -3949,11 +3949,6 @@ final_value_replacement_loop (class loop *loop) auto loc = gimple_phi_arg_location (phi, exit->dest_idx); remove_phi_node (&psi, false); - /* Propagate constants immediately, but leave an unused initialization - around to avoid invalidating the SCEV cache. */ - if (CONSTANT_CLASS_P (def) && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rslt)) - replace_uses_by (rslt, def); - /* Create the replacement statements. */ gimple_seq stmts; def = force_gimple_operand (def, &stmts, false, NULL_TREE); @@ -3961,6 +3956,11 @@ final_value_replacement_loop (class loop *loop) gimple_set_location (ass, loc); gimple_seq_add_stmt (&stmts, ass); + /* Propagate constants immediately, but leave an unused initialization + around to avoid invalidating the SCEV cache. */ + if (CONSTANT_CLASS_P (def) && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rslt)) + replace_uses_by (rslt, def); + /* If def's type has undefined overflow and there were folded casts, rewrite all stmts added for def into arithmetics with defined overflow behavior. */ @@ -3995,11 +3995,17 @@ final_value_replacement_loop (class loop *loop) { gimple *use_stmt; imm_use_iterator imm_iter; + auto_vec<gimple *, 4> to_fold; FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, rslt) + if (!stmt_can_throw_internal (cfun, use_stmt)) + to_fold.safe_push (use_stmt); + /* Delay folding until after the immediate use walk is completed + as we have an active ranger and that might walk immediate + uses of rslt again. See PR122502. */ + for (gimple *use_stmt : to_fold) { gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt); - if (!stmt_can_throw_internal (cfun, use_stmt) - && fold_stmt (&gsi, follow_all_ssa_edges)) + if (fold_stmt (&gsi, follow_all_ssa_edges)) update_stmt (gsi_stmt (gsi)); } } diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc index 79ac25f..9a993ab 100644 --- a/gcc/tree-ssa-forwprop.cc +++ b/gcc/tree-ssa-forwprop.cc @@ -216,31 +216,6 @@ static bitmap to_purge; /* Const-and-copy lattice. */ static vec<tree> lattice; -/* forwprop_may_propagate_copy is like may_propagate_copy except - after the final folding, don't allow propagating of pointer ORIG - that have a lower alignment than the DEST name. - This is to prevent losing alignment information from - __builtin_assume_aligned for expand (See also PR 122086). */ -static bool -forwprop_may_propagate_copy (tree dest, tree orig, - bool dest_not_abnormal_phi_edge_p = false) -{ - if (!may_propagate_copy (dest, orig, dest_not_abnormal_phi_edge_p)) - return false; - - /* Only check alignment for the final folding. */ - if (!(cfun->curr_properties & PROP_last_full_fold)) - return true; - - /* Alignment only matters for pointer types. */ - if (!POINTER_TYPE_P (TREE_TYPE (dest)) || !POINTER_TYPE_P (TREE_TYPE (orig))) - return true; - - unsigned aligndest = get_pointer_alignment (dest); - unsigned alignorig = get_pointer_alignment (orig); - return aligndest <= alignorig; -} - /* Set the lattice entry for NAME to VAL. */ static void fwprop_set_lattice_val (tree name, tree val) @@ -1818,6 +1793,7 @@ do_simple_agr_dse (gassign *stmt, bool full_walk) /* Only handle clobbers of a full decl. */ if (!DECL_P (lhs)) return; + clobber_kind kind = (clobber_kind)CLOBBER_KIND (gimple_assign_rhs1 (stmt)); ao_ref_init (&read, lhs); tree vuse = gimple_vuse (stmt); unsigned limit = full_walk ? param_sccvn_max_alias_queries_per_access : 4; @@ -1839,6 +1815,25 @@ do_simple_agr_dse (gassign *stmt, bool full_walk) basic_block ubb = gimple_bb (use_stmt); if (stmt == use_stmt) continue; + /* If the use is the same kind of clobber for lhs, + then it can be safely skipped; this happens with eh + and sometimes jump threading. */ + if (gimple_clobber_p (use_stmt, kind) + && lhs == gimple_assign_lhs (use_stmt)) + continue; + /* If the use is a phi and it is single use then check if that single use + is a clobber of the same kind and lhs is the same. */ + if (gphi *use_phi = dyn_cast<gphi*>(use_stmt)) + { + use_operand_p ou; + gimple *ostmt; + if (single_imm_use (gimple_phi_result (use_phi), &ou, &ostmt) + && gimple_clobber_p (ostmt, kind) + && lhs == gimple_assign_lhs (ostmt)) + continue; + /* A phi node will never be dominating the clobber. */ + return; + } /* The use needs to be dominating the clobber. */ if ((ubb != bb && !dominated_by_p (CDI_DOMINATORS, bb, ubb)) || ref_maybe_used_by_stmt_p (use_stmt, &read, false)) @@ -5202,7 +5197,7 @@ pass_forwprop::execute (function *fun) } if (all_same) { - if (forwprop_may_propagate_copy (res, first)) + if (may_propagate_copy (res, first)) to_remove_defs.safe_push (SSA_NAME_VERSION (res)); fwprop_set_lattice_val (res, first); } @@ -5557,7 +5552,7 @@ pass_forwprop::execute (function *fun) { if (!is_gimple_debug (stmt)) bitmap_set_bit (simple_dce_worklist, SSA_NAME_VERSION (use)); - if (forwprop_may_propagate_copy (use, val)) + if (may_propagate_copy (use, val)) { propagate_value (usep, val); substituted_p = true; @@ -5720,7 +5715,7 @@ pass_forwprop::execute (function *fun) /* If we can propagate the lattice-value mark the stmt for removal. */ if (val != lhs - && forwprop_may_propagate_copy (lhs, val)) + && may_propagate_copy (lhs, val)) to_remove_defs.safe_push (SSA_NAME_VERSION (lhs)); fwprop_set_lattice_val (lhs, val); } @@ -5742,7 +5737,7 @@ pass_forwprop::execute (function *fun) continue; tree val = fwprop_ssa_val (arg); if (val != arg - && forwprop_may_propagate_copy (arg, val, !(e->flags & EDGE_ABNORMAL))) + && may_propagate_copy (arg, val, !(e->flags & EDGE_ABNORMAL))) propagate_value (use_p, val); } diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc index 6e13086..cc76383 100644 --- a/gcc/tree-ssa-loop-niter.cc +++ b/gcc/tree-ssa-loop-niter.cc @@ -2321,6 +2321,48 @@ is_rshift_by_1 (gassign *stmt) return false; } +/* Helper for number_of_iterations_cltz that uses ranger to determine + if SRC's range, shifted left (when LEFT_SHIFT is true) or right + by NUM_IGNORED_BITS, is guaranteed to be != 0 on LOOP's preheader + edge. + Return true if so or false otherwise. */ + +static bool +shifted_range_nonzero_p (loop_p loop, tree src, + bool left_shift, int num_ignored_bits) +{ + int_range_max r (TREE_TYPE (src)); + gcc_assert (num_ignored_bits >= 0); + + if (get_range_query (cfun)->range_on_edge + (r, loop_preheader_edge (loop), src) + && !r.varying_p () + && !r.undefined_p ()) + { + if (num_ignored_bits) + { + range_op_handler op (left_shift ? LSHIFT_EXPR : RSHIFT_EXPR); + int_range_max shifted_range (TREE_TYPE (src)); + wide_int shift_count = wi::shwi (num_ignored_bits, + TYPE_PRECISION (TREE_TYPE + (src))); + int_range_max shift_amount + (TREE_TYPE (src), shift_count, shift_count); + + if (op.fold_range (shifted_range, TREE_TYPE (src), r, + shift_amount)) + r = shifted_range; + } + + /* If the range does not contain zero we are good. */ + if (!range_includes_zero_p (r)) + return true; + } + + return false; +} + + /* See comment below for number_of_iterations_bitcount. For c[lt]z, we have: @@ -2438,6 +2480,9 @@ number_of_iterations_cltz (loop_p loop, edge exit, tree src = gimple_phi_arg_def (phi, loop_preheader_edge (loop)->dest_idx); int src_precision = TYPE_PRECISION (TREE_TYPE (src)); + /* Save the original SSA name before preprocessing for ranger queries. */ + tree unshifted_src = src; + /* Apply any needed preprocessing to src. */ int num_ignored_bits; if (left_shift) @@ -2463,10 +2508,52 @@ number_of_iterations_cltz (loop_p loop, edge exit, expr = fold_convert (unsigned_type_node, expr); - tree assumptions = fold_build2 (NE_EXPR, boolean_type_node, src, - build_zero_cst (TREE_TYPE (src))); + /* If the copy-header (ch) pass peeled one iteration we're shifting + SRC by preprocessing it above. + + A loop like + if (bits) + { + while (!(bits & 1)) + { + bits >>= 1; + cnt += 1; + } + return cnt; + } + ch (roughly) transforms into: + if (bits) + { + if (!(bits & 1) + { + do + { + bits >>= 1; + cnt += 1; + } while (!(bits & 1)); + } + else + cnt = 1; + return cnt; + } + + Then, our preprocessed SRC (that is used for c[tl]z computation) + will be bits >> 1, and the assumption is bits >> 1 != 0. */ + + tree assumptions; + if (shifted_range_nonzero_p (loop, unshifted_src, + left_shift, num_ignored_bits)) + assumptions = boolean_true_node; + else + { + /* If ranger couldn't prove the assumption, try + simplify_using_initial_conditions. */ + assumptions = fold_build2 (NE_EXPR, boolean_type_node, src, + build_zero_cst (TREE_TYPE (src))); + assumptions = simplify_using_initial_conditions (loop, assumptions); + } - niter->assumptions = simplify_using_initial_conditions (loop, assumptions); + niter->assumptions = assumptions; niter->may_be_zero = boolean_false_node; niter->niter = simplify_using_initial_conditions (loop, expr); diff --git a/gcc/tree-ssa-loop.cc b/gcc/tree-ssa-loop.cc index 5629524..dc4b560 100644 --- a/gcc/tree-ssa-loop.cc +++ b/gcc/tree-ssa-loop.cc @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "fold-const.h" #include "gimple-iterator.h" +#include "gimple-range.h" #include "tree-ssa-loop-ivopts.h" #include "tree-ssa-loop-manip.h" #include "tree-ssa-loop-niter.h" @@ -404,11 +405,15 @@ pass_scev_cprop::execute (function *) { bool any = false; + enable_ranger (cfun); + /* Perform final value replacement in loops, in case the replacement expressions are cheap. */ for (auto loop : loops_list (cfun, LI_FROM_INNERMOST)) any |= final_value_replacement_loop (loop); + disable_ranger (cfun); + return any ? TODO_cleanup_cfg | TODO_update_ssa_only_virtuals : 0; } diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc index 66c4518..aa6c3e2 100644 --- a/gcc/tree-vect-slp.cc +++ b/gcc/tree-vect-slp.cc @@ -558,7 +558,8 @@ vect_get_operand_map (const gimple *stmt, bool gather_scatter_p = false, if (gimple_assign_rhs_code (assign) == COND_EXPR && COMPARISON_CLASS_P (gimple_assign_rhs1 (assign))) gcc_unreachable (); - if (TREE_CODE_CLASS (gimple_assign_rhs_code (assign)) == tcc_comparison + if ((TREE_CODE_CLASS (gimple_assign_rhs_code (assign)) == tcc_comparison + || commutative_tree_code (gimple_assign_rhs_code (assign))) && swap) return op1_op0_map; if (gather_scatter_p) @@ -1352,7 +1353,12 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap, uniform but only that of the first stmt matters. */ && !(first_reduc_idx != -1 && STMT_VINFO_REDUC_IDX (stmt_info) != -1 - && REDUC_GROUP_FIRST_ELEMENT (stmt_info))) + && REDUC_GROUP_FIRST_ELEMENT (stmt_info)) + && !(first_reduc_idx != -1 + && STMT_VINFO_REDUC_IDX (stmt_info) != -1 + && rhs_code.is_tree_code () + && commutative_tree_code (tree_code (rhs_code)) + && first_reduc_idx == 1 - STMT_VINFO_REDUC_IDX (stmt_info))) { if (dump_enabled_p ()) { @@ -1617,6 +1623,15 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap, && (swap_tree_comparison ((tree_code)first_stmt_code) == (tree_code)rhs_code)) swap[i] = 1; + + if (i != 0 + && first_reduc_idx != STMT_VINFO_REDUC_IDX (stmt_info) + && first_reduc_idx != -1 + && STMT_VINFO_REDUC_IDX (stmt_info) != -1 + && rhs_code.is_tree_code () + && commutative_tree_code (tree_code (rhs_code)) + && first_reduc_idx == 1 - STMT_VINFO_REDUC_IDX (stmt_info)) + swap[i] = 1; } matches[i] = true; @@ -4164,6 +4179,10 @@ vect_build_slp_instance (vec_info *vinfo, if (dump_enabled_p ()) { + if (kind == slp_inst_kind_reduc_group) + dump_printf_loc (MSG_NOTE, vect_location, + "SLP discovery of size %d reduction group " + "succeeded\n", group_size); dump_printf_loc (MSG_NOTE, vect_location, "Final SLP tree for instance %p:\n", (void *) new_instance); @@ -6302,6 +6321,7 @@ private: /* Layout selection. */ bool is_compatible_layout (slp_tree, unsigned int); + bool is_compatible_layout (const slpg_partition_info &, unsigned int); int change_layout_cost (slp_tree, unsigned int, unsigned int); slpg_partition_layout_costs &partition_layout_costs (unsigned int, unsigned int); @@ -6309,6 +6329,7 @@ private: int, unsigned int); int internal_node_cost (slp_tree, int, unsigned int); void start_choosing_layouts (); + bool legitimize (); /* Cost propagation. */ slpg_layout_cost edge_layout_cost (graph_edge *, unsigned int, @@ -6715,6 +6736,29 @@ vect_optimize_slp_pass::is_compatible_layout (slp_tree node, return true; } +/* Return true if layout LAYOUT_I is compatible with the number of SLP lanes + that NODE would operate on for each NODE in PARTITION. + This test is independent of NODE's actual operations. */ + +bool +vect_optimize_slp_pass::is_compatible_layout (const slpg_partition_info + &partition, + unsigned int layout_i) +{ + for (unsigned int order_i = partition.node_begin; + order_i < partition.node_end; ++order_i) + { + unsigned int node_i = m_partitioned_nodes[order_i]; + auto &vertex = m_vertices[node_i]; + + /* The layout is incompatible if it is individually incompatible + with any node in the partition. */ + if (!is_compatible_layout (vertex.node, layout_i)) + return false; + } + return true; +} + /* Return the cost (in arbtirary units) of going from layout FROM_LAYOUT_I to layout TO_LAYOUT_I for a node like NODE. Return -1 if either of the layouts is incompatible with NODE or if the change is not possible for @@ -8034,6 +8078,62 @@ vect_optimize_slp_pass::decide_masked_load_lanes () } } +/* Perform legitimizing attempts. This is intended to improve the + situation when layout 0 is not valid which is a situation the cost + based propagation does not handle well. + Return true if further layout optimization is possible, false if + the layout configuration should be considered final. */ + +bool +vect_optimize_slp_pass::legitimize () +{ + /* Perform a very simple legitimizing attempt by attempting to choose + a single layout for all partitions that will make all permutations + a noop. That should also be the optimal layout choice in case + layout zero is legitimate. + ??? Disconnected components of the SLP graph could have distinct + single layouts. */ + int single_layout_i = -1; + unsigned deferred_up_to = -1U; + for (unsigned partition_i = 0; partition_i < m_partitions.length (); + ++partition_i) + { + auto &partition = m_partitions[partition_i]; + if (single_layout_i == -1) + { + single_layout_i = partition.layout; + deferred_up_to = partition_i; + } + else if (partition.layout == single_layout_i || partition.layout == -1) + ; + else + single_layout_i = 0; + if (single_layout_i == 0) + return true; + + if (single_layout_i != -1 + && !is_compatible_layout (partition, single_layout_i)) + return true; + } + + if (single_layout_i <= 0) + return true; + + for (unsigned partition_i = 0; partition_i < deferred_up_to; ++partition_i) + if (!is_compatible_layout (m_partitions[partition_i], + single_layout_i)) + return true; + + for (unsigned partition_i = 0; partition_i < m_partitions.length (); + ++partition_i) + { + auto &partition = m_partitions[partition_i]; + partition.layout = single_layout_i; + } + + return false; +} + /* Main entry point for the SLP graph optimization pass. */ void @@ -8044,8 +8144,11 @@ vect_optimize_slp_pass::run () start_choosing_layouts (); if (m_perms.length () > 1) { - forward_pass (); - backward_pass (); + if (legitimize ()) + { + forward_pass (); + backward_pass (); + } if (dump_enabled_p ()) dump (); materialize (); @@ -9036,8 +9139,11 @@ vect_slp_analyze_operations (vec_info *vinfo) stmt_vec_info stmt_info; if (!SLP_INSTANCE_ROOT_STMTS (instance).is_empty ()) stmt_info = SLP_INSTANCE_ROOT_STMTS (instance)[0]; - else + else if (!SLP_TREE_SCALAR_STMTS (node).is_empty () + && SLP_TREE_SCALAR_STMTS (node)[0]) stmt_info = SLP_TREE_SCALAR_STMTS (node)[0]; + else + stmt_info = SLP_TREE_REPRESENTATIVE (node); if (is_a <loop_vec_info> (vinfo)) { if (dump_enabled_p ()) diff --git a/gcc/varpool.cc b/gcc/varpool.cc index 976e0fa..8dc5f98 100644 --- a/gcc/varpool.cc +++ b/gcc/varpool.cc @@ -172,11 +172,7 @@ void varpool_node::remove (void) { symtab->call_varpool_removal_hooks (this); - if (lto_file_data) - { - lto_free_function_in_decl_state_for_node (this); - lto_file_data = NULL; - } + lto_free_function_in_decl_state_for_node (this); /* When streaming we can have multiple nodes associated with decl. */ if (symtab->state == LTO_STREAMING) |
