#include "tree-iterator.h"
#include "tree-gimple.h"
-/* Places where an lvalue, or modifiable lvalue, may be required.
- Used to select diagnostic messages in lvalue_or_else and
- readonly_error. */
-enum lvalue_use {
- lv_assign,
- lv_increment,
- lv_decrement,
- lv_addressof,
- lv_asm
-};
-
/* Possible cases of implicit bad conversions. Used to select
diagnostic messages in convert_for_assignment. */
enum impl_conv {
static void set_nonincremental_init (void);
static void set_nonincremental_init_from_string (tree);
static tree find_init_member (tree);
-static int lvalue_or_else (tree, enum lvalue_use);
static void readonly_error (tree, enum lvalue_use);
static void record_maybe_used_decl (tree);
\f
tree
build_array_ref (tree array, tree index)
{
- if (index == 0)
- {
- error ("subscript missing in array reference");
- return error_mark_node;
- }
-
+ bool swapped = false;
if (TREE_TYPE (array) == error_mark_node
|| TREE_TYPE (index) == error_mark_node)
return error_mark_node;
- if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
+ if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE)
{
- tree rval, type;
-
- /* Subscripting with type char is likely to lose
- on a machine where chars are signed.
- So warn on any machine, but optionally.
- Don't warn for unsigned char since that type is safe.
- Don't warn for signed char because anyone who uses that
- must have done so deliberately. */
- if (warn_char_subscripts
- && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
- warning ("array subscript has type %<char%>");
-
- /* Apply default promotions *after* noticing character types. */
- index = default_conversion (index);
-
- /* Require integer *after* promotion, for sake of enums. */
- if (TREE_CODE (TREE_TYPE (index)) != INTEGER_TYPE)
+ tree temp;
+ if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
{
- error ("array subscript is not an integer");
+ error ("subscripted value is neither array nor pointer");
return error_mark_node;
}
+ temp = array;
+ array = index;
+ index = temp;
+ swapped = true;
+ }
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (index)))
+ {
+ error ("array subscript is not an integer");
+ return error_mark_node;
+ }
+
+ if (TREE_CODE (TREE_TYPE (TREE_TYPE (array))) == FUNCTION_TYPE)
+ {
+ error ("subscripted value is pointer to function");
+ return error_mark_node;
+ }
+
+ /* Subscripting with type char is likely to lose on a machine where
+ chars are signed. So warn on any machine, but optionally. Don't
+ warn for unsigned char since that type is safe. Don't warn for
+ signed char because anyone who uses that must have done so
+ deliberately. ??? Existing practice has also been to warn only
+ when the char index is syntactically the index, not for
+ char[array]. */
+ if (warn_char_subscripts && !swapped
+ && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
+ warning ("array subscript has type %<char%>");
+
+ /* Apply default promotions *after* noticing character types. */
+ index = default_conversion (index);
+
+ gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
+
+ if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
+ {
+ tree rval, type;
/* An array that is indexed by a non-constant
cannot be stored in a register; we must be able to do
| TREE_THIS_VOLATILE (array));
return require_complete_type (fold (rval));
}
+ else
+ {
+ tree ar = default_conversion (array);
- {
- tree ar = default_conversion (array);
- tree ind = default_conversion (index);
-
- /* Do the same warning check as above, but only on the part that's
- syntactically the index and only if it is also semantically
- the index. */
- if (warn_char_subscripts
- && TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE
- && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
- warning ("subscript has type %<char%>");
-
- /* Put the integer in IND to simplify error checking. */
- if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE)
- {
- tree temp = ar;
- ar = ind;
- ind = temp;
- }
-
- if (ar == error_mark_node)
- return ar;
+ if (ar == error_mark_node)
+ return ar;
- if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE
- || TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) == FUNCTION_TYPE)
- {
- error ("subscripted value is neither array nor pointer");
- return error_mark_node;
- }
- if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE)
- {
- error ("array subscript is not an integer");
- return error_mark_node;
- }
+ gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
+ gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
- return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, ind, 0),
- "array indexing");
- }
+ return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 0),
+ "array indexing");
+ }
}
\f
/* Build an external reference to identifier ID. FUN indicates
return 0;
}
}
-
-/* Return nonzero if REF is an lvalue valid for this language;
- otherwise, print an error message and return zero. USE says
- how the lvalue is being used and so selects the error message. */
-
-static int
-lvalue_or_else (tree ref, enum lvalue_use use)
-{
- int win = lvalue_p (ref);
-
- if (!win)
- {
- switch (use)
- {
- case lv_assign:
- error ("invalid lvalue in assignment");
- break;
- case lv_increment:
- error ("invalid lvalue in increment");
- break;
- case lv_decrement:
- error ("invalid lvalue in decrement");
- break;
- case lv_addressof:
- error ("invalid lvalue in unary %<&%>");
- break;
- case lv_asm:
- error ("invalid lvalue in asm statement");
- break;
- default:
- gcc_unreachable ();
- }
- }
-
- return win;
-}
-
\f
/* Give an error for storing in something that is 'const'. */
{
error ("switch quantity not an integer");
exp = integer_zero_node;
+ orig_type = error_mark_node;
}
else
{
{
tree entry = NULL, exit = NULL, t;
- /* Detect do { ... } while (0) and don't generate loop construct. */
- if (cond && !cond_is_first && integer_zerop (cond))
- cond = NULL;
- if (cond_is_first || cond)
+ /* If the condition is zero don't generate a loop construct. */
+ if (cond && integer_zerop (cond))
+ {
+ if (cond_is_first)
+ {
+ t = build_and_jump (&blab);
+ SET_EXPR_LOCATION (t, start_locus);
+ add_stmt (t);
+ }
+ }
+ else
{
tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
then we just build a jump back to the top. */
exit = build_and_jump (&LABEL_EXPR_LABEL (top));
- if (cond)
+ if (cond && !integer_nonzerop (cond))
{
/* Canonicalize the loop condition to the end. This means
generating a branch to the loop condition. Reuse the