aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-decl.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2003-06-04 10:06:00 -0700
committerRichard Henderson <rth@gcc.gnu.org>2003-06-04 10:06:00 -0700
commit0bfa5f65bfb186f10d43304946fd7fcd69988732 (patch)
treed3d591092d6a64dfc049785317e9f17e96cf7276 /gcc/c-decl.c
parent3edc56a9e5499b79239967350162066d99eaf95a (diff)
downloadgcc-0bfa5f65bfb186f10d43304946fd7fcd69988732.zip
gcc-0bfa5f65bfb186f10d43304946fd7fcd69988732.tar.gz
gcc-0bfa5f65bfb186f10d43304946fd7fcd69988732.tar.bz2
c-common.c (handle_cleanup_attribute): New.
* 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. * 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. From-SVN: r67449
Diffstat (limited to 'gcc/c-decl.c')
-rw-r--r--gcc/c-decl.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 6eb0f55..f9124e4 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -50,6 +50,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "c-pragma.h"
#include "cgraph.h"
#include "hashtab.h"
+#include "libfuncs.h"
+#include "except.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -2985,6 +2987,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,