This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
attribute cleanup
- From: Richard Henderson <rth at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 4 Jun 2003 10:05:51 -0700
- Subject: attribute cleanup
Mark, Jason and I came to an agreement at the Summit.
Committed to 3.3 and mainline. The following is the
3.3 version of the patch.
r~
Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ChangeLog,v
retrieving revision 1.16114.2.552
diff -c -p -d -u -r1.16114.2.552 ChangeLog
--- ChangeLog 4 Jun 2003 07:18:54 -0000 1.16114.2.552
+++ ChangeLog 4 Jun 2003 16:54:17 -0000
@@ -1,3 +1,15 @@
+2003-06-04 Richard Henderson <rth@redhat.com>
+
+ * 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/t-linux-gnulibc1,
+ config/ia64/t-ia64: Likewise.
+
2003-06-04 Eric Botcazou <ebotcazou@libertysurf.fr>
PR optimization/11018
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.958.2.10
diff -c -p -d -u -r1.958.2.10 Makefile.in
--- Makefile.in 3 Jun 2003 23:36:30 -0000 1.958.2.10
+++ Makefile.in 4 Jun 2003 16:54:18 -0000
@@ -401,7 +401,7 @@ CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(IN
# Additional sources to handle exceptions; overridden on ia64.
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
# nm flags to list global symbols in libgcc object files.
@@ -1200,7 +1200,7 @@ $(srcdir)/c-parse.y: c-parse.in
c-decl.o : c-decl.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) $(C_TREE_H) \
$(GGC_H) $(TARGET_H) flags.h function.h output.h $(EXPR_H) \
debug.h toplev.h intl.h $(TM_P_H) tree-inline.h $(TIMEVAR_H) c-pragma.h \
- gt-c-decl.h
+ gt-c-decl.h libfuncs.h except.h
c-typeck.o : c-typeck.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
$(TARGET_H) flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h $(TM_P_H)
c-lang.o : c-lang.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
@@ -1247,7 +1247,7 @@ tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB
c-common.o : c-common.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(OBSTACK_H) \
$(C_COMMON_H) flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
$(EXPR_H) $(TM_P_H) builtin-types.def builtin-attrs.def $(TARGET_H) \
- diagnostic.h except.h gt-c-common.h real.h langhooks.h
+ diagnostic.h except.h gt-c-common.h real.h langhooks.h c-tree.h
c-pretty-print.o : c-pretty-print.c c-pretty-print.h pretty-print.h \
$(C_COMMON_H) $(CONFIG_H) $(SYSTEM_H) real.h
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.393.2.3
diff -c -p -d -u -r1.393.2.3 c-common.c
--- c-common.c 9 Mar 2003 19:31:11 -0000 1.393.2.3
+++ c-common.c 4 Jun 2003 16:54:19 -0000
@@ -39,6 +39,7 @@ Software Foundation, 59 Temple Place - S
#include "langhooks.h"
#include "except.h" /* For USING_SJLJ_EXCEPTIONS. */
#include "tree-inline.h"
+#include "c-tree.h"
cpp_reader *parse_in; /* Declared in c-pragma.h. */
@@ -768,6 +769,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));
@@ -856,6 +859,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 }
};
@@ -6071,6 +6076,55 @@ handle_pure_attribute (node, name, args,
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;
+
+ /* ??? 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.356.2.8
diff -c -p -d -u -r1.356.2.8 c-decl.c
--- c-decl.c 18 Apr 2003 17:48:44 -0000 1.356.2.8
+++ c-decl.c 4 Jun 2003 16:54:21 -0000
@@ -46,6 +46,8 @@ Software Foundation, 59 Temple Place - S
#include "timevar.h"
#include "c-common.h"
#include "c-pragma.h"
+#include "libfuncs.h"
+#include "except.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -3168,6 +3170,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 4 Jun 2003 16:54:21 -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.1
diff -c -p -d -u -r1.1 t-darwin
--- config/t-darwin 7 Nov 2002 06:00:05 -0000 1.1
+++ config/t-darwin 4 Jun 2003 16:54:22 -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.13
diff -c -p -d -u -r1.13 t-linux
--- config/t-linux 28 Nov 2002 14:47:01 -0000 1.13
+++ config/t-linux 4 Jun 2003 16:54:22 -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)/unwind-sjlj.c $(srcdir)/unwind-c.c
LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.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 4 Jun 2003 16:54:22 -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.16
diff -c -p -d -u -r1.16 t-ia64
--- config/ia64/t-ia64 7 Nov 2002 22:48:10 -0000 1.16
+++ config/ia64/t-ia64 4 Jun 2003 16:54:22 -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) \
$(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.109.2.15
diff -c -p -d -u -r1.109.2.15 extend.texi
--- doc/extend.texi 23 May 2003 01:25:10 -0000 1.109.2.15
+++ doc/extend.texi 4 Jun 2003 16:54:24 -0000
@@ -3062,6 +3062,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 mode (@var{mode})
@cindex @code{mode} attribute
This attribute specifies the data type for the declaration---whichever
Index: testsuite/ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/ChangeLog,v
retrieving revision 1.2261.2.179
diff -c -p -d -u -r1.2261.2.179 ChangeLog
--- testsuite/ChangeLog 4 Jun 2003 07:19:06 -0000 1.2261.2.179
+++ testsuite/ChangeLog 4 Jun 2003 16:54:27 -0000
@@ -1,3 +1,13 @@
+2003-06-04 Richard Henderson <rth@redhat.com>
+
+ * gcc.dg/cleanup-1.c: New.
+ * gcc.dg/cleanup-2.c: New.
+ * gcc.dg/cleanup-3.c: New.
+ * gcc.dg/cleanup-4.c: New.
+ * gcc.dg/cleanup-5.c: New.
+ * gcc.dg/cleanup-6.c: New.
+ * gcc.dg/cleanup-7.c: New.
+
2003-06-04 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.dg/ultrasp9.c: New test.
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 4 Jun 2003 16:54:28 -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 4 Jun 2003 16:54:28 -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 4 Jun 2003 16:54:28 -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 4 Jun 2003 16:54:28 -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 4 Jun 2003 16:54:28 -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 4 Jun 2003 16:54:28 -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 4 Jun 2003 16:54:28 -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 ();
+}