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]

implement __attribute__((cleanup(function)))


This was surprisingly easy to do.  Testing is still
underway, but I expect to commit it after that passes.

Any comments?



r~



	* c-common.c (handle_cleanup_attribute): New.
	(c_common_attributes): Add it.
	* c-decl.c (finish_decl): Honor the cleanup attribute.
	* doc/extend.texi (Variable Attributes): Document it.

	* unwind-c.c: New file.
	* Makefile.in (LIB2ADDEH): Add it.
	* config/t-darwin, config/t-linux, config/ia64/t-ia64: Likewise.

	* gcc.dg/cleanup-1.c: New test.
	* gcc.dg/cleanup-2.c: New test.
	* gcc.dg/cleanup-3.c: New test.
	* gcc.dg/cleanup-4.c: New test.
	* gcc.dg/cleanup-5.c: New test.
	* gcc.dg/cleanup-6.c: New test.
	* gcc.dg/cleanup-7.c: New test.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1048
diff -c -p -d -u -r1.1048 Makefile.in
--- Makefile.in	4 May 2003 15:20:23 -0000	1.1048
+++ Makefile.in	5 May 2003 23:45:16 -0000
@@ -473,7 +473,7 @@ CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(IN
 
 # Additional sources to handle exceptions; overridden by targets as needed.
 LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
-   $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c
+   $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
 LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
 
 # nm flags to list global symbols in libgcc object files.
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.414
diff -c -p -d -u -r1.414 c-common.c
--- c-common.c	3 May 2003 21:44:25 -0000	1.414
+++ c-common.c	5 May 2003 23:45:18 -0000
@@ -41,7 +41,7 @@ Software Foundation, 59 Temple Place - S
 #include "target.h"
 #include "langhooks.h"
 #include "tree-inline.h"
-
+#include "c-tree.h"
 
 cpp_reader *parse_in;		/* Declared in c-pragma.h.  */
 
@@ -795,6 +795,8 @@ static tree handle_nonnull_attribute	PAR
 						 bool *));
 static tree handle_nothrow_attribute	PARAMS ((tree *, tree, tree, int,
 						 bool *));
+static tree handle_cleanup_attribute	PARAMS ((tree *, tree, tree, int,
+						 bool *));
 static tree vector_size_helper PARAMS ((tree, tree));
 
 static void check_function_nonnull	PARAMS ((tree, tree));
@@ -871,6 +873,8 @@ const struct attribute_spec c_common_att
   { "nothrow",                0, 0, true,  false, false,
 			      handle_nothrow_attribute },
   { "may_alias",	      0, 0, false, true, false, NULL },
+  { "cleanup",		      1, 1, true, false, false,
+			      handle_cleanup_attribute },
   { NULL,                     0, 0, false, false, false, NULL }
 };
 
