/* Subroutines shared by all languages that are variants of C.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002 Free Software Foundation, Inc.
+ 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "intl.h"
#include "tree.h"
-#include "real.h"
#include "flags.h"
#include "toplev.h"
#include "output.h"
#include "c-pragma.h"
#include "rtl.h"
#include "ggc.h"
+#include "varray.h"
#include "expr.h"
#include "c-common.h"
-#include "tree-inline.h"
#include "diagnostic.h"
#include "tm_p.h"
#include "obstack.h"
#include "cpplib.h"
#include "target.h"
#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. */
: "long long unsigned int"))
#endif
-#ifndef STDC_0_IN_SYSTEM_HEADERS
-#define STDC_0_IN_SYSTEM_HEADERS 0
-#endif
-
-#ifndef REGISTER_PREFIX
-#define REGISTER_PREFIX ""
-#endif
-
/* The variant of the C language being processed. */
enum c_language_kind c_language;
tree c_global_trees[CTI_MAX];
+/* TRUE if a code represents a statement. The front end init
+ langhook should take care of initialization of this array. */
+
+bool statement_code_p[MAX_TREE_CODES];
+
+/* Nonzero if we can read a PCH file now. */
+
+int allow_pch = 1;
+\f
+/* Switches common to the C front ends. */
+
/* Nonzero if prepreprocessing only. */
+
int flag_preprocess_only;
+/* Nonzero means don't output line number information. */
+
+char flag_no_line_commands;
+
+/* Nonzero causes -E output not to be done, but directives such as
+ #define that have side effects are still obeyed. */
+
+char flag_no_output;
+
+/* Nonzero means dump macros in some fashion. */
+
+char flag_dump_macros;
+
+/* Nonzero means pass #include lines through to the output. */
+
+char flag_dump_includes;
+
+/* The file name to which we should write a precompiled header, or
+ NULL if no header will be written in this compile. */
+
+const char *pch_file;
+
/* Nonzero if an ISO standard was selected. It rejects macros in the
user's namespace. */
int flag_iso;
+/* Nonzero whenever Objective-C functionality is being used. */
+int flag_objc;
+
/* Nonzero if -undef was given. It suppresses target built-in macros
and assertions. */
int flag_undef;
/* Nonzero means allow Microsoft extensions without warnings or errors. */
int flag_ms_extensions;
-/* Nonzero means warn about use of multicharacter literals. */
+/* Nonzero means don't recognize the keyword `asm'. */
+
+int flag_no_asm;
+
+/* Nonzero means give string constants the type `const char *', as mandated
+ by the standard. */
+
+int flag_const_strings;
+
+/* Nonzero means to treat bitfields as signed unless they say `unsigned'. */
+
+int flag_signed_bitfields = 1;
+int explicit_flag_signed_bitfields;
+
+/* Nonzero means warn about pointer casts that can drop a type qualifier
+ from the pointer target type. */
+
+int warn_cast_qual;
+
+/* Warn about functions which might be candidates for format attributes. */
+
+int warn_missing_format_attribute;
+
+/* Nonzero means warn about sizeof(function) or addition/subtraction
+ of function pointers. */
+
+int warn_pointer_arith;
+
+/* Nonzero means warn for any global function def
+ without separate previous prototype decl. */
+
+int warn_missing_prototypes;
+
+/* Warn if adding () is suggested. */
+
+int warn_parentheses;
+
+/* Warn if initializer is not completely bracketed. */
+
+int warn_missing_braces;
+
+/* Warn about comparison of signed and unsigned values.
+ If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified
+ (in which case -Wextra gets to decide). */
+
+int warn_sign_compare = -1;
+
+/* Nonzero means warn about usage of long long when `-pedantic'. */
+
+int warn_long_long = 1;
+
+/* Nonzero means warn about deprecated conversion from string constant to
+ `char *'. */
+
+int warn_write_strings;
+
+/* Nonzero means warn about multiple (redundant) decls for the same single
+ variable or function. */
+
+int warn_redundant_decls;
+
+/* Warn about testing equality of floating point numbers. */
+
+int warn_float_equal;
-int warn_multichar = 1;
+/* Warn about a subscript that has type char. */
+
+int warn_char_subscripts;
+
+/* Warn if a type conversion is done that might have confusing results. */
+
+int warn_conversion;
+
+/* Warn about #pragma directives that are not recognized. */
+
+int warn_unknown_pragmas; /* Tri state variable. */
+
+/* Warn about format/argument anomalies in calls to formatted I/O functions
+ (*printf, *scanf, strftime, strfmon, etc.). */
+
+int warn_format;
+
+/* Warn about Y2K problems with strftime formats. */
+
+int warn_format_y2k;
+
+/* Warn about excess arguments to formats. */
+
+int warn_format_extra_args;
+
+/* Warn about zero-length formats. */
+
+int warn_format_zero_length;
+
+/* Warn about non-literal format arguments. */
+
+int warn_format_nonliteral;
+
+/* Warn about possible security problems with calls to format functions. */
+
+int warn_format_security;
+
+
+/* C/ObjC language option variables. */
+
+
+/* Nonzero means message about use of implicit function declarations;
+ 1 means warning; 2 means error. */
+
+int mesg_implicit_function_declaration = -1;
+
+/* Nonzero means allow type mismatches in conditional expressions;
+ just make their values `void'. */
+
+int flag_cond_mismatch;
+
+/* Nonzero means enable C89 Amendment 1 features. */
+
+int flag_isoc94;
+
+/* Nonzero means use the ISO C99 dialect of C. */
+
+int flag_isoc99;
+
+/* Nonzero means that we have builtin functions, and main is an int */
+
+int flag_hosted = 1;
+
+/* Nonzero means add default format_arg attributes for functions not
+ in ISO C. */
+
+int flag_noniso_default_format_attributes = 1;
+
+/* Nonzero means warn when casting a function call to a type that does
+ not match the return type (e.g. (float)sqrt() or (anything*)malloc()
+ when there is no previous declaration of sqrt or malloc. */
+
+int warn_bad_function_cast;
+
+/* Warn about traditional constructs whose meanings changed in ANSI C. */
+
+int warn_traditional;
+
+/* Nonzero means warn for non-prototype function decls
+ or non-prototyped defs without previous prototype. */
+
+int warn_strict_prototypes;
+
+/* Nonzero means warn for any global function def
+ without separate previous decl. */
+
+int warn_missing_declarations;
+
+/* Nonzero means warn about declarations of objects not at
+ file-scope level and about *all* declarations of functions (whether
+ or static) not at file-scope level. Note that we exclude
+ implicit function declarations. To get warnings about those, use
+ -Wimplicit. */
+
+int warn_nested_externs;
+
+/* Warn if main is suspicious. */
+
+int warn_main;
/* Nonzero means warn about possible violations of sequence point rules. */
/* Nonzero means to warn about compile-time division by zero. */
int warn_div_by_zero = 1;
+/* Nonzero means warn about use of implicit int. */
+
+int warn_implicit_int;
+
/* Warn about NULL being passed to argument slots marked as requiring
non-NULL. */
int warn_nonnull;
+
+/* ObjC language option variables. */
+
+
+/* Open and close the file for outputting class declarations, if
+ requested (ObjC). */
+
+int flag_gen_declaration;
+
+/* Generate code for GNU or NeXT runtime environment. */
+
+#ifdef NEXT_OBJC_RUNTIME
+int flag_next_runtime = 1;
+#else
+int flag_next_runtime = 0;
+#endif
+
+/* Tells the compiler that this is a special run. Do not perform any
+ compiling, instead we are to test some platform dependent features
+ and output a C header file with appropriate definitions. */
+
+int print_struct_values;
+
+/* ???. Undocumented. */
+
+const char *constant_string_class_name;
+
+/* Warn if multiple methods are seen for the same selector, but with
+ different argument types. Performs the check on the whole selector
+ table at the end of compilation. */
+
+int warn_selector;
+
+/* Warn if a @selector() is found, and no method with that selector
+ has been previously declared. The check is done on each
+ @selector() as soon as it is found - so it warns about forward
+ declarations. */
+
+int warn_undeclared_selector;
+
+/* Warn if methods required by a protocol are not implemented in the
+ class adopting it. When turned off, methods inherited to that
+ class are also considered implemented. */
+
+int warn_protocol = 1;
+
+
+/* C++ language option variables. */
+
+
+/* Nonzero means don't recognize any extension keywords. */
+
+int flag_no_gnu_keywords;
+
+/* Nonzero means do emit exported implementations of functions even if
+ they can be inlined. */
+
+int flag_implement_inlines = 1;
+
+/* Nonzero means do emit exported implementations of templates, instead of
+ multiple static copies in each file that needs a definition. */
+
+int flag_external_templates;
+
+/* Nonzero means that the decision to emit or not emit the implementation of a
+ template depends on where the template is instantiated, rather than where
+ it is defined. */
+
+int flag_alt_external_templates;
+
+/* Nonzero means that implicit instantiations will be emitted if needed. */
+
+int flag_implicit_templates = 1;
+
+/* Nonzero means that implicit instantiations of inline templates will be
+ emitted if needed, even if instantiations of non-inline templates
+ aren't. */
+
+int flag_implicit_inline_templates = 1;
+
+/* Nonzero means generate separate instantiation control files and
+ juggle them at link time. */
+
+int flag_use_repository;
+
+/* Nonzero if we want to issue diagnostics that the standard says are not
+ required. */
+
+int flag_optional_diags = 1;
+
+/* Nonzero means we should attempt to elide constructors when possible. */
+
+int flag_elide_constructors = 1;
+
+/* Nonzero means that member functions defined in class scope are
+ inline by default. */
+
+int flag_default_inline = 1;
+
+/* Controls whether compiler generates 'type descriptor' that give
+ run-time type information. */
+
+int flag_rtti = 1;
+
+/* Nonzero if we want to conserve space in the .o files. We do this
+ by putting uninitialized data and runtime initialized data into
+ .common instead of .data at the expense of not flagging multiple
+ definitions. */
+
+int flag_conserve_space;
+
+/* Nonzero if we want to obey access control semantics. */
+
+int flag_access_control = 1;
+
+/* Nonzero if we want to check the return value of new and avoid calling
+ constructors if it is a null pointer. */
+
+int flag_check_new;
+
+/* Nonzero if we want the new ISO rules for pushing a new scope for `for'
+ initialization variables.
+ 0: Old rules, set by -fno-for-scope.
+ 2: New ISO rules, set by -ffor-scope.
+ 1: Try to implement new ISO rules, but with backup compatibility
+ (and warnings). This is the default, for now. */
+
+int flag_new_for_scope = 1;
+
+/* Nonzero if we want to emit defined symbols with common-like linkage as
+ weak symbols where possible, in order to conform to C++ semantics.
+ Otherwise, emit them as local symbols. */
+
+int flag_weak = 1;
+
+/* Nonzero to use __cxa_atexit, rather than atexit, to register
+ destructors for local statics and global objects. */
+
+int flag_use_cxa_atexit = DEFAULT_USE_CXA_ATEXIT;
+
+/* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc. */
+
+int flag_vtable_gc;
+
+/* Nonzero means make the default pedwarns warnings instead of errors.
+ The value of this flag is ignored if -pedantic is specified. */
+
+int flag_permissive;
+
+/* Nonzero means to implement standard semantics for exception
+ specifications, calling unexpected if an exception is thrown that
+ doesn't match the specification. Zero means to treat them as
+ assertions and optimize accordingly, but not check them. */
+
+int flag_enforce_eh_specs = 1;
+
+/* The version of the C++ ABI in use. The following values are
+ allowed:
+
+ 0: The version of the ABI believed most conformant with the
+ C++ ABI specification. This ABI may change as bugs are
+ discovered and fixed. Therefore, 0 will not necessarily
+ indicate the same ABI in different versions of G++.
+
+ 1: The version of the ABI first used in G++ 3.2.
+
+ Additional positive integers will be assigned as new versions of
+ the ABI become the default version of the ABI. */
+
+int flag_abi_version = 1;
+
+/* Nonzero means warn about things that will change when compiling
+ with an ABI-compliant compiler. */
+
+int warn_abi = 0;
+
+/* Nonzero means warn about invalid uses of offsetof. */
+
+int warn_invalid_offsetof = 1;
+
+/* Nonzero means warn about implicit declarations. */
+
+int warn_implicit = 1;
+
+/* Nonzero means warn when all ctors or dtors are private, and the class
+ has no friends. */
+
+int warn_ctor_dtor_privacy = 0;
+
+/* Nonzero means warn in function declared in derived class has the
+ same name as a virtual in the base class, but fails to match the
+ type signature of any virtual function in the base class. */
+
+int warn_overloaded_virtual;
+
+/* Nonzero means warn when declaring a class that has a non virtual
+ destructor, when it really ought to have a virtual one. */
+
+int warn_nonvdtor;
+
+/* Nonzero means warn when the compiler will reorder code. */
+
+int warn_reorder;
+
+/* Nonzero means warn when synthesis behavior differs from Cfront's. */
+
+int warn_synth;
+
+/* Nonzero means warn when we convert a pointer to member function
+ into a pointer to (void or function). */
+
+int warn_pmf2ptr = 1;
+
+/* Nonzero means warn about violation of some Effective C++ style rules. */
+
+int warn_ecpp;
+
+/* Nonzero means warn where overload resolution chooses a promotion from
+ unsigned to signed over a conversion to an unsigned of the same size. */
+
+int warn_sign_promo;
+
+/* Nonzero means warn when an old-style cast is used. */
+
+int warn_old_style_cast;
+
+/* Nonzero means warn when non-templatized friend functions are
+ declared within a template */
+
+int warn_nontemplate_friend = 1;
+
+/* Nonzero means complain about deprecated features. */
+
+int warn_deprecated = 1;
+
+/* Maximum template instantiation depth. This limit is rather
+ arbitrary, but it exists to limit the time it takes to notice
+ infinite template instantiations. */
+
+int max_tinst_depth = 500;
+
+
+
/* The elements of `ridpointers' are identifier nodes for the reserved
type names and storage classes. It is indexed by a RID_... value. */
tree *ridpointers;
tree (*make_fname_decl) PARAMS ((tree, int));
-/* If non-NULL, the address of a language-specific function that
- returns 1 for language-specific statement codes. */
-int (*lang_statement_code_p) PARAMS ((enum tree_code));
-
/* If non-NULL, the address of a language-specific function that takes
any action required right before expand_function_end is called. */
void (*lang_expand_function_end) PARAMS ((void));
typedef struct
{
int compstmt_count;
- int line;
- const char *file;
+ location_t locus;
int needs_warning;
tree if_stmt;
} if_elt;
/* Stack pointer. */
static int if_stack_pointer = 0;
-static void cb_register_builtins PARAMS ((cpp_reader *));
-
static tree handle_packed_attribute PARAMS ((tree *, tree, tree, int,
bool *));
static tree handle_nocommon_attribute PARAMS ((tree *, tree, tree, int,
bool *));
static tree handle_visibility_attribute PARAMS ((tree *, tree, tree, int,
bool *));
+static tree handle_tls_model_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree,
tree, int,
bool *));
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));
static bool nonnull_check_p PARAMS ((tree, unsigned HOST_WIDE_INT));
static bool get_nonnull_operand PARAMS ((tree,
unsigned HOST_WIDE_INT *));
-void builtin_define_std PARAMS ((const char *));
-static void builtin_define_with_value PARAMS ((const char *, const char *,
- int));
-static void builtin_define_type_max PARAMS ((const char *, tree, int));
/* Table of machine-independent attributes common to all C-like languages. */
const struct attribute_spec c_common_attribute_table[] =
handle_vector_size_attribute },
{ "visibility", 1, 1, true, false, false,
handle_visibility_attribute },
+ { "tls_model", 1, 1, true, false, false,
+ handle_tls_model_attribute },
{ "nonnull", 0, -1, false, true, true,
handle_nonnull_attribute },
{ "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 }
};
/* Give the specifications for the format attributes, used by C and all
- descendents. */
+ descendants. */
const struct attribute_spec c_common_format_attribute_table[] =
{
/* Record this if statement. */
if_stack[if_stack_pointer].compstmt_count = compstmt_count;
- if_stack[if_stack_pointer].file = input_filename;
- if_stack[if_stack_pointer].line = lineno;
+ if_stack[if_stack_pointer].locus = input_location;
if_stack[if_stack_pointer].needs_warning = 0;
if_stack[if_stack_pointer].if_stmt = if_stmt;
if_stack_pointer++;
{
if_stack_pointer--;
if (if_stack[if_stack_pointer].needs_warning)
- warning_with_file_and_line (if_stack[if_stack_pointer].file,
- if_stack[if_stack_pointer].line,
- "suggest explicit braces to avoid ambiguous `else'");
+ warning ("%Hsuggest explicit braces to avoid ambiguous `else'",
+ &if_stack[if_stack_pointer].locus);
last_expr_type = NULL_TREE;
}
if (body)
{
- /* They were called into existence, so add to statement tree. */
- body = chainon (body,
- TREE_CHAIN (DECL_SAVED_TREE (current_function_decl)));
- body = build_stmt (COMPOUND_STMT, body);
-
- COMPOUND_STMT_NO_SCOPE (body) = 1;
- TREE_CHAIN (DECL_SAVED_TREE (current_function_decl)) = body;
+ /* They were called into existence, so add to statement tree. Add
+ the DECL_STMTs inside the outermost scope. */
+ tree *p = &DECL_SAVED_TREE (current_function_decl);
+ /* Skip the dummy EXPR_STMT and any EH_SPEC_BLOCK. */
+ while (TREE_CODE (*p) != COMPOUND_STMT)
+ p = &TREE_CHAIN (*p);
+ p = &COMPOUND_BODY (*p);
+ if (TREE_CODE (*p) == SCOPE_STMT)
+ p = &TREE_CHAIN (*p);
+
+ body = chainon (body, *p);
+ *p = body;
}
for (ix = 0; fname_vars[ix].decl; ix++)
saved_function_name_decls = stack;
}
-/* Return the text name of the current function, suitable prettified
+/* Return the text name of the current function, suitably prettified
by PRETTY_P. */
const char *
if (!decl)
{
tree saved_last_tree = last_tree;
+ /* If a tree is built here, it would normally have the lineno of
+ the current statement. Later this tree will be moved to the
+ beginning of the function and this line number will be wrong.
+ To avoid this problem set the lineno to 0 here; that prevents
+ it from appearing in the RTL. */
+ int saved_lineno = input_line;
+ input_line = 0;
decl = (*make_fname_decl) (id, fname_vars[ix].pretty);
if (last_tree != saved_last_tree)
saved_function_name_decls);
}
*fname_vars[ix].decl = decl;
+ input_line = saved_lineno;
}
if (!ix && !current_function_decl)
pedwarn_with_decl (decl, "`%s' is not defined outside of function scope");
-
+
return decl;
}
}
}
-/* Try to warn for undefined behaviour in EXPR due to missing sequence
+/* Try to warn for undefined behavior in EXPR due to missing sequence
points. */
static void
return unsignedp ? unsigned_V2DI_type_node : V2DI_type_node;
case V2SImode:
return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
+ case V2HImode:
+ return unsignedp ? unsigned_V2HI_type_node : V2HI_type_node;
case V4HImode:
return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
case V8QImode:
return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
+ case V1DImode:
+ return unsignedp ? unsigned_V1DI_type_node : V1DI_type_node;
case V16SFmode:
return V16SF_type_node;
case V4SFmode:
case ABS_EXPR:
case FLOAT_EXPR:
case FFS_EXPR:
- /* These don't change whether an object is non-zero or zero. */
+ case POPCOUNT_EXPR:
+ /* These don't change whether an object is nonzero or zero. */
return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
case LROTATE_EXPR:
case RROTATE_EXPR:
- /* These don't change whether an object is zero or non-zero, but
+ /* These don't change whether an object is zero or nonzero, but
we can't ignore them if their second arg has side-effects. */
if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
return build (COMPOUND_EXPR, boolean_type_node, TREE_OPERAND (expr, 1),
if (! TYPE_P (t))
return -1;
- /* The C standard guarantess that any object may be accessed via an
+ /* The C standard guarantees that any object may be accessed via an
lvalue that has character type. */
if (t == char_type_node
|| t == signed_char_type_node
TYPE_IS_SIZETYPE means that certain things (like overflow) will
never happen. However, this node should really have type
`size_t', which is just a typedef for an ordinary integer type. */
- value = fold (build1 (NOP_EXPR, c_size_type_node, value));
+ value = fold (build1 (NOP_EXPR, size_type_node, value));
my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)), 20001021);
return value;
else
return c_alignof (TREE_TYPE (expr));
- return fold (build1 (NOP_EXPR, c_size_type_node, t));
+ return fold (build1 (NOP_EXPR, size_type_node, t));
}
\f
/* Handle C and C++ default attributes. */
#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
#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
};
/* `unsigned long' is the standard type for sizeof.
Note that stddef.h uses `unsigned long',
and this must agree, even if long and int are the same size. */
- c_size_type_node =
+ size_type_node =
TREE_TYPE (identifier_global_value (get_identifier (SIZE_TYPE)));
- signed_size_type_node = c_common_signed_type (c_size_type_node);
- set_sizetype (c_size_type_node);
+ signed_size_type_node = c_common_signed_type (size_type_node);
+ set_sizetype (size_type_node);
build_common_tree_nodes_2 (flag_short_double);
= 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));
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]);
#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)
c_init_attributes ();
#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, \
- BOTH_P, FALLBACK_P, NONANSI_P, ATTRS) \
+ BOTH_P, FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT) \
if (NAME) \
{ \
tree decl; \
built_in_attributes[(int) ATTRS]); \
\
built_in_decls[(int) ENUM] = decl; \
+ if (IMPLICIT) \
+ implicit_built_in_decls[(int) ENUM] = decl; \
}
#include "builtins.def"
#undef DEF_BUILTIN
+ (*targetm.init_builtins) ();
+
main_identifier_node = get_identifier ("main");
}
{
tree bdecl = NULL_TREE;
tree decl = NULL_TREE;
+
if (builtin_name != 0)
- {
- bdecl = builtin_function (builtin_name, builtin_type, function_code,
- class, library_name_p ? name : NULL,
- attrs);
- }
+ bdecl = builtin_function (builtin_name, builtin_type, function_code,
+ class, library_name_p ? name : NULL, attrs);
+
if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name)
&& !(nonansi_p && flag_no_nonansi_builtin))
- {
- decl = builtin_function (name, type, function_code, class, NULL,
- attrs);
- if (nonansi_p)
- DECL_BUILT_IN_NONANSI (decl) = 1;
- }
+ decl = builtin_function (name, type, function_code, class, NULL, attrs);
+
return (bdecl != 0 ? bdecl : decl);
}
\f
return NULL_TREE;
}
-/* Returns non-zero if CODE is the code for a statement. */
-
-int
-statement_code_p (code)
- enum tree_code code;
-{
- switch (code)
- {
- case CLEANUP_STMT:
- case EXPR_STMT:
- case COMPOUND_STMT:
- case DECL_STMT:
- case IF_STMT:
- case FOR_STMT:
- case WHILE_STMT:
- case DO_STMT:
- case RETURN_STMT:
- case BREAK_STMT:
- case CONTINUE_STMT:
- case SCOPE_STMT:
- case SWITCH_STMT:
- case GOTO_STMT:
- case LABEL_STMT:
- case ASM_STMT:
- case FILE_STMT:
- case CASE_LABEL:
- return 1;
-
- default:
- if (lang_statement_code_p)
- return (*lang_statement_code_p) (code);
- return 0;
- }
-}
-
/* Walk the statement tree, rooted at *tp. Apply FUNC to all the
sub-trees of *TP in a pre-order traversal. FUNC is called with the
DATA and the address of each sub-tree. If FUNC returns a non-NULL
return NULL_TREE;
/* Skip subtrees below non-statement nodes. */
- if (!statement_code_p (TREE_CODE (*tp)))
+ if (!STATEMENT_CODE_P (TREE_CODE (*tp)))
return NULL_TREE;
/* Call the function. */
/* FUNC may have modified the tree, recheck that we're looking at a
statement node. */
code = TREE_CODE (*tp);
- if (!statement_code_p (code))
+ if (!STATEMENT_CODE_P (code))
return NULL_TREE;
/* Visit the subtrees unless FUNC decided that there was nothing
return case_label;
}
-/* Finish an expression taking the address of LABEL. Returns an
- expression for the address. */
+/* Finish an expression taking the address of LABEL (an
+ IDENTIFIER_NODE). Returns an expression for the address. */
tree
finish_label_address_expr (label)
pedwarn ("ISO C forbids taking the address of a label");
}
+ if (label == error_mark_node)
+ return error_mark_node;
+
label = lookup_label (label);
if (label == NULL_TREE)
result = null_pointer_node;
tree rtl_expr;
rtx result;
bool preserve_result = false;
+ bool return_target = false;
/* Since expand_expr_stmt calls free_temp_slots after every
expression statement, we must call push_temp_slots here.
if (TREE_CODE (last) == SCOPE_STMT
&& TREE_CODE (expr) == EXPR_STMT)
{
- TREE_ADDRESSABLE (expr) = 1;
- preserve_result = true;
+ if (target && TREE_CODE (EXPR_STMT_EXPR (expr)) == VAR_DECL
+ && DECL_RTL_IF_SET (EXPR_STMT_EXPR (expr)) == target)
+ /* If the last expression is a variable whose RTL is the
+ same as our target, just return the target; if it
+ isn't valid expanding the decl would produce different
+ RTL, and store_expr would try to do a copy. */
+ return_target = true;
+ else
+ {
+ /* Otherwise, note that we want the value from the last
+ expression. */
+ TREE_ADDRESSABLE (expr) = 1;
+ preserve_result = true;
+ }
}
}
expand_end_stmt_expr (rtl_expr);
result = expand_expr (rtl_expr, target, tmode, modifier);
- if (preserve_result && GET_CODE (result) == MEM)
+ if (return_target)
+ result = target;
+ else if (preserve_result && GET_CODE (result) == MEM)
{
if (GET_MODE (result) != BLKmode)
result = copy_to_reg (result);
}
/* For any statement, we must follow the statement-chain. */
- if (statement_code_p (TREE_CODE (exp)) && TREE_CHAIN (exp))
+ if (STATEMENT_CODE_P (TREE_CODE (exp)) && TREE_CHAIN (exp))
return safe_from_p (target, TREE_CHAIN (exp), /*top_p=*/0);
/* Assume everything else is safe. */
int unlocked;
{
tree fn_putchar = unlocked ?
- built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED] : built_in_decls[BUILT_IN_PUTCHAR];
+ implicit_built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED] : implicit_built_in_decls[BUILT_IN_PUTCHAR];
tree fn_puts = unlocked ?
- built_in_decls[BUILT_IN_PUTS_UNLOCKED] : built_in_decls[BUILT_IN_PUTS];
+ implicit_built_in_decls[BUILT_IN_PUTS_UNLOCKED] : implicit_built_in_decls[BUILT_IN_PUTS];
tree fn, format_arg, stripped_string;
/* If the return value is used, or the replacement _DECL isn't
int unlocked;
{
tree fn_fputc = unlocked ?
- built_in_decls[BUILT_IN_FPUTC_UNLOCKED] : built_in_decls[BUILT_IN_FPUTC];
+ implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED] : implicit_built_in_decls[BUILT_IN_FPUTC];
tree fn_fputs = unlocked ?
- built_in_decls[BUILT_IN_FPUTS_UNLOCKED] : built_in_decls[BUILT_IN_FPUTS];
+ implicit_built_in_decls[BUILT_IN_FPUTS_UNLOCKED] : implicit_built_in_decls[BUILT_IN_FPUTS];
tree fn, format_arg, stripped_string;
/* If the return value is used, or the replacement _DECL isn't
return val;
}
\f
-/* Common initialization before parsing options. */
+/* Built-in macros for stddef.h, that require macros defined in this
+ file. */
void
-c_common_init_options (lang)
- enum c_language_kind lang;
-{
- c_language = lang;
- parse_in = cpp_create_reader (lang == clk_c || lang == clk_objective_c
- ? CLK_GNUC89 : CLK_GNUCXX);
- if (lang == clk_objective_c)
- cpp_get_options (parse_in)->objc = 1;
-
- /* Mark as "unspecified" (see c_common_post_options). */
- flag_bounds_check = -1;
-}
-
-/* Post-switch processing. */
-bool
-c_common_post_options ()
-{
- cpp_post_options (parse_in);
-
- flag_inline_trees = 1;
-
- /* Use tree inlining if possible. Function instrumentation is only
- done in the RTL level, so we disable tree inlining. */
- if (! flag_instrument_function_entry_exit)
- {
- if (!flag_no_inline)
- flag_no_inline = 1;
- if (flag_inline_functions)
- {
- flag_inline_trees = 2;
- flag_inline_functions = 0;
- }
- }
-
- /* If still "unspecified", make it match -fbounded-pointers. */
- if (flag_bounds_check == -1)
- flag_bounds_check = flag_bounded_pointers;
-
- /* Special format checking options don't work without -Wformat; warn if
- they are used. */
- if (warn_format_y2k && !warn_format)
- warning ("-Wformat-y2k ignored without -Wformat");
- if (warn_format_extra_args && !warn_format)
- warning ("-Wformat-extra-args ignored without -Wformat");
- if (warn_format_zero_length && !warn_format)
- warning ("-Wformat-zero-length ignored without -Wformat");
- if (warn_format_nonliteral && !warn_format)
- warning ("-Wformat-nonliteral ignored without -Wformat");
- if (warn_format_security && !warn_format)
- warning ("-Wformat-security ignored without -Wformat");
- if (warn_missing_format_attribute && !warn_format)
- warning ("-Wmissing-format-attribute ignored without -Wformat");
-
- /* If an error has occurred in cpplib, note it so we fail
- immediately. */
- errorcount += cpp_errors (parse_in);
-
- return flag_preprocess_only;
-}
-
-/* Hook that registers front end and target-specific built-ins. */
-static void
-cb_register_builtins (pfile)
- cpp_reader *pfile;
+c_stddef_cpp_builtins()
{
- /* -undef turns off target-specific built-ins. */
- if (flag_undef)
- return;
-
- if (c_language == clk_cplusplus)
- {
- if (SUPPORTS_ONE_ONLY)
- cpp_define (pfile, "__GXX_WEAK__=1");
- else
- cpp_define (pfile, "__GXX_WEAK__=0");
- }
-
- /* libgcc needs to know this. */
- if (USING_SJLJ_EXCEPTIONS)
- cpp_define (pfile, "__USING_SJLJ_EXCEPTIONS__");
-
- /* stddef.h needs to know these. */
builtin_define_with_value ("__SIZE_TYPE__", SIZE_TYPE, 0);
builtin_define_with_value ("__PTRDIFF_TYPE__", PTRDIFF_TYPE, 0);
builtin_define_with_value ("__WCHAR_TYPE__", MODIFIED_WCHAR_TYPE, 0);
builtin_define_with_value ("__WINT_TYPE__", WINT_TYPE, 0);
-
- /* limits.h needs to know these. */
- builtin_define_type_max ("__SCHAR_MAX__", signed_char_type_node, 0);
- builtin_define_type_max ("__SHRT_MAX__", short_integer_type_node, 0);
- builtin_define_type_max ("__INT_MAX__", integer_type_node, 0);
- builtin_define_type_max ("__LONG_MAX__", long_integer_type_node, 1);
- builtin_define_type_max ("__LONG_LONG_MAX__", long_long_integer_type_node, 2);
-
- {
- char buf[8];
- sprintf (buf, "%d", (int) TYPE_PRECISION (signed_char_type_node));
- builtin_define_with_value ("__CHAR_BIT__", buf, 0);
- }
-
- /* For use in assembly language. */
- builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0);
- builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0);
-
- /* Misc. */
- builtin_define_with_value ("__VERSION__", version_string, 1);
-
- /* Other target-independent built-ins determined by command-line
- options. */
- if (optimize_size)
- cpp_define (pfile, "__OPTIMIZE_SIZE__");
- if (optimize)
- cpp_define (pfile, "__OPTIMIZE__");
-
- if (flag_hosted)
- cpp_define (pfile, "__STDC_HOSTED__=1");
- else
- cpp_define (pfile, "__STDC_HOSTED__=0");
-
- if (fast_math_flags_set_p ())
- cpp_define (pfile, "__FAST_MATH__");
- if (flag_no_inline)
- cpp_define (pfile, "__NO_INLINE__");
- if (flag_signaling_nans)
- cpp_define (pfile, "__SUPPORT_SNAN__");
- if (flag_finite_math_only)
- cpp_define (pfile, "__FINITE_MATH_ONLY__");
-
- if (flag_iso)
- cpp_define (pfile, "__STRICT_ANSI__");
-
- if (!flag_signed_char)
- cpp_define (pfile, "__CHAR_UNSIGNED__");
-
- /* A straightforward target hook doesn't work, because of problems
- linking that hook's body when part of non-C front ends. */
-# define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM)
-# define builtin_define(TXT) cpp_define (pfile, TXT)
-# define builtin_assert(TXT) cpp_assert (pfile, TXT)
- TARGET_CPU_CPP_BUILTINS ();
- TARGET_OS_CPP_BUILTINS ();
-}
-
-/* Pass an object-like macro. If it doesn't lie in the user's
- namespace, defines it unconditionally. Otherwise define a version
- with two leading underscores, and another version with two leading
- and trailing underscores, and define the original only if an ISO
- standard was not nominated.
-
- e.g. passing "unix" defines "__unix", "__unix__" and possibly
- "unix". Passing "_mips" defines "__mips", "__mips__" and possibly
- "_mips". */
-void
-builtin_define_std (macro)
- const char *macro;
-{
- size_t len = strlen (macro);
- char *buff = alloca (len + 5);
- char *p = buff + 2;
- char *q = p + len;
-
- /* prepend __ (or maybe just _) if in user's namespace. */
- memcpy (p, macro, len + 1);
- if (!( *p == '_' && (p[1] == '_' || ISUPPER (p[1]))))
- {
- if (*p != '_')
- *--p = '_';
- if (p[1] != '_')
- *--p = '_';
- }
- cpp_define (parse_in, p);
-
- /* If it was in user's namespace... */
- if (p != buff + 2)
- {
- /* Define the macro with leading and following __. */
- if (q[-1] != '_')
- *q++ = '_';
- if (q[-2] != '_')
- *q++ = '_';
- *q = '\0';
- cpp_define (parse_in, p);
-
- /* Finally, define the original macro if permitted. */
- if (!flag_iso)
- cpp_define (parse_in, macro);
- }
-}
-
-/* Pass an object-like macro and a value to define it to. The third
- parameter says whether or not to turn the value into a string
- constant. */
-static void
-builtin_define_with_value (macro, expansion, is_str)
- const char *macro;
- const char *expansion;
- int is_str;
-{
- char *buf;
- size_t mlen = strlen (macro);
- size_t elen = strlen (expansion);
- size_t extra = 2; /* space for an = and a NUL */
-
- if (is_str)
- extra += 2; /* space for two quote marks */
-
- buf = alloca (mlen + elen + extra);
- if (is_str)
- sprintf (buf, "%s=\"%s\"", macro, expansion);
- else
- sprintf (buf, "%s=%s", macro, expansion);
-
- cpp_define (parse_in, buf);
-}
-
-/* Define MAX for TYPE based on the precision of the type, which is assumed
- to be signed. IS_LONG is 1 for type "long" and 2 for "long long". */
-
-static void
-builtin_define_type_max (macro, type, is_long)
- const char *macro;
- tree type;
- int is_long;
-{
- const char *value;
- char *buf;
- size_t mlen, vlen, extra;
-
- /* Pre-rendering the values mean we don't have to futz with printing a
- multi-word decimal value. There are also a very limited number of
- precisions that we support, so it's really a waste of time. */
- switch (TYPE_PRECISION (type))
- {
- case 8:
- value = "127";
- break;
- case 16:
- value = "32767";
- break;
- case 32:
- value = "2147483647";
- break;
- case 64:
- value = "9223372036854775807";
- break;
- case 128:
- value = "170141183460469231731687303715884105727";
- break;
- default:
- abort ();
- }
-
- mlen = strlen (macro);
- vlen = strlen (value);
- extra = 2 + is_long;
- buf = alloca (mlen + vlen + extra);
-
- sprintf (buf, "%s=%s%s", macro, value,
- (is_long == 1 ? "L" : is_long == 2 ? "LL" : ""));
-
- cpp_define (parse_in, buf);
-}
-
-/* Front end initialization common to C, ObjC and C++. */
-const char *
-c_common_init (filename)
- const char *filename;
-{
- cpp_options *options = cpp_get_options (parse_in);
-
- /* Set up preprocessor arithmetic. Must be done after call to
- c_common_nodes_and_builtins for wchar_type_node to be good. */
- options->precision = TYPE_PRECISION (intmax_type_node);
- options->char_precision = TYPE_PRECISION (char_type_node);
- options->int_precision = TYPE_PRECISION (integer_type_node);
- options->wchar_precision = TYPE_PRECISION (wchar_type_node);
- options->unsigned_wchar = TREE_UNSIGNED (wchar_type_node);
- options->unsigned_char = !flag_signed_char;
- options->warn_multichar = warn_multichar;
- options->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS;
-
- /* We want -Wno-long-long to override -pedantic -std=non-c99
- whatever the ordering. */
- options->warn_long_long = warn_long_long && !flag_isoc99 && pedantic;
-
- /* Register preprocessor built-ins before calls to
- cpp_main_file. */
- cpp_get_callbacks (parse_in)->register_builtins = cb_register_builtins;
-
- /* NULL is passed up to toplev.c and we exit quickly. */
- if (flag_preprocess_only)
- {
- cpp_preprocess_file (parse_in);
- return NULL;
- }
-
- /* Do this before initializing pragmas, as then cpplib's hash table
- has been set up. */
- filename = init_c_lex (filename);
-
- init_pragma ();
-
- if (!c_attrs_initialized)
- c_init_attributes ();
-
- return filename;
-}
-
-/* Common finish hook for the C, ObjC and C++ front ends. */
-void
-c_common_finish ()
-{
- cpp_finish (parse_in);
-
- /* For performance, avoid tearing down cpplib's internal structures.
- Call cpp_errors () instead of cpp_destroy (). */
- errorcount += cpp_errors (parse_in);
}
static void
#undef DEF_FN_ATTR
}
-/* Output a -Wshadow warning MSGID about NAME, an IDENTIFIER_NODE, and
- additionally give the location of the previous declaration DECL. */
+/* Output a -Wshadow warning MSGCODE about NAME, and give the location
+ of the previous declaration DECL. */
void
-shadow_warning (msgid, name, decl)
- const char *msgid;
- tree name, decl;
+shadow_warning (msgcode, name, decl)
+ enum sw_kind msgcode;
+ const char *name;
+ tree decl;
{
- warning ("declaration of `%s' shadows %s", IDENTIFIER_POINTER (name), msgid);
- warning_with_file_and_line (DECL_SOURCE_FILE (decl),
- DECL_SOURCE_LINE (decl),
- "shadowed declaration is here");
+ static const char *const msgs[] = {
+ /* SW_PARAM */ N_("declaration of \"%s\" shadows a parameter"),
+ /* SW_LOCAL */ N_("declaration of \"%s\" shadows a previous local"),
+ /* SW_GLOBAL */ N_("declaration of \"%s\" shadows a global declaration")
+ };
+
+ warning (msgs[msgcode], name);
+ warning ("%Hshadowed declaration is here", &DECL_SOURCE_LOCATION (decl));
}
/* Attribute handlers common to C front ends. */
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));
int len = strlen (p);
enum machine_mode mode = VOIDmode;
tree typefm;
+ tree ptr_type;
if (len > 4 && p[0] == '_' && p[1] == '_'
&& p[len - 1] == '_' && p[len - 2] == '_')
else if (0 == (typefm = (*lang_hooks.types.type_for_mode)
(mode, TREE_UNSIGNED (type))))
error ("no data type for mode `%s'", p);
+ else if ((TREE_CODE (type) == POINTER_TYPE
+ || TREE_CODE (type) == REFERENCE_TYPE)
+ && !(*targetm.valid_pointer_mode) (mode))
+ error ("invalid pointer mode `%s'", p);
else
{
/* If this is a vector, make sure we either have hardware
return NULL_TREE;
}
+ if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ ptr_type = build_pointer_type_for_mode (TREE_TYPE (type),
+ mode);
+ *node = ptr_type;
+ }
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ ptr_type = build_reference_type_for_mode (TREE_TYPE (type),
+ mode);
+ *node = ptr_type;
+ }
+ else
*node = typefm;
/* No need to layout the type here. The caller should do this. */
}
}
if (strcmp (TREE_STRING_POINTER (id), "hidden")
&& strcmp (TREE_STRING_POINTER (id), "protected")
- && strcmp (TREE_STRING_POINTER (id), "internal"))
+ && strcmp (TREE_STRING_POINTER (id), "internal")
+ && strcmp (TREE_STRING_POINTER (id), "default"))
{
- error ("visibility arg must be one of \"hidden\", \"protected\" or \"internal\"");
+ error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle an "tls_model" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_tls_model_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;
+
+ if (! DECL_THREAD_LOCAL (decl))
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ {
+ tree id;
+
+ id = TREE_VALUE (args);
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error ("tls_model arg not a string");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ if (strcmp (TREE_STRING_POINTER (id), "local-exec")
+ && strcmp (TREE_STRING_POINTER (id), "initial-exec")
+ && strcmp (TREE_STRING_POINTER (id), "local-dynamic")
+ && strcmp (TREE_STRING_POINTER (id), "global-dynamic"))
+ {
+ error ("tls_model arg must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
*no_add_attrs = true;
return NULL_TREE;
}
The normal mechanism to prevent duplicates is to use type_hash_canon, but
since we want to distinguish types that are essentially identical (except
for their debug representation), we use a local list here. */
-static tree vector_type_node_list = 0;
+static GTY(()) tree vector_type_node_list = 0;
/* Handle a "vector_size" attribute; arguments as in
struct attribute_spec.handler. */
unsigned HOST_WIDE_INT attr_arg_num;
/* If no arguments are specified, all pointer arguments should be
- non-null. Veryify a full prototype is given so that the arguments
+ non-null. Verify a full prototype is given so that the arguments
will have the correct types when we actually check them later. */
if (! args)
{
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;
+}
\f
/* Check for valid arguments being passed to a function. */
void