public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally.
@ 2014-11-27 14:53 Mark Wielaard
  2014-12-04 13:26 ` Mark Wielaard
  2014-12-04 14:02 ` Pedro Alves
  0 siblings, 2 replies; 11+ messages in thread
From: Mark Wielaard @ 2014-11-27 14:53 UTC (permalink / raw)
  To: gdb-patches; +Cc: Mark Wielaard

Add a flag field is_noreturn to struct func_type. Make calling_convention
a small bit field to not increase the size of the struct. Set is_noreturn
if the new GCC5/DWARF5 DW_AT_noreturn is set on a DW_TAG_subprogram.
Use this information to warn the user before doing a finish or return from
a function that does not return normally to its caller.

(gdb) finish
Warning. Function endless does not return normally.
Try to finish anyway? (y or n)

(gdb) return
warning: Function does not return normally to caller!
Make endless return now? (y or n)

gdb/ChangeLog

	* dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from
	DW_AT_noreturn.
	* gdbtypes.h (struct func_type): Add is_noreturn field flag. Make
	calling_convention an 8 bit bit field.
	(TYPE_NO_RETURN): New macro.
	* infcmd.c (finish_command): Query if function does not return
	normally.
	* stack.c (return_command): Likewise.

include/ChangeLog

	* dwarf2.def (DW_AT_noreturn): New DWARF5 attribute.

The dwarf2.h addition and the code to emit the new attribute is already in
the gcc tree.

OK to commit?

Thanks,

Mark

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 36cbbd9..56212e5 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -14312,6 +14312,12 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
   else
     TYPE_CALLING_CONVENTION (ftype) = DW_CC_normal;
 