@@ -6093,6 +6097,56 @@ handle_nothrow_attribute (node, name, ar
       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
+
+  return NULL_TREE;
+}
+
+/* Handle a "cleanup" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_cleanup_attribute (node, name, args, flags, no_add_attrs)
+     tree *node;
+     tree name;
+     tree args;
+     int flags ATTRIBUTE_UNUSED;
+     bool *no_add_attrs;
+{
+  tree decl = *node;
+  tree cleanup_id, cleanup_decl, cleanup_type;
+  tree cleanup_arg;
+
+  /* ??? Could perhaps support cleanups on TREE_STATIC, much like we do
+     for global destructors in C++.  This requires infrastructure that
+     we don't have generically at the moment.  It's also not a feature
+     we'd be missing too much, since we do have attribute constructor.  */
+  if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
+    {
+      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  /* Verify that the argument is a function in scope.  */
+  /* ??? We could support pointers to functions here as well, if
+     that was considered desirable.  */
+  cleanup_id = TREE_VALUE (args);
+  if (TREE_CODE (cleanup_id) != IDENTIFIER_NODE)
+    {
+      error ("cleanup arg not an identifier");
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+  cleanup_decl = lookup_name (cleanup_id);
+  if (!cleanup_decl || TREE_CODE (cleanup_decl) != FUNCTION_DECL)
+    {
+      error ("cleanup arg not a function");
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  /* That the function has proper type is checked with the 
+     eventual call to build_function_call.  */
 
   return NULL_TREE;
 }
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.385
diff -c -p -d -u -r1.385 c-decl.c
--- c-decl.c	3 May 2003 13:28:31 -0000	1.385
+++ c-decl.c	5 May 2003 23:45:19 -0000
@@ -49,6 +49,8 @@ Software Foundation, 59 Temple Place - S
 #include "c-common.h"
 #include "c-pragma.h"
 #include "cgraph.h"
+#include "libfuncs.h"
+#include "except.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -2971,6 +2973,41 @@ finish_decl (decl, init, asmspec_tree)
      computing them in the following function definition.  */
   if (current_binding_level == global_binding_level)
     get_pending_sizes ();
+
+  /* Install a cleanup (aka destructor) if one was given.  */
+  if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
+    {
+      tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
+      if (attr)
+	{
+          static bool eh_initialized_p;
+
+	  tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
+	  tree cleanup_decl = lookup_name (cleanup_id);
+	  tree cleanup;
+
+	  /* Build "cleanup(&decl)" for the destructor.  */
+	  cleanup = build_unary_op (ADDR_EXPR, decl, 0);
+	  cleanup = build_tree_list (NULL_TREE, cleanup);
+	  cleanup = build_function_call (cleanup_decl, cleanup);
+
+	  /* Don't warn about decl unused; the cleanup uses it.  */
+	  TREE_USED (decl) = 1;
+
+	  /* Initialize EH, if we've been told to do so.  */
+	  if (flag_exceptions && !eh_initialized_p)
+	    {
+	      eh_initialized_p = true;
+	      eh_personality_libfunc
+		= init_one_libfunc (USING_SJLJ_EXCEPTIONS
+				    ? "__gcc_personality_sj0"
+				    : "__gcc_personality_v0");
+	      using_eh_for_cleanups ();
+	    }
+
+	  add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
+	}
+    }
 }
 
 /* Given a parsed parameter declaration,
Index: unwind-c.c
===================================================================
RCS file: unwind-c.c
diff -N unwind-c.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ unwind-c.c	5 May 2003 23:45:19 -0000
@@ -0,0 +1,186 @@
+/* Supporting functions for C exception handling.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Contributed by Aldy Hernandez <aldy@quesejoda.com>.
+   Shamelessly stolen from the Java front end.
+
+This file is part of GCC.
+
+GCC 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 2, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "unwind.h"
+#include "unwind-pe.h"
+
+typedef struct
+{
+  _Unwind_Ptr Start;
+  _Unwind_Ptr LPStart;
+  _Unwind_Ptr ttype_base;
+  const unsigned char *TType;
+  const unsigned char *action_table;
+  unsigned char ttype_encoding;
+  unsigned char call_site_encoding;
+} lsda_header_info;
+
+static const unsigned char *
+parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
+		   lsda_header_info *info)
+{
+  _Unwind_Word tmp;
+  unsigned char lpstart_encoding;
+
+  info->Start = (context ? _Unwind_GetRegionStart (context) : 0);
+
+  /* Find @LPStart, the base to which landing pad offsets are relative.  */
+  lpstart_encoding = *p++;
+  if (lpstart_encoding != DW_EH_PE_omit)
+    p = read_encoded_value (context, lpstart_encoding, p, &info->LPStart);
+  else
+    info->LPStart = info->Start;
+
+  /* Find @TType, the base of the handler and exception spec type data.  */
+  info->ttype_encoding = *p++;
+  if (info->ttype_encoding != DW_EH_PE_omit)
+    {
+      p = read_uleb128 (p, &tmp);
+      info->TType = p + tmp;
+    }
+  else
+    info->TType = 0;
+
+  /* The encoding and length of the call-site table; the action table
+     immediately follows.  */
+  info->call_site_encoding = *p++;
+  p = read_uleb128 (p, &tmp);
+  info->action_table = p + tmp;
+
+  return p;
+}
+
+#ifdef __USING_SJLJ_EXCEPTIONS__
+#define PERSONALITY_FUNCTION    __gcc_personality_sj0
+#define __builtin_eh_return_data_regno(x) x
+#else
+#define PERSONALITY_FUNCTION    __gcc_personality_v0
+#endif
+#define PERSONALITY_FUNCTION    __gcc_personality_v0
+
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
+		      struct _Unwind_Exception *, struct _Unwind_Context *);
+
+_Unwind_Reason_Code
+PERSONALITY_FUNCTION (int version,
+		      _Unwind_Action actions,
+		      _Unwind_Exception_Class exception_class ATTRIBUTE_UNUSED,
+		      struct _Unwind_Exception *ue_header,
+		      struct _Unwind_Context *context)
+{
+  lsda_header_info info;
+  const unsigned char *language_specific_data, *p, *action_record;
+  _Unwind_Ptr landing_pad, ip;
+
+  if (version != 1)
+    return _URC_FATAL_PHASE1_ERROR;
+
+  /* Currently we only support cleanups for C.  */
+  if ((actions & _UA_CLEANUP_PHASE) == 0)
+    return _URC_CONTINUE_UNWIND;
+
+  language_specific_data = (const unsigned char *)
+    _Unwind_GetLanguageSpecificData (context);
+
+  /* If no LSDA, then there are no handlers or cleanups.  */
+  if (! language_specific_data)
+    return _URC_CONTINUE_UNWIND;
+
+  /* Parse the LSDA header.  */
+  p = parse_lsda_header (context, language_specific_data, &info);
+  ip = _Unwind_GetIP (context) - 1;
+  landing_pad = 0;
+
+#ifdef __USING_SJLJ_EXCEPTIONS__
+  /* The given "IP" is an index into the call-site table, with two
+     exceptions -- -1 means no-action, and 0 means terminate.  But
+     since we're using uleb128 values, we've not got random access
+     to the array.  */
+  if ((int) ip <= 0)
+    return _URC_CONTINUE_UNWIND;
+  else
+    {
+      _Unwind_Word cs_lp, cs_action;
+      do
+	{
+	  p = read_uleb128 (p, &cs_lp);
+	  p = read_uleb128 (p, &cs_action);
+	}
+      while (--ip);
+
+      /* Can never have null landing pad for sjlj -- that would have
+	 been indicated by a -1 call site index.  */
+      landing_pad = cs_lp + 1;
+      if (cs_action)
+	action_record = info.action_table + cs_action - 1;
+      goto found_something;
+    }
+#else
+  /* Search the call-site table for the action associated with this IP.  */
+  while (p < info.action_table)
+    {
+      _Unwind_Ptr cs_start, cs_len, cs_lp;
+      _Unwind_Word cs_action;
+
+      /* Note that all call-site encodings are "absolute" displacements.  */
+      p = read_encoded_value (0, info.call_site_encoding, p, &cs_start);
+      p = read_encoded_value (0, info.call_site_encoding, p, &cs_len);
+      p = read_encoded_value (0, info.call_site_encoding, p, &cs_lp);
+      p = read_uleb128 (p, &cs_action);
+
+      /* The table is sorted, so if we've passed the ip, stop.  */
+      if (ip < info.Start + cs_start)
+	p = info.action_table;
+      else if (ip < info.Start + cs_start + cs_len)
+	{
+	  if (cs_lp)
+	    landing_pad = info.LPStart + cs_lp;
+	  if (cs_action)
+	    action_record = info.action_table + cs_action - 1;
+	  goto found_something;
+	}
+    }
+  
+#endif
+
+  /* IP is not in table.  No associated cleanups.  */
+  /* ??? This is where C++ calls std::terminate to catch throw
+     from a destructor.  */
+  return _URC_CONTINUE_UNWIND;
+
+ found_something:
+  if (landing_pad == 0)
+    {
+      /* IP is present, but has a null landing pad.
+	 No handler to be run.  */
+      return _URC_CONTINUE_UNWIND;
+    }
+
+  _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
+		 (_Unwind_Ptr) ue_header);
+  _Unwind_SetGR (context, __builtin_eh_return_data_regno (1), 0);
+  _Unwind_SetIP (context, landing_pad);
+  return _URC_INSTALL_CONTEXT;
+}
Index: config/t-darwin
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/t-darwin,v
retrieving revision 1.2
diff -c -p -d -u -r1.2 t-darwin
--- config/t-darwin	16 Dec 2002 18:20:43 -0000	1.2
+++ config/t-darwin	5 May 2003 23:45:20 -0000
@@ -18,5 +18,5 @@ $(T)crt2$(objext): $(srcdir)/config/darw
 
 # Use unwind-dw2-fde-darwin
 LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-darwin.c \
