On Fri, Apr 7, 2017 at 11:42 PM, Jakub Jelinek <ja...@redhat.com> wrote: > Hi! > > The following C and Ada testcases show ICE due to endless recursion in > dwarf2out.c. The problem is that when processing BLOCK_NONLOCALIZED_VARS, > we want to treat all the FUNCTION_DECLs in there as mere declarations, > but gen_subprogram_die does: > int declaration = (current_function_decl != decl > || class_or_namespace_scope_p (context_die)); > and thus if there is some self-inlining and we are unlucky enough > not to reach some early-outs that just ignore the FUNCTION_DECL, > like: > /* Detect and ignore this case, where we are trying to output > something we have already output. */ > if (get_AT (old_die, DW_AT_low_pc) > || get_AT (old_die, DW_AT_ranges)) > return; > we will recurse infinitely. The following patch fixes it by > just ignoring current_function_decl seen from BLOCK_NONLOCALIZED_VARS, > that implies it is already inlined into somewhere and in the abstract > origin we emit properly a DW_AT_declaration decl if needed, that is pretty > much what gen_subprogram_die would do anyway in such cases, because there > is already old_die, we really don't want to make some child of it its parent > and otherwise no further action is performed. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok. Thanks, Richard. > Other possibilities include adding some global bool flag that > gen_subprogram_die's int declaration = ... above should ignore > decl == current_function_decl that we'd set in decls_for_scope when > seeing current_function_decl in BLOCK_NONLOCALIZED_VARS (and probably > save/clear + restore in dwarf2out_abstract_function where we change > current_function_decl). Or we could pass through from decls_for_scope > down through process_scope_var, gen_decl_die to gen_subprogram_die > a bool flag force_declaration. > > 2017-04-07 Jakub Jelinek <ja...@redhat.com> > > PR debug/80321 > * dwarf2out.c (decls_for_scope): Ignore declarations of > current_function_decl in BLOCK_NONLOCALIZED_VARS. > > * gcc.dg/debug/pr80321.c: New test. > > 2017-04-07 Eric Botcazou <ebotca...@adacore.com> > > * gnat.dg/debug10.adb: New test. > * gnat.dg/debug10_pkg.ads: New helper. > > --- gcc/dwarf2out.c.jj 2017-04-07 11:46:48.000000000 +0200 > +++ gcc/dwarf2out.c 2017-04-07 20:00:43.503772542 +0200 > @@ -24889,7 +24889,12 @@ decls_for_scope (tree stmt, dw_die_ref c > for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++) > { > decl = BLOCK_NONLOCALIZED_VAR (stmt, i); > - if (TREE_CODE (decl) == FUNCTION_DECL) > + if (decl == current_function_decl) > + /* Ignore declarations of the current function, while they > + are declarations, gen_subprogram_die would treat them > + as definitions again, because they are equal to > + current_function_decl and endlessly recurse. */; > + else if (TREE_CODE (decl) == FUNCTION_DECL) > process_scope_var (stmt, decl, NULL_TREE, context_die); > else > process_scope_var (stmt, NULL_TREE, decl, context_die); > --- gcc/testsuite/gcc.dg/debug/pr80321.c.jj 2017-04-07 21:39:01.930615179 > +0200 > +++ gcc/testsuite/gcc.dg/debug/pr80321.c 2017-04-07 21:39:49.722982635 > +0200 > @@ -0,0 +1,26 @@ > +/* PR debug/80321 */ > +/* { dg-do compile } */ > +/* { dg-options "-fkeep-inline-functions" } */ > + > +void bar (void); > + > +static inline void > +test (int x) > +{ > + inline void > + foo (int x) > + { > + test (0); > + asm volatile ("" : : : "memory"); > + } > + if (x != 0) > + foo (x); > + else > + bar (); > +} > + > +void > +baz (int x) > +{ > + test (x); > +} > --- gcc/testsuite/gnat.dg/debug10.adb.jj 2017-04-07 20:24:44.232473780 > +0200 > +++ gcc/testsuite/gnat.dg/debug10.adb 2017-04-07 20:26:40.493980722 +0200 > @@ -0,0 +1,68 @@ > +-- PR debug/80321 > + > +-- { dg-do compile } > +-- { dg-options "-O2 -g" } > + > +with Debug10_Pkg; use Debug10_Pkg; > + > +procedure Debug10 (T : Entity_Id) is > + > + procedure Inner (E : Entity_Id); > + pragma Inline (Inner); > + > + procedure Inner (E : Entity_Id) is > + begin > + if E /= Empty > + and then not Nodes (E + 3).Flag16 > + then > + Debug10 (E); > + end if; > + end Inner; > + > + function Ekind (E : Entity_Id) return Entity_Kind is > + begin > + return N_To_E (Nodes (E + 1).Nkind); > + end Ekind; > + > +begin > + > + if T = Empty then > + return; > + end if; > + > + Nodes (T + 3).Flag16 := True; > + > + if Ekind (T) in Object_Kind then > + Inner (T); > + > + elsif Ekind (T) in Type_Kind then > + Inner (T); > + > + if Ekind (T) in Record_Kind then > + > + if Ekind (T) = E_Class_Wide_Subtype then > + Inner (T); > + end if; > + > + elsif Ekind (T) in Array_Kind then > + Inner (T); > + > + elsif Ekind (T) in Access_Kind then > + Inner (T); > + > + elsif Ekind (T) in Scalar_Kind then > + > + if My_Scalar_Range (T) /= Empty > + and then My_Test (My_Scalar_Range (T)) > + then > + if My_Is_Entity_Name (T) then > + Inner (T); > + end if; > + > + if My_Is_Entity_Name (T) then > + Inner (T); > + end if; > + end if; > + end if; > + end if; > +end; > --- gcc/testsuite/gnat.dg/debug10_pkg.ads.jj 2017-04-07 20:24:47.384433302 > +0200 > +++ gcc/testsuite/gnat.dg/debug10_pkg.ads 2017-04-07 20:24:22.000000000 > +0200 > @@ -0,0 +1,138 @@ > +with Unchecked_Conversion; > + > +package Debug10_Pkg is > + > + type Node_Id is range 0 .. 99_999_999; > + > + Empty : constant Node_Id := 0; > + > + subtype Entity_Id is Node_Id; > + > + type Union_Id is new Integer; > + > + function My_Is_Entity_Name (N : Node_Id) return Boolean; > + > + function My_Scalar_Range (Id : Entity_Id) return Node_Id; > + > + function My_Test (N : Node_Id) return Boolean; > + > + type Node_Kind is (N_Unused_At_Start, N_Unused_At_End); > + > + type Entity_Kind is ( > + > + E_Void, > + E_Component, > + E_Constant, > + E_Discriminant, > + E_Loop_Parameter, > + E_Variable, > + E_Out_Parameter, > + E_In_Out_Parameter, > + E_In_Parameter, > + E_Generic_In_Out_Parameter, > + E_Generic_In_Parameter, > + E_Named_Integer, > + E_Named_Real, > + E_Enumeration_Type, > + E_Enumeration_Subtype, > + E_Signed_Integer_Type, > + E_Signed_Integer_Subtype, > + E_Modular_Integer_Type, > + E_Modular_Integer_Subtype, > + E_Ordinary_Fixed_Point_Type, > + E_Ordinary_Fixed_Point_Subtype, > + E_Decimal_Fixed_Point_Type, > + E_Decimal_Fixed_Point_Subtype, > + E_Floating_Point_Type, > + E_Floating_Point_Subtype, > + E_Access_Type, > + E_Access_Subtype, > + E_Access_Attribute_Type, > + E_Allocator_Type, > + E_General_Access_Type, > + E_Access_Subprogram_Type, > + E_Anonymous_Access_Subprogram_Type, > + E_Access_Protected_Subprogram_Type, > + E_Anonymous_Access_Protected_Subprogram_Type, > + E_Anonymous_Access_Type, > + E_Array_Type, > + E_Array_Subtype, > + E_String_Literal_Subtype, > + E_Class_Wide_Type, > + E_Class_Wide_Subtype, > + E_Record_Type, > + E_Record_Subtype, > + E_Record_Type_With_Private, > + E_Record_Subtype_With_Private, > + E_Private_Type, > + E_Private_Subtype, > + E_Limited_Private_Type, > + E_Limited_Private_Subtype, > + E_Incomplete_Type, > + E_Incomplete_Subtype, > + E_Task_Type, > + E_Task_Subtype, > + E_Protected_Type, > + E_Protected_Subtype, > + E_Exception_Type, > + E_Subprogram_Type, > + E_Enumeration_Literal, > + E_Function, > + E_Operator, > + E_Procedure, > + E_Abstract_State, > + E_Entry, > + E_Entry_Family, > + E_Block, > + E_Entry_Index_Parameter, > + E_Exception, > + E_Generic_Function, > + E_Generic_Procedure, > + E_Generic_Package, > + E_Label, > + E_Loop, > + E_Return_Statement, > + E_Package, > + E_Package_Body, > + E_Protected_Object, > + E_Protected_Body, > + E_Task_Body, > + E_Subprogram_Body > + ); > + > + subtype Access_Kind is Entity_Kind range > + E_Access_Type .. > + E_Anonymous_Access_Type; > + > + subtype Array_Kind is Entity_Kind range > + E_Array_Type .. > + E_String_Literal_Subtype; > + > + subtype Object_Kind is Entity_Kind range > + E_Component .. > + E_Generic_In_Parameter; > + > + subtype Record_Kind is Entity_Kind range > + E_Class_Wide_Type .. > + E_Record_Subtype_With_Private; > + > + subtype Scalar_Kind is Entity_Kind range > + E_Enumeration_Type .. > + E_Floating_Point_Subtype; > + > + subtype Type_Kind is Entity_Kind range > + E_Enumeration_Type .. > + E_Subprogram_Type; > + > + type Node_Record (Is_Extension : Boolean := False) is record > + Flag16 : Boolean; > + Nkind : Node_Kind; > + end record; > + > + function N_To_E is new Unchecked_Conversion (Node_Kind, Entity_Kind); > + > + type Arr is array (Node_Id) of Node_Record; > + > + Nodes : Arr; > + > +end Debug10_Pkg; > > Jakub