diff options
author | Richard Henderson <rth@redhat.com> | 2003-06-04 10:06:00 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2003-06-04 10:06:00 -0700 |
commit | 0bfa5f65bfb186f10d43304946fd7fcd69988732 (patch) | |
tree | d3d591092d6a64dfc049785317e9f17e96cf7276 /gcc/c-decl.c | |
parent | 3edc56a9e5499b79239967350162066d99eaf95a (diff) | |
download | gcc-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.c | 37 |
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, |