+  /* Record whether the function returns normally to its caller or not
+     if the DWARF producer set that information.  */
+  attr = dwarf2_attr (die, DW_AT_noreturn, cu);
+  if (attr && (DW_UNSND (attr) != 0))
+    TYPE_NO_RETURN (ftype) = 1;
+
   /* We need to add the subroutine type to the die immediately so
      we don't infinitely recurse when dealing with parameters
      declared as the same subroutine type.  */
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 14a1f08..779b728 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1019,9 +1019,16 @@ struct func_type
   {
     /* * The calling convention for targets supporting multiple ABIs.
        Right now this is only fetched from the Dwarf-2
-       DW_AT_calling_convention attribute.  */
+       DW_AT_calling_convention attribute.  The value is one of the
+       DW_CC enum dwarf_calling_convention constants.  */
 
-    unsigned calling_convention;
+    unsigned calling_convention : 8;
+
+    /* * Whether this function normally returns to its caller.  It is
+       set from the DW_AT_noreturn attribute if set on the
+       DW_TAG_subprogram.  */
+
+    unsigned int is_noreturn : 1;
 
     /* * Only those DW_TAG_GNU_call_site's in this function that have
        DW_AT_GNU_tail_call set are linked in this list.  Function
@@ -1245,6 +1252,7 @@ extern void allocate_gnat_aux_type (struct type *);
 #define TYPE_GNAT_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.gnat_stuff
 #define TYPE_DESCRIPTIVE_TYPE(thistype) TYPE_GNAT_SPECIFIC(thistype)->descriptive_type
 #define TYPE_CALLING_CONVENTION(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->calling_convention
+#define TYPE_NO_RETURN(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->is_noreturn
 #define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->tail_call_list
 #define TYPE_BASECLASS(thistype,index) TYPE_FIELD_TYPE(thistype, index)
 #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 4415b31..8231306 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1869,7 +1869,14 @@ finish_command (char *arg, int from_tty)
       if (execution_direction == EXEC_REVERSE)
 	printf_filtered (_("Run back to call of "));
       else
-	printf_filtered (_("Run till exit from "));
+	{
+	  if (function != NULL && TYPE_NO_RETURN (function->type)
+	      && ! query (_("Warning. Function %s does not return normally.\n"
+			    "Try to finish anyway? "),
+			  SYMBOL_PRINT_NAME (function)))
+	    error (_("Not confirmed."));
+	  printf_filtered (_("Run till exit from "));
+	}
 
       print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
     }
diff --git a/gdb/stack.c b/gdb/stack.c
index 2834801..c753005 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2462,8 +2462,12 @@ return_command (char *retval_exp, int from_tty)
 	confirmed = query (_("%sMake selected stack frame return now? "),
 			   query_prefix);
       else
-	confirmed = query (_("%sMake %s return now? "), query_prefix,
-			   SYMBOL_PRINT_NAME (thisfun));
+	{
+	  if (TYPE_NO_RETURN (thisfun->type))
+	    warning ("Function does not return normally to caller!");
+	  confirmed = query (_("%sMake %s return now? "), query_prefix,
+			     SYMBOL_PRINT_NAME (thisfun));
+	}
       if (!confirmed)
 	error (_("Not confirmed"));
     }
diff --git a/include/dwarf2.def b/include/dwarf2.def
index 8ca143c..8533a3e 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -308,6 +308,8 @@ DW_AT (DW_AT_data_bit_offset, 0x6b)
 DW_AT (DW_AT_const_expr, 0x6c)
 DW_AT (DW_AT_enum_class, 0x6d)
 DW_AT (DW_AT_linkage_name, 0x6e)
+/* DWARF 5.  */
+DW_AT (DW_AT_noreturn, 0x87)
 
 DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start.  */
 DW_AT_DUP (DW_AT_hi_user, 0x3fff) /* Implementation-defined range end.  */

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally.
  2014-11-27 14:53 [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally Mark Wielaard
@ 2014-12-04 13:26 ` Mark Wielaard
  2014-12-04 14:02 ` Pedro Alves
  1 sibling, 0 replies; 11+ messages in thread
From: Mark Wielaard @ 2014-12-04 13:26 UTC (permalink / raw)
  To: gdb-patches

On Thu, 2014-11-27 at 15:53 +0100, Mark Wielaard wrote:
> Add a flag field is_noreturn to struct func_type. Make calling_convention
> a small bit field to not increase the size of the struct. Set is_noreturn
> if the new GCC5/DWARF5 DW_AT_noreturn is set on a DW_TAG_subprogram.
> Use this information to warn the user before doing a finish or return from
> a function that does not return normally to its caller.
> 
> (gdb) finish
> Warning. Function endless does not return normally.
> Try to finish anyway? (y or n)
> 
> (gdb) return
> warning: Function does not return normally to caller!
> Make endless return now? (y or n)
> 
> gdb/ChangeLog
> 
> 	* dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from
> 	DW_AT_noreturn.
> 	* gdbtypes.h (struct func_type): Add is_noreturn field flag. Make
> 	calling_convention an 8 bit bit field.
> 	(TYPE_NO_RETURN): New macro.
> 	* infcmd.c (finish_command): Query if function does not return
> 	normally.
> 	* stack.c (return_command): Likewise.
> 
> include/ChangeLog
> 
> 	* dwarf2.def (DW_AT_noreturn): New DWARF5 attribute.
> 
> The dwarf2.h addition and the code to emit the new attribute is already in
> the gcc tree.
> 
> OK to commit?

Ping.

> diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
> index 36cbbd9..56212e5 100644
> --- a/gdb/dwarf2read.c
> +++ b/gdb/dwarf2read.c
> @@ -14312,6 +14312,12 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
>    else
>      TYPE_CALLING_CONVENTION (ftype) = DW_CC_normal;
>  
> +  /* Record whether the function returns normally to its caller or not
> +     if the DWARF producer set that information.  */
> +  attr = dwarf2_attr (die, DW_AT_noreturn, cu);
> +  if (attr && (DW_UNSND (attr) != 0))
> +    TYPE_NO_RETURN (ftype) = 1;
> +
>    /* We need to add the subroutine type to the die immediately so
>       we don't infinitely recurse when dealing with parameters
>       declared as the same subroutine type.  */
> diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
> index 14a1f08..779b728 100644
> --- a/gdb/gdbtypes.h
> +++ b/gdb/gdbtypes.h
> @@ -1019,9 +1019,16 @@ struct func_type
>    {
>      /* * The calling convention for targets supporting multiple ABIs.
>         Right now this is only fetched from the Dwarf-2
> -       DW_AT_calling_convention attribute.  */
> +       DW_AT_calling_convention attribute.  The value is one of the
> +       DW_CC enum dwarf_calling_convention constants.  */
>  
> -    unsigned calling_convention;
> +    unsigned calling_convention : 8;
> +
> +    /* * Whether this function normally returns to its caller.  It is
> +       set from the DW_AT_noreturn attribute if set on the
> +       DW_TAG_subprogram.  */
> +
> +    unsigned int is_noreturn : 1;
>  
>      /* * Only those DW_TAG_GNU_call_site's in this function that have
>         DW_AT_GNU_tail_call set are linked in this list.  Function
> @@ -1245,6 +1252,7 @@ extern void allocate_gnat_aux_type (struct type *);
>  #define TYPE_GNAT_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.gnat_stuff
>  #define TYPE_DESCRIPTIVE_TYPE(thistype) TYPE_GNAT_SPECIFIC(thistype)->descriptive_type
>  #define TYPE_CALLING_CONVENTION(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->calling_convention
> +#define TYPE_NO_RETURN(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->is_noreturn
>  #define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->tail_call_list
>  #define TYPE_BASECLASS(thistype,index) TYPE_FIELD_TYPE(thistype, index)
>  #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 4415b31..8231306 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -1869,7 +1869,14 @@ finish_command (char *arg, int from_tty)
>        if (execution_direction == EXEC_REVERSE)
>  	printf_filtered (_("Run back to call of "));
>        else
> -	printf_filtered (_("Run till exit from "));
> +	{
> +	  if (function != NULL && TYPE_NO_RETURN (function->type)
> +	      && ! query (_("Warning. Function %s does not return normally.\n"
> +			    "Try to finish anyway? "),
> +			  SYMBOL_PRINT_NAME (function)))
> +	    error (_("Not confirmed."));
> +	  printf_filtered (_("Run till exit from "));
> +	}
>  
>        print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
>      }
> diff --git a/gdb/stack.c b/gdb/stack.c
> index 2834801..c753005 100644
> --- a/gdb/stack.c
> +++ b/gdb/stack.c
> @@ -2462,8 +2462,12 @@ return_command (char *retval_exp, int from_tty)
>  	confirmed = query (_("%sMake selected stack frame return now? "),
>  			   query_prefix);
>        else
> -	confirmed = query (_("%sMake %s return now? "), query_prefix,
> -			   SYMBOL_PRINT_NAME (thisfun));
> +	{
> +	  if (TYPE_NO_RETURN (thisfun->type))
> +	    warning ("Function does not return normally to caller!");
> +	  confirmed = query (_("%sMake %s return now? "), query_prefix,
> +			     SYMBOL_PRINT_NAME (thisfun));
> +	}
>        if (!confirmed)
>  	error (_("Not confirmed"));
>      }
> diff --git a/include/dwarf2.def b/include/dwarf2.def
> index 8ca143c..8533a3e 100644
> --- a/include/dwarf2.def
> +++ b/include/dwarf2.def
> @@ -308,6 +308,8 @@ DW_AT (DW_AT_data_bit_offset, 0x6b)
>  DW_AT (DW_AT_const_expr, 0x6c)
>  DW_AT (DW_AT_enum_class, 0x6d)
>  DW_AT (DW_AT_linkage_name, 0x6e)
> +/* DWARF 5.  */
> +DW_AT (DW_AT_noreturn, 0x87)
>  
>  DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start.  */
>  DW_AT_DUP (DW_AT_hi_user, 0x3fff) /* Implementation-defined range end.  */
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally.
  2014-11-27 14:53 [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally Mark Wielaard
  2014-12-04 13:26 ` Mark Wielaard
@ 2014-12-04 14:02 ` Pedro Alves
  2014-12-09 10:49   ` Mark Wielaard
  1 sibling, 1 reply; 11+ messages in thread
From: Pedro Alves @ 2014-12-04 14:02 UTC (permalink / raw)
  To: Mark Wielaard, gdb-patches

Hi Mark,

Thanks for doing this.

On 11/27/2014 02:53 PM, Mark Wielaard wrote:
> Add a flag field is_noreturn to struct func_type. Make calling_convention
> a small bit field to not increase the size of the struct. Set is_noreturn
> if the new GCC5/DWARF5 DW_AT_noreturn is set on a DW_TAG_subprogram.
> Use this information to warn the user before doing a finish or return from
> a function that does not return normally to its caller.
> 
> (gdb) finish
> Warning. Function endless does not return normally.
> Try to finish anyway? (y or n)
> 
> (gdb) return
> warning: Function does not return normally to caller!
> Make endless return now? (y or n)

I'd suggest making the warnings a bit more consistent.

- "Warning." vs "warning: "

  Prefer the latter, as that's what the "warning" function uses.

- "." vs "!"

  I'd keep it calm and get rid of the "!".  :-)

> 
> gdb/ChangeLog
> 
> 	* dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from
> 	DW_AT_noreturn.
> 	* gdbtypes.h (struct func_type): Add is_noreturn field flag. Make
> 	calling_convention an 8 bit bit field.
> 	(TYPE_NO_RETURN): New macro.
> 	* infcmd.c (finish_command): Query if function does not return
> 	normally.
> 	* stack.c (return_command): Likewise.
> 
> include/ChangeLog
> 
> 	* dwarf2.def (DW_AT_noreturn): New DWARF5 attribute.

I wonder if we could have a test?  Could e.g., make sure we don't
crash when the user confirms a return in a noreturn function.

> diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
> index 36cbbd9..56212e5 100644
> --- a/gdb/dwarf2read.c
> +++ b/gdb/dwarf2read.c
> @@ -14312,6 +14312,12 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
>    else
>      TYPE_CALLING_CONVENTION (ftype) = DW_CC_normal;
>  
> +  /* Record whether the function returns normally to its caller or not
> +     if the DWARF producer set that information.  */
> +  attr = dwarf2_attr (die, DW_AT_noreturn, cu);
> +  if (attr && (DW_UNSND (attr) != 0))

 if (attr != NULL && (DW_UNSND (attr) != 0))

> +    TYPE_NO_RETURN (ftype) = 1;
> +
>    /* We need to add the subroutine type to the die immediately so
>       we don't infinitely recurse when dealing with parameters
>       declared as the same subroutine type.  */



> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -1869,7 +1869,14 @@ finish_command (char *arg, int from_tty)
>        if (execution_direction == EXEC_REVERSE)
>  	printf_filtered (_("Run back to call of "));
>        else
> -	printf_filtered (_("Run till exit from "));
> +	{
> +	  if (function != NULL && TYPE_NO_RETURN (function->type)
> +	      && ! query (_("Warning. Function %s does not return normally.\n"
> +			    "Try to finish anyway? "),
> +			  SYMBOL_PRINT_NAME (function)))
> +	    error (_("Not confirmed."));
> +	  printf_filtered (_("Run till exit from "));
> +	}

No space between "!" and query:

	      && !query ...

> --- a/gdb/stack.c
> +++ b/gdb/stack.c
> @@ -2462,8 +2462,12 @@ return_command (char *retval_exp, int from_tty)
>  	confirmed = query (_("%sMake selected stack frame return now? "),
>  			   query_prefix);
>        else
> -	confirmed = query (_("%sMake %s return now? "), query_prefix,
> -			   SYMBOL_PRINT_NAME (thisfun));
> +	{
> +	  if (TYPE_NO_RETURN (thisfun->type))
> +	    warning ("Function does not return normally to caller!");

i18n / _() .

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally.
  2014-12-04 14:02 ` Pedro Alves
@ 2014-12-09 10:49   ` Mark Wielaard
  2014-12-09 18:57     ` Stan Shebs
  0 siblings, 1 reply; 11+ messages in thread
From: Mark Wielaard @ 2014-12-09 10:49 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 3395 bytes --]

On Thu, 2014-12-04 at 14:02 +0000, Pedro Alves wrote:
> On 11/27/2014 02:53 PM, Mark Wielaard wrote:
> > Add a flag field is_noreturn to struct func_type. Make calling_convention
> > a small bit field to not increase the size of the struct. Set is_noreturn
> > if the new GCC5/DWARF5 DW_AT_noreturn is set on a DW_TAG_subprogram.
> > Use this information to warn the user before doing a finish or return from
> > a function that does not return normally to its caller.
> > 
> > (gdb) finish
> > Warning. Function endless does not return normally.
> > Try to finish anyway? (y or n)
> > 
> > (gdb) return
> > warning: Function does not return normally to caller!
> > Make endless return now? (y or n)
> 
> I'd suggest making the warnings a bit more consistent.
> 
> - "Warning." vs "warning: "
> 
>   Prefer the latter, as that's what the "warning" function uses.
> 
> - "." vs "!"
> 
>   I'd keep it calm and get rid of the "!".  :-)

Fixed both.

> > 
> > gdb/ChangeLog
> > 
> > 	* dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from
> > 	DW_AT_noreturn.
> > 	* gdbtypes.h (struct func_type): Add is_noreturn field flag. Make
> > 	calling_convention an 8 bit bit field.
> > 	(TYPE_NO_RETURN): New macro.
> > 	* infcmd.c (finish_command): Query if function does not return
> > 	normally.
> > 	* stack.c (return_command): Likewise.
> > 
> > include/ChangeLog
> > 
> > 	* dwarf2.def (DW_AT_noreturn): New DWARF5 attribute.
> 
> I wonder if we could have a test?  Could e.g., make sure we don't
> crash when the user confirms a return in a noreturn function.

I am not sure how to write such a test. This is mainly interactive code,
which will only trigger from_tty. I also am not sure such a test really
tests this new feature. Trying to return from a noreturn function
triggers undefined behavior. GDB probably won't crash, but the inferior
might since the result is unpredictable (that is precisely why I added
this, you forcibly return from a function and end up somewhere
unexpected). Which makes testing the expected output of the user
ignoring the warning somewhat hard.

> > --- a/gdb/infcmd.c
> > +++ b/gdb/infcmd.c
> > @@ -1869,7 +1869,14 @@ finish_command (char *arg, int from_tty)
> >        if (execution_direction == EXEC_REVERSE)
> >  	printf_filtered (_("Run back to call of "));
> >        else
> > -	printf_filtered (_("Run till exit from "));
> > +	{
> > +	  if (function != NULL && TYPE_NO_RETURN (function->type)
> > +	      && ! query (_("Warning. Function %s does not return normally.\n"
> > +			    "Try to finish anyway? "),
> > +			  SYMBOL_PRINT_NAME (function)))
> > +	    error (_("Not confirmed."));
> > +	  printf_filtered (_("Run till exit from "));
> > +	}
> 
> No space between "!" and query:
> 
> 	      && !query ...

Fixed.

> > --- a/gdb/stack.c
> > +++ b/gdb/stack.c
> > @@ -2462,8 +2462,12 @@ return_command (char *retval_exp, int from_tty)
> >  	confirmed = query (_("%sMake selected stack frame return now? "),
> >  			   query_prefix);
> >        else
> > -	confirmed = query (_("%sMake %s return now? "), query_prefix,
> > -			   SYMBOL_PRINT_NAME (thisfun));
> > +	{
> > +	  if (TYPE_NO_RETURN (thisfun->type))
> > +	    warning ("Function does not return normally to caller!");
> 
> i18n / _() .

Added.

Rebased patch attached.

Thanks,

Mark

[-- Attachment #2: 0001-Use-GCC5-DWARF5-DW_AT_noreturn-to-mark-functions-tha.patch --]
[-- Type: text/x-patch, Size: 6923 bytes --]

From 6b454703a5a53bee1355b5a871a10f6bbfcde64e Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Tue, 9 Dec 2014 11:45:41 +0100
Subject: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't
 return normally.

Add a flag field is_noreturn to struct func_type. Make calling_convention
a small bit field to not increase the size of the struct. Set is_noreturn
if the new GCC5/DWARF5 DW_AT_noreturn is set on a DW_TAG_subprogram.
Use this information to warn the user before doing a finish or return from
a function that does not return normally to its caller.

(gdb) finish
warning: Function endless does not return normally.
Try to finish anyway? (y or n)

(gdb) return
warning: Function does not return normally to caller.
Make endless return now? (y or n)

gdb/ChangeLog

	* dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from
	DW_AT_noreturn.
	* gdbtypes.h (struct func_type): Add is_noreturn field flag. Make
	calling_convention an 8 bit bit field.
	(TYPE_NO_RETURN): New macro.
	* infcmd.c (finish_command): Query if function does not return
	normally.
	* stack.c (return_command): Likewise.

include/ChangeLog

	* dwarf2.def (DW_AT_noreturn): New DWARF5 attribute.

The dwarf2.h addition and the code to emit the new attribute is already in
the gcc tree.
---
 gdb/ChangeLog      | 11 +++++++++++
 gdb/dwarf2read.c   |  6 ++++++
 gdb/gdbtypes.h     | 12 ++++++++++--
 gdb/infcmd.c       |  9 ++++++++-
 gdb/stack.c        |  8 ++++++--
 include/ChangeLog  |  4 ++++
 include/dwarf2.def |  2 ++
 7 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ad845a7..43a62af 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2014-12-09  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from
+	DW_AT_noreturn.
+	* gdbtypes.h (struct func_type): Add is_noreturn field flag. Make
+	calling_convention an 8 bit bit field.
+	(TYPE_NO_RETURN): New macro.
+	* infcmd.c (finish_command): Query if function does not return
+	normally.
+	* stack.c (return_command): Likewise.
+
 2014-12-08  Doug Evans  <dje@google.com>
 
 	* python/py-objfile.c (objfpy_get_owner): Increment refcount of result.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 829611d..90e7893 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -14308,6 +14308,12 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
   else
     TYPE_CALLING_CONVENTION (ftype) = DW_CC_normal;
 
+  /* Record whether the function returns normally to its caller or not
+     if the DWARF producer set that information.  */
+  attr = dwarf2_attr (die, DW_AT_noreturn, cu);
+  if (attr && (DW_UNSND (attr) != 0))
+    TYPE_NO_RETURN (ftype) = 1;
+
   /* We need to add the subroutine type to the die immediately so
      we don't infinitely recurse when dealing with parameters
      declared as the same subroutine type.  */
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index a56f543..2806c4d 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1019,9 +1019,16 @@ struct func_type
   {
     /* * The calling convention for targets supporting multiple ABIs.
        Right now this is only fetched from the Dwarf-2
-       DW_AT_calling_convention attribute.  */
+       DW_AT_calling_convention attribute.  The value is one of the
+       DW_CC enum dwarf_calling_convention constants.  */
 
-    unsigned calling_convention;
+    unsigned calling_convention : 8;
+
+    /* * Whether this function normally returns to its caller.  It is
+       set from the DW_AT_noreturn attribute if set on the
+       DW_TAG_subprogram.  */
+
+    unsigned int is_noreturn : 1;
 
     /* * Only those DW_TAG_GNU_call_site's in this function that have
        DW_AT_GNU_tail_call set are linked in this list.  Function
@@ -1245,6 +1252,7 @@ extern void allocate_gnat_aux_type (struct type *);
 #define TYPE_GNAT_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.gnat_stuff
 #define TYPE_DESCRIPTIVE_TYPE(thistype) TYPE_GNAT_SPECIFIC(thistype)->descriptive_type
 #define TYPE_CALLING_CONVENTION(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->calling_convention
+#define TYPE_NO_RETURN(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->is_noreturn
 #define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->tail_call_list
 #define TYPE_BASECLASS(thistype,index) TYPE_FIELD_TYPE(thistype, index)
 #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 4415b31..68d9ef9 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1869,7 +1869,14 @@ finish_command (char *arg, int from_tty)
       if (execution_direction == EXEC_REVERSE)
 	printf_filtered (_("Run back to call of "));
       else
-	printf_filtered (_("Run till exit from "));
+	{
+	  if (function != NULL && TYPE_NO_RETURN (function->type)
+	      && !query (_("warning: Function %s does not return normally.\n"
+			   "Try to finish anyway? "),
+			 SYMBOL_PRINT_NAME (function)))
+	    error (_("Not confirmed."));
+	  printf_filtered (_("Run till exit from "));
+	}
 
       print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
     }
diff --git a/gdb/stack.c b/gdb/stack.c
index 2834801..f7e77e4 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2462,8 +2462,12 @@ return_command (char *retval_exp, int from_tty)
 	confirmed = query (_("%sMake selected stack frame return now? "),
 			   query_prefix);
       else
-	confirmed = query (_("%sMake %s return now? "), query_prefix,
-			   SYMBOL_PRINT_NAME (thisfun));
+	{
+	  if (TYPE_NO_RETURN (thisfun->type))
+	    warning ("Function does not return normally to caller.");
+	  confirmed = query (_("%sMake %s return now? "), query_prefix,
+			     SYMBOL_PRINT_NAME (thisfun));
+	}
       if (!confirmed)
 	error (_("Not confirmed"));
     }
diff --git a/include/ChangeLog b/include/ChangeLog
index e80d2ec..69ed996 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2014-12-09  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf2.def (DW_AT_noreturn): New DWARF5 attribute.
+
 2014-12-06  Eric Botcazou  <ebotcazou@adacore.com>
 
 	* dis-asm.h (print_insn_visium): Declare.
diff --git a/include/dwarf2.def b/include/dwarf2.def
index 8ca143c..8533a3e 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -308,6 +308,8 @@ DW_AT (DW_AT_data_bit_offset, 0x6b)
 DW_AT (DW_AT_const_expr, 0x6c)
 DW_AT (DW_AT_enum_class, 0x6d)
 DW_AT (DW_AT_linkage_name, 0x6e)
+/* DWARF 5.  */
+DW_AT (DW_AT_noreturn, 0x87)
 
 DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start.  */
 DW_AT_DUP (DW_AT_hi_user, 0x3fff) /* Implementation-defined range end.  */
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally.
  2014-12-09 10:49   ` Mark Wielaard
@ 2014-12-09 18:57     ` Stan Shebs
  2014-12-10 11:25       ` Mark Wielaard
  0 siblings, 1 reply; 11+ messages in thread
From: Stan Shebs @ 2014-12-09 18:57 UTC (permalink / raw)
  To: gdb-patches

On 12/9/14, 2:49 AM, Mark Wielaard wrote:
> On Thu, 2014-12-04 at 14:02 +0000, Pedro Alves wrote:
>> On 11/27/2014 02:53 PM, Mark Wielaard wrote:
>>> Add a flag field is_noreturn to struct func_type. Make calling_convention
>>> a small bit field to not increase the size of the struct. Set is_noreturn
>>> if the new GCC5/DWARF5 DW_AT_noreturn is set on a DW_TAG_subprogram.
>>> Use this information to warn the user before doing a finish or return from
>>> a function that does not return normally to its caller.
>>>
>>> (gdb) finish
>>> Warning. Function endless does not return normally.
>>> Try to finish anyway? (y or n)
>>>
>>> (gdb) return
>>> warning: Function does not return normally to caller!
>>> Make endless return now? (y or n)
>>
>> I'd suggest making the warnings a bit more consistent.
>>
>> - "Warning." vs "warning: "
>>
>>   Prefer the latter, as that's what the "warning" function uses.
>>
>> - "." vs "!"
>>
>>   I'd keep it calm and get rid of the "!".  :-)
> 
> Fixed both.
> 
>>>
>>> gdb/ChangeLog
>>>
>>> 	* dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from
>>> 	DW_AT_noreturn.
>>> 	* gdbtypes.h (struct func_type): Add is_noreturn field flag. Make
>>> 	calling_convention an 8 bit bit field.
>>> 	(TYPE_NO_RETURN): New macro.
>>> 	* infcmd.c (finish_command): Query if function does not return
>>> 	normally.
>>> 	* stack.c (return_command): Likewise.
>>>
>>> include/ChangeLog
>>>
>>> 	* dwarf2.def (DW_AT_noreturn): New DWARF5 attribute.
>>
>> I wonder if we could have a test?  Could e.g., make sure we don't
>> crash when the user confirms a return in a noreturn function.
> 
> I am not sure how to write such a test. This is mainly interactive code,
> which will only trigger from_tty. I also am not sure such a test really
> tests this new feature. Trying to return from a noreturn function
> triggers undefined behavior. GDB probably won't crash, but the inferior
> might since the result is unpredictable (that is precisely why I added
> this, you forcibly return from a function and end up somewhere
> unexpected). Which makes testing the expected output of the user
> ignoring the warning somewhat hard.

Chiming in here, just write the test so that it passes whether or not
the inferior crashes - as you note, its behavior is undefined anyway.
If GDB crashes or hangs, on any platform, that's a bug that we have to
fix in GDB.

Stan
stan@codesourcery.com


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally.
  2014-12-09 18:57     ` Stan Shebs
@ 2014-12-10 11:25       ` Mark Wielaard
  2014-12-12 10:47         ` Pedro Alves
  0 siblings, 1 reply; 11+ messages in thread
From: Mark Wielaard @ 2014-12-10 11:25 UTC (permalink / raw)
  To: Stan Shebs; +Cc: gdb-patches

Hi Stan,

On Tue, 2014-12-09 at 10:57 -0800, Stan Shebs wrote:
> On 12/9/14, 2:49 AM, Mark Wielaard wrote:
> > On Thu, 2014-12-04 at 14:02 +0000, Pedro Alves wrote:
> >> I wonder if we could have a test?  Could e.g., make sure we don't
> >> crash when the user confirms a return in a noreturn function.
> > 
> > I am not sure how to write such a test. This is mainly interactive code,
> > which will only trigger from_tty. I also am not sure such a test really
> > tests this new feature. Trying to return from a noreturn function
> > triggers undefined behavior. GDB probably won't crash, but the inferior
> > might since the result is unpredictable (that is precisely why I added
> > this, you forcibly return from a function and end up somewhere
> > unexpected). Which makes testing the expected output of the user
> > ignoring the warning somewhat hard.
> 
> Chiming in here, just write the test so that it passes whether or not
> the inferior crashes - as you note, its behavior is undefined anyway.
> If GDB crashes or hangs, on any platform, that's a bug that we have to
> fix in GDB.

I am afraid I still don't understand what we would be testing (whether
the user if there is a tty gets to say yes or no?) or how to write such
a test where we don't seem interested in the actual result. Is there an
example to follow?

Thanks,

Mark

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally.
  2014-12-10 11:25       ` Mark Wielaard
@ 2014-12-12 10:47         ` Pedro Alves
  2015-01-15 23:56           ` Mark Wielaard
  0 siblings, 1 reply; 11+ messages in thread
From: Pedro Alves @ 2014-12-12 10:47 UTC (permalink / raw)
  To: Mark Wielaard, Stan Shebs; +Cc: gdb-patches

On 12/10/2014 11:24 AM, Mark Wielaard wrote:
> Hi Stan,
> 
> On Tue, 2014-12-09 at 10:57 -0800, Stan Shebs wrote:
>> On 12/9/14, 2:49 AM, Mark Wielaard wrote:
>>> On Thu, 2014-12-04 at 14:02 +0000, Pedro Alves wrote:
>>>> I wonder if we could have a test?  Could e.g., make sure we don't
>>>> crash when the user confirms a return in a noreturn function.
>>>
>>> I am not sure how to write such a test. This is mainly interactive code,
>>> which will only trigger from_tty. I also am not sure such a test really
>>> tests this new feature. Trying to return from a noreturn function
>>> triggers undefined behavior. GDB probably won't crash, but the inferior
>>> might since the result is unpredictable (that is precisely why I added
>>> this, you forcibly return from a function and end up somewhere
>>> unexpected). Which makes testing the expected output of the user
>>> ignoring the warning somewhat hard.
>>
>> Chiming in here, just write the test so that it passes whether or not
>> the inferior crashes - as you note, its behavior is undefined anyway.
>> If GDB crashes or hangs, on any platform, that's a bug that we have to
>> fix in GDB.
> 
> I am afraid I still don't understand what we would be testing (whether
> the user if there is a tty gets to say yes or no?) or how to write such
> a test where we don't seem interested in the actual result. Is there an
> example to follow?

The point is just to test the new/related code paths, and making sure
the commands do what you propose they do.

E.g., to make sure the new dwarf code (and future changes around it) don't
crash.  And then in the "return->no" path, make sure we really cancel the
command (that the backtrace looks the same after canceling), which also potentially
exercises bad/missing cleanups, for example.  By testing the "return->yes" path,
we'd  be making sure the unwinder doesn't crash (now and in the future)
in this situation, and that the current frame ends up being the one expected.
For the "finish" case, we'd be making sure that GDB doesn't crash when trying
to figure out where the function's return value is stored ("finish" prints the
function's return value when the function actually finishes).

There are some tests for "return" in the testsuite -- return.exp or
return2.exp -- and at least one for "finish" -- finish.exp.  I'd suggest
using these as inspiration.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally.
  2014-12-12 10:47         ` Pedro Alves
@ 2015-01-15 23:56           ` Mark Wielaard
  2015-01-21 17:07             ` Pedro Alves
  0 siblings, 1 reply; 11+ messages in thread
From: Mark Wielaard @ 2015-01-15 23:56 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Stan Shebs, gdb-patches

[-- Attachment #1: Type: text/plain, Size: 509 bytes --]

On Fri, 2014-12-12 at 10:47 +0000, Pedro Alves wrote:
> There are some tests for "return" in the testsuite -- return.exp or
> return2.exp -- and at least one for "finish" -- finish.exp.  I'd suggest
> using these as inspiration.

I added a test for answering no to the return query and and finish
queries if they and the warning are there. They PASS with (GCC5) and
without (older compilers) the new attribute. Also rebased the code to
current master as attached.

OK to commit?

Thanks,

Mark

[-- Attachment #2: 0001-Use-GCC5-DWARF5-DW_AT_noreturn-to-mark-functions-tha.patch --]
[-- Type: text/x-patch, Size: 12819 bytes --]

From ea5d7662c2bfa83d0de737f56956a88820643b61 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Tue, 9 Dec 2014 11:45:41 +0100
Subject: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't
 return normally.

Add a flag field is_noreturn to struct func_type. Make calling_convention
a small bit field to not increase the size of the struct. Set is_noreturn
if the new GCC5/DWARF5 DW_AT_noreturn is set on a DW_TAG_subprogram.
Use this information to warn the user before doing a finish or return from
a function that does not return normally to its caller.

(gdb) finish
warning: Function endless does not return normally.
Try to finish anyway? (y or n)

(gdb) return
warning: Function does not return normally to caller.
Make endless return now? (y or n)

gdb/ChangeLog

	* dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from
	DW_AT_noreturn.
	* gdbtypes.h (struct func_type): Add is_noreturn field flag. Make
	calling_convention an 8 bit bit field.
	(TYPE_NO_RETURN): New macro.
	* infcmd.c (finish_command): Query if function does not return
	normally.
	* stack.c (return_command): Likewise.

gdb/testsuite/ChangeLog

	* gdb.base/noreturn.c: New file.
	* gdb.base/noreturn.exp: New file.
	* gdb.base/noreturn_finish.c: New file.
	* gdb.base/noreturn_finish.exp: New file.

include/ChangeLog

	* dwarf2.def (DW_AT_noreturn): New DWARF5 attribute.

The dwarf2.h addition and the code to emit the new attribute is already in
the gcc tree.
---
 gdb/ChangeLog                              | 11 ++++++
 gdb/dwarf2read.c                           |  6 ++++
 gdb/gdbtypes.h                             | 12 +++++--
 gdb/infcmd.c                               |  9 ++++-
 gdb/stack.c                                |  8 +++--
 gdb/testsuite/ChangeLog                    |  7 ++++
 gdb/testsuite/gdb.base/noreturn.c          | 13 +++++++
 gdb/testsuite/gdb.base/noreturn.exp        | 54 ++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/noreturn_finish.c   | 14 ++++++++
 gdb/testsuite/gdb.base/noreturn_finish.exp | 54 ++++++++++++++++++++++++++++++
 include/ChangeLog                          |  4 +++
 include/dwarf2.def                         |  2 ++
 12 files changed, 189 insertions(+), 5 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/noreturn.c
 create mode 100644 gdb/testsuite/gdb.base/noreturn.exp
 create mode 100644 gdb/testsuite/gdb.base/noreturn_finish.c
 create mode 100644 gdb/testsuite/gdb.base/noreturn_finish.exp

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 5c45780..611008c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2015-01-15  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from
+	DW_AT_noreturn.
+	* gdbtypes.h (struct func_type): Add is_noreturn field flag. Make
+	calling_convention an 8 bit bit field.
+	(TYPE_NO_RETURN): New macro.
+	* infcmd.c (finish_command): Query if function does not return
+	normally.
+	* stack.c (return_command): Likewise.
+
 2015-01-15  Joel Brobecker  <brobecker@adacore.com>
 
 	GDB 7.8.2 released.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 96b2537..9d765c5 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -14343,6 +14343,12 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
   else
     TYPE_CALLING_CONVENTION (ftype) = DW_CC_normal;
 
+  /* Record whether the function returns normally to its caller or not
+     if the DWARF producer set that information.  */
+  attr = dwarf2_attr (die, DW_AT_noreturn, cu);
+  if (attr && (DW_UNSND (attr) != 0))
+    TYPE_NO_RETURN (ftype) = 1;
+
   /* We need to add the subroutine type to the die immediately so
      we don't infinitely recurse when dealing with parameters
      declared as the same subroutine type.  */
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 7c06a4f..ba5c857 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1019,9 +1019,16 @@ struct func_type
   {
     /* * The calling convention for targets supporting multiple ABIs.
        Right now this is only fetched from the Dwarf-2
-       DW_AT_calling_convention attribute.  */
+       DW_AT_calling_convention attribute.  The value is one of the
+       DW_CC enum dwarf_calling_convention constants.  */
 
-    unsigned calling_convention;
+    unsigned calling_convention : 8;
+
+    /* * Whether this function normally returns to its caller.  It is
+       set from the DW_AT_noreturn attribute if set on the
+       DW_TAG_subprogram.  */
+
+    unsigned int is_noreturn : 1;
 
     /* * Only those DW_TAG_GNU_call_site's in this function that have
        DW_AT_GNU_tail_call set are linked in this list.  Function
@@ -1245,6 +1252,7 @@ extern void allocate_gnat_aux_type (struct type *);
 #define TYPE_GNAT_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.gnat_stuff
 #define TYPE_DESCRIPTIVE_TYPE(thistype) TYPE_GNAT_SPECIFIC(thistype)->descriptive_type
 #define TYPE_CALLING_CONVENTION(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->calling_convention
+#define TYPE_NO_RETURN(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->is_noreturn
 #define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->tail_call_list
 #define TYPE_BASECLASS(thistype,index) TYPE_FIELD_TYPE(thistype, index)
 #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 7b26663..9a1fb8d 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1872,7 +1872,14 @@ finish_command (char *arg, int from_tty)
       if (execution_direction == EXEC_REVERSE)
 	printf_filtered (_("Run back to call of "));
       else
-	printf_filtered (_("Run till exit from "));
+	{
+	  if (function != NULL && TYPE_NO_RETURN (function->type)
+	      && !query (_("warning: Function %s does not return normally.\n"
+			   "Try to finish anyway? "),
+			 SYMBOL_PRINT_NAME (function)))
+	    error (_("Not confirmed."));
+	  printf_filtered (_("Run till exit from "));
+	}
 
       print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
     }
diff --git a/gdb/stack.c b/gdb/stack.c
index 0201d0a..5f2a3dc 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2462,8 +2462,12 @@ return_command (char *retval_exp, int from_tty)
 	confirmed = query (_("%sMake selected stack frame return now? "),
 			   query_prefix);
       else
-	confirmed = query (_("%sMake %s return now? "), query_prefix,
-			   SYMBOL_PRINT_NAME (thisfun));
+	{
+	  if (TYPE_NO_RETURN (thisfun->type))
+	    warning ("Function does not return normally to caller.");
+	  confirmed = query (_("%sMake %s return now? "), query_prefix,
+			     SYMBOL_PRINT_NAME (thisfun));
+	}
       if (!confirmed)
 	error (_("Not confirmed"));
     }
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index a71ee98..ab027a7 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2015-01-15  Mark Wielaard  <mjw@redhat.com>
+
+	* gdb.base/noreturn.c: New file.
+	* gdb.base/noreturn.exp: New file.
+	* gdb.base/noreturn_finish.c: New file.
+	* gdb.base/noreturn_finish.exp: New file.
+
 2015-01-15  Joel Brobecker  <brobecker@adacore.com>
 
 	* gdb.ada/var_arr_attrs: New testcase.
diff --git a/gdb/testsuite/gdb.base/noreturn.c b/gdb/testsuite/gdb.base/noreturn.c
new file mode 100644
index 0000000..e39cf15
--- /dev/null
+++ b/gdb/testsuite/gdb.base/noreturn.c
@@ -0,0 +1,13 @@
+void __attribute__((noreturn))
+noreturn_func ()
+{
+  while (1)
+    ;
+}
+
+int
+main ()
+{
+  noreturn_func ();
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/noreturn.exp b/gdb/testsuite/gdb.base/noreturn.exp
new file mode 100644
index 0000000..885642f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/noreturn.exp
@@ -0,0 +1,54 @@
+# Copyright 2015 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile .c
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+     untested noreturn.exp
+     return -1
+}
+
+proc noreturn_test { } {
+    global gdb_prompt
+
+    if { ! [ runto_main ] } then {
+	untested noreturn.exp
+	return -1
+    }
+
+    gdb_test "break noreturn_func" "Breakpoint \[0123456789\].*" \
+	    "set break on noreturn_func"
+    gdb_test "continue" "Breakpoint.* noreturn_func.*" \
+	    "continue to noreturn_func"
+
+    gdb_test_multiple "return" "return from noreturn_func" {
+	-re "warning: Function does not return normally to caller" {
+	    verbose -log "saw warning"
+	    exp_continue
+	}
+	-re "Make noreturn_func return now.*y or n. $" {
+	    send_gdb "n\n"
+	    exp_continue
+	}
+	-re "Not confirmed.*$gdb_prompt $" {
+	    pass "noreturn_func return cancelled"
+	}
+   }
+}
+
+clean_restart ${binfile}
+
+set timeout 30
+noreturn_test
diff --git a/gdb/testsuite/gdb.base/noreturn_finish.c b/gdb/testsuite/gdb.base/noreturn_finish.c
new file mode 100644
index 0000000..cd52769
--- /dev/null
+++ b/gdb/testsuite/gdb.base/noreturn_finish.c
@@ -0,0 +1,14 @@
+#include <stdlib.h>
+
+void __attribute__((noreturn))
+noreturn_func ()
+{
+  abort ();
+}
+
+int
+main ()
+{
+  noreturn_func ();
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/noreturn_finish.exp b/gdb/testsuite/gdb.base/noreturn_finish.exp
new file mode 100644
index 0000000..d518826
--- /dev/null
+++ b/gdb/testsuite/gdb.base/noreturn_finish.exp
@@ -0,0 +1,54 @@
+# Copyright 2015 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile .c
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+     untested noreturn_finish.exp
+     return -1
+}
+
+proc noreturn_finish_test { } {
+    global gdb_prompt
+
+    if { ! [ runto_main ] } then {
+	untested noreturn_finish.exp
+	return -1
+    }
+
+    gdb_test "break noreturn_func" "Breakpoint \[0123456789\].*" \
+	    "set break on noreturn_func"
+    gdb_test "continue" "Breakpoint.* noreturn_func.*" \
+	    "continue to noreturn_func"
+
+    gdb_test_multiple "finish" "return from noreturn_func" {
+	-re "warning: Function noreturn_func does not return normally" {
+	    verbose -log "saw warning"
+	    exp_continue
+	}
+	-re "Try to finish anyway.*y or n.* $" {
+	    send_gdb "n\n"
+	    exp_continue
+	}
+	-re ".*$gdb_prompt $" {
+	    pass "noreturn_func finish done"
+	}
+   }
+}
+
+clean_restart ${binfile}
+
+set timeout 30
+noreturn_finish_test
diff --git a/include/ChangeLog b/include/ChangeLog
index 31f1e18..21b6ae6 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2015-01-15  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf2.def (DW_AT_noreturn): New DWARF5 attribute.
+
 2015-01-14  Jan-Benedict Glaw  <jbglaw@lug-owl.de>
 
 	* libiberty.h: Merge from GCC.
diff --git a/include/dwarf2.def b/include/dwarf2.def
index 5da3ae0..3aecdfc 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -306,6 +306,8 @@ DW_AT (DW_AT_data_bit_offset, 0x6b)
 DW_AT (DW_AT_const_expr, 0x6c)
 DW_AT (DW_AT_enum_class, 0x6d)
 DW_AT (DW_AT_linkage_name, 0x6e)
+/* DWARF 5.  */
+DW_AT (DW_AT_noreturn, 0x87)
 
 DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start.  */
 DW_AT_DUP (DW_AT_hi_user, 0x3fff) /* Implementation-defined range end.  */
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally.
  2015-01-15 23:56           ` Mark Wielaard
@ 2015-01-21 17:07             ` Pedro Alves
  2015-01-23 16:42               ` Mark Wielaard
  0 siblings, 1 reply; 11+ messages in thread
From: Pedro Alves @ 2015-01-21 17:07 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: Stan Shebs, gdb-patches



On 01/15/2015 11:56 PM, Mark Wielaard wrote:

>  create mode 100644 gdb/testsuite/gdb.base/noreturn.c
>  create mode 100644 gdb/testsuite/gdb.base/noreturn.exp

How about "noreturn-return.{c|exp}", to go with noreturn_finish ?

>  create mode 100644 gdb/testsuite/gdb.base/noreturn_finish.c
>  create mode 100644 gdb/testsuite/gdb.base/noreturn_finish.exp

But please use '-' instead of '_':

  gdb/testsuite/gdb.base/noreturn-finish.c
  gdb/testsuite/gdb.base/noreturn-finish.exp

> diff --git a/gdb/testsuite/gdb.base/noreturn.c b/gdb/testsuite/gdb.base/noreturn.c
> new file mode 100644
> index 0000000..e39cf15
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/noreturn.c
> @@ -0,0 +1,13 @@

Please add a copyright header.  Even though some of our old
files don't have it, all new files should, even if the file
is small (so that we don't have to recall adding it back
if the file grows in future).


> +void __attribute__((noreturn))
> +noreturn_func ()

noreturn_func (void)


> +{
> +  while (1)
> +    ;

Please don't make the test loop forever if GDB crashes.
Does e.g., "abort()" like the other test work here too?

> +}
> +
> +int
> +main ()

likewise (void)

> +{
> +  noreturn_func ();
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.base/noreturn.exp b/gdb/testsuite/gdb.base/noreturn.exp
> new file mode 100644
> index 0000000..885642f
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/noreturn.exp
> @@ -0,0 +1,54 @@
> +# Copyright 2015 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 this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +standard_testfile .c

You can drop the ".c", as it's the default.

> +
> +if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
> +     untested noreturn.exp
> +     return -1
> +}

Use prepare_for_testing, like:

if [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {debug}] {
    return -1
}


> +
> +proc noreturn_test { } {
> +    global gdb_prompt
> +
> +    if { ! [ runto_main ] } then {
> +	untested noreturn.exp

Use $testfile, like "untested ${testfile}.exp".

> +	return -1
> +    }
> +
> +    gdb_test "break noreturn_func" "Breakpoint \[0123456789\].*" \
> +	    "set break on noreturn_func"
> +    gdb_test "continue" "Breakpoint.* noreturn_func.*" \
> +	    "continue to noreturn_func"

   gdb_breakpoint "noreturn_func"
   gdb_continue_to_breakpoint "noreturn_func"

> +
> +    gdb_test_multiple "return" "return from noreturn_func" {
> +	-re "warning: Function does not return normally to caller" {
> +	    verbose -log "saw warning"
> +	    exp_continue
> +	}
> +	-re "Make noreturn_func return now.*y or n. $" {
> +	    send_gdb "n\n"
> +	    exp_continue
> +	}
> +	-re "Not confirmed.*$gdb_prompt $" {
> +	    pass "noreturn_func return cancelled"
> +	}

Make the test message be the same in all paths, like:

    set test "return from noreturn_func"
    gdb_test_multiple "return" $test {
	-re "warning: Function does not return normally to caller" {
	    verbose -log "saw warning"
	    exp_continue
	}
	-re "Make noreturn_func return now.*y or n. $" {
	    send_gdb "n\n"
	    exp_continue
	}
	-re "Not confirmed.*$gdb_prompt $" {
	    pass $test
	}

> +   }
> +}
> +
> +clean_restart ${binfile}

prepare_for_testing does this for you.

> +
> +set timeout 30

I don't see why this is necessary.  I think this is just a copy/paste?

> +noreturn_test
> diff --git a/gdb/testsuite/gdb.base/noreturn_finish.c b/gdb/testsuite/gdb.base/noreturn_finish.c
> new file mode 100644
> index 0000000..cd52769
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/noreturn_finish.c
> @@ -0,0 +1,14 @@
> +#include <stdlib.h>
> +
> +void __attribute__((noreturn))
> +noreturn_func ()
> +{
> +  abort ();
> +}
> +
> +int
> +main ()
> +{
> +  noreturn_func ();
> +  return 0;
> +}

Same comments apply to noreturn_finish.c|exp.

Otherwise OK.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally.
  2015-01-21 17:07             ` Pedro Alves
@ 2015-01-23 16:42               ` Mark Wielaard
  2015-01-24  0:32                 ` Pedro Alves
  0 siblings, 1 reply; 11+ messages in thread
From: Mark Wielaard @ 2015-01-23 16:42 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Stan Shebs, gdb-patches

[-- Attachment #1: Type: text/plain, Size: 5746 bytes --]

On Wed, 2015-01-21 at 17:07 +0000, Pedro Alves wrote:
> 
> On 01/15/2015 11:56 PM, Mark Wielaard wrote:
> 
> >  create mode 100644 gdb/testsuite/gdb.base/noreturn.c
> >  create mode 100644 gdb/testsuite/gdb.base/noreturn.exp
> 
> How about "noreturn-return.{c|exp}", to go with noreturn_finish ?
>
> >  create mode 100644 gdb/testsuite/gdb.base/noreturn_finish.c
> >  create mode 100644 gdb/testsuite/gdb.base/noreturn_finish.exp
> 
> But please use '-' instead of '_':
>
>   gdb/testsuite/gdb.base/noreturn-finish.c
>   gdb/testsuite/gdb.base/noreturn-finish.exp

OK, changed all file and test names.

> > diff --git a/gdb/testsuite/gdb.base/noreturn.c b/gdb/testsuite/gdb.base/noreturn.c
> > new file mode 100644
> > index 0000000..e39cf15
> > --- /dev/null
> > +++ b/gdb/testsuite/gdb.base/noreturn.c
> > @@ -0,0 +1,13 @@
> 
> Please add a copyright header.  Even though some of our old
> files don't have it, all new files should, even if the file
> is small (so that we don't have to recall adding it back
> if the file grows in future).

Added.
Note that most .c files in gdb.base don't have such a header.

> > +void __attribute__((noreturn))
> > +noreturn_func ()
> 
> noreturn_func (void)

Added the void.
Note most existing .c tests in gdb.base don't declare functions with
void arguments.

> > +{
> > +  while (1)
> > +    ;
> 
> Please don't make the test loop forever if GDB crashes.
> Does e.g., "abort()" like the other test work here too?

Changed.
It isn't semantically the same, but it does work.

> > +}
> > +
> > +int
> > +main ()
> 
> likewise (void)

Added.

> > +{
> > +  noreturn_func ();
> > +  return 0;
> > +}
> > diff --git a/gdb/testsuite/gdb.base/noreturn.exp b/gdb/testsuite/gdb.base/noreturn.exp
> > new file mode 100644
> > index 0000000..885642f
> > --- /dev/null
> > +++ b/gdb/testsuite/gdb.base/noreturn.exp
> > @@ -0,0 +1,54 @@
> > +# Copyright 2015 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 this program.  If not, see <http://www.gnu.org/licenses/>.
> > +
> > +standard_testfile .c
> 
> You can drop the ".c", as it's the default.

Dropped. It is used in other .exp files though.

> > +
> > +if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
> > +     untested noreturn.exp
> > +     return -1
> > +}
> 
> Use prepare_for_testing, like:
> 
> if [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {debug}] {
>     return -1
> }

Changed. This idiom comes from existing .exp files though.

> > +
> > +proc noreturn_test { } {
> > +    global gdb_prompt
> > +
> > +    if { ! [ runto_main ] } then {
> > +	untested noreturn.exp
> 
> Use $testfile, like "untested ${testfile}.exp".

Changed.

> > +	return -1
> > +    }
> > +
> > +    gdb_test "break noreturn_func" "Breakpoint \[0123456789\].*" \
> > +	    "set break on noreturn_func"
> > +    gdb_test "continue" "Breakpoint.* noreturn_func.*" \
> > +	    "continue to noreturn_func"
> 
>    gdb_breakpoint "noreturn_func"
>    gdb_continue_to_breakpoint "noreturn_func"

Changed. Note that the above comes from existing .exp testcases.

> > +
> > +    gdb_test_multiple "return" "return from noreturn_func" {
> > +	-re "warning: Function does not return normally to caller" {
> > +	    verbose -log "saw warning"
> > +	    exp_continue
> > +	}
> > +	-re "Make noreturn_func return now.*y or n. $" {
> > +	    send_gdb "n\n"
> > +	    exp_continue
> > +	}
> > +	-re "Not confirmed.*$gdb_prompt $" {
> > +	    pass "noreturn_func return cancelled"
> > +	}
> 
> Make the test message be the same in all paths, like:
> 
>     set test "return from noreturn_func"
>     gdb_test_multiple "return" $test {
> 	-re "warning: Function does not return normally to caller" {
> 	    verbose -log "saw warning"
> 	    exp_continue
> 	}
> 	-re "Make noreturn_func return now.*y or n. $" {
> 	    send_gdb "n\n"
> 	    exp_continue
> 	}
> 	-re "Not confirmed.*$gdb_prompt $" {
> 	    pass $test
> 	}

Changed

> > +   }
> > +}
> > +
> > +clean_restart ${binfile}
> 
> prepare_for_testing does this for you.

Dropped.

> > +
> > +set timeout 30
> 
> I don't see why this is necessary.

Dropped.

>   I think this is just a copy/paste?

Yes, I just took the testcases you recommended and changed them to test
the new warning messages added.

> > +noreturn_test
> > diff --git a/gdb/testsuite/gdb.base/noreturn_finish.c b/gdb/testsuite/gdb.base/noreturn_finish.c
> > new file mode 100644
> > index 0000000..cd52769
> > --- /dev/null
> > +++ b/gdb/testsuite/gdb.base/noreturn_finish.c
> > @@ -0,0 +1,14 @@
> > +#include <stdlib.h>
> > +
> > +void __attribute__((noreturn))
> > +noreturn_func ()
> > +{
> > +  abort ();
> > +}
> > +
> > +int
> > +main ()
> > +{
> > +  noreturn_func ();
> > +  return 0;
> > +}
> 
> Same comments apply to noreturn_finish.c|exp.

Same changes made.

> Otherwise OK.

Pushed as attached after retesting under GCC 5 and 4.8.2.

Thanks,

Mark

[-- Attachment #2: 0001-Use-GCC5-DWARF5-DW_AT_noreturn-to-mark-functions-tha.patch --]
[-- Type: text/x-patch, Size: 14192 bytes --]

From 743649fd80776de922475362bf3ac8b44511bb24 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Tue, 9 Dec 2014 11:45:41 +0100
Subject: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't
 return normally.

Add a flag field is_noreturn to struct func_type. Make calling_convention
a small bit field to not increase the size of the struct. Set is_noreturn
if the new GCC5/DWARF5 DW_AT_noreturn is set on a DW_TAG_subprogram.
Use this information to warn the user before doing a finish or return from
a function that does not return normally to its caller.

(gdb) finish
warning: Function endless does not return normally.
Try to finish anyway? (y or n)

(gdb) return
warning: Function does not return normally to caller.
Make endless return now? (y or n)

gdb/ChangeLog

	* dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from
	DW_AT_noreturn.
	* gdbtypes.h (struct func_type): Add is_noreturn field flag. Make
	calling_convention an 8 bit bit field.
	(TYPE_NO_RETURN): New macro.
	* infcmd.c (finish_command): Query if function does not return
	normally.
	* stack.c (return_command): Likewise.

gdb/testsuite/ChangeLog

	* gdb.base/noreturn-return.c: New file.
	* gdb.base/noreturn-return.exp: New file.
	* gdb.base/noreturn-finish.c: New file.
	* gdb.base/noreturn-finish.exp: New file.

include/ChangeLog

	* dwarf2.def (DW_AT_noreturn): New DWARF5 attribute.

The dwarf2.h addition and the code to emit the new attribute is already in
the gcc tree.
---
 gdb/ChangeLog                              | 11 +++++++
 gdb/dwarf2read.c                           |  6 ++++
 gdb/gdbtypes.h                             | 12 +++++--
 gdb/infcmd.c                               |  9 +++++-
 gdb/stack.c                                |  8 +++--
 gdb/testsuite/ChangeLog                    |  7 ++++
 gdb/testsuite/gdb.base/noreturn-finish.c   | 31 ++++++++++++++++++
 gdb/testsuite/gdb.base/noreturn-finish.exp | 51 ++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/noreturn-return.c   | 31 ++++++++++++++++++
 gdb/testsuite/gdb.base/noreturn-return.exp | 51 ++++++++++++++++++++++++++++++
 include/ChangeLog                          |  4 +++
 include/dwarf2.def                         |  2 ++
 12 files changed, 218 insertions(+), 5 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/noreturn-finish.c
 create mode 100644 gdb/testsuite/gdb.base/noreturn-finish.exp
 create mode 100644 gdb/testsuite/gdb.base/noreturn-return.c
 create mode 100644 gdb/testsuite/gdb.base/noreturn-return.exp

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 818eb7c..c195f5d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2015-01-15  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf2read.c (read_subroutine_type): Set TYPE_NO_RETURN from
+	DW_AT_noreturn.
+	* gdbtypes.h (struct func_type): Add is_noreturn field flag. Make
+	calling_convention an 8 bit bit field.
+	(TYPE_NO_RETURN): New macro.
+	* infcmd.c (finish_command): Query if function does not return
+	normally.
+	* stack.c (return_command): Likewise.
+
 2015-01-23  Pedro Alves  <palves@redhat.com>
 
 	* linux-nat.c (linux_is_async_p): New macro.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 96b2537..9d765c5 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -14343,6 +14343,12 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
   else
     TYPE_CALLING_CONVENTION (ftype) = DW_CC_normal;
 
+  /* Record whether the function returns normally to its caller or not
+     if the DWARF producer set that information.  */
+  attr = dwarf2_attr (die, DW_AT_noreturn, cu);
+  if (attr && (DW_UNSND (attr) != 0))
+    TYPE_NO_RETURN (ftype) = 1;
+
   /* We need to add the subroutine type to the die immediately so
      we don't infinitely recurse when dealing with parameters
      declared as the same subroutine type.  */
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 7c06a4f..ba5c857 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1019,9 +1019,16 @@ struct func_type
   {
     /* * The calling convention for targets supporting multiple ABIs.
        Right now this is only fetched from the Dwarf-2
-       DW_AT_calling_convention attribute.  */
+       DW_AT_calling_convention attribute.  The value is one of the
+       DW_CC enum dwarf_calling_convention constants.  */
 
-    unsigned calling_convention;
+    unsigned calling_convention : 8;
+
+    /* * Whether this function normally returns to its caller.  It is
+       set from the DW_AT_noreturn attribute if set on the
+       DW_TAG_subprogram.  */
+
+    unsigned int is_noreturn : 1;
 
     /* * Only those DW_TAG_GNU_call_site's in this function that have
        DW_AT_GNU_tail_call set are linked in this list.  Function
@@ -1245,6 +1252,7 @@ extern void allocate_gnat_aux_type (struct type *);
 #define TYPE_GNAT_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.gnat_stuff
 #define TYPE_DESCRIPTIVE_TYPE(thistype) TYPE_GNAT_SPECIFIC(thistype)->descriptive_type
 #define TYPE_CALLING_CONVENTION(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->calling_convention
+#define TYPE_NO_RETURN(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->is_noreturn
 #define TYPE_TAIL_CALL_LIST(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.func_stuff->tail_call_list
 #define TYPE_BASECLASS(thistype,index) TYPE_FIELD_TYPE(thistype, index)
 #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 7b26663..9a1fb8d 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1872,7 +1872,14 @@ finish_command (char *arg, int from_tty)
       if (execution_direction == EXEC_REVERSE)
 	printf_filtered (_("Run back to call of "));
       else
-	printf_filtered (_("Run till exit from "));
+	{
+	  if (function != NULL && TYPE_NO_RETURN (function->type)
+	      && !query (_("warning: Function %s does not return normally.\n"
+			   "Try to finish anyway? "),
+			 SYMBOL_PRINT_NAME (function)))
+	    error (_("Not confirmed."));
+	  printf_filtered (_("Run till exit from "));
+	}
 
       print_stack_frame (get_selected_frame (NULL), 1, LOCATION, 0);
     }
diff --git a/gdb/stack.c b/gdb/stack.c
index 0201d0a..5f2a3dc 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2462,8 +2462,12 @@ return_command (char *retval_exp, int from_tty)
 	confirmed = query (_("%sMake selected stack frame return now? "),
 			   query_prefix);
       else
-	confirmed = query (_("%sMake %s return now? "), query_prefix,
-			   SYMBOL_PRINT_NAME (thisfun));
+	{
+	  if (TYPE_NO_RETURN (thisfun->type))
+	    warning ("Function does not return normally to caller.");
+	  confirmed = query (_("%sMake %s return now? "), query_prefix,
+			     SYMBOL_PRINT_NAME (thisfun));
+	}
       if (!confirmed)
 	error (_("Not confirmed"));
     }
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 1a17ba4..5b53cdd 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2015-01-15  Mark Wielaard  <mjw@redhat.com>
+
+	* gdb.base/noreturn-return.c: New file.
+	* gdb.base/noreturn-return.exp: New file.
+	* gdb.base/noreturn-finish.c: New file.
+	* gdb.base/noreturn-finish.exp: New file.
+
 2015-01-23  Pedro Alves  <palves@redhat.com>
 
 	* gdb.threads/continue-pending-after-query.c: New file.
diff --git a/gdb/testsuite/gdb.base/noreturn-finish.c b/gdb/testsuite/gdb.base/noreturn-finish.c
new file mode 100644
index 0000000..3ec48cd
--- /dev/null
+++ b/gdb/testsuite/gdb.base/noreturn-finish.c
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+
+void __attribute__((noreturn))
+noreturn_func (void)
+{
+  abort ();
+}
+
+int
+main (void)
+{
+  noreturn_func ();
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/noreturn-finish.exp b/gdb/testsuite/gdb.base/noreturn-finish.exp
new file mode 100644
index 0000000..a2ae0db
--- /dev/null
+++ b/gdb/testsuite/gdb.base/noreturn-finish.exp
@@ -0,0 +1,51 @@
+# Copyright 2015 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+if [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {debug}] {
+    return -1
+}
+
+proc noreturn_finish_test { } {
+    global gdb_prompt
+
+    if { ! [ runto_main ] } then {
+	untested ${testfile}.exp
+	return -1
+    }
+
+    gdb_breakpoint "noreturn_func"
+    gdb_continue_to_breakpoint "noreturn_func"
+
+    set test "cancel finish from noreturn_func"
+    gdb_test_multiple "finish" $test {
+	-re "warning: Function noreturn_func does not return normally" {
+	    verbose -log "saw warning"
+	    exp_continue
+	}
+	-re "Try to finish anyway.*y or n.* $" {
+	    send_gdb "n\n"
+	    exp_continue
+	}
+	-re ".*$gdb_prompt $" {
+	    pass $test
+	}
+   }
+}
+
+clean_restart ${binfile}
+
+noreturn_finish_test
diff --git a/gdb/testsuite/gdb.base/noreturn-return.c b/gdb/testsuite/gdb.base/noreturn-return.c
new file mode 100644
index 0000000..3ec48cd
--- /dev/null
+++ b/gdb/testsuite/gdb.base/noreturn-return.c
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+
+void __attribute__((noreturn))
+noreturn_func (void)
+{
+  abort ();
+}
+
+int
+main (void)
+{
+  noreturn_func ();
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/noreturn-return.exp b/gdb/testsuite/gdb.base/noreturn-return.exp
new file mode 100644
index 0000000..8a64a3e
--- /dev/null
+++ b/gdb/testsuite/gdb.base/noreturn-return.exp
@@ -0,0 +1,51 @@
+# Copyright 2015 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+if [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} {debug}] {
+    return -1
+}
+
+proc noreturn_test { } {
+    global gdb_prompt
+
+    if { ! [ runto_main ] } then {
+	untested ${testfile}.exp
+	return -1
+    }
+
+    gdb_breakpoint "noreturn_func"
+    gdb_continue_to_breakpoint "noreturn_func"
+
+    set test "cancel return from noreturn_func"
+    gdb_test_multiple "return" $test {
+	-re "warning: Function does not return normally to caller" {
+	    verbose -log "saw warning"
+	    exp_continue
+	}
+	-re "Make noreturn_func return now.*y or n. $" {
+	    send_gdb "n\n"
+	    exp_continue
+	}
+	-re "Not confirmed.*$gdb_prompt $" {
+	    pass $test
+	}
+   }
+}
+
+clean_restart ${binfile}
+
+noreturn_test
diff --git a/include/ChangeLog b/include/ChangeLog
index 31f1e18..21b6ae6 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2015-01-15  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf2.def (DW_AT_noreturn): New DWARF5 attribute.
+
 2015-01-14  Jan-Benedict Glaw  <jbglaw@lug-owl.de>
 
 	* libiberty.h: Merge from GCC.
diff --git a/include/dwarf2.def b/include/dwarf2.def
index 5da3ae0..3aecdfc 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -306,6 +306,8 @@ DW_AT (DW_AT_data_bit_offset, 0x6b)
 DW_AT (DW_AT_const_expr, 0x6c)
 DW_AT (DW_AT_enum_class, 0x6d)
 DW_AT (DW_AT_linkage_name, 0x6e)
+/* DWARF 5.  */
+DW_AT (DW_AT_noreturn, 0x87)
 
 DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start.  */
 DW_AT_DUP (DW_AT_hi_user, 0x3fff) /* Implementation-defined range end.  */
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally.
  2015-01-23 16:42               ` Mark Wielaard
@ 2015-01-24  0:32                 ` Pedro Alves
  0 siblings, 0 replies; 11+ messages in thread
From: Pedro Alves @ 2015-01-24  0:32 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: Stan Shebs, gdb-patches

On 01/23/2015 04:33 PM, Mark Wielaard wrote:
> On Wed, 2015-01-21 at 17:07 +0000, Pedro Alves wrote:

>>> diff --git a/gdb/testsuite/gdb.base/noreturn.c b/gdb/testsuite/gdb.base/noreturn.c
>>> new file mode 100644
>>> index 0000000..e39cf15
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.base/noreturn.c
>>> @@ -0,0 +1,13 @@
>>
>> Please add a copyright header.  Even though some of our old
>> files don't have it, all new files should, even if the file
>> is small (so that we don't have to recall adding it back
>> if the file grows in future).
> 
> Added.
> Note that most .c files in gdb.base don't have such a header.

Yeah, that's why I felt completed to explain why we add it for
new files.  Adding the header to old files now requires looking at
the logs to know what would be the correct year range.  That's a lot
of boring work, so nobody ever does it.  And that's exactly
the work you've now spared someone in the future by adding
the copyright header now.

> Added the void.
> Note most existing .c tests in gdb.base don't declare functions with
> void arguments.

Yes, a lot of old code in the testsuite doesn't follow
the currently agreed rules for new files.
Doesn't mean we need to keep repeating past mistakes though.

See:
 https://sourceware.org/gdb/wiki/Internals%20GDB-Testsuite-Coding-Standards
 https://sourceware.org/gdb/wiki/GDBTestcaseCookbook

It's just the usual problem of lacking manpower to go through the
existing tests and update them.  It'd be great to see that
done (volunteers very much welcome!), but meanwhile, we try to
avoid propagating bad idioms in new tests.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2015-01-23 17:18 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-27 14:53 [PATCH] Use GCC5/DWARF5 DW_AT_noreturn to mark functions that don't return normally Mark Wielaard
2014-12-04 13:26 ` Mark Wielaard
2014-12-04 14:02 ` Pedro Alves
2014-12-09 10:49   ` Mark Wielaard
2014-12-09 18:57     ` Stan Shebs
2014-12-10 11:25       ` Mark Wielaard
2014-12-12 10:47         ` Pedro Alves
2015-01-15 23:56           ` Mark Wielaard
2015-01-21 17:07             ` Pedro Alves
2015-01-23 16:42               ` Mark Wielaard
2015-01-24  0:32                 ` Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).