/* 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.
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.
-
- 2: The version of the ABI first used in G++ 3.4.
-
- Additional positive integers will be assigned as new versions of
- the ABI become the default version of the ABI. */
-
-int flag_abi_version = 2;
-
/* Nonzero means warn about things that will change when compiling
with an ABI-compliant compiler. */
static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
bool *);
-static tree vector_size_helper (tree, tree);
static void check_function_nonnull (tree, tree);
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
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);
-Wwrite-strings says make the string constant an array of const char
so that copying it to a non-const pointer will get a warning.
For C++, this is the standard behavior. */
- if (flag_const_strings && ! flag_writable_strings)
+ if (flag_const_strings)
{
tree elements
= build_type_variant (wide_flag ? wchar_type_node : char_type_node,
build_index_type (build_int_2 (nchars - 1, 0)));
TREE_CONSTANT (value) = 1;
- TREE_READONLY (value) = ! flag_writable_strings;
+ TREE_READONLY (value) = 1;
TREE_STATIC (value) = 1;
return value;
}
if (TREE_CODE (expr) == FUNCTION_DECL)
expr = build_unary_op (ADDR_EXPR, expr, 0);
-#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 truthvalue_false_node;
-
- case UNION_TYPE:
- error ("union type value used where scalar is required");
- return truthvalue_false_node;
-
- case ARRAY_TYPE:
- error ("array type value used where scalar is required");
- return truthvalue_false_node;
-
- default:
- break;
- }
-#endif /* 0 */
-
switch (TREE_CODE (expr))
{
case EQ_EXPR:
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:
/* 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:
we can't ignore them if their second arg has side-effects. */
if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
return build (COMPOUND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 1),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+ (*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, truthvalue_type_node, TREE_OPERAND (expr, 0),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
- c_common_truthvalue_conversion (TREE_OPERAND (expr, 2))));
+ (*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 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:
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),
c_apply_type_quals_to_decl (int type_quals, tree decl)
{
tree type = TREE_TYPE (decl);
+
+ if (type == error_mark_node)
+ return;
if (((type_quals & TYPE_QUAL_CONST)
|| (type && TREE_CODE (type) == REFERENCE_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
/* 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)
{
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);
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:
#undef DEF_ATTR_TREE_LIST
}
-/* 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 ("%Jshadowed declaration is here", decl);
-}
-
/* Attribute handlers common to C front ends. */
/* Handle a "packed" attribute; arguments as in
error ("%J'%D' defined both normally and as an alias", decl, decl);
*no_add_attrs = true;
}
- else if (decl_function_context (decl) == 0)
+
+ /* Note that the very first time we process a nested declaration,
+ decl_function_context will not be set. Indeed, *would* never
+ be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that
+ we do below. After such frobbery, pushdecl would set the context.
+ In any case, this is never what we want. */
+ else if (decl_function_context (decl) == 0 && current_function_decl == NULL)
{
tree id;
}
/* 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_DOMAIN (type));
- }
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- inner = vector_size_helper (TREE_TYPE (type), bottom);
- outer = build_function_type (inner, TYPE_ARG_TYPES (type));
- }
- else if (TREE_CODE (type) == METHOD_TYPE)
- {
- inner = vector_size_helper (TREE_TYPE (type), bottom);
- outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type),
- inner,
- TYPE_ARG_TYPES (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,
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. */