From: Viljar Indus <in...@adacore.com> Replace calls to Is_Ignored_Ghost_Entity and Predicates_Ignored with their In_Codegen versions in places where we would analyze those nodes differently from checked nodes.
Describe the motive and use cases for those In_Codegen functions. gcc/ada/ChangeLog: * contracts.adb: Use the In_Codegen function instead. * exp_ch3.adb: Likewise. * exp_ch5.adb: Likewise. * exp_ch6.adb: Likewise. * exp_ch7.adb: Likewise. * exp_ch9.adb: Likewise. * exp_disp.adb: Likewise. * exp_util.adb: Likewise. * freeze.adb: Likewise. * ghost.adb: Likewise. * inline.adb: Likewise. * repinfo.adb: Likewise. * sem_ch10.adb: Likewise. * sem_ch13.adb: Likewise. * sem_ch3.adb: Likewise. * sem_ch6.adb: Likewise. * sem_elab.adb: Likewise. * sem_res.adb: Likewise. * sem_util.adb (Predicates_Ignored_In_Codegen): Add new function for the Predicates_Ignored property. (Predicates_Enabled): Use Predicates_Ignored_In_Codegen instead. * sem_util.ads (Predicates_Ignored_In_Codegen): New function. (Is_Ignored_In_Codegen): Add documentation on how _In_Codegen functions should be used. Tested on x86_64-pc-linux-gnu, committed on master. --- gcc/ada/contracts.adb | 2 +- gcc/ada/exp_ch3.adb | 4 ++-- gcc/ada/exp_ch5.adb | 6 +++--- gcc/ada/exp_ch6.adb | 4 ++-- gcc/ada/exp_ch7.adb | 12 ++++++------ gcc/ada/exp_ch9.adb | 2 +- gcc/ada/exp_disp.adb | 2 +- gcc/ada/exp_util.adb | 10 +++++----- gcc/ada/freeze.adb | 4 +++- gcc/ada/ghost.adb | 8 +++----- gcc/ada/inline.adb | 4 +++- gcc/ada/repinfo.adb | 2 +- gcc/ada/sem_ch10.adb | 2 +- gcc/ada/sem_ch13.adb | 2 +- gcc/ada/sem_ch3.adb | 12 +++++++----- gcc/ada/sem_ch6.adb | 5 +++-- gcc/ada/sem_elab.adb | 2 +- gcc/ada/sem_res.adb | 4 ++-- gcc/ada/sem_util.adb | 19 +++++++++++++++---- gcc/ada/sem_util.ads | 35 +++++++++++++++++++++++++++++++++++ 20 files changed, 96 insertions(+), 45 deletions(-) diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb index b7b2c507885..a6862c42416 100644 --- a/gcc/ada/contracts.adb +++ b/gcc/ada/contracts.adb @@ -3282,7 +3282,7 @@ package body Contracts is -- The contract of an ignored Ghost subprogram does not need expansion, -- because the subprogram and all calls to it will be removed. - elsif Is_Ignored_Ghost_Entity (Subp_Id) then + elsif Is_Ignored_Ghost_Entity_In_Codegen (Subp_Id) then return; -- No action needed for helpers and indirect-call wrapper built to diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index c6ef88faca2..07cb4eb84de 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -2145,7 +2145,7 @@ package body Exp_Ch3 is end if; if Policy_In_Effect (Name_Assert) = Name_Check - and then not Predicates_Ignored (Etype (Discr)) + and then not Predicates_Ignored_In_Codegen (Etype (Discr)) then Prepend_To (Res, Make_Predicate_Check (Typ, Val)); end if; @@ -5878,7 +5878,7 @@ package body Exp_Ch3 is -- the subtype. if not No_Exception_Handlers_Set - and then not Predicates_Ignored (Typ) + and then not Predicates_Ignored_In_Codegen (Typ) then Append_To (Lst, Make_Case_Statement_Alternative (Loc, diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 66a4fc0512b..d78df5c8315 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -4118,7 +4118,7 @@ package body Exp_Ch5 is if Compile_Time_Known_Value (Expr) and then Has_Predicates (Etype (Expr)) - and then not Predicates_Ignored (Etype (Expr)) + and then not Predicates_Ignored_In_Codegen (Etype (Expr)) and then not Is_OK_Static_Expression (Expr) then Rewrite (N, @@ -4203,7 +4203,7 @@ package body Exp_Ch5 is -- generated case statements). if Validity_Check_Default - and then not Predicates_Ignored (Etype (Expr)) + and then not Predicates_Ignored_In_Codegen (Etype (Expr)) then -- Recognize the simple case where Expr is an object reference -- and the case statement is directly preceded by an @@ -4378,7 +4378,7 @@ package body Exp_Ch5 is -- predicate, and there is no Others choice, Constraint_Error -- must be raised (RM 4.5.7 (21/3) and 5.4 (13)). - if Predicates_Ignored (Etype (Expr)) then + if Predicates_Ignored_In_Codegen (Etype (Expr)) then declare Except : constant Node_Id := Make_Raise_Constraint_Error (Loc, diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index a7b694270d8..18551d4899e 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -5247,7 +5247,7 @@ package body Exp_Ch6 is -- the current subprogram is called. if Is_Subprogram (Subp) - and then not Is_Ignored_Ghost_Entity (Subp) + and then not Is_Ignored_Ghost_Entity_In_Codegen (Subp) and then Same_Or_Aliased_Subprograms (Subp, Current_Scope) then Check_Subprogram_Variant; @@ -7274,7 +7274,7 @@ package body Exp_Ch6 is elsif (not Needs_Secondary_Stack (R_Type) and then not Is_Secondary_Stack_Thunk (Scope_Id)) - or else Is_Ignored_Ghost_Entity (Scope_Id) + or else Is_Ignored_Ghost_Entity_In_Codegen (Scope_Id) then -- Mutable records with variable-length components are not returned -- on the sec-stack, so we need to make sure that the back end will diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index dd864b7ffd3..62e9d2cbb73 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -2429,7 +2429,7 @@ package body Exp_Ch7 is -- Do not inspect an ignored Ghost package body because all -- code found within will not appear in the final tree. - if Is_Ignored_Ghost_Entity (Defining_Entity (Decl)) then + if Is_Ignored_Ghost_Entity_In_Codegen (Defining_Entity (Decl)) then null; elsif Ekind (Corresponding_Spec (Decl)) /= E_Generic_Package then @@ -2507,7 +2507,7 @@ package body Exp_Ch7 is -- Ignored Ghost types do not need any cleanup actions because -- they will not appear in the final tree. - if Is_Ignored_Ghost_Entity (Typ) then + if Is_Ignored_Ghost_Entity_In_Codegen (Typ) then null; elsif Is_Tagged_Type (Typ) @@ -2553,7 +2553,7 @@ package body Exp_Ch7 is -- Ignored Ghost objects do not need any cleanup actions -- because they will not appear in the final tree. - elsif Is_Ignored_Ghost_Entity (Obj_Id) then + elsif Is_Ignored_Ghost_Entity_In_Codegen (Obj_Id) then null; -- Conversely, if one of the above cases created a Master_Node, @@ -2655,7 +2655,7 @@ package body Exp_Ch7 is -- Freeze nodes for ignored Ghost types do not need cleanup -- actions because they will never appear in the final tree. - if Is_Ignored_Ghost_Entity (Typ) then + if Is_Ignored_Ghost_Entity_In_Codegen (Typ) then null; elsif (Is_Access_Object_Type (Typ) @@ -2680,7 +2680,7 @@ package body Exp_Ch7 is -- Do not inspect an ignored Ghost package because all code -- found within will not appear in the final tree. - if Is_Ignored_Ghost_Entity (Pack_Id) then + if Is_Ignored_Ghost_Entity_In_Codegen (Pack_Id) then null; elsif Ekind (Pack_Id) /= E_Generic_Package then @@ -5281,7 +5281,7 @@ package body Exp_Ch7 is -- Ignored Ghost objects do not need any cleanup actions because -- they will not appear in the final tree. - if Is_Ignored_Ghost_Entity (Obj_Id) then + if Is_Ignored_Ghost_Entity_In_Codegen (Obj_Id) then return; end if; diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb index c979cf6899b..a9eac808af6 100644 --- a/gcc/ada/exp_ch9.adb +++ b/gcc/ada/exp_ch9.adb @@ -4686,7 +4686,7 @@ package body Exp_Ch9 is -- by a missing activation chain entity; also skip generating it when -- it is a ghost entity. - if No (Chain) or else Is_Ignored_Ghost_Entity (Chain) then + if No (Chain) or else Is_Ignored_Ghost_Entity_In_Codegen (Chain) then return; -- The availability of the activation chain entity does not ensure diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb index 0f6bef17ecf..f15d5244ba8 100644 --- a/gcc/ada/exp_disp.adb +++ b/gcc/ada/exp_disp.adb @@ -6056,7 +6056,7 @@ package body Exp_Disp is -- Skip ignored Ghost subprograms as those will be removed -- from the executable. - and then not Is_Ignored_Ghost_Entity (E) + and then not Is_Ignored_Ghost_Entity_In_Codegen (E) then pragma Assert (UI_To_Int (DT_Position (Prim)) <= Nb_Prim); diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index ed515d0d49e..6ce6c0cd81d 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -13498,7 +13498,7 @@ package body Exp_Util is -- Ignored Ghost types do not need any cleanup actions because -- they will not appear in the final tree. - if Is_Ignored_Ghost_Entity (Typ) then + if Is_Ignored_Ghost_Entity_In_Codegen (Typ) then null; elsif Is_Tagged_Type (Typ) @@ -13544,7 +13544,7 @@ package body Exp_Util is -- Ignored Ghost objects do not need any cleanup actions because -- they will not appear in the final tree. - elsif Is_Ignored_Ghost_Entity (Obj_Id) then + elsif Is_Ignored_Ghost_Entity_In_Codegen (Obj_Id) then null; -- Conversely, if one of the above cases created a Master_Node, @@ -13640,7 +13640,7 @@ package body Exp_Util is -- Freeze nodes for ignored Ghost types do not need cleanup -- actions because they will never appear in the final tree. - if Is_Ignored_Ghost_Entity (Typ) then + if Is_Ignored_Ghost_Entity_In_Codegen (Typ) then null; elsif ((Is_Access_Object_Type (Typ) @@ -13663,7 +13663,7 @@ package body Exp_Util is -- Do not inspect an ignored Ghost package because all code found -- within will not appear in the final tree. - if Is_Ignored_Ghost_Entity (Pack_Id) then + if Is_Ignored_Ghost_Entity_In_Codegen (Pack_Id) then null; elsif Ekind (Pack_Id) /= E_Generic_Package @@ -13680,7 +13680,7 @@ package body Exp_Util is -- Do not inspect an ignored Ghost package body because all code -- found within will not appear in the final tree. - if Is_Ignored_Ghost_Entity (Defining_Entity (Decl)) then + if Is_Ignored_Ghost_Entity_In_Codegen (Defining_Entity (Decl)) then null; elsif Ekind (Corresponding_Spec (Decl)) /= E_Generic_Package diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index f383b57ae23..8fa25b3d851 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -4685,7 +4685,9 @@ package body Freeze is -- Declaring too big an array in disabled ghost code is OK - if Is_Array_Type (Typ) and then not Is_Ignored_Ghost_Entity (E) then + if Is_Array_Type (Typ) + and then not Is_Ignored_Ghost_Entity_In_Codegen (E) + then Check_Large_Modular_Array (Typ); end if; end Freeze_Object_Declaration; diff --git a/gcc/ada/ghost.adb b/gcc/ada/ghost.adb index f0c62f3dc06..54153081ad5 100644 --- a/gcc/ada/ghost.adb +++ b/gcc/ada/ghost.adb @@ -1777,7 +1777,7 @@ package body Ghost is return Nkind (N) = N_Compilation_Unit - and then Is_Ignored_Ghost_Entity + and then Is_Ignored_Ghost_Entity_In_Codegen (Defining_Entity (Ultimate_Original_Node (Unit (N)))); end Is_Ignored_Ghost_Unit; @@ -2189,9 +2189,7 @@ package body Ghost is -- Inherit the "ghostness" of the generic unit, but the current Ghost -- policy is the relevant one for the instantiation. - elsif Is_Checked_Ghost_Entity (Gen_Id) - or else Is_Ignored_Ghost_Entity (Gen_Id) - then + elsif Is_Ghost_Entity (Gen_Id) then Policy := Ghost_Policy_In_Effect (Gen_Id); if Policy = No_Name then @@ -2278,7 +2276,7 @@ package body Ghost is if Present (Nam) and then Is_Entity_Name (Nam) and then Present (Entity (Nam)) - and then Is_Ignored_Ghost_Entity (Entity (Nam)) + and then Is_Ignored_Ghost_Entity_In_Codegen (Entity (Nam)) then Set_Is_Ignored_Ghost_Node (N); Record_Ignored_Ghost_Node (N); diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb index 5e2f033b913..a592494500f 100644 --- a/gcc/ada/inline.adb +++ b/gcc/ada/inline.adb @@ -1061,7 +1061,9 @@ package body Inline is E : constant Subprogram_Kind_Id := Inlined.Table (Index).Name; begin - if Is_Called (E) and then not Is_Ignored_Ghost_Entity (E) then + if Is_Called (E) + and then not Is_Ignored_Ghost_Entity_In_Codegen (E) + then Add_Inlined_Subprogram (E); end if; end; diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index bbf92a77800..e236e4e54be 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -455,7 +455,7 @@ package body Repinfo is if Present (Ent) and then Nkind (Declaration_Node (Ent)) not in N_Renaming_Declaration - and then not Is_Ignored_Ghost_Entity (Ent) + and then not Sem_Util.Is_Ignored_Ghost_Entity_In_Codegen (Ent) then -- If entity is a subprogram and we are listing mechanisms, -- then we need to list mechanisms for this entity. We skip this diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb index f58513d115f..7b126aa0f3f 100644 --- a/gcc/ada/sem_ch10.adb +++ b/gcc/ada/sem_ch10.adb @@ -1494,7 +1494,7 @@ package body Sem_Ch10 is -- No checked needed for ignored ghost units - or else Is_Ignored_Ghost_Entity (Spec_Id) + or else Is_Ignored_Ghost_Entity_In_Codegen (Spec_Id) ) then -- This is a case where we only need the entity for checking to diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 370df803c25..a4f15ac979c 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -5103,7 +5103,7 @@ package body Sem_Ch13 is if Class_Present (Aspect) and then A_Id in Aspect_Pre | Aspect_Post and then Is_Subprogram (E) - and then not Is_Ignored_Ghost_Entity (E) + and then not Is_Ignored_Ghost_Entity_In_Codegen (E) then if A_Id = Aspect_Pre then if Is_Ignored_In_Codegen (Aspect) then diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index c8922cdee65..eae366e09d7 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -2898,12 +2898,14 @@ package body Sem_Ch3 is -- private type from a library unit, otherwise premature freezing of -- the private type will occur. - elsif not Analyzed (Next_Decl) and then Is_Body (Next_Decl) + elsif not Analyzed (Next_Decl) + and then Is_Body (Next_Decl) and then ((Nkind (Next_Decl) /= N_Subprogram_Body - or else not Was_Expression_Function (Next_Decl)) - or else (not Is_Ignored_Ghost_Entity (Current_Scope) - and then not Contains_Lib_Incomplete_Type - (Current_Scope))) + or else not Was_Expression_Function (Next_Decl)) + or else (not Is_Ignored_Ghost_Entity_In_Codegen + (Current_Scope) + and then not Contains_Lib_Incomplete_Type + (Current_Scope))) then -- When a controlled type is frozen, the expander generates stream -- and controlled-type support routines. If the freeze is caused diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index a427c7a86b0..9042b3378ce 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -581,7 +581,8 @@ package body Sem_Ch6 is -- Ghost subprogram. if Inside_A_Generic then - Set_Has_Completion (Def_Id, not Is_Ignored_Ghost_Entity (Def_Id)); + Set_Has_Completion + (Def_Id, not Is_Ignored_Ghost_Entity_In_Codegen (Def_Id)); Push_Scope (Def_Id); Install_Formals (Def_Id); Preanalyze_And_Resolve_Spec_Expression (Expr, Typ); @@ -3907,7 +3908,7 @@ package body Sem_Ch6 is and then Serious_Errors_Detected = 0 and then (Expander_Active or else Operating_Mode = Check_Semantics - or else Is_Ignored_Ghost_Entity (Spec_Id)) + or else Is_Ignored_Ghost_Entity_In_Codegen (Spec_Id)) then -- The body generated for an expression function that is not a -- completion is a freeze point neither for the profile nor for diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb index 77b1e120b80..0ce2b35305a 100644 --- a/gcc/ada/sem_elab.adb +++ b/gcc/ada/sem_elab.adb @@ -11199,7 +11199,7 @@ package body Sem_Elab is (Id : Entity_Id) return Extended_Ghost_Mode is begin - return To_Ghost_Mode (Is_Ignored_Ghost_Entity (Id)); + return To_Ghost_Mode (Is_Ignored_Ghost_Entity_In_Codegen (Id)); end Ghost_Mode_Of_Entity; ------------------------ diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 29b77668802..f02c223809c 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -6954,7 +6954,7 @@ package body Sem_Res is -- checkable, the case of calling an immediately containing -- subprogram is easy to catch. - if not Is_Ignored_Ghost_Entity (Nam) then + if not Is_Ignored_Ghost_Entity_In_Codegen (Nam) then Check_Restriction (No_Recursion, N); end if; @@ -7092,7 +7092,7 @@ package body Sem_Res is and then Ekind (Nam) in E_Function | E_Subprogram_Type and then Requires_Transient_Scope (Etype (Nam)) and then not Is_Intrinsic_Subprogram (Nam) - and then not Is_Ignored_Ghost_Entity (Nam) + and then not Is_Ignored_Ghost_Entity_In_Codegen (Nam) and then not Is_Build_In_Place_Function (Nam) and then not Is_Inlinable_Expression_Function (Nam) and then not (Is_Inlined (Nam) diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index b3b6dec5515..8a3998d7d12 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -26658,9 +26658,8 @@ package body Sem_Util is begin return Present (Predicate_Function (Typ)) - and then (GNATprove_Mode - or else (not Predicates_Ignored (Typ) - and then not Predicate_Checks_Suppressed (Empty))); + and then not Predicates_Ignored_In_Codegen (Typ) + and then not Predicate_Checks_Suppressed (Empty); end Predicate_Enabled; ---------------------------------- @@ -26726,6 +26725,18 @@ package body Sem_Util is return Empty; end Predicate_Failure_Expression; + ----------------------------------- + -- Predicates_Ignored_In_Codegen -- + ----------------------------------- + + function Predicates_Ignored_In_Codegen (N : Node_Id) return Boolean is + begin + return + Predicates_Ignored (N) + and then not CodePeer_Mode + and then not GNATprove_Mode; + end Predicates_Ignored_In_Codegen; + ---------------------------------- -- Predicate_Tests_On_Arguments -- ---------------------------------- @@ -28163,7 +28174,7 @@ package body Sem_Util is -- Nothing to do for an ignored Ghost entity because the entity will be -- eliminated from the tree. - elsif Is_Ignored_Ghost_Entity (T) then + elsif Is_Ignored_Ghost_Entity_In_Codegen (T) then return; -- Nothing to do if entity comes from a predefined file. Library files diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index a1d4ae0a897..04caed57506 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -2102,14 +2102,42 @@ package Sem_Util is function Is_Ignored_Ghost_Entity_In_Codegen (N : Node_Id) return Boolean; -- True if N Is_Ignored_Ghost_Entity and GNATProve_mode and Codepeer_Mode -- are not active. + -- + -- See Is_Ignored_In_Codegen for instructions on when this function should + -- be used. function Is_Ignored_Ghost_Pragma_In_Codegen (N : Node_Id) return Boolean; -- True if N Is_Ignored_Ghost_Pragma and GNATProve_mode and Codepeer_Mode -- are not active. + -- + -- See Is_Ignored_In_Codegen for instructions on when this function should + -- be used. function Is_Ignored_In_Codegen (N : Node_Id) return Boolean; -- True if N Is_Ignored and GNATProve_mode and Codepeer_Mode are not -- active. + -- + -- Tools like GNATProve and Codepeer that use the frontend to get the + -- representation of the source code along with all of the code generated + -- for assertions. This includes even the ones that are ignored. The + -- frontend normally avoids the generation of such assertions and ghost + -- code if marked as ignored. However we should still enable the generation + -- when working in one of those tool modes. In most cases this means that + -- we should ignore the fact the given node is marked as ignored and behave + -- as if it was not. This involves checking attributes such as Is_Ignored + -- along with these tool modes. + -- + -- This function (and similar _In_Codegen functions) behaves as a wrapper + -- for such conditions. We should use this functions in scenarios where we + -- would normally stop the code generation for such ignored nodes. For + -- example in the expander where we normally transform non-ignored nodes. + -- Not doing so may lead to a partially expanded tree for those tools. + -- + -- On the other hand we should use these attributes directly when + -- propagating the Is_Ignored or other similar property related values + -- between nodes. Additionally we should be using the original attributes + -- when checking for the compatibility of the checked/ignored properties + -- between nodes. function Is_EVF_Expression (N : Node_Id) return Boolean; -- Determine whether node N denotes a reference to a formal parameter of @@ -2959,6 +2987,13 @@ package Sem_Util is -- returns the result of recursing on the ancestor subtype. -- Otherwise, returns Empty. + function Predicates_Ignored_In_Codegen (N : Node_Id) return Boolean; + -- True if N Predicates_Ignored is set and GNATProve_mode and Codepeer_Mode + -- are not active. + -- + -- See Is_Ignored_In_Codegen for instructions on when this function should + -- be used. + function Predicate_Function_Needs_Membership_Parameter (Typ : Entity_Id) return Boolean is (Present (Predicate_Failure_Expression (Typ, Inherited_OK => True))); -- 2.43.0