This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR c/14411
- From: Alexey Neyman <alex dot neyman at auriga dot ru>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 22 Nov 2004 21:30:01 +0300
- Subject: [PATCH] Fix PR c/14411
- Organization: Auriga
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