This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR c/14411


This patch allows one to mark a function as setjmp-like/longjmp-like 
with attributes setjmp/longjmp, respectively.

Comments from jsm@polyomino.org.uk (oddly enough, captured in PR 
c/18180) addressed, except that I did not rename the attribute to 
"returns_twice". Having the name __attribute__((setjmp)) is 
consistent with other attributes named after a common function, e.g. 
__attribute__((malloc)).

Regards,
Alexey.
2004-10-29  Alexey Neyman  <alex.neyman@auriga.ru>

	PR c/14411
	* calls.c (flags_from_decl_or_type): Handle `setjmp' and `longjmp'
	attributes.
	* c-common.c (handle_setjmp_attribute): New function.
	(handle_longjmp_attribute): New function.
	(c_common_attribute_table): Declare `setjmp' and `longjmp' attributes.
	* doc/extend.texi: Document `setjmp' and `longjmp' attributes.
	* tree.h (DECL_IS_SETJMP): New macro.
	(DECL_IS_LONGJMP): New macro.
	(struct tree_decl): Add setjmp_flag, longjmp_flag.


2004-10-29  Alexey Neyman  <alex.neyman@auriga.ru>
	* gcc.dg/attr-setjmp-1.c: New test.

diff -crN gcc.orig/gcc/calls.c gcc.setjmp/gcc/calls.c
*** gcc.orig/gcc/calls.c	2004-09-08 22:44:55.000000000 +0400
--- gcc.setjmp/gcc/calls.c	2004-10-28 11:16:07.000000000 +0400
***************
*** 583,588 ****
--- 583,596 ----
        if (DECL_IS_MALLOC (exp))
  	flags |= ECF_MALLOC;
  
+       /* The function exp may have the `setjmp' attribute.  */
+       if (DECL_P (exp) && DECL_IS_SETJMP (exp))
+ 	flags |= ECF_RETURNS_TWICE;
+ 
+       /* The function exp may have the `longjmp' attribute.  */
+       if (DECL_P (exp) && DECL_IS_LONGJMP (exp))
+ 	flags |= ECF_LONGJMP;
+ 
        /* The function exp may have the `pure' attribute.  */
        if (DECL_IS_PURE (exp))
  	flags |= ECF_PURE | ECF_LIBCALL_BLOCK;
diff -crN gcc.orig/gcc/c-common.c gcc.setjmp/gcc/c-common.c
*** gcc.orig/gcc/c-common.c	2004-10-19 02:01:51.000000000 +0400
--- gcc.setjmp/gcc/c-common.c	2004-10-28 11:51:45.000000000 +0400
***************
*** 545,550 ****
--- 545,552 ----
  static tree handle_no_instrument_function_attribute (tree *, tree,
  						     tree, int, bool *);
  static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
+ static tree handle_setjmp_attribute (tree *, tree, tree, int, bool *);
+ static tree handle_longjmp_attribute (tree *, tree, tree, int, bool *);
  static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
  					     bool *);
  static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
***************
*** 615,620 ****
--- 617,626 ----
  			      handle_no_instrument_function_attribute },
    { "malloc",                 0, 0, true,  false, false,
  			      handle_malloc_attribute },
+   { "setjmp",                 0, 0, true,  false, false,
+ 			      handle_setjmp_attribute },
+   { "longjmp",                0, 0, true,  false, false,
+ 			      handle_longjmp_attribute },
    { "no_stack_limit",         0, 0, true,  false, false,
  			      handle_no_limit_stack_attribute },
    { "pure",                   0, 0, true,  false, false,
***************
*** 4786,4791 ****
--- 4792,4833 ----
    return NULL_TREE;
  }
  
+ /* Handle a "setjmp" attribute; arguments as in
+    struct attribute_spec.handler.  */
+ 
+ static tree
+ handle_setjmp_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ 			 int ARG_UNUSED (flags), bool *no_add_attrs)
+ {
+   if (TREE_CODE (*node) == FUNCTION_DECL)
+     DECL_IS_SETJMP (*node) = 1;
+   else
+     {
+       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+       *no_add_attrs = true;
+     }
+ 
+   return NULL_TREE;
+ }
+ 
+ /* Handle a "longjmp" attribute; arguments as in
+    struct attribute_spec.handler.  */
+ 
+ static tree
+ handle_longjmp_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ 			 int ARG_UNUSED (flags), bool *no_add_attrs)
+ {
+   if (TREE_CODE (*node) == FUNCTION_DECL)
+     DECL_IS_LONGJMP (*node) = 1;
+   else
+     {
+       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+       *no_add_attrs = true;
+     }
+ 
+   return NULL_TREE;
+ }
+ 
  /* Handle a "no_limit_stack" attribute; arguments as in
     struct attribute_spec.handler.  */
  
diff -crN gcc.orig/gcc/doc/extend.texi gcc.setjmp/gcc/doc/extend.texi
*** gcc.orig/gcc/doc/extend.texi	2004-10-20 03:17:06.000000000 +0400
--- gcc.setjmp/gcc/doc/extend.texi	2004-11-22 20:00:40.427288421 +0300
***************
*** 1479,1484 ****
--- 1479,1486 ----
  @cindex functions that have no side effects
  @cindex functions in arbitrary sections
  @cindex functions that behave like malloc
