aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r--gcc/c-common.c92
1 files changed, 83 insertions, 9 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 76f79274861..b40a35aecb5 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -39,6 +39,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#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 PARAMS ((tree *, tree, tree, int,
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_attribute_table[] =
{ "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 }
};
@@ -3185,6 +3190,7 @@ c_common_nodes_and_builtins ()
#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
+#define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
#include "builtin-types.def"
#undef DEF_PRIMITIVE_TYPE
@@ -3196,6 +3202,7 @@ c_common_nodes_and_builtins ()
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
#undef DEF_POINTER_TYPE
BT_LAST
};
@@ -3390,8 +3397,6 @@ c_common_nodes_and_builtins ()
= build_pointer_type (build_qualified_type
(char_type_node, TYPE_QUAL_CONST));
- (*targetm.init_builtins) ();
-
/* This is special for C++ so functions can be overloaded. */
wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE);
wchar_type_node = TREE_TYPE (identifier_global_value (wchar_type_node));
@@ -3515,6 +3520,19 @@ c_common_nodes_and_builtins ()
tree_cons (NULL_TREE, \
builtin_types[(int) ARG2], \
NULL_TREE)));
+
+#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
+ builtin_types[(int) ENUM] \
+ = build_function_type \
+ (builtin_types[(int) RETURN], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG1], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG2], \
+ tree_cons (NULL_TREE, \
+ builtin_types[(int) ARG3], \
+ NULL_TREE))));
+
#define DEF_POINTER_TYPE(ENUM, TYPE) \
builtin_types[(int) ENUM] \
= build_pointer_type (builtin_types[(int) TYPE]);
@@ -3526,6 +3544,8 @@ c_common_nodes_and_builtins ()
#undef DEF_FUNCTION_TYPE_4
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
#undef DEF_POINTER_TYPE
if (!c_attrs_initialized)
@@ -3563,6 +3583,8 @@ c_common_nodes_and_builtins ()
#include "builtins.def"
#undef DEF_BUILTIN
+ (*targetm.init_builtins) ();
+
main_identifier_node = get_identifier ("main");
}
@@ -4894,11 +4916,11 @@ cb_register_builtins (pfile)
cpp_define (pfile, "__GXX_WEAK__=1");
else
cpp_define (pfile, "__GXX_WEAK__=0");
- if (flag_exceptions)
- cpp_define (pfile, "__EXCEPTIONS");
if (warn_deprecated)
cpp_define (pfile, "__DEPRECATED");
}
+ if (flag_exceptions)
+ cpp_define (pfile, "__EXCEPTIONS");
/* represents the C++ ABI version, always defined so it can be used while
preprocessing C and assembler. */
@@ -5383,16 +5405,19 @@ handle_always_inline_attribute (node, name, args, flags, no_add_attrs)
struct attribute_spec.handler. */
static tree
-handle_used_attribute (node, name, args, flags, no_add_attrs)
- tree *node;
+handle_used_attribute (pnode, name, args, flags, no_add_attrs)
+ tree *pnode;
tree name;
tree args ATTRIBUTE_UNUSED;
int flags ATTRIBUTE_UNUSED;
bool *no_add_attrs;
{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (*node))
- = TREE_USED (*node) = 1;
+ tree node = *pnode;
+
+ if (TREE_CODE (node) == FUNCTION_DECL
+ || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node)))
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (node))
+ = TREE_USED (node) = 1;
else
{
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
@@ -6055,6 +6080,55 @@ handle_pure_attribute (node, name, args, flags, no_add_attrs)
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;
+}
+
/* Handle a "deprecated" attribute; arguments as in
struct attribute_spec.handler. */