/* Subroutines shared by all languages that are variants of C.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
tree long_unsigned_type_node;
tree long_long_unsigned_type_node;
- tree boolean_type_node;
- tree boolean_false_node;
- tree boolean_true_node;
+ tree truthvalue_type_node;
+ tree truthvalue_false_node;
+ tree truthvalue_true_node;
tree ptrdiff_type_node;
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. */
int warn_format_security;
-
+/* Zero means that faster, ...NonNil variants of objc_msgSend...
+ calls will be used in ObjC; passing nil receivers to such calls
+ will most likely result in crashes. */
+int flag_nil_receivers = 1;
+
+/* Nonzero means that we will allow new ObjC exception syntax (@throw,
+ @try, etc.) in source code. */
+int flag_objc_exceptions = 0;
+
+/* Nonzero means that code generation will be altered to support
+ "zero-link" execution. This currently affects ObjC only, but may
+ affect other languages in the future. */
+int flag_zero_link = 0;
+
+/* Nonzero means emit an '__OBJC, __image_info' for the current translation
+ unit. It will inform the ObjC runtime that class definition(s) herein
+ contained are to replace one(s) previously loaded. */
+int flag_replace_objc_classes = 0;
+
/* C/ObjC language option variables. */
int flag_isoc99;
-/* Nonzero means that we have builtin functions, and main is an int */
+/* 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_traditional;
+/* Nonzero means warn for a declaration found after a statement. */
+
+int warn_declaration_after_statement;
+
/* Nonzero means warn for non-prototype function decls
or non-prototyped defs without previous prototype. */
int warn_sequence_point;
+/* Nonzero means warn about uninitialized variable when it is initialized with itself.
+ For example: int i = i;, GCC will not warn about this when warn_init_self is nonzero. */
+
+int warn_init_self;
+
/* Nonzero means to warn about compile-time division by zero. */
int warn_div_by_zero = 1;
int warn_nonnull;
+/* Warn about old-style parameter declaration. */
+
+int warn_old_style_definition;
+
/* ObjC language option variables. */
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;
int flag_weak = 1;
+/* 0 means we want the preprocessor to not emit line directives for
+ the current working directory. 1 means we want it to do it. -1
+ means we should decide depending on whether debugging information
+ is being emitted or not. */
+
+int flag_working_directory = -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_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. */
static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
-static tree vector_size_helper (tree, tree);
+static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
+ bool *);
static void check_function_nonnull (tree, tree);
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
{ "may_alias", 0, 0, false, true, false, NULL },
{ "cleanup", 1, 1, true, false, false,
handle_cleanup_attribute },
+ { "warn_unused_result", 0, 0, false, true, true,
+ handle_warn_unused_result_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
if (if_stack_space == 0)
{
if_stack_space = 10;
- if_stack = (if_elt *) xmalloc (10 * sizeof (if_elt));
+ if_stack = xmalloc (10 * sizeof (if_elt));
}
else if (if_stack_space == if_stack_pointer)
{
if_stack_space += 10;
- if_stack = (if_elt *) xrealloc (if_stack, if_stack_space * sizeof (if_elt));
+ if_stack = xrealloc (if_stack, if_stack_space * sizeof (if_elt));
}
IF_COND (if_stmt) = cond;
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);
+ {
+ if (TREE_CODE (*p) == EXPR_STMT)
+ p = &TREE_CHAIN (*p);
+ else
+ p = &TREE_OPERAND(*p, 0);
+ }
+
p = &COMPOUND_BODY (*p);
if (TREE_CODE (*p) == SCOPE_STMT)
p = &TREE_CHAIN (*p);
const char *
fname_as_string (int pretty_p)
{
- const char *name = NULL;
-
- if (pretty_p)
- name = (current_function_decl
- ? (*lang_hooks.decl_printable_name) (current_function_decl, 2)
- : "top level");
- else if (current_function_decl && DECL_NAME (current_function_decl))
- name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
- else
- name = "";
+ const char *name = "top level";
+ int vrb = 2;
+
+ if (! pretty_p)
+ {
+ name = "";
+ vrb = 0;
+ }
+
+ if (current_function_decl)
+ name = (*lang_hooks.decl_printable_name) (current_function_decl, vrb);
+
return name;
}
input_line = saved_lineno;
}
if (!ix && !current_function_decl)
- pedwarn ("%H'%D' is not defined outside of function scope",
- &DECL_SOURCE_LOCATION (decl), decl);
+ pedwarn ("%J'%D' is not defined outside of function scope", decl, decl);
return decl;
}
return value;
}
\f
-static int is_valid_printf_arglist (tree);
-static rtx c_expand_builtin (tree, rtx, enum machine_mode,
- enum expand_modifier);
-static rtx c_expand_builtin_printf (tree, rtx, enum machine_mode,
- enum expand_modifier, int, int);
-static rtx c_expand_builtin_fprintf (tree, rtx, enum machine_mode,
- enum expand_modifier, int, int);
-\f
/* Print a warning if a constant expression had overflow in folding.
Invoke this function on every expression that the language
requires to be a constant expression.
new_tlist (struct tlist *next, tree t, tree writer)
{
struct tlist *l;
- l = (struct tlist *) obstack_alloc (&tlist_obstack, sizeof *l);
+ l = obstack_alloc (&tlist_obstack, sizeof *l);
l->next = next;
l->expr = t;
l->writer = writer;
if (! t)
{
- t = (struct tlist_cache *) obstack_alloc (&tlist_obstack,
- sizeof *t);
+ t = obstack_alloc (&tlist_obstack, sizeof *t);
t->next = save_expr_cache;
t->expr = x;
save_expr_cache = t;
return 0;
}
+/* Used for communication between c_common_type_for_mode and
+ c_register_builtin_type. */
+static GTY(()) tree registered_builtin_types;
+
/* Return a data type that has machine mode MODE.
If the mode is an integer,
then UNSIGNEDP selects between signed and unsigned types. */
tree
c_common_type_for_mode (enum machine_mode mode, int unsignedp)
{
+ tree t;
+
if (mode == TYPE_MODE (integer_type_node))
return unsignedp ? unsigned_type_node : integer_type_node;
if (mode == TYPE_MODE (long_double_type_node))
return long_double_type_node;
+ if (mode == TYPE_MODE (void_type_node))
+ return void_type_node;
+
if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
- return build_pointer_type (char_type_node);
+ return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode);
if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
- return build_pointer_type (integer_type_node);
+ return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode);
switch (mode)
{
break;
}
+ for (t = registered_builtin_types; t; t = TREE_CHAIN (t))
+ if (TYPE_MODE (TREE_VALUE (t)) == mode)
+ return TREE_VALUE (t);
+
return 0;
}
|| TREE_UNSIGNED (type) == unsignedp)
return type;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
+ /* Must check the mode of the types, not the precision. Enumeral types
+ in C++ have precision set to match their range, but may use a wider
+ mode to match an ABI. If we change modes, we may wind up with bad
+ conversions. */
+
+ if (TYPE_MODE (type) == TYPE_MODE (signed_char_type_node))
return unsignedp ? unsigned_char_type_node : signed_char_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
+ if (TYPE_MODE (type) == TYPE_MODE (integer_type_node))
return unsignedp ? unsigned_type_node : integer_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
+ if (TYPE_MODE (type) == TYPE_MODE (short_integer_type_node))
return unsignedp ? short_unsigned_type_node : short_integer_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
+ if (TYPE_MODE (type) == TYPE_MODE (long_integer_type_node))
return unsignedp ? long_unsigned_type_node : long_integer_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
+ if (TYPE_MODE (type) == TYPE_MODE (long_long_integer_type_node))
return (unsignedp ? long_long_unsigned_type_node
: long_long_integer_type_node);
- if (TYPE_PRECISION (type) == TYPE_PRECISION (widest_integer_literal_type_node))
+ if (TYPE_MODE (type) == TYPE_MODE (widest_integer_literal_type_node))
return (unsignedp ? widest_unsigned_literal_type_node
: widest_integer_literal_type_node);
#if HOST_BITS_PER_WIDE_INT >= 64
- if (TYPE_PRECISION (type) == TYPE_PRECISION (intTI_type_node))
+ if (TYPE_MODE (type) == TYPE_MODE (intTI_type_node))
return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
#endif
- if (TYPE_PRECISION (type) == TYPE_PRECISION (intDI_type_node))
+ if (TYPE_MODE (type) == TYPE_MODE (intDI_type_node))
return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (intSI_type_node))
+ if (TYPE_MODE (type) == TYPE_MODE (intSI_type_node))
return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (intHI_type_node))
+ if (TYPE_MODE (type) == TYPE_MODE (intHI_type_node))
return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
- if (TYPE_PRECISION (type) == TYPE_PRECISION (intQI_type_node))
+ if (TYPE_MODE (type) == TYPE_MODE (intQI_type_node))
return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
return type;
}
+
+/* The C version of the register_builtin_type langhook. */
+
+void
+c_register_builtin_type (tree type, const char* name)
+{
+ tree decl;
+
+ decl = build_decl (TYPE_DECL, get_identifier (name), type);
+ DECL_ARTIFICIAL (decl) = 1;
+ if (!TYPE_NAME (type))
+ TYPE_NAME (type) = decl;
+ pushdecl (decl);
+
+ registered_builtin_types = tree_cons (0, type, registered_builtin_types);
+}
+
\f
/* Return the minimum number of bits needed to represent VALUE in a
signed or unsigned type, UNSIGNEDP says which. */
type = c_common_signed_or_unsigned_type (unsignedp0,
TREE_TYPE (primop0));
- /* If TYPE is an enumeration, then we need to get its min/max
- values from it's underlying integral type, not the enumerated
- type itself. */
- if (TREE_CODE (type) == ENUMERAL_TYPE)
+ /* In C, if TYPE is an enumeration, then we need to get its
+ min/max values from it's underlying integral type, not the
+ enumerated type itself. In C++, TYPE_MAX_VALUE and
+ TYPE_MIN_VALUE have already been set correctly on the
+ enumeration type. */
+ if (!c_dialect_cxx() && TREE_CODE (type) == ENUMERAL_TYPE)
type = c_common_type_for_size (TYPE_PRECISION (type), unsignedp0);
maxval = TYPE_MAX_VALUE (type);
if (code == NE_EXPR)
{
if (max_lt || min_gt)
- val = boolean_true_node;
+ val = truthvalue_true_node;
}
else if (code == EQ_EXPR)
{
if (max_lt || min_gt)
- val = boolean_false_node;
+ val = truthvalue_false_node;
}
else if (code == LT_EXPR)
{
if (max_lt)
- val = boolean_true_node;
+ val = truthvalue_true_node;
if (!min_lt)
- val = boolean_false_node;
+ val = truthvalue_false_node;
}
else if (code == GT_EXPR)
{
if (min_gt)
- val = boolean_true_node;
+ val = truthvalue_true_node;
if (!max_gt)
- val = boolean_false_node;
+ val = truthvalue_false_node;
}
else if (code == LE_EXPR)
{
if (!max_gt)
- val = boolean_true_node;
+ val = truthvalue_true_node;
if (min_gt)
- val = boolean_false_node;
+ val = truthvalue_false_node;
}
else if (code == GE_EXPR)
{
if (!min_lt)
- val = boolean_true_node;
+ val = truthvalue_true_node;
if (max_lt)
- val = boolean_false_node;
+ val = truthvalue_false_node;
}
/* If primop0 was sign-extended and unsigned comparison specd,
if (TREE_CODE (primop0) != INTEGER_CST)
{
- if (val == boolean_false_node)
+ if (val == truthvalue_false_node)
warning ("comparison is always false due to limited range of data type");
- if (val == boolean_true_node)
+ if (val == truthvalue_true_node)
warning ("comparison is always true due to limited range of data type");
}
&& ! TREE_OVERFLOW (convert (c_common_signed_type (type),
primop0))))
warning ("comparison of unsigned expression >= 0 is always true");
- value = boolean_true_node;
+ value = truthvalue_true_node;
break;
case LT_EXPR:
&& ! TREE_OVERFLOW (convert (c_common_signed_type (type),
primop0))))
warning ("comparison of unsigned expression < 0 is always false");
- value = boolean_false_node;
+ value = truthvalue_false_node;
break;
default:
*op0_ptr = convert (type, primop0);
*op1_ptr = convert (type, primop1);
- *restype_ptr = boolean_type_node;
+ *restype_ptr = truthvalue_type_node;
return 0;
}
This preparation consists of taking the ordinary
representation of an expression expr and producing a valid tree
boolean expression describing whether expr is nonzero. We could
- simply always do build_binary_op (NE_EXPR, expr, boolean_false_node, 1),
+ simply always do build_binary_op (NE_EXPR, expr, truthvalue_false_node, 1),
but we optimize comparisons, &&, ||, and !.
- The resulting type should always be `boolean_type_node'. */
+ The resulting type should always be `truthvalue_type_node'. */
tree
c_common_truthvalue_conversion (tree expr)
if (TREE_CODE (expr) == ERROR_MARK)
return expr;
-#if 0 /* This appears to be wrong for C++. */
- /* These really should return error_mark_node after 2.4 is stable.
- But not all callers handle ERROR_MARK properly. */
- switch (TREE_CODE (TREE_TYPE (expr)))
- {
- case RECORD_TYPE:
- error ("struct type value used where scalar is required");
- return boolean_false_node;
-
- case UNION_TYPE:
- error ("union type value used where scalar is required");
- return boolean_false_node;
-
- case ARRAY_TYPE:
- error ("array type value used where scalar is required");
- return boolean_false_node;
-
- default:
- break;
- }
-#endif /* 0 */
+ if (TREE_CODE (expr) == FUNCTION_DECL)
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
switch (TREE_CODE (expr))
{
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
case TRUTH_NOT_EXPR:
- TREE_TYPE (expr) = boolean_type_node;
+ TREE_TYPE (expr) = truthvalue_type_node;
return expr;
case ERROR_MARK:
return expr;
case INTEGER_CST:
- return integer_zerop (expr) ? boolean_false_node : boolean_true_node;
+ return integer_zerop (expr) ? truthvalue_false_node : truthvalue_true_node;
case REAL_CST:
- return real_zerop (expr) ? boolean_false_node : boolean_true_node;
+ return real_zerop (expr) ? truthvalue_false_node : truthvalue_true_node;
case ADDR_EXPR:
- /* If we are taking the address of an external decl, it might be zero
- if it is weak, so we cannot optimize. */
- if (DECL_P (TREE_OPERAND (expr, 0))
- && DECL_EXTERNAL (TREE_OPERAND (expr, 0)))
- break;
+ {
+ if (TREE_CODE (TREE_OPERAND (expr, 0)) == FUNCTION_DECL
+ && ! DECL_WEAK (TREE_OPERAND (expr, 0)))
+ {
+ /* Common Ada/Pascal programmer's mistake. We always warn
+ about this since it is so bad. */
+ warning ("the address of `%D', will always evaluate as `true'",
+ TREE_OPERAND (expr, 0));
+ return truthvalue_true_node;
+ }
- if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
- return build (COMPOUND_EXPR, boolean_type_node,
- TREE_OPERAND (expr, 0), boolean_true_node);
- else
- return boolean_true_node;
+ /* If we are taking the address of an external decl, it might be
+ zero if it is weak, so we cannot optimize. */
+ if (DECL_P (TREE_OPERAND (expr, 0))
+ && DECL_EXTERNAL (TREE_OPERAND (expr, 0)))
+ break;
+
+ if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
+ return build (COMPOUND_EXPR, truthvalue_type_node,
+ TREE_OPERAND (expr, 0), truthvalue_true_node);
+ else
+ return truthvalue_true_node;
+ }
case COMPLEX_EXPR:
return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
+ (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0)),
+ (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 1)),
0);
case NEGATE_EXPR:
case ABS_EXPR:
case FLOAT_EXPR:
- case FFS_EXPR:
- case POPCOUNT_EXPR:
/* These don't change whether an object is nonzero or zero. */
- return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+ return (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0));
case LROTATE_EXPR:
case RROTATE_EXPR:
/* 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),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+ return build (COMPOUND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 1),
+ (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0)));
else
- return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+ return (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0));
case COND_EXPR:
/* Distribute the conversion into the arms of a COND_EXPR. */
- return fold (build (COND_EXPR, boolean_type_node, TREE_OPERAND (expr, 0),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 2))));
+ return fold (build (COND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 0),
+ (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 1)),
+ (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 2))));
case CONVERT_EXPR:
/* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
|| TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
break;
- /* fall through... */
+ /* Fall through.... */
case NOP_EXPR:
/* If this is widening the argument, we can ignore it. */
if (TYPE_PRECISION (TREE_TYPE (expr))
>= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
- return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+ return (*lang_hooks.truthvalue_conversion) (TREE_OPERAND (expr, 0));
break;
case MINUS_EXPR:
be false. */
if (HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (TREE_OPERAND (expr, 0)))))
break;
- /* fall through... */
+ /* Fall through.... */
case BIT_XOR_EXPR:
/* This and MINUS_EXPR can be changed into a comparison of the
two objects. */
case BIT_AND_EXPR:
if (integer_onep (TREE_OPERAND (expr, 1))
- && TREE_TYPE (expr) != boolean_type_node)
+ && TREE_TYPE (expr) != truthvalue_type_node)
/* Using convert here would cause infinite recursion. */
- return build1 (NOP_EXPR, boolean_type_node, expr);
+ return build1 (NOP_EXPR, truthvalue_type_node, expr);
break;
case MODIFY_EXPR:
return (build_binary_op
((TREE_SIDE_EFFECTS (expr)
? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
- c_common_truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)),
- c_common_truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)),
+ (*lang_hooks.truthvalue_conversion) (build_unary_op (REALPART_EXPR, t, 0)),
+ (*lang_hooks.truthvalue_conversion) (build_unary_op (IMAGPART_EXPR, t, 0)),
0));
}
tree
c_build_qualified_type (tree type, int type_quals)
{
+ if (type == error_mark_node)
+ return type;
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ return build_array_type (c_build_qualified_type (TREE_TYPE (type),
+ type_quals),
+ TYPE_DOMAIN (type));
+
/* A restrict-qualified pointer type must be a pointer to object or
incomplete type. Note that the use of POINTER_TYPE_P also allows
- REFERENCE_TYPEs, which is appropriate for C++. Unfortunately,
- the C++ front-end also use POINTER_TYPE for pointer-to-member
- values, so even though it should be illegal to use `restrict'
- with such an entity we don't flag that here. Thus, special case
- code for that case is required in the C++ front-end. */
+ REFERENCE_TYPEs, which is appropriate for C++. */
if ((type_quals & TYPE_QUAL_RESTRICT)
&& (!POINTER_TYPE_P (type)
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
type_quals &= ~TYPE_QUAL_RESTRICT;
}
- if (TREE_CODE (type) == ARRAY_TYPE)
- return build_array_type (c_build_qualified_type (TREE_TYPE (type),
- type_quals),
- TYPE_DOMAIN (type));
return build_qualified_type (type, type_quals);
}
void
c_apply_type_quals_to_decl (int type_quals, tree decl)
{
- if ((type_quals & TYPE_QUAL_CONST)
- || (TREE_TYPE (decl)
- && TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE))
+ tree type = TREE_TYPE (decl);
+
+ if (type == error_mark_node)
+ return;
+
+ if (((type_quals & TYPE_QUAL_CONST)
+ || (type && TREE_CODE (type) == REFERENCE_TYPE))
+ /* An object declared 'const' is only readonly after it is
+ initialized. We don't have any way of expressing this currently,
+ so we need to be conservative and unset TREE_READONLY for types
+ with constructors. Otherwise aliasing code will ignore stores in
+ an inline constructor. */
+ && !(type && TYPE_NEEDS_CONSTRUCTING (type)))
TREE_READONLY (decl) = 1;
if (type_quals & TYPE_QUAL_VOLATILE)
{
}
if (type_quals & TYPE_QUAL_RESTRICT)
{
- if (!TREE_TYPE (decl)
- || !POINTER_TYPE_P (TREE_TYPE (decl))
- || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (TREE_TYPE (decl))))
+ while (type && TREE_CODE (type) == ARRAY_TYPE)
+ /* Allow 'restrict' on arrays of pointers.
+ FIXME currently we just ignore it. */
+ type = TREE_TYPE (type);
+ if (!type
+ || !POINTER_TYPE_P (type)
+ || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))
error ("invalid use of `restrict'");
- else if (flag_strict_aliasing)
+ else if (flag_strict_aliasing && type == TREE_TYPE (decl))
/* Indicate we need to make a unique alias set for this pointer.
We can't do it here because it might be pointing to an
incomplete type. */
int *ip;
int **ipp = &ip;
- const int* const* cipp = &ipp;
+ const int* const* cipp = ipp;
And, it doesn't make sense for that to be legal unless you
can dereference IPP and CIPP. So, we ignore cv-qualifiers on
#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 (void);
/* Build tree nodes and builtin functions common to both C and C++ language
#undef DEF_FUNCTION_TYPE_VAR_3
#undef DEF_POINTER_TYPE
- if (!c_attrs_initialized)
- c_init_attributes ();
+ c_init_attributes ();
#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, \
BOTH_P, FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT) \
return type;
}
+/* Recursively remove any '*' or '&' operator from TYPE. */
+tree
+strip_pointer_operator (tree t)
+{
+ while (POINTER_TYPE_P (t))
+ t = TREE_TYPE (t);
+ return t;
+}
+
static tree expand_unordered_cmp (tree, tree, enum tree_code, enum tree_code);
/* Expand a call to an unordered comparison function such as
case BUILT_IN_CREALL:
if (coerced_params == 0)
return integer_zero_node;
- return build_unary_op (REALPART_EXPR, TREE_VALUE (coerced_params), 0);
+ return non_lvalue (build_unary_op (REALPART_EXPR,
+ TREE_VALUE (coerced_params), 0));
case BUILT_IN_CIMAG:
case BUILT_IN_CIMAGF:
case BUILT_IN_CIMAGL:
if (coerced_params == 0)
return integer_zero_node;
- return build_unary_op (IMAGPART_EXPR, TREE_VALUE (coerced_params), 0);
+ return non_lvalue (build_unary_op (IMAGPART_EXPR,
+ TREE_VALUE (coerced_params), 0));
case BUILT_IN_ISGREATER:
return expand_unordered_cmp (function, params, UNLE_EXPR, LE_EXPR);
if (high_value)
{
error ("duplicate (or overlapping) case value");
- error ("%Hthis is the first entry overlapping that value",
- &DECL_SOURCE_LOCATION (duplicate));
+ error ("%Jthis is the first entry overlapping that value", duplicate);
}
else if (low_value)
{
error ("duplicate case value") ;
- error ("%Hpreviously used here", &DECL_SOURCE_LOCATION (duplicate));
+ error ("%Jpreviously used here", duplicate);
}
else
{
error ("multiple default labels in one switch");
- error ("%Hthis is the first default label",
- &DECL_SOURCE_LOCATION (duplicate));
+ error ("%Jthis is the first default label", duplicate);
}
if (!cases->root)
add_stmt (build_case_label (NULL_TREE, NULL_TREE, label));
/* Hook used by expand_expr to expand language-specific tree codes. */
rtx
-c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier)
- /* Actually enum_modifier. */
+c_expand_expr (tree exp, rtx target, enum machine_mode tmode,
+ int modifier /* Actually enum_modifier. */,
+ rtx *alt_rtl)
{
switch (TREE_CODE (exp))
{
tree rtl_expr;
rtx result;
bool preserve_result = false;
- bool return_target = false;
+
+ if (STMT_EXPR_WARN_UNUSED_RESULT (exp) && target == const0_rtx)
+ {
+ tree stmt = STMT_EXPR_STMT (exp);
+ tree scope;
+
+ for (scope = COMPOUND_BODY (stmt);
+ scope && TREE_CODE (scope) != SCOPE_STMT;
+ scope = TREE_CHAIN (scope));
+
+ if (scope && SCOPE_STMT_BLOCK (scope))
+ warning ("%Hignoring return value of `%D', "
+ "declared with attribute warn_unused_result",
+ &expr_wfl_stack->location,
+ BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope)));
+ else
+ warning ("%Hignoring return value of function "
+ "declared with attribute warn_unused_result",
+ &expr_wfl_stack->location);
+ }
/* 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)
{
- 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;
- }
+ /* Otherwise, note that we want the value from the last
+ expression. */
+ TREE_ADDRESSABLE (expr) = 1;
+ preserve_result = true;
}
}
expand_stmt (STMT_EXPR_STMT (exp));
expand_end_stmt_expr (rtl_expr);
- result = expand_expr (rtl_expr, target, tmode, modifier);
- if (return_target)
- result = target;
- else if (preserve_result && GET_CODE (result) == MEM)
+ result = expand_expr_real (rtl_expr, target, tmode, modifier, alt_rtl);
+ if (preserve_result && GET_CODE (result) == MEM)
{
if (GET_MODE (result) != BLKmode)
result = copy_to_reg (result);
}
break;
- case CALL_EXPR:
- {
- if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
- && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
- == FUNCTION_DECL)
- && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
- && (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
- == BUILT_IN_FRONTEND))
- return c_expand_builtin (exp, target, tmode, modifier);
- else
- abort ();
- }
- break;
-
case COMPOUND_LITERAL_EXPR:
{
/* Initialize the anonymous variable declared in the compound
literal, then return the variable. */
tree decl = COMPOUND_LITERAL_EXPR_DECL (exp);
emit_local_var (decl);
- return expand_expr (decl, target, tmode, modifier);
+ return expand_expr_real (decl, target, tmode, modifier, alt_rtl);
}
default:
return 1;
return 0;
}
-
-#define CALLED_AS_BUILT_IN(NODE) \
- (!strncmp (IDENTIFIER_POINTER (DECL_NAME (NODE)), "__builtin_", 10))
-
-static rtx
-c_expand_builtin (tree exp, rtx target, enum machine_mode tmode,
- enum expand_modifier modifier)
-{
- tree type = TREE_TYPE (exp);
- tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
- tree arglist = TREE_OPERAND (exp, 1);
- enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
- enum tree_code code = TREE_CODE (exp);
- const int ignore = (target == const0_rtx
- || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
- || code == CONVERT_EXPR || code == REFERENCE_EXPR
- || code == COND_EXPR)
- && TREE_CODE (type) == VOID_TYPE));
-
- if (! optimize && ! CALLED_AS_BUILT_IN (fndecl))
- return expand_call (exp, target, ignore);
-
- switch (fcode)
- {
- case BUILT_IN_PRINTF:
- target = c_expand_builtin_printf (arglist, target, tmode,
- modifier, ignore, /*unlocked=*/ 0);
- if (target)
- return target;
- break;
-
- case BUILT_IN_PRINTF_UNLOCKED:
- target = c_expand_builtin_printf (arglist, target, tmode,
- modifier, ignore, /*unlocked=*/ 1);
- if (target)
- return target;
- break;
-
- case BUILT_IN_FPRINTF:
- target = c_expand_builtin_fprintf (arglist, target, tmode,
- modifier, ignore, /*unlocked=*/ 0);
- if (target)
- return target;
- break;
-
- case BUILT_IN_FPRINTF_UNLOCKED:
- target = c_expand_builtin_fprintf (arglist, target, tmode,
- modifier, ignore, /*unlocked=*/ 1);
- if (target)
- return target;
- break;
-
- default: /* just do library call, if unknown builtin */
- error ("built-in function `%s' not currently supported",
- IDENTIFIER_POINTER (DECL_NAME (fndecl)));
- }
-
- /* The switch statement above can drop through to cause the function
- to be called normally. */
- return expand_call (exp, target, ignore);
-}
-
-/* Check an arglist to *printf for problems. The arglist should start
- at the format specifier, with the remaining arguments immediately
- following it. */
-static int
-is_valid_printf_arglist (tree arglist)
-{
- /* Save this value so we can restore it later. */
- const int SAVE_pedantic = pedantic;
- int diagnostic_occurred = 0;
- tree attrs;
-
- /* Set this to a known value so the user setting won't affect code
- generation. */
- pedantic = 1;
- /* Check to make sure there are no format specifier errors. */
- attrs = tree_cons (get_identifier ("format"),
- tree_cons (NULL_TREE,
- get_identifier ("printf"),
- tree_cons (NULL_TREE,
- integer_one_node,
- tree_cons (NULL_TREE,
- build_int_2 (2, 0),
- NULL_TREE))),
- NULL_TREE);
- check_function_format (&diagnostic_occurred, attrs, arglist);
-
- /* Restore the value of `pedantic'. */
- pedantic = SAVE_pedantic;
-
- /* If calling `check_function_format_ptr' produces a warning, we
- return false, otherwise we return true. */
- return ! diagnostic_occurred;
-}
-
-/* If the arguments passed to printf are suitable for optimizations,
- we attempt to transform the call. */
-static rtx
-c_expand_builtin_printf (tree arglist, rtx target, enum machine_mode tmode,
- enum expand_modifier modifier, int ignore,
- int unlocked)
-{
- tree fn_putchar = unlocked ?
- implicit_built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED] : implicit_built_in_decls[BUILT_IN_PUTCHAR];
- tree fn_puts = unlocked ?
- 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
- initialized, don't do the transformation. */
- if (!ignore || !fn_putchar || !fn_puts)
- return 0;
-
- /* Verify the required arguments in the original call. */
- if (arglist == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE))
- return 0;
-
- /* Check the specifier vs. the parameters. */
- if (!is_valid_printf_arglist (arglist))
- return 0;
-
- format_arg = TREE_VALUE (arglist);
- stripped_string = format_arg;
- STRIP_NOPS (stripped_string);
- if (stripped_string && TREE_CODE (stripped_string) == ADDR_EXPR)
- stripped_string = TREE_OPERAND (stripped_string, 0);
-
- /* If the format specifier isn't a STRING_CST, punt. */
- if (TREE_CODE (stripped_string) != STRING_CST)
- return 0;
-
- /* OK! We can attempt optimization. */
-
- /* If the format specifier was "%s\n", call __builtin_puts(arg2). */
- if (strcmp (TREE_STRING_POINTER (stripped_string), "%s\n") == 0)
- {
- arglist = TREE_CHAIN (arglist);
- fn = fn_puts;
- }
- /* If the format specifier was "%c", call __builtin_putchar (arg2). */
- else if (strcmp (TREE_STRING_POINTER (stripped_string), "%c") == 0)
- {
- arglist = TREE_CHAIN (arglist);
- fn = fn_putchar;
- }
- else
- {
- /* We can't handle anything else with % args or %% ... yet. */
- if (strchr (TREE_STRING_POINTER (stripped_string), '%'))
- return 0;
-
- /* If the resulting constant string has a length of 1, call
- putchar. Note, TREE_STRING_LENGTH includes the terminating
- NULL in its count. */
- if (TREE_STRING_LENGTH (stripped_string) == 2)
- {
- /* Given printf("c"), (where c is any one character,)
- convert "c"[0] to an int and pass that to the replacement
- function. */
- arglist = build_int_2 (TREE_STRING_POINTER (stripped_string)[0], 0);
- arglist = build_tree_list (NULL_TREE, arglist);
-
- fn = fn_putchar;
- }
- /* If the resulting constant was "string\n", call
- __builtin_puts("string"). Ensure "string" has at least one
- character besides the trailing \n. Note, TREE_STRING_LENGTH
- includes the terminating NULL in its count. */
- else if (TREE_STRING_LENGTH (stripped_string) > 2
- && TREE_STRING_POINTER (stripped_string)
- [TREE_STRING_LENGTH (stripped_string) - 2] == '\n')
- {
- /* Create a NULL-terminated string that's one char shorter
- than the original, stripping off the trailing '\n'. */
- const int newlen = TREE_STRING_LENGTH (stripped_string) - 1;
- char *newstr = (char *) alloca (newlen);
- memcpy (newstr, TREE_STRING_POINTER (stripped_string), newlen - 1);
- newstr[newlen - 1] = 0;
-
- arglist = fix_string_type (build_string (newlen, newstr));
- arglist = build_tree_list (NULL_TREE, arglist);
- fn = fn_puts;
- }
- else
- /* We'd like to arrange to call fputs(string) here, but we
- need stdout and don't have a way to get it ... yet. */
- return 0;
- }
-
- return expand_expr (build_function_call (fn, arglist),
- (ignore ? const0_rtx : target),
- tmode, modifier);
-}
-
-/* If the arguments passed to fprintf are suitable for optimizations,
- we attempt to transform the call. */
-static rtx
-c_expand_builtin_fprintf (tree arglist, rtx target, enum machine_mode tmode,
- enum expand_modifier modifier, int ignore,
- int unlocked)
-{
- tree fn_fputc = unlocked ?
- implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED] : implicit_built_in_decls[BUILT_IN_FPUTC];
- tree fn_fputs = unlocked ?
- 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
- initialized, don't do the transformation. */
- if (!ignore || !fn_fputc || !fn_fputs)
- return 0;
-
- /* Verify the required arguments in the original call. */
- if (arglist == 0
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
- || (TREE_CHAIN (arglist) == 0)
- || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) !=
- POINTER_TYPE))
- return 0;
-
- /* Check the specifier vs. the parameters. */
- if (!is_valid_printf_arglist (TREE_CHAIN (arglist)))
- return 0;
-
- format_arg = TREE_VALUE (TREE_CHAIN (arglist));
- stripped_string = format_arg;
- STRIP_NOPS (stripped_string);
- if (stripped_string && TREE_CODE (stripped_string) == ADDR_EXPR)
- stripped_string = TREE_OPERAND (stripped_string, 0);
-
- /* If the format specifier isn't a STRING_CST, punt. */
- if (TREE_CODE (stripped_string) != STRING_CST)
- return 0;
-
- /* OK! We can attempt optimization. */
-
- /* If the format specifier was "%s", call __builtin_fputs(arg3, arg1). */
- if (strcmp (TREE_STRING_POINTER (stripped_string), "%s") == 0)
- {
- tree newarglist = build_tree_list (NULL_TREE, TREE_VALUE (arglist));
- arglist = tree_cons (NULL_TREE,
- TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))),
- newarglist);
- fn = fn_fputs;
- }
- /* If the format specifier was "%c", call __builtin_fputc (arg3, arg1). */
- else if (strcmp (TREE_STRING_POINTER (stripped_string), "%c") == 0)
- {
- tree newarglist = build_tree_list (NULL_TREE, TREE_VALUE (arglist));
- arglist = tree_cons (NULL_TREE,
- TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))),
- newarglist);
- fn = fn_fputc;
- }
- else
- {
- /* We can't handle anything else with % args or %% ... yet. */
- if (strchr (TREE_STRING_POINTER (stripped_string), '%'))
- return 0;
-
- /* When "string" doesn't contain %, replace all cases of
- fprintf(stream,string) with fputs(string,stream). The fputs
- builtin will take take of special cases like length==1. */
- arglist = tree_cons (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)),
- build_tree_list (NULL_TREE, TREE_VALUE (arglist)));
- fn = fn_fputs;
- }
-
- return expand_expr (build_function_call (fn, arglist),
- (ignore ? const0_rtx : target),
- tmode, modifier);
-}
\f
/* Given a boolean expression ARG, return a tree representing an increment
boolean_increment (enum tree_code code, tree arg)
{
tree val;
- tree true_res = (c_dialect_cxx () ? boolean_true_node : c_bool_true_node);
+ tree true_res = boolean_true_node;
arg = stabilize_reference (arg);
switch (code)
= tree_cons (built_in_attributes[(int) PURPOSE], \
built_in_attributes[(int) VALUE], \
built_in_attributes[(int) CHAIN]);
-#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No initialization needed. */
#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
- c_attrs_initialized = true;
-}
-
-/* Depending on the name of DECL, apply default attributes to it. */
-
-void
-c_common_insert_default_attributes (tree decl)
-{
- tree name = DECL_NAME (decl);
-
- if (!c_attrs_initialized)
- c_init_attributes ();
-
-#define DEF_ATTR_NULL_TREE(ENUM) /* Nothing needed after initialization. */
-#define DEF_ATTR_INT(ENUM, VALUE)
-#define DEF_ATTR_IDENT(ENUM, STRING)
-#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)
-#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) \
- if ((PREDICATE) && name == built_in_attributes[(int) NAME]) \
- decl_attributes (&decl, built_in_attributes[(int) ATTRS], \
- ATTR_FLAG_BUILT_IN);
-#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
-}
-
-/* Output a -Wshadow warning MSGCODE about NAME, and give the location
- of the previous declaration DECL. */
-void
-shadow_warning (enum sw_kind msgcode, const char *name, tree decl)
-{
- 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. */
handle_packed_attribute (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 (TYPE_P (*node))
{
if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
- *type = build_type_copy (*type);
- TYPE_PACKED (*type) = 1;
+ *node = build_type_copy (*node);
+ TYPE_PACKED (*node) = 1;
+ if (TYPE_MAIN_VARIANT (*node) == *node)
+ {
+ /* If it is the main variant, then pack the other variants
+ too. This happens in,
+
+ struct Foo {
+ struct Foo const *ptr; // creates a variant w/o packed flag
+ } __ attribute__((packed)); // packs it now.
+ */
+ tree probe;
+
+ for (probe = *node; probe; probe = TYPE_NEXT_VARIANT (probe))
+ TYPE_PACKED (probe) = 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. */
+ used for DECL_REGISTER. It wouldn't mean anything anyway.
+ We can't set DECL_PACKED on the type of a TYPE_DECL, because
+ that changes what the typedef is typing. */
else
{
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
if (len > 4 && p[0] == '_' && p[1] == '_'
&& p[len - 1] == '_' && p[len - 2] == '_')
{
- char *newp = (char *) alloca (len - 1);
+ char *newp = alloca (len - 1);
strcpy (newp, &p[2]);
newp[len - 4] = '\0';
&& current_function_decl != NULL_TREE
&& ! TREE_STATIC (decl))
{
- error ("%Hsection attribute cannot be specified for "
- "local variables", &DECL_SOURCE_LOCATION (decl));
+ error ("%Jsection attribute cannot be specified for "
+ "local variables", decl);
*no_add_attrs = true;
}
&& strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
{
- error ("%Hsection of '%D' conflicts with previous declaration",
- &DECL_SOURCE_LOCATION (*node), *node);
+ error ("%Jsection of '%D' conflicts with previous declaration",
+ *node, *node);
*no_add_attrs = true;
}
else
}
else
{
- error ("%Hsection attribute not allowed for '%D'",
- &DECL_SOURCE_LOCATION (*node), *node);
+ error ("%Jsection attribute not allowed for '%D'", *node, *node);
*no_add_attrs = true;
}
}
else
{
- error ("%Hsection attributes are not supported for this target",
- &DECL_SOURCE_LOCATION (*node));
+ error ("%Jsection attributes are not supported for this target", *node);
*no_add_attrs = true;
}
else if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FIELD_DECL)
{
- error ("%Halignment may not be specified for '%D'",
- &DECL_SOURCE_LOCATION (decl), decl);
+ error ("%Jalignment may not be specified for '%D'", decl, decl);
*no_add_attrs = true;
}
else
if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
|| (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
{
- error ("%H'%D' defined both normally and as an alias",
- &DECL_SOURCE_LOCATION (decl), decl);
+ error ("%J'%D' defined both normally and as an alias", decl, decl);
*no_add_attrs = true;
}
else if (decl_function_context (decl) == 0)
bool *no_add_attrs)
{
tree decl = *node;
+ tree id = TREE_VALUE (args);
+
+ *no_add_attrs = true;
if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
{
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
+ return NULL_TREE;
}
- 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;
- }
+ if (TREE_CODE (id) != STRING_CST)
+ {
+ error ("visibility arg not a string");
+ return NULL_TREE;
}
+ if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
+ DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+ else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
+ DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL;
+ else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
+ DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED;
+ else
+ error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+
return NULL_TREE;
}
if (TREE_CODE (decl) != FUNCTION_DECL)
{
- error ("%H'%E' attribute applies only to functions",
- &DECL_SOURCE_LOCATION (decl), name);
+ error ("%J'%E' attribute applies only to functions", decl, name);
*no_add_attrs = true;
}
else if (DECL_INITIAL (decl))
{
- error ("%Hcan't set '%E' attribute after definition",
- &DECL_SOURCE_LOCATION (decl), name);
+ error ("%Jcan't set '%E' attribute after definition", decl, name);
*no_add_attrs = true;
}
else
if (TREE_CODE (decl) != FUNCTION_DECL)
{
- error ("%H'%E' attribute applies only to functions",
- &DECL_SOURCE_LOCATION (decl), name);
+ error ("%J'%E' attribute applies only to functions", decl, name);
*no_add_attrs = true;
}
else if (DECL_INITIAL (decl))
{
- error ("%Hcan't set '%E' attribute after definition",
- &DECL_SOURCE_LOCATION (decl), name);
+ error ("%Jcan't set '%E' attribute after definition", decl, name);
*no_add_attrs = true;
}
else
while (POINTER_TYPE_P (type)
|| TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE
|| TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
}
/* Build back pointers if needed. */
- *node = vector_size_helper (*node, new_type);
+ *node = reconstruct_complex_type (*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 (tree type, tree 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 (tree *node, tree name ATTRIBUTE_UNUSED,
return NULL_TREE;
}
+
+/* Handle a "warn_unused_result" attribute. No special handling. */
+
+static tree
+handle_warn_unused_result_attribute (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+ /* Ignore the attribute for functions not returning any value. */
+ if (VOID_TYPE_P (TREE_TYPE (*node)))
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
\f
/* Check for valid arguments being passed to a function. */
void
return NULL;
}
/* Assume that constants and references counts nothing. These should
- be majorized by amount of operations amoung them we count later
+ be majorized by amount of operations among them we count later
and are common target of CSE and similar optimizations. */
if (TREE_CODE_CLASS (TREE_CODE (x)) == 'c'
|| TREE_CODE_CLASS (TREE_CODE (x)) == 'r')
return NULL;
switch (TREE_CODE (x))
{
- /* Reconginze assignments of large structures and constructors of
+ /* Recognize assignments of large structures and constructors of
big arrays. */
case MODIFY_EXPR:
case CONSTRUCTOR:
{
- int size = int_size_in_bytes (TREE_TYPE (x));
+ HOST_WIDE_INT size;
+
+ size = int_size_in_bytes (TREE_TYPE (x));
- if (!size || size > MOVE_MAX_PIECES)
+ if (size < 0 || size > MOVE_MAX_PIECES * MOVE_RATIO)
*count += 10;
else
- *count += 2 * (size + MOVE_MAX - 1) / MOVE_MAX;
- return NULL;
+ *count += ((size + MOVE_MAX_PIECES - 1) / MOVE_MAX_PIECES);
}
break;
- /* Few special cases of expensive operations. This is usefull
+ case CALL_EXPR:
+ {
+ tree decl = get_callee_fndecl (x);
+
+ if (decl && DECL_BUILT_IN (decl))
+ switch (DECL_FUNCTION_CODE (decl))
+ {
+ case BUILT_IN_CONSTANT_P:
+ *walk_subtrees = 0;
+ return NULL_TREE;
+ case BUILT_IN_EXPECT:
+ return NULL_TREE;
+ default:
+ break;
+ }
+ *count += 10;
+ break;
+ }
+ /* Few special cases of expensive operations. This is useful
to avoid inlining on functions having too many of these. */
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_MOD_EXPR:
case ROUND_MOD_EXPR:
case RDIV_EXPR:
- case CALL_EXPR:
*count += 10;
break;
/* Various containers that will produce no code themselves. */
return num;
}
+/* Used by c_decl_uninit to find where expressions like x = x + 1; */
+
+static tree
+c_decl_uninit_1 (tree *t, int *walk_sub_trees, void *x)
+{
+ /* If x = EXP(&x)EXP, then do not warn about the use of x. */
+ if (TREE_CODE (*t) == ADDR_EXPR && TREE_OPERAND (*t, 0) == x)
+ {
+ *walk_sub_trees = 0;
+ return NULL_TREE;
+ }
+ if (*t == x)
+ return *t;
+ return NULL_TREE;
+}
+
+/* Find out if a variable is uninitialized based on DECL_INITIAL. */
+
+bool
+c_decl_uninit (tree t)
+{
+ /* int x = x; is GCC extension to turn off this warning, only if warn_init_self is zero. */
+ if (DECL_INITIAL (t) == t)
+ return warn_init_self ? true : false;
+
+ /* Walk the trees looking for the variable itself. */
+ if (walk_tree_without_duplicates (&DECL_INITIAL (t), c_decl_uninit_1, t))
+ return true;
+ return false;
+}
+
+/* Issue the error given by MSGID, indicating that it occurred before
+ TOKEN, which had the associated VALUE. */
+
+void
+c_parse_error (const char *msgid, enum cpp_ttype token, tree value)
+{
+ const char *string = _(msgid);
+
+ if (token == CPP_EOF)
+ error ("%s at end of input", string);
+ else if (token == CPP_CHAR || token == CPP_WCHAR)
+ {
+ unsigned int val = TREE_INT_CST_LOW (value);
+ const char *const ell = (token == CPP_CHAR) ? "" : "L";
+ if (val <= UCHAR_MAX && ISGRAPH (val))
+ error ("%s before %s'%c'", string, ell, val);
+ else
+ error ("%s before %s'\\x%x'", string, ell, val);
+ }
+ else if (token == CPP_STRING
+ || token == CPP_WSTRING)
+ error ("%s before string constant", string);
+ else if (token == CPP_NUMBER)
+ error ("%s before numeric constant", string);
+ else if (token == CPP_NAME)
+ error ("%s before \"%s\"", string, IDENTIFIER_POINTER (value));
+ else if (token < N_TTYPES)
+ error ("%s before '%s' token", string, cpp_type2name (token));
+ else
+ error ("%s", string);
+}
+
#include "gt-c-common.h"