-  $(srcdir)/unwind-sjlj.c
+  $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
 LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c
Index: config/t-linux
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/t-linux,v
retrieving revision 1.14
diff -c -p -d -u -r1.14 t-linux
--- config/t-linux	22 Apr 2003 21:52:04 -0000	1.14
+++ config/t-linux	5 May 2003 23:45:20 -0000
@@ -12,5 +12,5 @@ SHLIB_MAPFILES += $(srcdir)/config/libgc
 
 # Use unwind-dw2-fde-glibc
 LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c \
-  $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c
+  $(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
 LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c gthr-gnat.c
Index: config/t-linux-gnulibc1
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/t-linux-gnulibc1,v
retrieving revision 1.3
diff -c -p -d -u -r1.3 t-linux-gnulibc1
--- config/t-linux-gnulibc1	15 Dec 2001 11:46:55 -0000	1.3
+++ config/t-linux-gnulibc1	5 May 2003 23:45:20 -0000
@@ -3,5 +3,5 @@ T_CFLAGS = -DUSE_GNULIBC_1
 
 # Use unwind-dw2-fde
 LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
-  $(srcdir)/unwind-sjlj.c
+  $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
 LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
Index: config/ia64/t-ia64
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/t-ia64,v
retrieving revision 1.18
diff -c -p -d -u -r1.18 t-ia64
--- config/ia64/t-ia64	22 Jan 2003 14:20:45 -0000	1.18
+++ config/ia64/t-ia64	5 May 2003 23:45:20 -0000
@@ -40,7 +40,8 @@ crtfastmath.o: $(srcdir)/config/ia64/crt
 	$(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -c -o crtfastmath.o \
 		$(srcdir)/config/ia64/crtfastmath.c
 
-LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c
+LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c \
+  $(srcdir)/unwind-c.c
 
 ia64-c.o: $(srcdir)/config/ia64/ia64-c.c $(CONFIG_H) $(SYSTEM_H) \
     coretypes.h $(TM_H) $(TREE_H) $(CPPLIB_H) $(C_COMMON_H) c-pragma.h toplev.h
Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.138
diff -c -p -d -u -r1.138 extend.texi
--- doc/extend.texi	5 May 2003 23:12:37 -0000	1.138
+++ doc/extend.texi	5 May 2003 23:45:22 -0000
@@ -3023,6 +3023,22 @@ up to a maximum of 8 byte alignment, the
 in an @code{__attribute__} will still only provide you with 8 byte
 alignment.  See your linker documentation for further information.
 
+@item cleanup (@var{cleanup_function})
+@cindex @code{cleanup} attribute
+The @code{cleanup} attribute runs a function when the variable goes
+out of scope.  This attribute can only be applied to auto function
+scope variables; it may not be applied to parameters or variables
+with static storage duration.  The function must take one parameter,
+a pointer to a type compatible with the variable.  The return value
+of the function (if any) is ignored.
+
+If @option{-fexceptions} is enabled, then @var{cleanup_function}
+will be run during the stack unwinding that happens during the
+processing of the exception.  Note that the @code{cleanup} attribute
+does not allow the exception to be caught, only to perform an action.
+It is undefined what happens if @var{cleanup_function} does not
+return normally.
+
 @item common
 @itemx nocommon
 @cindex @code{common} attribute
Index: testsuite/gcc.dg/cleanup-1.c
===================================================================
RCS file: testsuite/gcc.dg/cleanup-1.c
diff -N testsuite/gcc.dg/cleanup-1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cleanup-1.c	5 May 2003 23:45:24 -0000
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+/* Validate expected warnings and errors.  */
+
+#define U	__attribute__((unused))
+#define C(x)	__attribute__((cleanup(x)))
+
+static int f1(void *x U) { return 0; }
+static void f2() { }
+static void f3(void) { }
+static void f4(void *x U) { }
+static void f5(int *x U) { }
+static void f6(double *x U) { }
+static void f7(const int *x U) { }
+static void f8(const int *x U, int y U) { }
+static void f9(int x U) { }
+
+void test(void)
+{
+  int o1 C(f1);
+  int o2 C(f2);
+  int o3 C(f3);		/* { dg-error "too many arguments" } */
+  int o4 C(f4);
+  int o5 C(f5);
+  int o6 C(f6);		/* { dg-warning "incompatible pointer type" } */
+  int o7 C(f7);
+  int o8 C(f8);		/* { dg-error "too few arguments" } */
+  int o9 C(f9);		/* { dg-warning "from pointer without a cast" } */
+  int o10 U C(undef);	/* { dg-error "not a function" } */
+  int o11 U C(o1);	/* { dg-error "not a function" } */
+  int o12 U C("f1");	/* { dg-error "not an identifier" } */
+  static int o13 U C(f1); /* { dg-warning "attribute ignored" } */
+}
+
+int o14 C(f1);		/* { dg-warning "attribute ignored" } */
+void t15(int o U C(f1)) {} /* { dg-warning "attribute ignored" } */
Index: testsuite/gcc.dg/cleanup-2.c
===================================================================
RCS file: testsuite/gcc.dg/cleanup-2.c
diff -N testsuite/gcc.dg/cleanup-2.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cleanup-2.c	5 May 2003 23:45:24 -0000
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-options "" } */
+/* Verify that cleanup works in the most basic of ways.  */
+
+extern void exit(int);
+extern void abort(void);
+
+static void handler(void *p __attribute__((unused)))
+{
+  exit (0);
+}
+
+static void doit(void)
+{
+  int x __attribute__((cleanup (handler)));
+}
+
+int main()
+{
+  doit ();
+  abort ();
+}
Index: testsuite/gcc.dg/cleanup-3.c
===================================================================
RCS file: testsuite/gcc.dg/cleanup-3.c
diff -N testsuite/gcc.dg/cleanup-3.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cleanup-3.c	5 May 2003 23:45:24 -0000
@@ -0,0 +1,45 @@
+/* { dg-do run } */
+/* { dg-options "" } */
+/* Verify that the cleanup handler receives the proper contents
+   of the variable.  */
+
+extern void exit(int);
+extern void abort(void);
+
+static int expected;
+
+static void
+handler(int *p)
+{
+  if (*p != expected)
+    abort ();
+}
+
+static void __attribute__((noinline))
+bar(void)
+{
+}
+
+static void doit(int x, int y)
+{
+  int r __attribute__((cleanup (handler)));
+  if (x < y)
+    {
+      r = 0;
+      return;
+    }
+
+  bar();
+  r = x + y;
+}
+
+int main()
+{
+  expected = 0;
+  doit (1, 2);
+
+  expected = 3;
+  doit (2, 1);
+
+  return 0;
+}
Index: testsuite/gcc.dg/cleanup-4.c
===================================================================
RCS file: testsuite/gcc.dg/cleanup-4.c
diff -N testsuite/gcc.dg/cleanup-4.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cleanup-4.c	5 May 2003 23:45:24 -0000
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+/* { dg-options "" } */
+/* Verify cleanup execution on non-trivial exit from a block.  */
+
+extern void exit(int);
+extern void abort(void);
+
+static int counter;
+
+static void
+handler(int *p)
+{
+  counter += *p;
+}
+
+static void __attribute__((noinline))
+bar(void)
+{
+}
+
+static void doit(int n, int n2)
+{
+  int i;
+  for (i = 0; i < n; ++i)
+    {
+      int dummy __attribute__((cleanup (handler))) = i;
+      if (i == n2)
+	break;
+      bar();
+    }
+}
+
+int main()
+{
+  doit (10, 6);
+  if (counter != 0 + 1 + 2 + 3 + 4 + 5 + 6)
+    abort ();
+  return 0;
+}
Index: testsuite/gcc.dg/cleanup-5.c
===================================================================
RCS file: testsuite/gcc.dg/cleanup-5.c
diff -N testsuite/gcc.dg/cleanup-5.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cleanup-5.c	5 May 2003 23:45:24 -0000
@@ -0,0 +1,50 @@
+/* { dg-do run } */
+/* { dg-options "-fexceptions" } */
+/* Verify that cleanups work with exception handling.  */
+
+#include <unwind.h>
+#include <stdlib.h>
+
+static _Unwind_Reason_Code
+force_unwind_stop (int version, _Unwind_Action actions,
+                   _Unwind_Exception_Class exc_class,
+                   struct _Unwind_Exception *exc_obj,
+                   struct _Unwind_Context *context,
+                   void *stop_parameter)
+{
+  if (actions & _UA_END_OF_STACK)
+    abort ();
+  return _URC_NO_REASON;
+}
+
+static void force_unwind ()
+{
+  struct _Unwind_Exception *exc = malloc (sizeof (*exc));
+  exc->exception_class = 0;
+  exc->exception_cleanup = 0;
+                   
+#ifndef __USING_SJLJ_EXCEPTIONS__
+  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
+#else
+  _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0);
+#endif
+                   
+  abort ();
+}
+
+static void handler (void *p __attribute__((unused)))
+{
+  exit (0);
+}
+
+static void doit ()
+{
+  char dummy __attribute__((cleanup (handler)));
+  force_unwind ();
+}
+
+int main()
+{ 
+  doit ();
+  abort ();
+}
Index: testsuite/gcc.dg/cleanup-6.c
===================================================================
RCS file: testsuite/gcc.dg/cleanup-6.c
diff -N testsuite/gcc.dg/cleanup-6.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cleanup-6.c	5 May 2003 23:45:24 -0000
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* Verify that a cleanup marked "inline" gets inlined.  */
+
+static inline void xyzzy(void *p __attribute__((unused)))
+{
+}
+
+void doit(void)
+{
+  int x __attribute__((cleanup (xyzzy)));
+}
+
+/* { dg-final { scan-assembler-not "xyzzy" } } */
Index: testsuite/gcc.dg/cleanup-7.c
===================================================================
RCS file: testsuite/gcc.dg/cleanup-7.c
diff -N testsuite/gcc.dg/cleanup-7.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cleanup-7.c	5 May 2003 23:45:24 -0000
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-options "" } */
+/* Verify that the search for function happens in the proper scope.  */
+
+extern void exit(int);
+extern void abort(void);
+
+int main()
+{
+  auto void xyzzy(void *p __attribute__((unused)))
+  {
+    exit (0);
+  }
+
+  auto void doit ()
+  {
+    int x __attribute__((cleanup (xyzzy)));
+  }
+
+  doit ();
+  abort ();
+}


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