/* Build expressions with type checking for C compiler.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1998, 1999, 2000, 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 "rtl.h"
#include "tree.h"
#include "c-tree.h"
static tree decl_constant_value_for_broken_optimization PARAMS ((tree));
static tree default_function_array_conversion PARAMS ((tree));
static tree lookup_field PARAMS ((tree, tree));
+static void undeclared_variable PARAMS ((tree));
static tree convert_arguments PARAMS ((tree, tree, tree, tree));
static tree pointer_diff PARAMS ((tree, tree));
static tree unary_complex_lvalue PARAMS ((enum tree_code, tree, int));
val = 1;
break;
+ case VECTOR_TYPE:
+ /* The target might allow certain vector types to be compatible. */
+ val = (*targetm.vector_opaque_p) (t1)
+ || (*targetm.vector_opaque_p) (t2);
+ break;
+
default:
break;
}
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
int val = 1;
int val1;
-
- if (!(TREE_TYPE (f1) == TREE_TYPE (f2)
- || (val = comptypes (TREE_TYPE (f1), TREE_TYPE (f2)))))
+ tree ret1, ret2;
+
+ ret1 = TREE_TYPE (f1);
+ ret2 = TREE_TYPE (f2);
+
+ /* 'volatile' qualifiers on a function's return type mean the function
+ is noreturn. */
+ if (pedantic && TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2))
+ pedwarn ("function return types not compatible due to `volatile'");
+ if (TYPE_VOLATILE (ret1))
+ ret1 = build_qualified_type (TYPE_MAIN_VARIANT (ret1),
+ TYPE_QUALS (ret1) & ~TYPE_QUAL_VOLATILE);
+ if (TYPE_VOLATILE (ret2))
+ ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
+ TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
+ val = comptypes (ret1, ret2);
+ if (val == 0)
return 0;
args1 = TYPE_ARG_TYPES (f1);
end does it - by giving the anonymous entities each a
separate name and type, and then have build_component_ref
recursively call itself. We can't do that here. */
- for (; field; field = TREE_CHAIN (field))
+ do
{
tree subdatum = TREE_VALUE (field);
warn_deprecated_use (subdatum);
datum = ref;
+
+ field = TREE_CHAIN (field);
}
+ while (field);
return ref;
}
if (TREE_CODE (type) == POINTER_TYPE)
{
if (TREE_CODE (pointer) == ADDR_EXPR
- && !flag_volatile
&& (TREE_TYPE (TREE_OPERAND (pointer, 0))
== TREE_TYPE (type)))
return TREE_OPERAND (pointer, 0);
to change it via some other pointer. */
TREE_READONLY (ref) = TYPE_READONLY (t);
TREE_SIDE_EFFECTS (ref)
- = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer) || flag_volatile;
+ = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
return ref;
}
}
}
\f
+/* Issue an error message for a reference to an undeclared variable ID,
+ including a reference to a builtin outside of function-call context.
+ Arrange to suppress further errors for the same identifier. */
+static void
+undeclared_variable (id)
+ tree id;
+{
+ if (current_function_decl == 0)
+ {
+ error ("`%s' undeclared here (not in a function)",
+ IDENTIFIER_POINTER (id));
+ IDENTIFIER_SYMBOL_VALUE (id) = error_mark_node;
+ }
+ else
+ {
+ error ("`%s' undeclared (first use in this function)",
+ IDENTIFIER_POINTER (id));
+
+ if (! undeclared_variable_notice)
+ {
+ error ("(Each undeclared identifier is reported only once");
+ error ("for each function it appears in.)");
+ undeclared_variable_notice = 1;
+ }
+
+ /* Set IDENTIFIER_SYMBOL_VALUE (id) to error_mark_node
+ at function scope. This suppresses further warnings
+ about this undeclared identifier in this function. */
+ pushdecl_function_level (error_mark_node, id);
+ }
+}
+
/* Build an external reference to identifier ID. FUN indicates
whether this will be used for a function call. */
tree
tree decl = lookup_name (id);
tree objc_ivar = lookup_objc_ivar (id);
- if (decl && TREE_DEPRECATED (decl))
- warn_deprecated_use (decl);
-
- if (!decl || decl == error_mark_node || C_DECL_ANTICIPATED (decl))
- {
- if (objc_ivar)
- ref = objc_ivar;
- else if (fun)
- {
- if (!decl || decl == error_mark_node)
- /* Ordinary implicit function declaration. */
- ref = implicitly_declare (id);
- else
- {
- /* Implicit declaration of built-in function. Don't
- change the built-in declaration, but don't let this
- go by silently, either. */
- implicit_decl_warning (id);
-
- /* only issue this warning once */
- C_DECL_ANTICIPATED (decl) = 0;
- ref = decl;
- }
- }
- else
- {
- /* Reference to undeclared variable, including reference to
- builtin outside of function-call context. */
- if (current_function_decl == 0)
- error ("`%s' undeclared here (not in a function)",
- IDENTIFIER_POINTER (id));
- else
- {
- if (IDENTIFIER_GLOBAL_VALUE (id) != error_mark_node
- || IDENTIFIER_ERROR_LOCUS (id) != current_function_decl)
- {
- error ("`%s' undeclared (first use in this function)",
- IDENTIFIER_POINTER (id));
-
- if (! undeclared_variable_notice)
- {
- error ("(Each undeclared identifier is reported only once");
- error ("for each function it appears in.)");
- undeclared_variable_notice = 1;
- }
- }
- IDENTIFIER_GLOBAL_VALUE (id) = error_mark_node;
- IDENTIFIER_ERROR_LOCUS (id) = current_function_decl;
- }
- return error_mark_node;
- }
- }
- else
+ if (decl && decl != error_mark_node)
{
/* Properly declared variable or function reference. */
if (!objc_ivar)
ref = decl;
- else if (decl != objc_ivar && IDENTIFIER_LOCAL_VALUE (id))
+ else if (decl != objc_ivar && DECL_CONTEXT (decl) != 0)
{
warning ("local declaration of `%s' hides instance variable",
IDENTIFIER_POINTER (id));
else
ref = objc_ivar;
}
+ else if (objc_ivar)
+ ref = objc_ivar;
+ else if (fun)
+ /* Implicit function declaration. */
+ ref = implicitly_declare (id);
+ else if (decl == error_mark_node)
+ /* Don't complain about something that's already been
+ complained about. */
+ return error_mark_node;
+ else
+ {
+ undeclared_variable (id);
+ return error_mark_node;
+ }
if (TREE_TYPE (ref) == error_mark_node)
return error_mark_node;
+ if (TREE_DEPRECATED (ref))
+ warn_deprecated_use (ref);
+
if (!skip_evaluation)
assemble_external (ref);
TREE_USED (ref) = 1;
ref = DECL_INITIAL (ref);
TREE_CONSTANT (ref) = 1;
}
+ else if (current_function_decl != 0
+ && DECL_CONTEXT (current_function_decl) != 0
+ && (TREE_CODE (ref) == VAR_DECL
+ || TREE_CODE (ref) == PARM_DECL
+ || TREE_CODE (ref) == FUNCTION_DECL))
+ {
+ tree context = decl_function_context (ref);
+
+ if (context != 0 && context != current_function_decl)
+ DECL_NONLOCAL (ref) = 1;
+ }
return ref;
}
{
tree fntype, fundecl = 0;
tree coerced_params;
- tree name = NULL_TREE, assembler_name = NULL_TREE, result;
+ tree name = NULL_TREE, result;
/* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
STRIP_TYPE_NOPS (function);
if (TREE_CODE (function) == FUNCTION_DECL)
{
name = DECL_NAME (function);
- assembler_name = DECL_ASSEMBLER_NAME (function);
/* Differs from default_conversion by not setting TREE_ADDRESSABLE
(because calling an inline function does not mean the function
converted = 1;
resultcode = xresultcode;
- if ((warn_sign_compare < 0 ? extra_warnings : warn_sign_compare != 0)
- && skip_evaluation == 0)
+ if (warn_sign_compare && skip_evaluation == 0)
{
int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
{
if (TREE_CODE (t) == STMT_EXPR)
{
- t=COMPOUND_BODY (STMT_EXPR_STMT (t));
+ t = COMPOUND_BODY (STMT_EXPR_STMT (t));
/* Find the last statement in the chain, ignoring the final
* scope statement */
while (TREE_CHAIN (t) != NULL_TREE
&& TREE_CODE (TREE_CHAIN (t)) != SCOPE_STMT)
- t=TREE_CHAIN (t);
+ t = TREE_CHAIN (t);
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
}
return tree_expr_nonnegative_p (t);
pedwarn ("address of register variable `%s' requested",
IDENTIFIER_POINTER (DECL_NAME (x)));
}
- put_var_into_stack (x);
+ put_var_into_stack (x, /*rescan=*/true);
/* drops in */
case FUNCTION_DECL:
and later code won't know it used to be different.
Do this check on the original types, so that explicit casts
will be considered, but default promotions won't. */
- if ((warn_sign_compare < 0 ? extra_warnings : warn_sign_compare)
- && !skip_evaluation)
+ if (warn_sign_compare && !skip_evaluation)
{
int unsigned_op1 = TREE_UNSIGNED (TREE_TYPE (orig_op1));
int unsigned_op2 = TREE_UNSIGNED (TREE_TYPE (orig_op2));
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
{
/* The left-hand operand of a comma expression is like an expression
- statement: with -W or -Wunused, we should warn if it doesn't have
+ statement: with -Wextra or -Wunused, we should warn if it doesn't have
any side-effects, unless it was explicitly cast to (void). */
- if ((extra_warnings || warn_unused_value)
+ if (warn_unused_value
&& ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR
&& VOID_TYPE_P (TREE_TYPE (TREE_VALUE (list)))))
warning ("left-hand operand of comma expression has no effect");
if (field)
{
- const char *name;
tree t;
if (pedantic)
pedwarn ("ISO C forbids casts to union type");
- if (TYPE_NAME (type) != 0)
- {
- if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- name = IDENTIFIER_POINTER (TYPE_NAME (type));
- else
- name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
- }
- else
- name = "";
- t = digest_init (type, build (CONSTRUCTOR, type, NULL_TREE,
- build_tree_list (field, value)), 0);
+ t = digest_init (type,
+ build_constructor (type,
+ build_tree_list (field, value)),
+ 0);
TREE_CONSTANT (t) = TREE_CONSTANT (value);
return t;
}
get_alias_set (TREE_TYPE (type))))
warning ("dereferencing type-punned pointer will break strict-aliasing rules");
}
-
+
ovalue = value;
+ /* Replace a nonvolatile const static variable with its value. */
+ if (optimize && TREE_CODE (value) == VAR_DECL)
+ value = decl_constant_value (value);
value = convert (type, value);
/* Ignore any integer overflow caused by the cast. */
rhs = build1 (NOP_EXPR, type, rhs);
return rhs;
}
+ /* Some types can interconvert without explicit casts. */
+ else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE
+ && ((*targetm.vector_opaque_p) (type)
+ || (*targetm.vector_opaque_p) (rhstype)))
+ return convert (type, rhs);
/* Arithmetic types all interconvert, and enum is treated like int. */
else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
|| codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
{
tree ttl = TREE_TYPE (type);
tree ttr = TREE_TYPE (rhstype);
+ bool is_opaque_pointer;
+
+ /* Opaque pointers are treated like void pointers. */
+ is_opaque_pointer = ((*targetm.vector_opaque_p) (type)
+ || (*targetm.vector_opaque_p) (rhstype))
+ && TREE_CODE (ttl) == VECTOR_TYPE
+ && TREE_CODE (ttr) == VECTOR_TYPE;
/* Any non-function converts to a [const][volatile] void *
and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of the rhs. */
if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
|| comp_target_types (type, rhstype, 0)
+ || is_opaque_pointer
|| (c_common_unsigned_type (TYPE_MAIN_VARIANT (ttl))
== c_common_unsigned_type (TYPE_MAIN_VARIANT (ttr))))
{
}
}
+ /* Build a VECTOR_CST from a *constant* vector constructor. If the
+ vector constructor is not constant (e.g. {1,2,3,foo()}) then punt
+ below and handle as a constructor. */
+ if (code == VECTOR_TYPE
+ && comptypes (TREE_TYPE (inside_init), type)
+ && TREE_CONSTANT (inside_init))
+ {
+ if (TREE_CODE (inside_init) == VECTOR_CST
+ && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
+ TYPE_MAIN_VARIANT (type)))
+ return inside_init;
+ else
+ return build_vector (type, CONSTRUCTOR_ELTS (inside_init));
+ }
+
/* Any type can be initialized
from an expression of the same type, optionally with braces. */
/* 1 if this constructor is erroneous so far. */
static int constructor_erroneous;
-/* 1 if have called defer_addressed_constants. */
-static int constructor_subconstants_deferred;
-
/* Structure for managing pending initializer elements, organized as an
AVL tree. */
char top_level;
char require_constant_value;
char require_constant_elements;
- char deferred;
};
struct initializer_stack *initializer_stack;
p->spelling = spelling;
p->spelling_base = spelling_base;
p->spelling_size = spelling_size;
- p->deferred = constructor_subconstants_deferred;
p->top_level = constructor_top_level;
p->next = initializer_stack;
initializer_stack = p;
constructor_decl = decl;
constructor_asmspec = asmspec;
- constructor_subconstants_deferred = 0;
constructor_designated = 0;
constructor_top_level = top_level;
{
struct initializer_stack *p = initializer_stack;
- /* Output subconstants (string constants, usually)
- that were referenced within this initializer and saved up.
- Must do this if and only if we called defer_addressed_constants. */
- if (constructor_subconstants_deferred)
- output_deferred_addressed_constants ();
-
/* Free the whole constructor stack of this initializer. */
while (constructor_stack)
{
spelling = p->spelling;
spelling_base = p->spelling_base;
spelling_size = p->spelling_size;
- constructor_subconstants_deferred = p->deferred;
constructor_top_level = p->top_level;
initializer_stack = p->next;
free (p);
if (type == 0)
type = TREE_TYPE (constructor_decl);
+ if ((*targetm.vector_opaque_p) (type))
+ error ("opaque vector types cannot be initialized");
+
p->type = constructor_type;
p->fields = constructor_fields;
p->index = constructor_index;
constructor_max_index = build_int_2 (-1, -1);
/* constructor_max_index needs to be an INTEGER_CST. Attempts
- to initialize VLAs will cause an proper error; avoid tree
+ to initialize VLAs will cause a proper error; avoid tree
checking errors as well by setting a safe value. */
if (constructor_max_index
&& TREE_CODE (constructor_max_index) != INTEGER_CST)
&& constructor_fields == 0)
process_init_element (pop_init_level (1));
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+ && constructor_max_index
&& tree_int_cst_lt (constructor_max_index, constructor_index))
process_init_element (pop_init_level (1));
else
{
constructor_constant = TREE_CONSTANT (value);
constructor_simple = TREE_STATIC (value);
- constructor_elements = TREE_OPERAND (value, 1);
+ constructor_elements = CONSTRUCTOR_ELTS (value);
if (constructor_elements
&& (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == ARRAY_TYPE))
constructor_max_index = build_int_2 (-1, -1);
/* constructor_max_index needs to be an INTEGER_CST. Attempts
- to initialize VLAs will cause an proper error; avoid tree
+ to initialize VLAs will cause a proper error; avoid tree
checking errors as well by setting a safe value. */
if (constructor_max_index
&& TREE_CODE (constructor_max_index) != INTEGER_CST)
constructor = error_mark_node;
else
{
- constructor = build (CONSTRUCTOR, constructor_type, NULL_TREE,
- nreverse (constructor_elements));
+ constructor = build_constructor (constructor_type,
+ nreverse (constructor_elements));
if (constructor_constant)
TREE_CONSTANT (constructor) = 1;
if (constructor_constant && constructor_simple)
tree value, type, field;
int pending;
{
+ if (type == error_mark_node)
+ {
+ constructor_erroneous = 1;
+ return;
+ }
if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
|| (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
&& !(TREE_CODE (value) == STRING_CST
bit_position (constructor_fields),
DECL_SIZE (constructor_fields));
- constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
- /* Skip any nameless bit fields. */
- while (constructor_unfilled_fields != 0
- && DECL_C_BIT_FIELD (constructor_unfilled_fields)
- && DECL_NAME (constructor_unfilled_fields) == 0)
- constructor_unfilled_fields =
- TREE_CHAIN (constructor_unfilled_fields);
+ /* If the current field was the first one not yet written out,
+ it isn't now, so update. */
+ if (constructor_unfilled_fields == constructor_fields)
+ {
+ constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+ /* Skip any nameless bit fields. */
+ while (constructor_unfilled_fields != 0
+ && DECL_C_BIT_FIELD (constructor_unfilled_fields)
+ && DECL_NAME (constructor_unfilled_fields) == 0)
+ constructor_unfilled_fields =
+ TREE_CHAIN (constructor_unfilled_fields);
+ }
}
constructor_fields = TREE_CHAIN (constructor_fields);
{
tree stmt;
- stmt = add_stmt (build_stmt (ASM_STMT, NULL_TREE, expr,
- NULL_TREE, NULL_TREE,
- NULL_TREE));
+ /* Simple asm statements are treated as volatile. */
+ stmt = add_stmt (build_stmt (ASM_STMT, ridpointers[(int) RID_VOLATILE],
+ expr, NULL_TREE, NULL_TREE, NULL_TREE));
ASM_INPUT_P (stmt) = 1;
return stmt;
}
/* Record the contents of OUTPUTS before it is modified. */
for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
- o[i] = TREE_VALUE (tail);
+ {
+ o[i] = TREE_VALUE (tail);
+ if (o[i] == error_mark_node)
+ return;
+ }
/* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of
OUTPUTS some trees for where the values were actually stored. */
if (switch_stack)
{
+ bool switch_was_empty_p = (SWITCH_BODY (switch_stack->switch_stmt) == NULL_TREE);
+
label = c_add_case_label (switch_stack->cases,
SWITCH_COND (switch_stack->switch_stmt),
low_value, high_value);
if (label == error_mark_node)
label = NULL_TREE;
+ else if (switch_was_empty_p)
+ {
+ /* Attach the first case label to the SWITCH_BODY. */
+ SWITCH_BODY (switch_stack->switch_stmt) = TREE_CHAIN (switch_stack->switch_stmt);
+ TREE_CHAIN (switch_stack->switch_stmt) = NULL_TREE;
+ }
}
else if (low_value)
error ("case label not within a switch statement");
{
struct c_switch *cs = switch_stack;
- RECHAIN_STMTS (cs->switch_stmt, SWITCH_BODY (cs->switch_stmt));
+ /* Rechain the next statements to the SWITCH_STMT. */
+ last_tree = cs->switch_stmt;
/* Pop the stack. */
switch_stack = switch_stack->next;