+ @cindex functions that behave like setjmp
+ @cindex functions that behave like longjmp
  @cindex @code{volatile} applied to function
  @cindex @code{const} applied to function
  @cindex functions with @code{printf}, @code{scanf}, @code{strftime} or @code{strfmon} style arguments
***************
*** 1499,1509 ****
  @code{pure}, @code{const}, @code{nothrow}, @code{sentinel},
  @code{format}, @code{format_arg}, @code{no_instrument_function},
  @code{section}, @code{constructor}, @code{destructor}, @code{used},
! @code{unused}, @code{deprecated}, @code{weak}, @code{malloc},
! @code{alias}, @code{warn_unused_result} and @code{nonnull}.  Several other
! attributes are defined for functions on particular target systems.  Other
! attributes, including @code{section} are supported for variables declarations
! (@pxref{Variable Attributes}) and for types (@pxref{Type Attributes}).
  
  You may also specify attributes with @samp{__} preceding and following
  each keyword.  This allows you to use them in header files without
--- 1501,1512 ----
  @code{pure}, @code{const}, @code{nothrow}, @code{sentinel},
  @code{format}, @code{format_arg}, @code{no_instrument_function},
  @code{section}, @code{constructor}, @code{destructor}, @code{used},
! @code{unused}, @code{deprecated}, @code{weak}, @code{malloc}, @code{setjmp},
! @code{longjmp}, @code{alias}, @code{warn_unused_result} and @code{nonnull}.
! Several other attributes are defined for functions on particular target
! systems.  Other attributes, including @code{section} are supported for
! variables declarations (@pxref{Variable Attributes}) and for types
! (@pxref{Type Attributes}).
  
  You may also specify attributes with @samp{__} preceding and following
  each keyword.  This allows you to use them in header files without
***************
*** 1516,1521 ****
--- 1519,1536 ----
  @table @code
  @c Keep this table alphabetized by attribute name. Treat _ as space.
  
+ @item setjmp
+ @cindex @code{setjmp} attribute
+ The @code{setjmp} attribute tells the compiler that a function may return
+ more than one time.  The compiler will ensure that all registers are dead
+ before calling such a function and will emit a warning about the variables
+ that may be clobbered after the second return from the function.
+ 
+ @item longjmp
+ @cindex @code{longjmp} attribute
+ The @code{longjmp} attribute tells the compiler that a function is a
+ counterpart of the respective @code{setjmp}-like function.
+ 
  @item alias ("@var{target}")
  @cindex @code{alias} attribute
  The @code{alias} attribute causes the declaration to be emitted as an
diff -crN gcc.orig/gcc/testsuite/gcc.dg/attr-setjmp-1.c gcc.setjmp/gcc/testsuite/gcc.dg/attr-setjmp-1.c
*** gcc.orig/gcc/testsuite/gcc.dg/attr-setjmp-1.c	1970-01-01 03:00:00.000000000 +0300
--- gcc.setjmp/gcc/testsuite/gcc.dg/attr-setjmp-1.c	2004-10-28 19:57:21.000000000 +0400
***************
*** 0 ****
--- 1,23 ----
+ /* { dg-do compile { target i?86-*-* } } */
+ /* { dg-options "-W" } */
+ 
+ int newsetjmp(void) __attribute__((setjmp));
+ void g(int);
+ 
+ int
+ main (void)
+ {
+   register int reg asm ("esi") = 1; /* { dg-warning "might be clobbered" "" } */
+ 
+   if (!newsetjmp ())
+     {
+       reg = 2;
+       g (reg);
+     }
+   else
+     {
+       g (reg);
+     }
+ 
+   return 0;
+ }
diff -crN gcc.orig/gcc/tree.h gcc.setjmp/gcc/tree.h
*** gcc.orig/gcc/tree.h	2004-10-22 22:52:19.000000000 +0400
--- gcc.setjmp/gcc/tree.h	2004-10-28 11:54:38.000000000 +0400
***************
*** 2160,2165 ****
--- 2160,2174 ----
  #define DECL_IS_MALLOC(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.malloc_flag)
  
  /* Nonzero in a FUNCTION_DECL means this function should be treated
+    as if it were a setjmp, meaning it could return more than once */
+ #define DECL_IS_SETJMP(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.setjmp_flag)
+ 
+ /* Nonzero in a FUNCTION_DECL means this function should be treated
+    as if it were a longjmp, meaning it will return to the previously
+    set point.  */
+ #define DECL_IS_LONGJMP(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.longjmp_flag)
+ 
+ /* Nonzero in a FUNCTION_DECL means this function should be treated
     as "pure" function (like const function, but may read global memory).  */
  #define DECL_IS_PURE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.pure_flag)
  
***************
*** 2363,2369 ****
    unsigned possibly_inlined : 1;
    unsigned preserve_flag: 1;
    unsigned gimple_formal_temp : 1;
!   /* 13 unused bits.  */
  
    union tree_decl_u1 {
      /* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is
--- 2372,2380 ----
    unsigned possibly_inlined : 1;
    unsigned preserve_flag: 1;
    unsigned gimple_formal_temp : 1;
!   unsigned setjmp_flag : 1;
!   unsigned longjmp_flag : 1;
!   /* 11 unused bits.  */
  
    union tree_decl_u1 {
      /* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]