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