Deleted Added
full compact
24a25
> #include "real.h"
33d33
< #include "tree-inline.h"
37d36
< #include "c-lex.h"
40c39,42
< cpp_reader *parse_in; /* Declared in c-lex.h. */
---
> #include "langhooks.h"
> #include "except.h" /* For USING_SJLJ_EXCEPTIONS. */
> #include "tree-inline.h"
> #include "c-tree.h"
42,43c44
< #undef WCHAR_TYPE_SIZE
< #define WCHAR_TYPE_SIZE TYPE_PRECISION (wchar_type_node)
---
> cpp_reader *parse_in; /* Declared in c-pragma.h. */
58a60,63
> /* WCHAR_TYPE gets overridden by -fshort-wchar. */
> #define MODIFIED_WCHAR_TYPE \
> (flag_short_wchar ? "short unsigned int" : WCHAR_TYPE)
>
82a88,91
> #ifndef REGISTER_PREFIX
> #define REGISTER_PREFIX ""
> #endif
>
182a192,207
> /* Switches common to the C front ends. */
>
> /* Nonzero if prepreprocessing only. */
> int flag_preprocess_only;
>
> /* 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;
>
199a225,398
> /* Nonzero means allow Microsoft extensions without warnings or errors. */
> int flag_ms_extensions;
>
> /* 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 `$' can be in an identifier. */
>
> #ifndef DOLLARS_IN_IDENTIFIERS
> #define DOLLARS_IN_IDENTIFIERS 1
> #endif
> int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
>
> /* 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. */
>
> int warn_sign_compare;
>
> /* 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;
>
> /* 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;
>
206a406,653
> /* 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 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 = 1;
>
> /* 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;
>
>
>
269a717,879
> 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_common_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_noreturn_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_noinline_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_always_inline_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_used_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_unused_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_const_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_transparent_union_attribute PARAMS ((tree *, tree, tree,
> int, bool *));
> static tree handle_constructor_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_destructor_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_mode_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_section_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_aligned_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_weak_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_alias_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 *));
> static tree handle_malloc_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_pure_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_deprecated_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> static tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int,
> bool *));
> 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));
> static void check_nonnull_arg PARAMS ((void *, tree,
> unsigned HOST_WIDE_INT));
> 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_with_int_value PARAMS ((const char *,
> HOST_WIDE_INT));
> static void builtin_define_with_hex_fp_value PARAMS ((const char *, tree,
> int, const char *,
> const char *));
> static void builtin_define_type_max PARAMS ((const char *, tree, int));
> static void builtin_define_type_precision PARAMS ((const char *, tree));
> static void builtin_define_float_constants PARAMS ((const char *,
> const char *, tree));
>
> /* Table of machine-independent attributes common to all C-like languages. */
> const struct attribute_spec c_common_attribute_table[] =
> {
> /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
> { "packed", 0, 0, false, false, false,
> handle_packed_attribute },
> { "nocommon", 0, 0, true, false, false,
> handle_nocommon_attribute },
> { "common", 0, 0, true, false, false,
> handle_common_attribute },
> /* FIXME: logically, noreturn attributes should be listed as
> "false, true, true" and apply to function types. But implementing this
> would require all the places in the compiler that use TREE_THIS_VOLATILE
> on a decl to identify non-returning functions to be located and fixed
> to check the function type instead. */
> { "noreturn", 0, 0, true, false, false,
> handle_noreturn_attribute },
> { "volatile", 0, 0, true, false, false,
> handle_noreturn_attribute },
> { "noinline", 0, 0, true, false, false,
> handle_noinline_attribute },
> { "always_inline", 0, 0, true, false, false,
> handle_always_inline_attribute },
> { "used", 0, 0, true, false, false,
> handle_used_attribute },
> { "unused", 0, 0, false, false, false,
> handle_unused_attribute },
> /* The same comments as for noreturn attributes apply to const ones. */
> { "const", 0, 0, true, false, false,
> handle_const_attribute },
> { "transparent_union", 0, 0, false, false, false,
> handle_transparent_union_attribute },
> { "constructor", 0, 0, true, false, false,
> handle_constructor_attribute },
> { "destructor", 0, 0, true, false, false,
> handle_destructor_attribute },
> { "mode", 1, 1, false, true, false,
> handle_mode_attribute },
> { "section", 1, 1, true, false, false,
> handle_section_attribute },
> { "aligned", 0, 1, false, false, false,
> handle_aligned_attribute },
> { "weak", 0, 0, true, false, false,
> handle_weak_attribute },
> { "alias", 1, 1, true, false, false,
> handle_alias_attribute },
> { "no_instrument_function", 0, 0, true, false, false,
> handle_no_instrument_function_attribute },
> { "malloc", 0, 0, true, false, false,
> handle_malloc_attribute },
> { "no_stack_limit", 0, 0, true, false, false,
> handle_no_limit_stack_attribute },
> { "pure", 0, 0, true, false, false,
> handle_pure_attribute },
> { "deprecated", 0, 0, false, false, false,
> handle_deprecated_attribute },
> { "vector_size", 1, 1, false, true, false,
> 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. */
>
> const struct attribute_spec c_common_format_attribute_table[] =
> {
> /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
> { "format", 3, 3, false, true, true,
> handle_format_attribute },
> { "format_arg", 1, 1, false, true, true,
> handle_format_arg_attribute },
> { NULL, 0, 0, false, false, false, NULL }
> };
>
486c1096
< ? (*decl_printable_name) (current_function_decl, 2)
---
> ? (*lang_hooks.decl_printable_name) (current_function_decl, 2)
532a1143,1149
> /* 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 = lineno;
> lineno = 0;
547a1165
> lineno = saved_lineno;
555,557c1173
< /* Given a chain of STRING_CST nodes,
< concatenate them into one STRING_CST
< and give it a suitable array-of-chars data type. */
---
> /* Given a STRING_CST, give it a suitable array-of-chars data type. */
559a1176,1219
> fix_string_type (value)
> tree value;
> {
> const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
> const int wide_flag = TREE_TYPE (value) == wchar_array_type_node;
> const int nchars_max = flag_isoc99 ? 4095 : 509;
> int length = TREE_STRING_LENGTH (value);
> int nchars;
>
> /* Compute the number of elements, for the array type. */
> nchars = wide_flag ? length / wchar_bytes : length;
>
> if (pedantic && nchars - 1 > nchars_max && c_language == clk_c)
> pedwarn ("string length `%d' is greater than the length `%d' ISO C%d compilers are required to support",
> nchars - 1, nchars_max, flag_isoc99 ? 99 : 89);
>
> /* Create the array type for the string constant.
> -Wwrite-strings says make the string constant an array of const char
> so that copying it to a non-const pointer will get a warning.
> For C++, this is the standard behavior. */
> if (flag_const_strings && ! flag_writable_strings)
> {
> tree elements
> = build_type_variant (wide_flag ? wchar_type_node : char_type_node,
> 1, 0);
> TREE_TYPE (value)
> = build_array_type (elements,
> build_index_type (build_int_2 (nchars - 1, 0)));
> }
> else
> TREE_TYPE (value)
> = build_array_type (wide_flag ? wchar_type_node : char_type_node,
> build_index_type (build_int_2 (nchars - 1, 0)));
>
> TREE_CONSTANT (value) = 1;
> TREE_READONLY (value) = ! flag_writable_strings;
> TREE_STATIC (value) = 1;
> return value;
> }
>
> /* Given a VARRAY of STRING_CST nodes, concatenate them into one
> STRING_CST. */
>
> tree
561c1221
< tree strings;
---
> varray_type strings;
562a1223,1224
> const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
> const int nstrings = VARRAY_ACTIVE_SIZE (strings);
567,569c1229,1230
< int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
< int nchars;
< const int nchars_max = flag_isoc99 ? 4095 : 509;
---
> int i;
> char *p, *q;
571c1232,1234
< if (TREE_CHAIN (strings))
---
> /* Don't include the \0 at the end of each substring. Count wide
> strings and ordinary strings separately. */
> for (i = 0; i < nstrings; ++i)
573,574c1236
< /* More than one in the chain, so concatenate. */
< char *p, *q;
---
> t = VARRAY_TREE (strings, i);
576,579c1238
< /* Don't include the \0 at the end of each substring,
< except for the last one.
< Count wide strings and ordinary strings separately. */
< for (t = strings; t; t = TREE_CHAIN (t))
---
> if (TREE_TYPE (t) == wchar_array_type_node)
581,591c1240,1241
< if (TREE_TYPE (t) == wchar_array_type_node)
< {
< wide_length += (TREE_STRING_LENGTH (t) - wchar_bytes);
< wide_flag = 1;
< }
< else
< {
< length += (TREE_STRING_LENGTH (t) - 1);
< if (C_ARTIFICIAL_STRING_P (t) && !in_system_header)
< warning ("concatenation of string literals with __FUNCTION__ is deprecated");
< }
---
> wide_length += TREE_STRING_LENGTH (t) - wchar_bytes;
> wide_flag = 1;
592a1243,1249
> else
> {
> length += (TREE_STRING_LENGTH (t) - 1);
> if (C_ARTIFICIAL_STRING_P (t) && !in_system_header)
> warning ("concatenation of string literals with __FUNCTION__ is deprecated");
> }
> }
594,597c1251,1254
< /* If anything is wide, the non-wides will be converted,
< which makes them take more space. */
< if (wide_flag)
< length = length * wchar_bytes + wide_length;
---
> /* If anything is wide, the non-wides will be converted,
> which makes them take more space. */
> if (wide_flag)
> length = length * wchar_bytes + wide_length;
599c1256
< p = xmalloc (length);
---
> p = xmalloc (length);
601,603c1258,1260
< /* Copy the individual strings into the new combined string.
< If the combined string is wide, convert the chars to ints
< for any individual strings that are not wide. */
---
> /* Copy the individual strings into the new combined string.
> If the combined string is wide, convert the chars to ints
> for any individual strings that are not wide. */
605,606c1262,1270
< q = p;
< for (t = strings; t; t = TREE_CHAIN (t))
---
> q = p;
> for (i = 0; i < nstrings; ++i)
> {
> int len, this_wide;
>
> t = VARRAY_TREE (strings, i);
> this_wide = TREE_TYPE (t) == wchar_array_type_node;
> len = TREE_STRING_LENGTH (t) - (this_wide ? wchar_bytes : 1);
> if (this_wide == wide_flag)
608,611c1272,1281
< int len = (TREE_STRING_LENGTH (t)
< - ((TREE_TYPE (t) == wchar_array_type_node)
< ? wchar_bytes : 1));
< if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)
---
> memcpy (q, TREE_STRING_POINTER (t), len);
> q += len;
> }
> else
> {
> const int nzeros = (TYPE_PRECISION (wchar_type_node)
> / BITS_PER_UNIT) - 1;
> int j, k;
>
> if (BYTES_BIG_ENDIAN)
613,614c1283,1288
< memcpy (q, TREE_STRING_POINTER (t), len);
< q += len;
---
> for (k = 0; k < len; k++)
> {
> for (j = 0; j < nzeros; j++)
> *q++ = 0;
> *q++ = TREE_STRING_POINTER (t)[k];
> }
618,619c1292
< int i, j;
< for (i = 0; i < len; i++)
---
> for (k = 0; k < len; k++)
621,632c1294,1296
< if (BYTES_BIG_ENDIAN)
< {
< for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
< *q++ = 0;
< *q++ = TREE_STRING_POINTER (t)[i];
< }
< else
< {
< *q++ = TREE_STRING_POINTER (t)[i];
< for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
< *q++ = 0;
< }
---
> *q++ = TREE_STRING_POINTER (t)[k];
> for (j = 0; j < nzeros; j++)
> *q++ = 0;
636,646d1299
< if (wide_flag)
< {
< int i;
< for (i = 0; i < wchar_bytes; i++)
< *q++ = 0;
< }
< else
< *q = 0;
<
< value = build_string (length, p);
< free (p);
648c1301,1303
< else
---
>
> /* Nul terminate the string. */
> if (wide_flag)
650,653c1305,1306
< value = strings;
< length = TREE_STRING_LENGTH (value);
< if (TREE_TYPE (value) == wchar_array_type_node)
< wide_flag = 1;
---
> for (i = 0; i < wchar_bytes; i++)
> *q++ = 0;
654a1308,1309
> else
> *q = 0;
656,657c1311,1312
< /* Compute the number of elements, for the array type. */
< nchars = wide_flag ? length / wchar_bytes : length;
---
> value = build_string (length, p);
> free (p);
659,676c1314,1315
< if (pedantic && nchars - 1 > nchars_max && c_language == clk_c)
< pedwarn ("string length `%d' is greater than the length `%d' ISO C%d compilers are required to support",
< nchars - 1, nchars_max, flag_isoc99 ? 99 : 89);
<
< /* Create the array type for the string constant.
< -Wwrite-strings says make the string constant an array of const char
< so that copying it to a non-const pointer will get a warning.
< For C++, this is the standard behavior. */
< if (flag_const_strings
< && (! flag_traditional && ! flag_writable_strings))
< {
< tree elements
< = build_type_variant (wide_flag ? wchar_type_node : char_type_node,
< 1, 0);
< TREE_TYPE (value)
< = build_array_type (elements,
< build_index_type (build_int_2 (nchars - 1, 0)));
< }
---
> if (wide_flag)
> TREE_TYPE (value) = wchar_array_type_node;
678,680c1317
< TREE_TYPE (value)
< = build_array_type (wide_flag ? wchar_type_node : char_type_node,
< build_index_type (build_int_2 (nchars - 1, 0)));
---
> TREE_TYPE (value) = char_array_type_node;
682,684d1318
< TREE_CONSTANT (value) = 1;
< TREE_READONLY (value) = ! flag_writable_strings;
< TREE_STATIC (value) = 1;
757a1392,1393
> tree type = TREE_TYPE (result);
>
759,760c1395,1396
< && TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE
< && TREE_UNSIGNED (TREE_TYPE (result))
---
> && TREE_CODE (type) == INTEGER_TYPE
> && TREE_UNSIGNED (type)
762c1398
< && !int_fits_type_p (operand, TREE_TYPE (result)))
---
> && !int_fits_type_p (operand, type))
764c1400
< if (!int_fits_type_p (operand, signed_type (TREE_TYPE (result))))
---
> if (!int_fits_type_p (operand, c_common_signed_type (type)))
813c1449,1450
< || ! constant_fits_type_p (expr, unsigned_type (type)))
---
> || ! constant_fits_type_p (expr,
> c_common_unsigned_type (type)))
1215c1852
< /* Try to warn for undefined behaviour in EXPR due to missing sequence
---
> /* Try to warn for undefined behavior in EXPR due to missing sequence
1303c1940
< type_for_size (bits, unsignedp)
---
> c_common_type_for_size (bits, unsignedp)
1347c1984
< type_for_mode (mode, unsignedp)
---
> c_common_type_for_mode (mode, unsignedp)
1402,1403c2039
< #ifdef VECTOR_MODE_SUPPORTED_P
< if (VECTOR_MODE_SUPPORTED_P (mode))
---
> switch (mode)
1405,1427c2041,2068
< switch (mode)
< {
< case V16QImode:
< return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
< case V8HImode:
< return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
< case V4SImode:
< return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
< case V2SImode:
< return unsignedp ? unsigned_V2SI_type_node : V2SI_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 V16SFmode:
< return V16SF_type_node;
< case V4SFmode:
< return V4SF_type_node;
< case V2SFmode:
< return V2SF_type_node;
< default:
< break;
< }
---
> case V16QImode:
> return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
> case V8HImode:
> return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
> case V4SImode:
> return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
> case V2DImode:
> 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:
> return V4SF_type_node;
> case V2SFmode:
> return V2SF_type_node;
> case V2DFmode:
> return V2DF_type_node;
> default:
> break;
1429d2069
< #endif
1436c2076
< unsigned_type (type)
---
> c_common_unsigned_type (type)
1465c2105
< return signed_or_unsigned_type (1, type);
---
> return c_common_signed_or_unsigned_type (1, type);
1471c2111
< signed_type (type)
---
> c_common_signed_type (type)
1500c2140
< return signed_or_unsigned_type (0, type);
---
> return c_common_signed_or_unsigned_type (0, type);
1507c2147
< signed_or_unsigned_type (unsignedp, type)
---
> c_common_signed_or_unsigned_type (unsignedp, type)
1575,1576c2215,2217
< /* Print an error message for invalid operands to arith operation CODE.
< NOP_EXPR is used as a special case (see truthvalue_conversion). */
---
> /* Print an error message for invalid operands to arith operation
> CODE. NOP_EXPR is used as a special case (see
> c_common_truthvalue_conversion). */
1756c2397,2398
< type = signed_or_unsigned_type (unsignedp0, TREE_TYPE (primop0));
---
> type = c_common_signed_or_unsigned_type (unsignedp0,
> TREE_TYPE (primop0));
1762c2404
< type = type_for_size (TYPE_PRECISION (type), unsignedp0);
---
> type = c_common_type_for_size (TYPE_PRECISION (type), unsignedp0);
1768c2410
< *restype_ptr = signed_type (*restype_ptr);
---
> *restype_ptr = c_common_signed_type (*restype_ptr);
1865c2507
< type = unsigned_type (type);
---
> type = c_common_unsigned_type (type);
1868c2510
< if (!max_gt && !unsignedp0 && TREE_CODE (primop0) != INTEGER_CST)
---
> if (TREE_CODE (primop0) != INTEGER_CST)
1870,1871d2511
< /* This is the case of (char)x >?< 0x80, which people used to use
< expecting old C compilers to change the 0x80 into -0x80. */
1878,1886d2517
< if (!min_lt && unsignedp0 && TREE_CODE (primop0) != INTEGER_CST)
< {
< /* This is the case of (unsigned char)x >?< -1 or < 0. */
< if (val == boolean_false_node)
< warning ("comparison is always false due to limited range of data type");
< if (val == boolean_true_node)
< warning ("comparison is always true due to limited range of data type");
< }
<
1917,1919c2548,2550
< type = signed_or_unsigned_type (unsignedp0
< || TREE_UNSIGNED (*restype_ptr),
< type);
---
> type = c_common_signed_or_unsigned_type (unsignedp0
> || TREE_UNSIGNED (*restype_ptr),
> type);
1922,1925c2553,2560
< primop0 = convert (signed_or_unsigned_type (unsignedp0, TREE_TYPE (primop0)),
< primop0);
< primop1 = convert (signed_or_unsigned_type (unsignedp1, TREE_TYPE (primop1)),
< primop1);
---
> primop0
> = convert (c_common_signed_or_unsigned_type (unsignedp0,
> TREE_TYPE (primop0)),
> primop0);
> primop1
> = convert (c_common_signed_or_unsigned_type (unsignedp1,
> TREE_TYPE (primop1)),
> primop1);
1948c2583
< && ! TREE_OVERFLOW (convert (signed_type (type),
---
> && ! TREE_OVERFLOW (convert (c_common_signed_type (type),
1957c2592
< && ! TREE_OVERFLOW (convert (signed_type (type),
---
> && ! TREE_OVERFLOW (convert (c_common_signed_type (type),
2066,2067c2701,2702
< intop = convert (type_for_size (TYPE_PRECISION (sizetype),
< TREE_UNSIGNED (sizetype)), intop);
---
> intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype),
> TREE_UNSIGNED (sizetype)), intop);
2099c2734
< truthvalue_conversion (expr)
---
> c_common_truthvalue_conversion (expr)
2165,2166c2800,2801
< truthvalue_conversion (TREE_OPERAND (expr, 0)),
< truthvalue_conversion (TREE_OPERAND (expr, 1)),
---
> c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
> c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
2173,2174c2808,2809
< /* These don't change whether an object is non-zero or zero. */
< return truthvalue_conversion (TREE_OPERAND (expr, 0));
---
> /* These don't change whether an object is nonzero or zero. */
> return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
2178c2813
< /* 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
2182c2817
< truthvalue_conversion (TREE_OPERAND (expr, 0)));
---
> c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
2184c2819
< return truthvalue_conversion (TREE_OPERAND (expr, 0));
---
> return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
2189,2190c2824,2825
< truthvalue_conversion (TREE_OPERAND (expr, 1)),
< truthvalue_conversion (TREE_OPERAND (expr, 2))));
---
> c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
> c_common_truthvalue_conversion (TREE_OPERAND (expr, 2))));
2203c2838
< return truthvalue_conversion (TREE_OPERAND (expr, 0));
---
> return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
2207,2210c2842,2850
< /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
< this case. */
< if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
< && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
---
> /* Perhaps reduce (x - y) != 0 to (x != y). The expressions
> aren't guaranteed to the be same for modes that can represent
> infinity, since if x and y are both +infinity, or both
> -infinity, then x - y is not a number.
>
> Note that this transformation is safe when x or y is NaN.
> (x - y) is then NaN, and both (x - y) != 0 and x != y will
> be false. */
> if (HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (TREE_OPERAND (expr, 0)))))
2243c2883
< tree tem = save_expr (expr);
---
> tree t = save_expr (expr);
2247,2248c2887,2888
< truthvalue_conversion (build_unary_op (REALPART_EXPR, tem, 0)),
< truthvalue_conversion (build_unary_op (IMAGPART_EXPR, tem, 0)),
---
> c_common_truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)),
> c_common_truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)),
2257c2897
< int));
---
> tree));
2319d2958
<
2352c2991,2995
<
---
>
> /* If it has the may_alias attribute, it can alias anything. */
> if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (t)))
> return 0;
>
2358c3001
< tree t1 = signed_type (t);
---
> tree t1 = c_common_signed_type (t);
2399,2401c3042,3045
< /* Implement the __alignof keyword: Return the minimum required
< alignment of TYPE, measured in bytes. */
<
---
> /* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where the
> second parameter indicates which OPERATOR is being applied. The COMPLAIN
> flag controls whether we should diagnose possibly ill-formed
> constructs or not. */
2403c3047
< c_alignof (type)
---
> c_sizeof_or_alignof_type (type, op, complain)
2404a3049,3050
> enum tree_code op;
> int complain;
2406,2410c3052,3059
< enum tree_code code = TREE_CODE (type);
< tree t;
<
< /* In C++, sizeof applies to the referent. Handle alignof the same way. */
< if (code == REFERENCE_TYPE)
---
> const char *op_name;
> tree value = NULL;
> enum tree_code type_code = TREE_CODE (type);
>
> my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
> op_name = op == SIZEOF_EXPR ? "sizeof" : "__alignof__";
>
> if (type_code == FUNCTION_TYPE)
2412,2413c3061,3068
< type = TREE_TYPE (type);
< code = TREE_CODE (type);
---
> if (op == SIZEOF_EXPR)
> {
> if (complain && (pedantic || warn_pointer_arith))
> pedwarn ("invalid application of `sizeof' to a function type");
> value = size_one_node;
> }
> else
> value = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
2415,2419c3070,3076
<
< if (code == FUNCTION_TYPE)
< t = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
< else if (code == VOID_TYPE || code == ERROR_MARK)
< t = size_one_node;
---
> else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
> {
> if (type_code == VOID_TYPE
> && complain && (pedantic || warn_pointer_arith))
> pedwarn ("invalid application of `%s' to a void type", op_name);
> value = size_one_node;
> }
2422,2423c3079,3081
< error ("__alignof__ applied to an incomplete type");
< t = size_zero_node;
---
> if (complain)
> error ("invalid application of `%s' to an incomplete type", op_name);
> value = size_zero_node;
2426c3084,3092
< t = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
---
> {
> if (op == SIZEOF_EXPR)
> /* Convert in case a char is more than one unit. */
> value = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
> size_int (TYPE_PRECISION (char_type_node)
> / BITS_PER_UNIT));
> else
> value = size_int (TYPE_ALIGN (type) / BITS_PER_UNIT);
> }
2428c3094,3101
< return fold (build1 (NOP_EXPR, size_type_node, t));
---
> /* VALUE will have an integer type with TYPE_IS_SIZETYPE set.
> 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, size_type_node, value));
> my_friendly_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)), 20001021);
>
> return value;
2479,2480c3152
< /* Give the specifications for the format attributes, used by C and all
< descendents. */
---
> /* Handle C and C++ default attributes. */
2482c3154
< static const struct attribute_spec c_format_attribute_table[] =
---
> enum built_in_attribute
2484,2489c3156,3167
< /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
< { "format", 3, 3, false, true, true,
< handle_format_attribute },
< { "format_arg", 1, 1, false, true, true,
< handle_format_arg_attribute },
< { NULL, 0, 0, false, false, false, NULL }
---
> #define DEF_ATTR_NULL_TREE(ENUM) ENUM,
> #define DEF_ATTR_INT(ENUM, VALUE) ENUM,
> #define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
> #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
> #define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum. */
> #include "builtin-attrs.def"
> #undef DEF_ATTR_NULL_TREE
> #undef DEF_ATTR_INT
> #undef DEF_ATTR_IDENT
> #undef DEF_ATTR_TREE_LIST
> #undef DEF_FN_ATTR
> ATTR_LAST
2491a3170,3175
> static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
>
> static bool c_attrs_initialized = false;
>
> static void c_init_attributes PARAMS ((void));
>
2508a3193
> #define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
2519a3205
> #undef DEF_FUNCTION_TYPE_VAR_3
2529,2533d3214
< /* Either char* or void*. */
< tree traditional_ptr_type_node;
< /* Either const char* or const void*. */
< tree traditional_cptr_type_node;
< tree traditional_len_type_node;
2537,2540d3217
< /* We must initialize this before any builtin functions (which might have
< attributes) are declared. (c_common_init is too late.) */
< format_attribute_table = c_format_attribute_table;
<
2574,2578c3251,3260
< /* These are types that type_for_size and type_for_mode use. */
< pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node));
< pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node));
< pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node));
< pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
---
> /* These are types that c_common_type_for_size and
> c_common_type_for_mode use. */
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
> intQI_type_node));
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
> intHI_type_node));
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
> intSI_type_node));
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
> intDI_type_node));
2580c3262,3264
< pushdecl (build_decl (TYPE_DECL, get_identifier ("__int128_t"), intTI_type_node));
---
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
> get_identifier ("__int128_t"),
> intTI_type_node));
2582,2585c3266,3273
< pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
< pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node));
< pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node));
< pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
---
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
> unsigned_intQI_type_node));
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
> unsigned_intHI_type_node));
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
> unsigned_intSI_type_node));
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
> unsigned_intDI_type_node));
2587c3275,3277
< pushdecl (build_decl (TYPE_DECL, get_identifier ("__uint128_t"), unsigned_intTI_type_node));
---
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
> get_identifier ("__uint128_t"),
> unsigned_intTI_type_node));
2593,2594c3283,3284
< pushdecl (build_decl (TYPE_DECL, NULL_TREE,
< widest_integer_literal_type_node));
---
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
> widest_integer_literal_type_node));
2598,2599c3288,3289
< pushdecl (build_decl (TYPE_DECL, NULL_TREE,
< widest_unsigned_literal_type_node));
---
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
> widest_unsigned_literal_type_node));
2606,2608c3296
< signed_size_type_node = signed_type (size_type_node);
< if (flag_traditional)
< size_type_node = signed_size_type_node;
---
> signed_size_type_node = c_common_signed_type (size_type_node);
2617,2624c3305,3316
< pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
< complex_integer_type_node));
< pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
< complex_float_type_node));
< pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
< complex_double_type_node));
< pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
< complex_long_double_type_node));
---
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
> get_identifier ("complex int"),
> complex_integer_type_node));
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
> get_identifier ("complex float"),
> complex_float_type_node));
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
> get_identifier ("complex double"),
> complex_double_type_node));
> (*lang_hooks.decls.pushdecl)
> (build_decl (TYPE_DECL, get_identifier ("complex long double"),
> complex_long_double_type_node));
2646,2651c3338,3343
< pushdecl (build_decl (TYPE_DECL,
< get_identifier ("__g77_integer"),
< g77_integer_type_node));
< pushdecl (build_decl (TYPE_DECL,
< get_identifier ("__g77_uinteger"),
< g77_uinteger_type_node));
---
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
> get_identifier ("__g77_integer"),
> g77_integer_type_node));
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
> get_identifier ("__g77_uinteger"),
> g77_uinteger_type_node));
2671,2676c3363,3368
< pushdecl (build_decl (TYPE_DECL,
< get_identifier ("__g77_longint"),
< g77_longint_type_node));
< pushdecl (build_decl (TYPE_DECL,
< get_identifier ("__g77_ulongint"),
< g77_ulongint_type_node));
---
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
> get_identifier ("__g77_longint"),
> g77_longint_type_node));
> (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
> get_identifier ("__g77_ulongint"),
> g77_ulongint_type_node));
2708,2716d3399
< traditional_ptr_type_node = ((flag_traditional &&
< c_language != clk_cplusplus)
< ? string_type_node : ptr_type_node);
< traditional_cptr_type_node = ((flag_traditional &&
< c_language != clk_cplusplus)
< ? const_string_type_node : const_ptr_type_node);
<
< (*targetm.init_builtins) ();
<
2718,2720c3401
< wchar_type_node = get_identifier (flag_short_wchar
< ? "short unsigned int"
< : WCHAR_TYPE);
---
> wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE);
2733,2734c3414,3415
< signed_wchar_type_node = signed_type (wchar_type_node);
< unsigned_wchar_type_node = unsigned_type (wchar_type_node);
---
> signed_wchar_type_node = c_common_signed_type (wchar_type_node);
> unsigned_wchar_type_node = c_common_unsigned_type (wchar_type_node);
2752c3433
< unsigned_ptrdiff_type_node = unsigned_type (ptrdiff_type_node);
---
> unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);
2754,2755c3435,3437
< pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
< va_list_type_node));
---
> (*lang_hooks.decls.pushdecl)
> (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
> va_list_type_node));
2757,2758c3439,3441
< pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_ptrdiff_t"),
< ptrdiff_type_node));
---
> (*lang_hooks.decls.pushdecl)
> (build_decl (TYPE_DECL, get_identifier ("__builtin_ptrdiff_t"),
> ptrdiff_type_node));
2760,2761c3443,3445
< pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"),
< sizetype));
---
> (*lang_hooks.decls.pushdecl)
> (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"),
> sizetype));
2774,2777d3457
< traditional_len_type_node = ((flag_traditional &&
< c_language != clk_cplusplus)
< ? integer_type_node : sizetype);
<
2842a3523,3535
>
> #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))));
>
2853a3547,3548
> #undef DEF_FUNCTION_TYPE_VAR_2
> #undef DEF_FUNCTION_TYPE_VAR_3
2856,2857c3551,3555
< #define DEF_BUILTIN(ENUM, NAME, CLASS, \
< TYPE, LIBTYPE, BOTH_P, FALLBACK_P, NONANSI_P) \
---
> if (!c_attrs_initialized)
> c_init_attributes ();
>
> #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, \
> BOTH_P, FALLBACK_P, NONANSI_P, ATTRS) \
2870c3568,3569
< : NULL)); \
---
> : NULL), \
> built_in_attributes[(int) ATTRS]); \
2880c3579
< /*noreturn_p=*/0); \
---
> built_in_attributes[(int) ATTRS]); \
2887,2893c3586
< /* Declare _exit and _Exit just to mark them as non-returning. */
< builtin_function_2 (NULL, "_exit", NULL_TREE,
< builtin_types[BT_FN_VOID_INT],
< 0, NOT_BUILT_IN, 0, 1, 1);
< builtin_function_2 (NULL, "_Exit", NULL_TREE,
< builtin_types[BT_FN_VOID_INT],
< 0, NOT_BUILT_IN, 0, !flag_isoc99, 1);
---
> (*targetm.init_builtins) ();
2895,2908d3587
< /* Declare these functions non-returning
< to avoid spurious "control drops through" warnings. */
< builtin_function_2 (NULL, "abort",
< NULL_TREE, ((c_language == clk_cplusplus)
< ? builtin_types[BT_FN_VOID]
< : builtin_types[BT_FN_VOID_VAR]),
< 0, NOT_BUILT_IN, 0, 0, 1);
<
< builtin_function_2 (NULL, "exit",
< NULL_TREE, ((c_language == clk_cplusplus)
< ? builtin_types[BT_FN_VOID_INT]
< : builtin_types[BT_FN_VOID_VAR]),
< 0, NOT_BUILT_IN, 0, 0, 1);
<
2910,2913d3588
<
< /* ??? Perhaps there's a better place to do this. But it is related
< to __builtin_va_arg, so it isn't that off-the-wall. */
< lang_type_promotes_to = simple_type_promotes_to;
2980,2981c3655,3656
< If NONANSI_P is nonzero, the name NAME is treated as a non-ANSI name; if
< NORETURN_P is nonzero, the function is marked as non-returning.
---
> If NONANSI_P is nonzero, the name NAME is treated as a non-ANSI name;
> ATTRS is the tree list representing the builtin's function attributes.
2988c3663
< class, library_name_p, nonansi_p, noreturn_p)
---
> class, library_name_p, nonansi_p, attrs)
2997c3672
< int noreturn_p;
---
> tree attrs;
3004,3009c3679,3680
< class, library_name_p ? name : NULL);
< if (noreturn_p)
< {
< TREE_THIS_VOLATILE (bdecl) = 1;
< TREE_SIDE_EFFECTS (bdecl) = 1;
< }
---
> class, library_name_p ? name : NULL,
> attrs);
3014c3685,3686
< decl = builtin_function (name, type, function_code, class, NULL);
---
> decl = builtin_function (name, type, function_code, class, NULL,
> attrs);
3017,3021d3688
< if (noreturn_p)
< {
< TREE_THIS_VOLATILE (decl) = 1;
< TREE_SIDE_EFFECTS (decl) = 1;
< }
3057,3084d3723
< /* Given a type, apply default promotions wrt unnamed function arguments
< and return the new type. Return NULL_TREE if no change. */
< /* ??? There is a function of the same name in the C++ front end that
< does something similar, but is more thorough and does not return NULL
< if no change. We could perhaps share code, but it would make the
< self_promoting_type property harder to identify. */
<
< tree
< simple_type_promotes_to (type)
< tree type;
< {
< if (TYPE_MAIN_VARIANT (type) == float_type_node)
< return double_type_node;
<
< if (c_promoting_integer_type_p (type))
< {
< /* Traditionally, unsignedness is preserved in default promotions.
< Also preserve unsignedness if not really getting any wider. */
< if (TREE_UNSIGNED (type)
< && (flag_traditional
< || TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
< return unsigned_type_node;
< return integer_type_node;
< }
<
< return NULL_TREE;
< }
<
3124a3764,3838
> static tree expand_unordered_cmp PARAMS ((tree, tree, enum tree_code,
> enum tree_code));
>
> /* Expand a call to an unordered comparison function such as
> __builtin_isgreater(). FUNCTION is the function's declaration and
> PARAMS a list of the values passed. For __builtin_isunordered(),
> UNORDERED_CODE is UNORDERED_EXPR and ORDERED_CODE is NOP_EXPR. In
> other cases, UNORDERED_CODE and ORDERED_CODE are comparison codes
> that give the opposite of the desired result. UNORDERED_CODE is
> used for modes that can hold NaNs and ORDERED_CODE is used for the
> rest. */
>
> static tree
> expand_unordered_cmp (function, params, unordered_code, ordered_code)
> tree function, params;
> enum tree_code unordered_code, ordered_code;
> {
> tree arg0, arg1, type;
> enum tree_code code0, code1;
>
> /* Check that we have exactly two arguments. */
> if (params == 0 || TREE_CHAIN (params) == 0)
> {
> error ("too few arguments to function `%s'",
> IDENTIFIER_POINTER (DECL_NAME (function)));
> return error_mark_node;
> }
> else if (TREE_CHAIN (TREE_CHAIN (params)) != 0)
> {
> error ("too many arguments to function `%s'",
> IDENTIFIER_POINTER (DECL_NAME (function)));
> return error_mark_node;
> }
>
> arg0 = TREE_VALUE (params);
> arg1 = TREE_VALUE (TREE_CHAIN (params));
>
> code0 = TREE_CODE (TREE_TYPE (arg0));
> code1 = TREE_CODE (TREE_TYPE (arg1));
>
> /* Make sure that the arguments have a common type of REAL. */
> type = 0;
> if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
> && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
> type = common_type (TREE_TYPE (arg0), TREE_TYPE (arg1));
>
> if (type == 0 || TREE_CODE (type) != REAL_TYPE)
> {
> error ("non-floating-point argument to function `%s'",
> IDENTIFIER_POINTER (DECL_NAME (function)));
> return error_mark_node;
> }
>
> if (unordered_code == UNORDERED_EXPR)
> {
> if (MODE_HAS_NANS (TYPE_MODE (type)))
> return build_binary_op (unordered_code,
> convert (type, arg0),
> convert (type, arg1),
> 0);
> else
> return integer_zero_node;
> }
>
> return build_unary_op (TRUTH_NOT_EXPR,
> build_binary_op (MODE_HAS_NANS (TYPE_MODE (type))
> ? unordered_code
> : ordered_code,
> convert (type, arg0),
> convert (type, arg1),
> 0),
> 0);
> }
>
>
3137,3138d3850
< enum tree_code code;
<
3177,3181c3889
< if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
< code = UNLE_EXPR;
< else
< code = LE_EXPR;
< goto unordered_cmp;
---
> return expand_unordered_cmp (function, params, UNLE_EXPR, LE_EXPR);
3184,3188c3892
< if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
< code = UNLT_EXPR;
< else
< code = LT_EXPR;
< goto unordered_cmp;
---
> return expand_unordered_cmp (function, params, UNLT_EXPR, LT_EXPR);
3191,3195c3895
< if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
< code = UNGE_EXPR;
< else
< code = GE_EXPR;
< goto unordered_cmp;
---
> return expand_unordered_cmp (function, params, UNGE_EXPR, GE_EXPR);
3198,3202c3898
< if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
< code = UNGT_EXPR;
< else
< code = GT_EXPR;
< goto unordered_cmp;
---
> return expand_unordered_cmp (function, params, UNGT_EXPR, GT_EXPR);
3205,3209c3901
< if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
< code = UNEQ_EXPR;
< else
< code = EQ_EXPR;
< goto unordered_cmp;
---
> return expand_unordered_cmp (function, params, UNEQ_EXPR, EQ_EXPR);
3212,3215c3904
< if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
< return integer_zero_node;
< code = UNORDERED_EXPR;
< goto unordered_cmp;
---
> return expand_unordered_cmp (function, params, UNORDERED_EXPR, NOP_EXPR);
3217,3243d3905
< unordered_cmp:
< {
< tree arg0, arg1;
<
< if (params == 0
< || TREE_CHAIN (params) == 0)
< {
< error ("too few arguments to function `%s'",
< IDENTIFIER_POINTER (DECL_NAME (function)));
< return error_mark_node;
< }
< else if (TREE_CHAIN (TREE_CHAIN (params)) != 0)
< {
< error ("too many arguments to function `%s'",
< IDENTIFIER_POINTER (DECL_NAME (function)));
< return error_mark_node;
< }
<
< arg0 = TREE_VALUE (params);
< arg1 = TREE_VALUE (TREE_CHAIN (params));
< arg0 = build_binary_op (code, arg0, arg1, 0);
< if (code != UNORDERED_EXPR)
< arg0 = build_unary_op (TRUTH_NOT_EXPR, arg0, 0);
< return arg0;
< }
< break;
<
3251c3913
< /* Returns non-zero if CODE is the code for a statement. */
---
> /* Returns nonzero if CODE is the code for a statement. */
3569,3603d4230
< /* Mark P (a stmt_tree) for GC. The use of a `void *' for the
< parameter allows this function to be used as a GC-marking
< function. */
<
< void
< mark_stmt_tree (p)
< void *p;
< {
< stmt_tree st = (stmt_tree) p;
<
< ggc_mark_tree (st->x_last_stmt);
< ggc_mark_tree (st->x_last_expr_type);
< }
<
< /* Mark LD for GC. */
<
< void
< c_mark_lang_decl (c)
< struct c_lang_decl *c ATTRIBUTE_UNUSED;
< {
< }
<
< /* Mark F for GC. */
<
< void
< mark_c_language_function (f)
< struct language_function *f;
< {
< if (!f)
< return;
<
< mark_stmt_tree (&f->x_stmt_tree);
< ggc_mark_tree (f->x_scope_stmt_stack);
< }
<
3611c4238
< enum expand_modifier modifier;
---
> int modifier; /* Actually enum_modifier. */
3752c4379
< c_unsafe_for_reeval (exp)
---
> c_common_unsafe_for_reeval (exp)
3777,3826d4403
< /* Tree code classes. */
<
< #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
<
< static const char c_tree_code_type[] = {
< 'x',
< #include "c-common.def"
< };
< #undef DEFTREECODE
<
< /* Table indexed by tree code giving number of expression
< operands beyond the fixed part of the node structure.
< Not used for types or decls. */
<
< #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
<
< static const int c_tree_code_length[] = {
< 0,
< #include "c-common.def"
< };
< #undef DEFTREECODE
<
< /* Names of tree components.
< Used for printing out the tree and error messages. */
< #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
<
< static const char *const c_tree_code_name[] = {
< "@@dummy",
< #include "c-common.def"
< };
< #undef DEFTREECODE
<
< /* Adds the tree codes specific to the C front end to the list of all
< tree codes. */
<
< void
< add_c_tree_codes ()
< {
< memcpy (tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
< c_tree_code_type,
< (int) LAST_C_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE);
< memcpy (tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE,
< c_tree_code_length,
< (LAST_C_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE) * sizeof (int));
< memcpy (tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE,
< c_tree_code_name,
< (LAST_C_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
< lang_unsafe_for_reeval = c_unsafe_for_reeval;
< }
<
4015c4592
< arglist = combine_strings (build_string (newlen, newstr));
---
> arglist = fix_string_type (build_string (newlen, newstr));
4154c4731,4738
< /* Handle C and C++ default attributes. */
---
> /* Define NAME with value TYPE precision. */
> static void
> builtin_define_type_precision (name, type)
> const char *name;
> tree type;
> {
> builtin_define_with_int_value (name, TYPE_PRECISION (type));
> }
4156c4740,4745
< enum built_in_attribute
---
> /* Define the float.h constants for TYPE using NAME_PREFIX and FP_SUFFIX. */
> static void
> builtin_define_float_constants (name_prefix, fp_suffix, type)
> const char *name_prefix;
> const char *fp_suffix;
> tree type;
4158,4170c4747
< #define DEF_ATTR_NULL_TREE(ENUM) ENUM,
< #define DEF_ATTR_INT(ENUM, VALUE) ENUM,
< #define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
< #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
< #define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum. */
< #include "builtin-attrs.def"
< #undef DEF_ATTR_NULL_TREE
< #undef DEF_ATTR_INT
< #undef DEF_ATTR_IDENT
< #undef DEF_ATTR_TREE_LIST
< #undef DEF_FN_ATTR
< ATTR_LAST
< };
---
> /* Used to convert radix-based values to base 10 values in several cases.
4172c4749,4753
< static tree built_in_attributes[(int) ATTR_LAST];
---
> In the max_exp -> max_10_exp conversion for 128-bit IEEE, we need at
> least 6 significant digits for correct results. Using the fraction
> formed by (log(2)*1e6)/(log(10)*1e6) overflows a 32-bit integer as an
> intermediate; perhaps someone can find a better approximation, in the
> mean time, I suspect using doubles won't harm the bootstrap here. */
4174c4755,4757
< static bool c_attrs_initialized = false;
---
> const double log10_2 = .30102999566398119521;
> double log10_b;
> const struct real_format *fmt;
4176c4759,4761
< static void c_init_attributes PARAMS ((void));
---
> char name[64], buf[128];
> int dig, min_10_exp, max_10_exp;
> int decimal_dig;
4178c4763,4904
< /* Common initialization before parsing options. */
---
> fmt = real_format_for_mode[TYPE_MODE (type) - QFmode];
>
> /* The radix of the exponent representation. */
> if (type == float_type_node)
> builtin_define_with_int_value ("__FLT_RADIX__", fmt->b);
> log10_b = log10_2 * fmt->log2_b;
>
> /* The number of radix digits, p, in the floating-point significand. */
> sprintf (name, "__%s_MANT_DIG__", name_prefix);
> builtin_define_with_int_value (name, fmt->p);
>
> /* The number of decimal digits, q, such that any floating-point number
> with q decimal digits can be rounded into a floating-point number with
> p radix b digits and back again without change to the q decimal digits,
>
> p log10 b if b is a power of 10
> floor((p - 1) log10 b) otherwise
> */
> dig = (fmt->p - 1) * log10_b;
> sprintf (name, "__%s_DIG__", name_prefix);
> builtin_define_with_int_value (name, dig);
>
> /* The minimum negative int x such that b**(x-1) is a normalized float. */
> sprintf (name, "__%s_MIN_EXP__", name_prefix);
> sprintf (buf, "(%d)", fmt->emin);
> builtin_define_with_value (name, buf, 0);
>
> /* The minimum negative int x such that 10**x is a normalized float,
>
> ceil (log10 (b ** (emin - 1)))
> = ceil (log10 (b) * (emin - 1))
>
> Recall that emin is negative, so the integer truncation calculates
> the ceiling, not the floor, in this case. */
> min_10_exp = (fmt->emin - 1) * log10_b;
> sprintf (name, "__%s_MIN_10_EXP__", name_prefix);
> sprintf (buf, "(%d)", min_10_exp);
> builtin_define_with_value (name, buf, 0);
>
> /* The maximum int x such that b**(x-1) is a representable float. */
> sprintf (name, "__%s_MAX_EXP__", name_prefix);
> builtin_define_with_int_value (name, fmt->emax);
>
> /* The maximum int x such that 10**x is in the range of representable
> finite floating-point numbers,
>
> floor (log10((1 - b**-p) * b**emax))
> = floor (log10(1 - b**-p) + log10(b**emax))
> = floor (log10(1 - b**-p) + log10(b)*emax)
>
> The safest thing to do here is to just compute this number. But since
> we don't link cc1 with libm, we cannot. We could implement log10 here
> a series expansion, but that seems too much effort because:
>
> Note that the first term, for all extant p, is a number exceedingly close
> to zero, but slightly negative. Note that the second term is an integer
> scaling an irrational number, and that because of the floor we are only
> interested in its integral portion.
>
> In order for the first term to have any effect on the integral portion
> of the second term, the second term has to be exceedingly close to an
> integer itself (e.g. 123.000000000001 or something). Getting a result
> that close to an integer requires that the irrational multiplicand have
> a long series of zeros in its expansion, which doesn't occur in the
> first 20 digits or so of log10(b).
>
> Hand-waving aside, crunching all of the sets of constants above by hand
> does not yield a case for which the first term is significant, which
> in the end is all that matters. */
> max_10_exp = fmt->emax * log10_b;
> sprintf (name, "__%s_MAX_10_EXP__", name_prefix);
> builtin_define_with_int_value (name, max_10_exp);
>
> /* The number of decimal digits, n, such that any floating-point number
> can be rounded to n decimal digits and back again without change to
> the value.
>
> p * log10(b) if b is a power of 10
> ceil(1 + p * log10(b)) otherwise
>
> The only macro we care about is this number for the widest supported
> floating type, but we want this value for rendering constants below. */
> {
> double d_decimal_dig = 1 + fmt->p * log10_b;
> decimal_dig = d_decimal_dig;
> if (decimal_dig < d_decimal_dig)
> decimal_dig++;
> }
> if (type == long_double_type_node)
> builtin_define_with_int_value ("__DECIMAL_DIG__", decimal_dig);
>
> /* Since, for the supported formats, B is always a power of 2, we
> construct the following numbers directly as a hexadecimal
> constants. */
>
> /* The maximum representable finite floating-point number,
> (1 - b**-p) * b**emax */
> {
> int i, n;
> char *p;
>
> strcpy (buf, "0x0.");
> n = fmt->p * fmt->log2_b;
> for (i = 0, p = buf + 4; i + 3 < n; i += 4)
> *p++ = 'f';
> if (i < n)
> *p++ = "08ce"[n - i];
> sprintf (p, "p%d", fmt->emax * fmt->log2_b);
> }
> sprintf (name, "__%s_MAX__", name_prefix);
> builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
>
> /* The minimum normalized positive floating-point number,
> b**(emin-1). */
> sprintf (name, "__%s_MIN__", name_prefix);
> sprintf (buf, "0x1p%d", (fmt->emin - 1) * fmt->log2_b);
> builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
>
> /* The difference between 1 and the least value greater than 1 that is
> representable in the given floating point type, b**(1-p). */
> sprintf (name, "__%s_EPSILON__", name_prefix);
> sprintf (buf, "0x1p%d", (1 - fmt->p) * fmt->log2_b);
> builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
>
> /* For C++ std::numeric_limits<T>::denorm_min. The minimum denormalized
> positive floating-point number, b**(emin-p). Zero for formats that
> don't support denormals. */
> sprintf (name, "__%s_DENORM_MIN__", name_prefix);
> if (fmt->has_denorm)
> {
> sprintf (buf, "0x1p%d", (fmt->emin - fmt->p) * fmt->log2_b);
> builtin_define_with_hex_fp_value (name, type, decimal_dig,
> buf, fp_suffix);
> }
> else
> {
> sprintf (buf, "0.0%s", fp_suffix);
> builtin_define_with_value (name, buf, 0);
> }
> }
>
> /* Hook that registers front end and target-specific built-ins. */
4180,4181c4906,4907
< c_common_init_options (lang)
< enum c_language_kind lang;
---
> cb_register_builtins (pfile)
> cpp_reader *pfile;
4183,4185c4909,4911
< c_language = lang;
< parse_in = cpp_create_reader (lang == clk_c ? CLK_GNUC89:
< lang == clk_cplusplus ? CLK_GNUCXX: CLK_OBJC);
---
> /* -undef turns off target-specific built-ins. */
> if (flag_undef)
> return;
4187,4188c4913,5008
< /* Mark as "unspecified" (see c_common_post_options). */
< flag_bounds_check = -1;
---
> if (c_language == clk_cplusplus)
> {
> if (SUPPORTS_ONE_ONLY)
> cpp_define (pfile, "__GXX_WEAK__=1");
> else
> cpp_define (pfile, "__GXX_WEAK__=0");
> 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. */
> cpp_define (pfile, "__GXX_ABI_VERSION=102");
>
> /* 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);
> builtin_define_type_max ("__WCHAR_MAX__", wchar_type_node, 0);
>
> builtin_define_type_precision ("__CHAR_BIT__", char_type_node);
>
> /* float.h needs to know these. */
>
> builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
> TARGET_FLT_EVAL_METHOD);
>
> builtin_define_float_constants ("FLT", "F", float_type_node);
> builtin_define_float_constants ("DBL", "", double_type_node);
> builtin_define_float_constants ("LDBL", "L", long_double_type_node);
>
> /* 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_really_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__=1");
> else
> cpp_define (pfile, "__FINITE_MATH_ONLY__=0");
>
> if (flag_iso)
> cpp_define (pfile, "__STRICT_ANSI__");
>
> if (!flag_signed_char)
> cpp_define (pfile, "__CHAR_UNSIGNED__");
>
> if (c_language == clk_cplusplus && TREE_UNSIGNED (wchar_type_node))
> cpp_define (pfile, "__WCHAR_UNSIGNED__");
>
> /* Make the choice of ObjC runtime visible to source code. */
> if (flag_objc && flag_next_runtime)
> cpp_define (pfile, "__NEXT_RUNTIME__");
>
> /* 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 preprocessing_trad_p() (cpp_get_options (pfile)->traditional)
> # define builtin_define(TXT) cpp_define (pfile, TXT)
> # define builtin_assert(TXT) cpp_assert (pfile, TXT)
> TARGET_CPU_CPP_BUILTINS ();
> TARGET_OS_CPP_BUILTINS ();
4191c5011,5019
< /* Post-switch processing. */
---
> /* 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". */
4193c5021,5022
< c_common_post_options ()
---
> builtin_define_std (macro)
> const char *macro;
4195c5024,5027
< cpp_post_options (parse_in);
---
> size_t len = strlen (macro);
> char *buff = alloca (len + 5);
> char *p = buff + 2;
> char *q = p + len;
4197c5029,5038
< flag_inline_trees = 1;
---
> /* 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);
4199,4201c5040,5041
< /* 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 it was in user's namespace... */
> if (p != buff + 2)
4203,4209c5043,5053
< if (!flag_no_inline)
< flag_no_inline = 1;
< if (flag_inline_functions)
< {
< flag_inline_trees = 2;
< flag_inline_functions = 0;
< }
---
> /* 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);
4210a5055
> }
4212,4214c5057,5069
< /* If still "unspecified", make it match -fbounded-pointers. */
< if (flag_bounds_check == -1)
< flag_bounds_check = flag_bounded_pointers;
---
> /* 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 */
4216,4227c5071,5072
< /* 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_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 (is_str)
> extra += 2; /* space for two quote marks */
4229,4231c5074,5080
< /* If an error has occurred in cpplib, note it so we fail
< immediately. */
< errorcount += cpp_errors (parse_in);
---
> 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);
4234,4237c5083,5087
< /* Front end initialization common to C, ObjC and C++. */
< const char *
< c_common_init (filename)
< const char *filename;
---
> /* Pass an object-like macro and an integer value to define it to. */
> static void
> builtin_define_with_int_value (macro, value)
> const char *macro;
> HOST_WIDE_INT value;
4239,4241c5089,5092
< /* Do this before initializing pragmas, as then cpplib's hash table
< has been set up. */
< filename = init_c_lex (filename);
---
> char *buf;
> size_t mlen = strlen (macro);
> size_t vlen = 18;
> size_t extra = 2; /* space for = and NUL. */
4243c5094,5097
< init_pragma ();
---
> buf = alloca (mlen + vlen + extra);
> memcpy (buf, macro, mlen);
> buf[mlen] = '=';
> sprintf (buf + mlen + 1, HOST_WIDE_INT_PRINT_DEC, value);
4245,4246c5099,5100
< if (!c_attrs_initialized)
< c_init_attributes ();
---
> cpp_define (parse_in, buf);
> }
4248c5102,5128
< return filename;
---
> /* Pass an object-like macro a hexadecimal floating-point value. */
> static void
> builtin_define_with_hex_fp_value (macro, type, digits, hex_str, fp_suffix)
> const char *macro;
> tree type ATTRIBUTE_UNUSED;
> int digits;
> const char *hex_str;
> const char *fp_suffix;
> {
> REAL_VALUE_TYPE real;
> char dec_str[64], buf[256];
>
> /* Hex values are really cool and convenient, except that they're
> not supported in strict ISO C90 mode. First, the "p-" sequence
> is not valid as part of a preprocessor number. Second, we get a
> pedwarn from the preprocessor, which has no context, so we can't
> suppress the warning with __extension__.
>
> So instead what we do is construct the number in hex (because
> it's easy to get the exact correct value), parse it as a real,
> then print it back out as decimal. */
>
> real_from_string (&real, hex_str);
> real_to_decimal (dec_str, &real, sizeof (dec_str), digits, 0);
>
> sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix);
> cpp_define (parse_in, buf);
4251,4253c5131,5139
< /* Common finish hook for the C, ObjC and C++ front ends. */
< void
< c_common_finish ()
---
> /* Define MAX for TYPE based on the precision of the type. IS_LONG is
> 1 for type "long" and 2 for "long long". We have to handle
> unsigned types, since wchar_t might be unsigned. */
>
> static void
> builtin_define_type_max (macro, type, is_long)
> const char *macro;
> tree type;
> int is_long;
4255c5141,5148
< cpp_finish (parse_in);
---
> static const char *const values[]
> = { "127", "255",
> "32767", "65535",
> "2147483647", "4294967295",
> "9223372036854775807", "18446744073709551615",
> "170141183460469231731687303715884105727",
> "340282366920938463463374607431768211455" };
> static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" };
4257,4259c5150,5173
< /* For performance, avoid tearing down cpplib's internal structures.
< Call cpp_errors () instead of cpp_destroy (). */
< errorcount += cpp_errors (parse_in);
---
> const char *value, *suffix;
> char *buf;
> size_t idx;
>
> /* 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: idx = 0; break;
> case 16: idx = 2; break;
> case 32: idx = 4; break;
> case 64: idx = 6; break;
> case 128: idx = 8; break;
> default: abort ();
> }
>
> value = values[idx + TREE_UNSIGNED (type)];
> suffix = suffixes[is_long * 2 + TREE_UNSIGNED (type)];
>
> buf = alloca (strlen (macro) + 1 + strlen (value) + strlen (suffix) + 1);
> sprintf (buf, "%s=%s%s", macro, value, suffix);
>
> cpp_define (parse_in, buf);
4284d5197
< ggc_add_tree_root (built_in_attributes, (int) ATTR_LAST);
4327a5241,6684
> /* Attribute handlers common to C front ends. */
>
> /* Handle a "packed" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_packed_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags;
> bool *no_add_attrs;
> {
> tree *type = NULL;
> if (DECL_P (*node))
> {
> if (TREE_CODE (*node) == TYPE_DECL)
> type = &TREE_TYPE (*node);
> }
> else
> type = node;
>
> if (type)
> {
> if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
> *type = build_type_copy (*type);
> TYPE_PACKED (*type) = 1;
> }
> else if (TREE_CODE (*node) == FIELD_DECL)
> DECL_PACKED (*node) = 1;
> /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
> used for DECL_REGISTER. It wouldn't mean anything anyway. */
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "nocommon" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_nocommon_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> if (TREE_CODE (*node) == VAR_DECL)
> DECL_COMMON (*node) = 0;
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "common" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_common_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> if (TREE_CODE (*node) == VAR_DECL)
> DECL_COMMON (*node) = 1;
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "noreturn" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_noreturn_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> tree type = TREE_TYPE (*node);
>
> /* See FIXME comment in c_common_attribute_table. */
> if (TREE_CODE (*node) == FUNCTION_DECL)
> TREE_THIS_VOLATILE (*node) = 1;
> else if (TREE_CODE (type) == POINTER_TYPE
> && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
> TREE_TYPE (*node)
> = build_pointer_type
> (build_type_variant (TREE_TYPE (type),
> TREE_READONLY (TREE_TYPE (type)), 1));
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "noinline" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_noinline_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> if (TREE_CODE (*node) == FUNCTION_DECL)
> DECL_UNINLINABLE (*node) = 1;
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "always_inline" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_always_inline_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> if (TREE_CODE (*node) == FUNCTION_DECL)
> {
> /* Do nothing else, just set the attribute. We'll get at
> it later with lookup_attribute. */
> }
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "used" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> 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;
> {
> 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));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "unused" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_unused_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags;
> bool *no_add_attrs;
> {
> if (DECL_P (*node))
> {
> tree decl = *node;
>
> if (TREE_CODE (decl) == PARM_DECL
> || TREE_CODE (decl) == VAR_DECL
> || TREE_CODE (decl) == FUNCTION_DECL
> || TREE_CODE (decl) == LABEL_DECL
> || TREE_CODE (decl) == TYPE_DECL)
> TREE_USED (decl) = 1;
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
> }
> else
> {
> if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
> *node = build_type_copy (*node);
> TREE_USED (*node) = 1;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "const" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_const_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> tree type = TREE_TYPE (*node);
>
> /* See FIXME comment on noreturn in c_common_attribute_table. */
> if (TREE_CODE (*node) == FUNCTION_DECL)
> TREE_READONLY (*node) = 1;
> else if (TREE_CODE (type) == POINTER_TYPE
> && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
> TREE_TYPE (*node)
> = build_pointer_type
> (build_type_variant (TREE_TYPE (type), 1,
> TREE_THIS_VOLATILE (TREE_TYPE (type))));
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "transparent_union" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_transparent_union_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags;
> bool *no_add_attrs;
> {
> tree decl = NULL_TREE;
> tree *type = NULL;
> int is_type = 0;
>
> if (DECL_P (*node))
> {
> decl = *node;
> type = &TREE_TYPE (decl);
> is_type = TREE_CODE (*node) == TYPE_DECL;
> }
> else if (TYPE_P (*node))
> type = node, is_type = 1;
>
> if (is_type
> && TREE_CODE (*type) == UNION_TYPE
> && (decl == 0
> || (TYPE_FIELDS (*type) != 0
> && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
> {
> if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
> *type = build_type_copy (*type);
> TYPE_TRANSPARENT_UNION (*type) = 1;
> }
> else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
> && TREE_CODE (*type) == UNION_TYPE
> && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
> DECL_TRANSPARENT_UNION (decl) = 1;
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "constructor" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_constructor_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> tree decl = *node;
> tree type = TREE_TYPE (decl);
>
> if (TREE_CODE (decl) == FUNCTION_DECL
> && TREE_CODE (type) == FUNCTION_TYPE
> && decl_function_context (decl) == 0)
> {
> DECL_STATIC_CONSTRUCTOR (decl) = 1;
> TREE_USED (decl) = 1;
> }
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "destructor" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_destructor_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> tree decl = *node;
> tree type = TREE_TYPE (decl);
>
> if (TREE_CODE (decl) == FUNCTION_DECL
> && TREE_CODE (type) == FUNCTION_TYPE
> && decl_function_context (decl) == 0)
> {
> DECL_STATIC_DESTRUCTOR (decl) = 1;
> TREE_USED (decl) = 1;
> }
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "mode" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_mode_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> tree type = *node;
>
> *no_add_attrs = true;
>
> if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> else
> {
> int j;
> const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
> int len = strlen (p);
> enum machine_mode mode = VOIDmode;
> tree typefm;
>
> if (len > 4 && p[0] == '_' && p[1] == '_'
> && p[len - 1] == '_' && p[len - 2] == '_')
> {
> char *newp = (char *) alloca (len - 1);
>
> strcpy (newp, &p[2]);
> newp[len - 4] = '\0';
> p = newp;
> }
>
> /* Change this type to have a type with the specified mode.
> First check for the special modes. */
> if (! strcmp (p, "byte"))
> mode = byte_mode;
> else if (!strcmp (p, "word"))
> mode = word_mode;
> else if (! strcmp (p, "pointer"))
> mode = ptr_mode;
> else
> for (j = 0; j < NUM_MACHINE_MODES; j++)
> if (!strcmp (p, GET_MODE_NAME (j)))
> mode = (enum machine_mode) j;
>
> if (mode == VOIDmode)
> error ("unknown machine mode `%s'", p);
> else if (0 == (typefm = (*lang_hooks.types.type_for_mode)
> (mode, TREE_UNSIGNED (type))))
> error ("no data type for mode `%s'", p);
> else
> {
> /* If this is a vector, make sure we either have hardware
> support, or we can emulate it. */
> if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
> || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
> && !vector_mode_valid_p (mode))
> {
> error ("unable to emulate '%s'", GET_MODE_NAME (mode));
> return NULL_TREE;
> }
>
> *node = typefm;
> /* No need to layout the type here. The caller should do this. */
> }
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "section" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_section_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name ATTRIBUTE_UNUSED;
> tree args;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> tree decl = *node;
>
> if (targetm.have_named_sections)
> {
> if ((TREE_CODE (decl) == FUNCTION_DECL
> || TREE_CODE (decl) == VAR_DECL)
> && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
> {
> if (TREE_CODE (decl) == VAR_DECL
> && current_function_decl != NULL_TREE
> && ! TREE_STATIC (decl))
> {
> error_with_decl (decl,
> "section attribute cannot be specified for local variables");
> *no_add_attrs = true;
> }
>
> /* The decl may have already been given a section attribute
> from a previous declaration. Ensure they match. */
> else if (DECL_SECTION_NAME (decl) != NULL_TREE
> && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
> TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
> {
> error_with_decl (*node,
> "section of `%s' conflicts with previous declaration");
> *no_add_attrs = true;
> }
> else
> DECL_SECTION_NAME (decl) = TREE_VALUE (args);
> }
> else
> {
> error_with_decl (*node,
> "section attribute not allowed for `%s'");
> *no_add_attrs = true;
> }
> }
> else
> {
> error_with_decl (*node,
> "section attributes are not supported for this target");
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "aligned" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_aligned_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name ATTRIBUTE_UNUSED;
> tree args;
> int flags;
> bool *no_add_attrs;
> {
> tree decl = NULL_TREE;
> tree *type = NULL;
> int is_type = 0;
> tree align_expr = (args ? TREE_VALUE (args)
> : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
> int i;
>
> if (DECL_P (*node))
> {
> decl = *node;
> type = &TREE_TYPE (decl);
> is_type = TREE_CODE (*node) == TYPE_DECL;
> }
> else if (TYPE_P (*node))
> type = node, is_type = 1;
>
> /* Strip any NOPs of any kind. */
> while (TREE_CODE (align_expr) == NOP_EXPR
> || TREE_CODE (align_expr) == CONVERT_EXPR
> || TREE_CODE (align_expr) == NON_LVALUE_EXPR)
> align_expr = TREE_OPERAND (align_expr, 0);
>
> if (TREE_CODE (align_expr) != INTEGER_CST)
> {
> error ("requested alignment is not a constant");
> *no_add_attrs = true;
> }
> else if ((i = tree_log2 (align_expr)) == -1)
> {
> error ("requested alignment is not a power of 2");
> *no_add_attrs = true;
> }
> else if (i > HOST_BITS_PER_INT - 2)
> {
> error ("requested alignment is too large");
> *no_add_attrs = true;
> }
> else if (is_type)
> {
> /* If we have a TYPE_DECL, then copy the type, so that we
> don't accidentally modify a builtin type. See pushdecl. */
> if (decl && TREE_TYPE (decl) != error_mark_node
> && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
> {
> tree tt = TREE_TYPE (decl);
> *type = build_type_copy (*type);
> DECL_ORIGINAL_TYPE (decl) = tt;
> TYPE_NAME (*type) = decl;
> TREE_USED (*type) = TREE_USED (decl);
> TREE_TYPE (decl) = *type;
> }
> else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
> *type = build_type_copy (*type);
>
> TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
> TYPE_USER_ALIGN (*type) = 1;
> }
> else if (TREE_CODE (decl) != VAR_DECL
> && TREE_CODE (decl) != FIELD_DECL)
> {
> error_with_decl (decl,
> "alignment may not be specified for `%s'");
> *no_add_attrs = true;
> }
> else
> {
> DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
> DECL_USER_ALIGN (decl) = 1;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "weak" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_weak_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name ATTRIBUTE_UNUSED;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs ATTRIBUTE_UNUSED;
> {
> declare_weak (*node);
>
> return NULL_TREE;
> }
>
> /* Handle an "alias" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_alias_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 ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
> || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
> {
> error_with_decl (decl,
> "`%s' defined both normally and as an alias");
> *no_add_attrs = true;
> }
> else if (decl_function_context (decl) == 0)
> {
> tree id;
>
> id = TREE_VALUE (args);
> if (TREE_CODE (id) != STRING_CST)
> {
> error ("alias arg not a string");
> *no_add_attrs = true;
> return NULL_TREE;
> }
> id = get_identifier (TREE_STRING_POINTER (id));
> /* This counts as a use of the object pointed to. */
> TREE_USED (id) = 1;
>
> if (TREE_CODE (decl) == FUNCTION_DECL)
> DECL_INITIAL (decl) = error_mark_node;
> else
> DECL_EXTERNAL (decl) = 0;
> }
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle an "visibility" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_visibility_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_function_context (decl) != 0 || ! TREE_PUBLIC (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 ("visibility arg not a string");
> *no_add_attrs = true;
> return NULL_TREE;
> }
> if (strcmp (TREE_STRING_POINTER (id), "hidden")
> && strcmp (TREE_STRING_POINTER (id), "protected")
> && strcmp (TREE_STRING_POINTER (id), "internal")
> && strcmp (TREE_STRING_POINTER (id), "default"))
> {
> 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;
> }
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "no_instrument_function" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_no_instrument_function_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> tree decl = *node;
>
> if (TREE_CODE (decl) != FUNCTION_DECL)
> {
> error_with_decl (decl,
> "`%s' attribute applies only to functions",
> IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
> else if (DECL_INITIAL (decl))
> {
> error_with_decl (decl,
> "can't set `%s' attribute after definition",
> IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
> else
> DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
>
> return NULL_TREE;
> }
>
> /* Handle a "malloc" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_malloc_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> if (TREE_CODE (*node) == FUNCTION_DECL)
> DECL_IS_MALLOC (*node) = 1;
> /* ??? TODO: Support types. */
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Handle a "no_limit_stack" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_no_limit_stack_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> tree decl = *node;
>
> if (TREE_CODE (decl) != FUNCTION_DECL)
> {
> error_with_decl (decl,
> "`%s' attribute applies only to functions",
> IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
> else if (DECL_INITIAL (decl))
> {
> error_with_decl (decl,
> "can't set `%s' attribute after definition",
> IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
> else
> DECL_NO_LIMIT_STACK (decl) = 1;
>
> return NULL_TREE;
> }
>
> /* Handle a "pure" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_pure_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> if (TREE_CODE (*node) == FUNCTION_DECL)
> DECL_IS_PURE (*node) = 1;
> /* ??? TODO: Support types. */
> else
> {
> 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;
> }
>
> /* Handle a "deprecated" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_deprecated_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags;
> bool *no_add_attrs;
> {
> tree type = NULL_TREE;
> int warn = 0;
> const char *what = NULL;
>
> if (DECL_P (*node))
> {
> tree decl = *node;
> type = TREE_TYPE (decl);
>
> if (TREE_CODE (decl) == TYPE_DECL
> || TREE_CODE (decl) == PARM_DECL
> || TREE_CODE (decl) == VAR_DECL
> || TREE_CODE (decl) == FUNCTION_DECL
> || TREE_CODE (decl) == FIELD_DECL)
> TREE_DEPRECATED (decl) = 1;
> else
> warn = 1;
> }
> else if (TYPE_P (*node))
> {
> if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
> *node = build_type_copy (*node);
> TREE_DEPRECATED (*node) = 1;
> type = *node;
> }
> else
> warn = 1;
>
> if (warn)
> {
> *no_add_attrs = true;
> if (type && TYPE_NAME (type))
> {
> if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
> what = IDENTIFIER_POINTER (TYPE_NAME (*node));
> else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
> && DECL_NAME (TYPE_NAME (type)))
> what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
> }
> if (what)
> warning ("`%s' attribute ignored for `%s'",
> IDENTIFIER_POINTER (name), what);
> else
> warning ("`%s' attribute ignored",
> IDENTIFIER_POINTER (name));
> }
>
> return NULL_TREE;
> }
>
> /* Keep a list of vector type nodes we created in handle_vector_size_attribute,
> to prevent us from duplicating type nodes unnecessarily.
> 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 GTY(()) tree vector_type_node_list = 0;
>
> /* Handle a "vector_size" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_vector_size_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> unsigned HOST_WIDE_INT vecsize, nunits;
> enum machine_mode mode, orig_mode, new_mode;
> tree type = *node, new_type = NULL_TREE;
> tree type_list_node;
>
> *no_add_attrs = true;
>
> if (! host_integerp (TREE_VALUE (args), 1))
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> return NULL_TREE;
> }
>
> /* Get the vector size (in bytes). */
> vecsize = tree_low_cst (TREE_VALUE (args), 1);
>
> /* We need to provide for vector pointers, vector arrays, and
> functions returning vectors. For example:
>
> __attribute__((vector_size(16))) short *foo;
>
> In this case, the mode is SI, but the type being modified is
> HI, so we need to look further. */
>
> while (POINTER_TYPE_P (type)
> || TREE_CODE (type) == FUNCTION_TYPE
> || TREE_CODE (type) == ARRAY_TYPE)
> type = TREE_TYPE (type);
>
> /* Get the mode of the type being modified. */
> orig_mode = TYPE_MODE (type);
>
> if (TREE_CODE (type) == RECORD_TYPE
> || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT
> && GET_MODE_CLASS (orig_mode) != MODE_INT)
> || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
> {
> error ("invalid vector type for attribute `%s'",
> IDENTIFIER_POINTER (name));
> return NULL_TREE;
> }
>
> /* Calculate how many units fit in the vector. */
> nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
>
> /* Find a suitably sized vector. */
> new_mode = VOIDmode;
> for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT
> ? MODE_VECTOR_INT
> : MODE_VECTOR_FLOAT);
> mode != VOIDmode;
> mode = GET_MODE_WIDER_MODE (mode))
> if (vecsize == GET_MODE_SIZE (mode)
> && nunits == (unsigned HOST_WIDE_INT) GET_MODE_NUNITS (mode))
> {
> new_mode = mode;
> break;
> }
>
> if (new_mode == VOIDmode)
> {
> error ("no vector mode with the size and type specified could be found");
> return NULL_TREE;
> }
>
> for (type_list_node = vector_type_node_list; type_list_node;
> type_list_node = TREE_CHAIN (type_list_node))
> {
> tree other_type = TREE_VALUE (type_list_node);
> tree record = TYPE_DEBUG_REPRESENTATION_TYPE (other_type);
> tree fields = TYPE_FIELDS (record);
> tree field_type = TREE_TYPE (fields);
> tree array_type = TREE_TYPE (field_type);
> if (TREE_CODE (fields) != FIELD_DECL
> || TREE_CODE (field_type) != ARRAY_TYPE)
> abort ();
>
> if (TYPE_MODE (other_type) == mode && type == array_type)
> {
> new_type = other_type;
> break;
> }
> }
>
> if (new_type == NULL_TREE)
> {
> tree index, array, rt, list_node;
>
> new_type = (*lang_hooks.types.type_for_mode) (new_mode,
> TREE_UNSIGNED (type));
>
> if (!new_type)
> {
> error ("no vector mode with the size and type specified could be found");
> return NULL_TREE;
> }
>
> new_type = build_type_copy (new_type);
>
> /* If this is a vector, make sure we either have hardware
> support, or we can emulate it. */
> if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
> || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
> && !vector_mode_valid_p (mode))
> {
> error ("unable to emulate '%s'", GET_MODE_NAME (mode));
> return NULL_TREE;
> }
>
> /* Set the debug information here, because this is the only
> place where we know the underlying type for a vector made
> with vector_size. For debugging purposes we pretend a vector
> is an array within a structure. */
> index = build_int_2 (TYPE_VECTOR_SUBPARTS (new_type) - 1, 0);
> array = build_array_type (type, build_index_type (index));
> rt = make_node (RECORD_TYPE);
>
> TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
> DECL_CONTEXT (TYPE_FIELDS (rt)) = rt;
> layout_type (rt);
> TYPE_DEBUG_REPRESENTATION_TYPE (new_type) = rt;
>
> list_node = build_tree_list (NULL, new_type);
> TREE_CHAIN (list_node) = vector_type_node_list;
> vector_type_node_list = list_node;
> }
>
> /* Build back pointers if needed. */
> *node = vector_size_helper (*node, new_type);
>
> return NULL_TREE;
> }
>
> /* HACK. GROSS. This is absolutely disgusting. I wish there was a
> better way.
>
> If we requested a pointer to a vector, build up the pointers that
> we stripped off while looking for the inner type. Similarly for
> return values from functions.
>
> The argument "type" is the top of the chain, and "bottom" is the
> new type which we will point to. */
>
> static tree
> vector_size_helper (type, bottom)
> tree type, bottom;
> {
> tree inner, outer;
>
> if (POINTER_TYPE_P (type))
> {
> inner = vector_size_helper (TREE_TYPE (type), bottom);
> outer = build_pointer_type (inner);
> }
> else if (TREE_CODE (type) == ARRAY_TYPE)
> {
> inner = vector_size_helper (TREE_TYPE (type), bottom);
> outer = build_array_type (inner, TYPE_VALUES (type));
> }
> else if (TREE_CODE (type) == FUNCTION_TYPE)
> {
> inner = vector_size_helper (TREE_TYPE (type), bottom);
> outer = build_function_type (inner, TYPE_VALUES (type));
> }
> else
> return bottom;
>
> TREE_READONLY (outer) = TREE_READONLY (type);
> TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type);
>
> return outer;
> }
>
> /* Handle the "nonnull" attribute. */
> static tree
> handle_nonnull_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name ATTRIBUTE_UNUSED;
> tree args;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> tree type = *node;
> 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
> will have the correct types when we actually check them later. */
> if (! args)
> {
> if (! TYPE_ARG_TYPES (type))
> {
> error ("nonnull attribute without arguments on a non-prototype");
> *no_add_attrs = true;
> }
> return NULL_TREE;
> }
>
> /* Argument list specified. Verify that each argument number references
> a pointer argument. */
> for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
> {
> tree argument;
> unsigned HOST_WIDE_INT arg_num, ck_num;
>
> if (! get_nonnull_operand (TREE_VALUE (args), &arg_num))
> {
> error ("nonnull argument has invalid operand number (arg %lu)",
> (unsigned long) attr_arg_num);
> *no_add_attrs = true;
> return NULL_TREE;
> }
>
> argument = TYPE_ARG_TYPES (type);
> if (argument)
> {
> for (ck_num = 1; ; ck_num++)
> {
> if (! argument || ck_num == arg_num)
> break;
> argument = TREE_CHAIN (argument);
> }
>
> if (! argument
> || TREE_CODE (TREE_VALUE (argument)) == VOID_TYPE)
> {
> error ("nonnull argument with out-of-range operand number (arg %lu, operand %lu)",
> (unsigned long) attr_arg_num, (unsigned long) arg_num);
> *no_add_attrs = true;
> return NULL_TREE;
> }
>
> if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE)
> {
> error ("nonnull argument references non-pointer operand (arg %lu, operand %lu)",
> (unsigned long) attr_arg_num, (unsigned long) arg_num);
> *no_add_attrs = true;
> return NULL_TREE;
> }
> }
> }
>
> return NULL_TREE;
> }
>
> /* Check the argument list of a function call for null in argument slots
> that are marked as requiring a non-null pointer argument. */
>
> static void
> check_function_nonnull (attrs, params)
> tree attrs;
> tree params;
> {
> tree a, args, param;
> int param_num;
>
> for (a = attrs; a; a = TREE_CHAIN (a))
> {
> if (is_attribute_p ("nonnull", TREE_PURPOSE (a)))
> {
> args = TREE_VALUE (a);
>
> /* Walk the argument list. If we encounter an argument number we
> should check for non-null, do it. If the attribute has no args,
> then every pointer argument is checked (in which case the check
> for pointer type is done in check_nonnull_arg). */
> for (param = params, param_num = 1; ;
> param_num++, param = TREE_CHAIN (param))
> {
> if (! param)
> break;
> if (! args || nonnull_check_p (args, param_num))
> check_function_arguments_recurse (check_nonnull_arg, NULL,
> TREE_VALUE (param),
> param_num);
> }
> }
> }
> }
>
> /* Helper for check_function_nonnull; given a list of operands which
> must be non-null in ARGS, determine if operand PARAM_NUM should be
> checked. */
>
> static bool
> nonnull_check_p (args, param_num)
> tree args;
> unsigned HOST_WIDE_INT param_num;
> {
> unsigned HOST_WIDE_INT arg_num;
>
> for (; args; args = TREE_CHAIN (args))
> {
> if (! get_nonnull_operand (TREE_VALUE (args), &arg_num))
> abort ();
>
> if (arg_num == param_num)
> return true;
> }
> return false;
> }
>
> /* Check that the function argument PARAM (which is operand number
> PARAM_NUM) is non-null. This is called by check_function_nonnull
> via check_function_arguments_recurse. */
>
> static void
> check_nonnull_arg (ctx, param, param_num)
> void *ctx ATTRIBUTE_UNUSED;
> tree param;
> unsigned HOST_WIDE_INT param_num;
> {
> /* Just skip checking the argument if it's not a pointer. This can
> happen if the "nonnull" attribute was given without an operand
> list (which means to check every pointer argument). */
>
> if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE)
> return;
>
> if (integer_zerop (param))
> warning ("null argument where non-null required (arg %lu)",
> (unsigned long) param_num);
> }
>
> /* Helper for nonnull attribute handling; fetch the operand number
> from the attribute argument list. */
>
> static bool
> get_nonnull_operand (arg_num_expr, valp)
> tree arg_num_expr;
> unsigned HOST_WIDE_INT *valp;
> {
> /* Strip any conversions from the arg number and verify they
> are constants. */
> while (TREE_CODE (arg_num_expr) == NOP_EXPR
> || TREE_CODE (arg_num_expr) == CONVERT_EXPR
> || TREE_CODE (arg_num_expr) == NON_LVALUE_EXPR)
> arg_num_expr = TREE_OPERAND (arg_num_expr, 0);
>
> if (TREE_CODE (arg_num_expr) != INTEGER_CST
> || TREE_INT_CST_HIGH (arg_num_expr) != 0)
> return false;
>
> *valp = TREE_INT_CST_LOW (arg_num_expr);
> return true;
> }
>
> /* Handle a "nothrow" attribute; arguments as in
> struct attribute_spec.handler. */
>
> static tree
> handle_nothrow_attribute (node, name, args, flags, no_add_attrs)
> tree *node;
> tree name;
> tree args ATTRIBUTE_UNUSED;
> int flags ATTRIBUTE_UNUSED;
> bool *no_add_attrs;
> {
> if (TREE_CODE (*node) == FUNCTION_DECL)
> TREE_NOTHROW (*node) = 1;
> /* ??? TODO: Support types. */
> else
> {
> warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
> *no_add_attrs = true;
> }
>
> return NULL_TREE;
> }
>
> /* Check for valid arguments being passed to a function. */
> void
> check_function_arguments (attrs, params)
> tree attrs;
> tree params;
> {
> /* Check for null being passed in a pointer argument that must be
> non-null. We also need to do this if format checking is enabled. */
>
> if (warn_nonnull)
> check_function_nonnull (attrs, params);
>
> /* Check for errors in format strings. */
>
> if (warn_format)
> check_function_format (NULL, attrs, params);
> }
>
> /* Generic argument checking recursion routine. PARAM is the argument to
> be checked. PARAM_NUM is the number of the argument. CALLBACK is invoked
> once the argument is resolved. CTX is context for the callback. */
> void
> check_function_arguments_recurse (callback, ctx, param, param_num)
> void (*callback) PARAMS ((void *, tree, unsigned HOST_WIDE_INT));
> void *ctx;
> tree param;
> unsigned HOST_WIDE_INT param_num;
> {
> if (TREE_CODE (param) == NOP_EXPR)
> {
> /* Strip coercion. */
> check_function_arguments_recurse (callback, ctx,
> TREE_OPERAND (param, 0), param_num);
> return;
> }
>
> if (TREE_CODE (param) == CALL_EXPR)
> {
> tree type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (param, 0)));
> tree attrs;
> bool found_format_arg = false;
>
> /* See if this is a call to a known internationalization function
> that modifies a format arg. Such a function may have multiple
> format_arg attributes (for example, ngettext). */
>
> for (attrs = TYPE_ATTRIBUTES (type);
> attrs;
> attrs = TREE_CHAIN (attrs))
> if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs)))
> {
> tree inner_args;
> tree format_num_expr;
> int format_num;
> int i;
>
> /* Extract the argument number, which was previously checked
> to be valid. */
> format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
> while (TREE_CODE (format_num_expr) == NOP_EXPR
> || TREE_CODE (format_num_expr) == CONVERT_EXPR
> || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR)
> format_num_expr = TREE_OPERAND (format_num_expr, 0);
>
> if (TREE_CODE (format_num_expr) != INTEGER_CST
> || TREE_INT_CST_HIGH (format_num_expr) != 0)
> abort ();
>
> format_num = TREE_INT_CST_LOW (format_num_expr);
>
> for (inner_args = TREE_OPERAND (param, 1), i = 1;
> inner_args != 0;
> inner_args = TREE_CHAIN (inner_args), i++)
> if (i == format_num)
> {
> check_function_arguments_recurse (callback, ctx,
> TREE_VALUE (inner_args),
> param_num);
> found_format_arg = true;
> break;
> }
> }
>
> /* If we found a format_arg attribute and did a recursive check,
> we are done with checking this argument. Otherwise, we continue
> and this will be considered a non-literal. */
> if (found_format_arg)
> return;
> }
>
> if (TREE_CODE (param) == COND_EXPR)
> {
> /* Check both halves of the conditional expression. */
> check_function_arguments_recurse (callback, ctx,
> TREE_OPERAND (param, 1), param_num);
> check_function_arguments_recurse (callback, ctx,
> TREE_OPERAND (param, 2), param_num);
> return;
> }
>
> (*callback) (ctx, param, param_num);
> }
>
> #include "gt-c-common.h"