#include "c-lang.h"
#include "flags.h"
#include "output.h"
-#include "expr.h"
-#include "toplev.h"
#include "intl.h"
#include "target.h"
#include "tree-iterator.h"
-#include "tree-flow.h"
+#include "bitmap.h"
+#include "gimple.h"
/* Possible cases of implicit bad conversions. Used to select
diagnostic messages in convert_for_assignment. */
ic_return
};
-/* Whether we are building a boolean conversion inside
- convert_for_assignment, or some other late binary operation. If
- build_binary_op is called (from code shared with C++) in this case,
- then the operands have already been folded and the result will not
- be folded again, so C_MAYBE_CONST_EXPR should not be generated. */
-bool in_late_binary_op;
-
/* The level of nesting inside "__alignof__". */
int in_alignof;
&& TREE_CODE (mv2) != ARRAY_TYPE)
mv2 = TYPE_MAIN_VARIANT (mv2);
for (memb = TYPE_FIELDS (TREE_VALUE (p1));
- memb; memb = TREE_CHAIN (memb))
+ memb; memb = DECL_CHAIN (memb))
{
tree mv3 = TREE_TYPE (memb);
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv1) != ARRAY_TYPE)
mv1 = TYPE_MAIN_VARIANT (mv1);
for (memb = TYPE_FIELDS (TREE_VALUE (p2));
- memb; memb = TREE_CHAIN (memb))
+ memb; memb = DECL_CHAIN (memb))
{
tree mv3 = TREE_TYPE (memb);
if (mv3 && mv3 != error_mark_node
|| TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)
return 1;
- /* If either type is the internal version of sizetype, return the
- language version. */
- if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1)
- && TYPE_ORIG_SIZE_TYPE (t1))
- t1 = TYPE_ORIG_SIZE_TYPE (t1);
-
- if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2)
- && TYPE_ORIG_SIZE_TYPE (t2))
- t2 = TYPE_ORIG_SIZE_TYPE (t2);
-
-
/* Enumerated types are compatible with integer types, but this is
not transitive: two enumerated types in the same translation unit
are compatible with each other only if they are the same type. */
/* Speed up the common case where the fields are in the same order. */
for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2;
- s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
+ s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2))
{
int result;
return tu->val;
}
- for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1))
+ for (s1 = TYPE_FIELDS (t1); s1; s1 = DECL_CHAIN (s1))
{
bool ok = false;
- for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
+ for (s2 = TYPE_FIELDS (t2); s2; s2 = DECL_CHAIN (s2))
if (DECL_NAME (s1) == DECL_NAME (s2))
{
int result;
for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
s1 && s2;
- s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
+ s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2))
{
int result;
if (TREE_CODE (s1) != TREE_CODE (s2)
{
tree memb;
for (memb = TYPE_FIELDS (a1);
- memb; memb = TREE_CHAIN (memb))
+ memb; memb = DECL_CHAIN (memb))
{
tree mv3 = TREE_TYPE (memb);
if (mv3 && mv3 != error_mark_node
{
tree memb;
for (memb = TYPE_FIELDS (a2);
- memb; memb = TREE_CHAIN (memb))
+ memb; memb = DECL_CHAIN (memb))
{
tree mv3 = TREE_TYPE (memb);
if (mv3 && mv3 != error_mark_node
mark_exp_read (TREE_OPERAND (exp, 0));
break;
case COMPOUND_EXPR:
+ case C_MAYBE_CONST_EXPR:
mark_exp_read (TREE_OPERAND (exp, 1));
break;
default:
if (anon)
return tree_cons (NULL_TREE, field, anon);
+
+ /* The Plan 9 compiler permits referring
+ directly to an anonymous struct/union field
+ using a typedef name. */
+ if (flag_plan9_extensions
+ && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
+ && (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
+ == TYPE_DECL)
+ && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
+ == component))
+ break;
}
}
}
else
{
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
if (DECL_NAME (field) == NULL_TREE
&& (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
if (anon)
return tree_cons (NULL_TREE, field, anon);
+
+ /* The Plan 9 compiler permits referring directly to an
+ anonymous struct/union field using a typedef
+ name. */
+ if (flag_plan9_extensions
+ && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
+ && TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL
+ && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
+ == component))
+ break;
}
if (DECL_NAME (field) == component)
if (!objc_is_public (datum, component))
return error_mark_node;
+ /* Detect Objective-C property syntax object.property. */
+ if (c_dialect_objc ()
+ && (ref = objc_maybe_build_component_ref (datum, component)))
+ return ref;
+
/* See if there is a field or component with name COMPONENT. */
if (code == RECORD_TYPE || code == UNION_TYPE)
arrays that are not lvalues (for example, members of structures returned
by functions).
+ For vector types, allow vector[i] but not i[vector], and create
+ *(((type*)&vectortype) + i) for the expression.
+
LOC is the location to use for the returned expression. */
tree
return error_mark_node;
if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
- && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE)
+ && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE
+ /* Allow vector[index] but not index[vector]. */
+ && TREE_CODE (TREE_TYPE (array)) != VECTOR_TYPE)
{
tree temp;
if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
{
- error_at (loc, "subscripted value is neither array nor pointer");
+ error_at (loc,
+ "subscripted value is neither array nor pointer nor vector");
+
return error_mark_node;
}
temp = array;
index = default_conversion (index);
gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
+
+ /* For vector[index], convert the vector to a
+ pointer of the underlying type. */
+ if (TREE_CODE (TREE_TYPE (array)) == VECTOR_TYPE)
+ {
+ tree type = TREE_TYPE (array);
+ tree type1;
+
+ if (TREE_CODE (index) == INTEGER_CST)
+ if (!host_integerp (index, 1)
+ || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1)
+ >= TYPE_VECTOR_SUBPARTS (TREE_TYPE (array))))
+ warning_at (loc, OPT_Warray_bounds, "index value is out of bound");
+
+ c_common_mark_addressable_vec (array);
+ type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
+ type = build_pointer_type (type);
+ type1 = build_pointer_type (TREE_TYPE (array));
+ array = build1 (ADDR_EXPR, type1, array);
+ array = convert (type, array);
+ }
if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
{
build_constructor (return_type, 0),
false);
else
- rhs = fold_convert_loc (loc, return_type, integer_zero_node);
+ rhs = build_zero_cst (return_type);
return require_complete_type (build2 (COMPOUND_EXPR, return_type,
trap, rhs));
if (type == void_type_node)
{
- error_at (input_location,
- "too many arguments to function %qE", function);
+ if (selector)
+ error_at (input_location,
+ "too many arguments to method %qE", selector);
+ else
+ error_at (input_location,
+ "too many arguments to function %qE", function);
+
if (fundecl && !DECL_BUILT_IN (fundecl))
inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
return parmnum;
if (type_generic)
parmval = val;
else
- /* Convert `float' to `double'. */
- parmval = convert (double_type_node, val);
+ {
+ /* Convert `float' to `double'. */
+ if (warn_double_promotion && !c_inhibit_evaluation_warnings)
+ warning (OPT_Wdouble_promotion,
+ "implicit conversion from %qT to %qT when passing "
+ "argument to function",
+ valtype, double_type_node);
+ parmval = convert (double_type_node, val);
+ }
}
else if (excess_precision && !type_generic)
/* A "double" argument with excess precision being passed
goto return_build_unary_op;
case REALPART_EXPR:
- if (TREE_CODE (arg) == COMPLEX_CST)
- ret = TREE_REALPART (arg);
- else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
- ret = fold_build1_loc (location,
- REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
- else
- ret = arg;
- if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
- eptype = TREE_TYPE (eptype);
- goto return_build_unary_op;
-
case IMAGPART_EXPR:
- if (TREE_CODE (arg) == COMPLEX_CST)
- ret = TREE_IMAGPART (arg);
- else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
- ret = fold_build1_loc (location,
- IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
- else
- ret = omit_one_operand_loc (location, TREE_TYPE (arg),
- integer_zero_node, arg);
+ ret = build_real_imag_expr (location, code, arg);
+ if (ret == error_mark_node)
+ return error_mark_node;
if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
eptype = TREE_TYPE (eptype);
goto return_build_unary_op;
goto return_build_unary_op;
}
- /* Complain about anything that is not a true lvalue. */
- if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? lv_increment
- : lv_decrement)))
+ /* Complain about anything that is not a true lvalue. In
+ Objective-C, skip this check for property_refs. */
+ if (!objc_is_property_ref (arg)
+ && !lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
+ || code == POSTINCREMENT_EXPR)
+ ? lv_increment
+ : lv_decrement)))
return error_mark_node;
if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
inc = convert (argtype, inc);
}
+ /* If 'arg' is an Objective-C PROPERTY_REF expression, then we
+ need to ask Objective-C to build the increment or decrement
+ expression for it. */
+ if (objc_is_property_ref (arg))
+ return objc_build_incr_expr_for_property_ref (location, code,
+ arg, inc);
+
/* Report a read-only lvalue. */
if (TYPE_READONLY (argtype))
{
argtype = TREE_TYPE (arg);
/* If the lvalue is const or volatile, merge that into the type
- to which the address will point. Note that you can't get a
- restricted pointer by taking the address of something, so we
- only have to deal with `const' and `volatile' here. */
+ to which the address will point. This should only be needed
+ for function types. */
if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
&& (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
- argtype = c_build_type_variant (argtype,
- TREE_READONLY (arg),
- TREE_THIS_VOLATILE (arg));
+ {
+ int orig_quals = TYPE_QUALS (strip_array_types (argtype));
+ int quals = orig_quals;
+
+ if (TREE_READONLY (arg))
+ quals |= TYPE_QUAL_CONST;
+ if (TREE_THIS_VOLATILE (arg))
+ quals |= TYPE_QUAL_VOLATILE;
+
+ gcc_assert (quals == orig_quals
+ || TREE_CODE (argtype) == FUNCTION_TYPE);
+
+ argtype = c_build_qualified_type (argtype, quals);
+ }
if (!c_mark_addressable (arg))
return error_mark_node;
bool int_const, op1_int_operands, op2_int_operands, int_operands;
bool ifexp_int_operands;
tree ret;
- bool objc_ok;
op1_int_operands = EXPR_INT_CONST_OPERANDS (orig_op1);
if (op1_int_operands)
return error_mark_node;
}
- objc_ok = objc_compare_types (type1, type2, -3, NULL_TREE);
-
if ((TREE_CODE (op1) == EXCESS_PRECISION_EXPR
|| TREE_CODE (op2) == EXCESS_PRECISION_EXPR)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|| code2 == COMPLEX_TYPE))
{
result_type = c_common_type (type1, type2);
+ do_warn_double_promotion (result_type, type1, type2,
+ "implicit conversion from %qT to %qT to "
+ "match other result of conditional",
+ colon_loc);
/* If -Wsign-compare, warn here if type1 and type2 have
different signedness. We'll promote the signed to unsigned
result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
TREE_TYPE (type1)));
}
+ /* Objective-C pointer comparisons are a bit more lenient. */
+ else if (objc_have_common_type (type1, type2, -3, NULL_TREE))
+ result_type = objc_common_type (type1, type2);
else
{
int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
- if (!objc_ok)
- pedwarn (colon_loc, 0,
- "pointer type mismatch in conditional expression");
+ pedwarn (colon_loc, 0,
+ "pointer type mismatch in conditional expression");
result_type = build_pointer_type
(build_qualified_type (void_type_node, qual));
}
/* Issue -Wcast-qual warnings when appropriate. TYPE is the type to
which we are casting. OTYPE is the type of the expression being
- cast. Both TYPE and OTYPE are pointer types. -Wcast-qual appeared
- on the command line. Named address space qualifiers are not handled
- here, because they result in different warnings. */
+ cast. Both TYPE and OTYPE are pointer types. LOC is the location
+ of the cast. -Wcast-qual appeared on the command line. Named
+ address space qualifiers are not handled here, because they result
+ in different warnings. */
static void
-handle_warn_cast_qual (tree type, tree otype)
+handle_warn_cast_qual (location_t loc, tree type, tree otype)
{
tree in_type = type;
tree in_otype = otype;
&& TREE_CODE (in_otype) == POINTER_TYPE);
if (added)
- warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
+ warning_at (loc, OPT_Wcast_qual,
+ "cast adds %q#v qualifier to function type", added);
if (discarded)
/* There are qualifiers present in IN_OTYPE that are not present
in IN_TYPE. */
- warning (OPT_Wcast_qual,
- "cast discards qualifiers from pointer target type");
+ warning_at (loc, OPT_Wcast_qual,
+ "cast discards %q#v qualifier from pointer target type",
+ discarded);
if (added || discarded)
return;
if ((TYPE_QUALS (in_type) &~ TYPE_QUALS (in_otype)) != 0
&& !is_const)
{
- warning (OPT_Wcast_qual,
- ("new qualifiers in middle of multi-level non-const cast "
- "are unsafe"));
+ warning_at (loc, OPT_Wcast_qual,
+ "to be safe all intermediate pointers in cast from "
+ "%qT to %qT must be %<const%> qualified",
+ otype, type);
break;
}
if (is_const)
{
tree field;
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_TYPE (field) != error_mark_node
&& comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
TYPE_MAIN_VARIANT (TREE_TYPE (value))))
if (warn_cast_qual
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE)
- handle_warn_cast_qual (type, otype);
+ handle_warn_cast_qual (loc, type, otype);
/* Warn about conversions between pointers to disjoint
address spaces. */
if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret))
SET_EXPR_LOCATION (ret, loc);
- /* C++ does not permits types to be defined in a cast. */
- if (warn_cxx_compat && type_name->specs->tag_defined_p)
+ /* C++ does not permits types to be defined in a cast, but it
+ allows references to incomplete types. */
+ if (warn_cxx_compat && type_name->specs->typespec_kind == ctsk_tagdef)
warning_at (loc, OPT_Wc___compat,
"defining a type in a cast is invalid in C++");
if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
return error_mark_node;
- if (!lvalue_or_else (lhs, lv_assign))
+ /* For ObjC properties, defer this check. */
+ if (!objc_is_property_ref (lhs) && !lvalue_or_else (lhs, lv_assign))
return error_mark_node;
if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
rhs_origtype = NULL_TREE;
}
+ if (c_dialect_objc ())
+ {
+ /* Check if we are modifying an Objective-C property reference;
+ if so, we need to generate setter calls. */
+ result = objc_maybe_build_modify_expr (lhs, newrhs);
+ if (result)
+ return result;
+
+ /* Else, do the check that we postponed for Objective-C. */
+ if (!lvalue_or_else (lhs, lv_assign))
+ return error_mark_node;
+ }
+
/* Give an error for storing in something that is 'const'. */
if (TYPE_READONLY (lhstype)
return result;
}
\f
+/* Return whether STRUCT_TYPE has an anonymous field with type TYPE.
+ This is used to implement -fplan9-extensions. */
+
+static bool
+find_anonymous_field_with_type (tree struct_type, tree type)
+{
+ tree field;
+ bool found;
+
+ gcc_assert (TREE_CODE (struct_type) == RECORD_TYPE
+ || TREE_CODE (struct_type) == UNION_TYPE);
+ found = false;
+ for (field = TYPE_FIELDS (struct_type);
+ field != NULL_TREE;
+ field = TREE_CHAIN (field))
+ {
+ if (DECL_NAME (field) == NULL
+ && comptypes (type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+ {
+ if (found)
+ return false;
+ found = true;
+ }
+ else if (DECL_NAME (field) == NULL
+ && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+ && find_anonymous_field_with_type (TREE_TYPE (field), type))
+ {
+ if (found)
+ return false;
+ found = true;
+ }
+ }
+ return found;
+}
+
+/* RHS is an expression whose type is pointer to struct. If there is
+ an anonymous field in RHS with type TYPE, then return a pointer to
+ that field in RHS. This is used with -fplan9-extensions. This
+ returns NULL if no conversion could be found. */
+
+static tree
+convert_to_anonymous_field (location_t location, tree type, tree rhs)
+{
+ tree rhs_struct_type, lhs_main_type;
+ tree field, found_field;
+ bool found_sub_field;
+ tree ret;
+
+ gcc_assert (POINTER_TYPE_P (TREE_TYPE (rhs)));
+ rhs_struct_type = TREE_TYPE (TREE_TYPE (rhs));
+ gcc_assert (TREE_CODE (rhs_struct_type) == RECORD_TYPE
+ || TREE_CODE (rhs_struct_type) == UNION_TYPE);
+
+ gcc_assert (POINTER_TYPE_P (type));
+ lhs_main_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+
+ found_field = NULL_TREE;
+ found_sub_field = false;
+ for (field = TYPE_FIELDS (rhs_struct_type);
+ field != NULL_TREE;
+ field = TREE_CHAIN (field))
+ {
+ if (DECL_NAME (field) != NULL_TREE
+ || (TREE_CODE (TREE_TYPE (field)) != RECORD_TYPE
+ && TREE_CODE (TREE_TYPE (field)) != UNION_TYPE))
+ continue;
+ if (comptypes (lhs_main_type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+ {
+ if (found_field != NULL_TREE)
+ return NULL_TREE;
+ found_field = field;
+ }
+ else if (find_anonymous_field_with_type (TREE_TYPE (field),
+ lhs_main_type))
+ {
+ if (found_field != NULL_TREE)
+ return NULL_TREE;
+ found_field = field;
+ found_sub_field = true;
+ }
+ }
+
+ if (found_field == NULL_TREE)
+ return NULL_TREE;
+
+ ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (found_field),
+ build_fold_indirect_ref (rhs), found_field,
+ NULL_TREE);
+ ret = build_fold_addr_expr_loc (location, ret);
+
+ if (found_sub_field)
+ {
+ ret = convert_to_anonymous_field (location, type, ret);
+ gcc_assert (ret != NULL_TREE);
+ }
+
+ return ret;
+}
+
/* Convert value RHS to type TYPE as preparation for an assignment to
an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the
original type of RHS; this differs from TREE_TYPE (RHS) for enum
pedwarn (LOCATION, OPT, AS); \
break; \
case ic_init: \
- pedwarn (LOCATION, OPT, IN); \
+ pedwarn_init (LOCATION, OPT, IN); \
break; \
case ic_return: \
pedwarn (LOCATION, OPT, RE); \
} \
} while (0)
+ /* This macro is used to emit diagnostics to ensure that all format
+ strings are complete sentences, visible to gettext and checked at
+ compile time. It is the same as WARN_FOR_ASSIGNMENT but with an
+ extra parameter to enumerate qualifiers. */
+
+#define WARN_FOR_QUALIFIERS(LOCATION, OPT, AR, AS, IN, RE, QUALS) \
+ do { \
+ switch (errtype) \
+ { \
+ case ic_argpass: \
+ if (pedwarn (LOCATION, OPT, AR, parmnum, rname, QUALS)) \
+ inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
+ ? DECL_SOURCE_LOCATION (fundecl) : LOCATION, \
+ "expected %qT but argument is of type %qT", \
+ type, rhstype); \
+ break; \
+ case ic_assign: \
+ pedwarn (LOCATION, OPT, AS, QUALS); \
+ break; \
+ case ic_init: \
+ pedwarn (LOCATION, OPT, IN, QUALS); \
+ break; \
+ case ic_return: \
+ pedwarn (LOCATION, OPT, RE, QUALS); \
+ break; \
+ default: \
+ gcc_unreachable (); \
+ } \
+ } while (0)
+
if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
rhs = TREE_OPERAND (rhs, 0);
{
tree memb, marginal_memb = NULL_TREE;
- for (memb = TYPE_FIELDS (type); memb ; memb = TREE_CHAIN (memb))
+ for (memb = TYPE_FIELDS (type); memb ; memb = DECL_CHAIN (memb))
{
tree memb_type = TREE_TYPE (memb);
vice-versa. */
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
- WARN_FOR_ASSIGNMENT (location, 0,
+ WARN_FOR_QUALIFIERS (location, 0,
G_("passing argument %d of %qE "
- "makes qualified function "
+ "makes %q#v qualified function "
"pointer from unqualified"),
- G_("assignment makes qualified "
+ G_("assignment makes %q#v qualified "
"function pointer from "
"unqualified"),
- G_("initialization makes qualified "
+ G_("initialization makes %q#v qualified "
"function pointer from "
"unqualified"),
- G_("return makes qualified function "
- "pointer from unqualified"));
+ G_("return makes %q#v qualified function "
+ "pointer from unqualified"),
+ TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
}
else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
- WARN_FOR_ASSIGNMENT (location, 0,
+ WARN_FOR_QUALIFIERS (location, 0,
G_("passing argument %d of %qE discards "
- "qualifiers from pointer target type"),
- G_("assignment discards qualifiers "
+ "%qv qualifier from pointer target type"),
+ G_("assignment discards %qv qualifier "
"from pointer target type"),
- G_("initialization discards qualifiers "
+ G_("initialization discards %qv qualifier "
"from pointer target type"),
- G_("return discards qualifiers from "
- "pointer target type"));
+ G_("return discards %qv qualifier from "
+ "pointer target type"),
+ TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
memb = marginal_memb;
}
/* Opaque pointers are treated like void pointers. */
is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
+ /* The Plan 9 compiler permits a pointer to a struct to be
+ automatically converted into a pointer to an anonymous field
+ within the struct. */
+ if (flag_plan9_extensions
+ && (TREE_CODE (mvl) == RECORD_TYPE || TREE_CODE(mvl) == UNION_TYPE)
+ && (TREE_CODE (mvr) == RECORD_TYPE || TREE_CODE(mvr) == UNION_TYPE)
+ && mvl != mvr)
+ {
+ tree new_rhs = convert_to_anonymous_field (location, type, rhs);
+ if (new_rhs != NULL_TREE)
+ {
+ rhs = new_rhs;
+ rhstype = TREE_TYPE (rhs);
+ coder = TREE_CODE (rhstype);
+ ttr = TREE_TYPE (rhstype);
+ mvr = TYPE_MAIN_VARIANT (ttr);
+ }
+ }
+
/* C++ does not allow the implicit conversion void* -> T*. However,
for the purpose of reducing the number of false positives, we
tolerate the special case of
if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
{
- /* Types differing only by the presence of the 'volatile'
- qualifier are acceptable if the 'volatile' has been added
- in by the Objective-C EH machinery. */
- if (!objc_type_quals_match (ttl, ttr))
- WARN_FOR_ASSIGNMENT (location, 0,
- G_("passing argument %d of %qE discards "
- "qualifiers from pointer target type"),
- G_("assignment discards qualifiers "
- "from pointer target type"),
- G_("initialization discards qualifiers "
- "from pointer target type"),
- G_("return discards qualifiers from "
- "pointer target type"));
+ WARN_FOR_QUALIFIERS (location, 0,
+ G_("passing argument %d of %qE discards "
+ "%qv qualifier from pointer target type"),
+ G_("assignment discards %qv qualifier "
+ "from pointer target type"),
+ G_("initialization discards %qv qualifier "
+ "from pointer target type"),
+ G_("return discards %qv qualifier from "
+ "pointer target type"),
+ TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
}
/* If this is not a case of ignoring a mismatch in signedness,
no warning. */
where an ordinary one is wanted, but not vice-versa. */
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
- WARN_FOR_ASSIGNMENT (location, 0,
+ WARN_FOR_QUALIFIERS (location, 0,
G_("passing argument %d of %qE makes "
- "qualified function pointer "
+ "%q#v qualified function pointer "
"from unqualified"),
- G_("assignment makes qualified function "
+ G_("assignment makes %q#v qualified function "
"pointer from unqualified"),
- G_("initialization makes qualified "
+ G_("initialization makes %q#v qualified "
"function pointer from unqualified"),
- G_("return makes qualified function "
- "pointer from unqualified"));
+ G_("return makes %q#v qualified function "
+ "pointer from unqualified"),
+ TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
}
}
else
}
/* Issue an error message for a bad initializer component.
- MSGID identifies the message.
+ GMSGID identifies the message.
The component name is taken from the spelling stack. */
void
-error_init (const char *msgid)
+error_init (const char *gmsgid)
{
char *ofwhat;
- error ("%s", _(msgid));
+ /* The gmsgid may be a format string with %< and %>. */
+ error (gmsgid);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
error ("(near initialization for %qs)", ofwhat);
/* Issue a pedantic warning for a bad initializer component. OPT is
the option OPT_* (from options.h) controlling this warning or 0 if
- it is unconditionally given. MSGID identifies the message. The
+ it is unconditionally given. GMSGID identifies the message. The
component name is taken from the spelling stack. */
void
-pedwarn_init (location_t location, int opt, const char *msgid)
+pedwarn_init (location_t location, int opt, const char *gmsgid)
{
char *ofwhat;
-
- pedwarn (location, opt, "%s", _(msgid));
+
+ /* The gmsgid may be a format string with %< and %>. */
+ pedwarn (location, opt, gmsgid);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
/* Issue a warning for a bad initializer component.
OPT is the OPT_W* value corresponding to the warning option that
- controls this warning. MSGID identifies the message. The
+ controls this warning. GMSGID identifies the message. The
component name is taken from the spelling stack. */
static void
-warning_init (int opt, const char *msgid)
+warning_init (int opt, const char *gmsgid)
{
char *ofwhat;
- warning (opt, "%s", _(msgid));
+ /* The gmsgid may be a format string with %< and %>. */
+ warning (opt, gmsgid);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
warning (opt, "(near initialization for %qs)", ofwhat);
/* Skip any nameless bit fields at the beginning. */
while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
- constructor_fields = TREE_CHAIN (constructor_fields);
+ constructor_fields = DECL_CHAIN (constructor_fields);
constructor_unfilled_fields = constructor_fields;
constructor_bit_index = bitsize_zero_node;
/* Detect non-empty initializations of zero-length arrays. */
if (constructor_max_index == NULL_TREE
&& TYPE_SIZE (constructor_type))
- constructor_max_index = build_int_cst (NULL_TREE, -1);
+ constructor_max_index = integer_minus_one_node;
/* constructor_max_index needs to be an INTEGER_CST. Attempts
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_max_index = build_int_cst (NULL_TREE, -1);
+ constructor_max_index = integer_minus_one_node;
constructor_index
= convert (bitsizetype,
/* Skip any nameless bit fields at the beginning. */
while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
- constructor_fields = TREE_CHAIN (constructor_fields);
+ constructor_fields = DECL_CHAIN (constructor_fields);
constructor_unfilled_fields = constructor_fields;
constructor_bit_index = bitsize_zero_node;
/* Detect non-empty initializations of zero-length arrays. */
if (constructor_max_index == NULL_TREE
&& TYPE_SIZE (constructor_type))
- constructor_max_index = build_int_cst (NULL_TREE, -1);
+ constructor_max_index = integer_minus_one_node;
/* constructor_max_index needs to be an INTEGER_CST. Attempts
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_max_index = build_int_cst (NULL_TREE, -1);
+ constructor_max_index = integer_minus_one_node;
constructor_index
= convert (bitsizetype,
/* We have already issued an error message for the existence
of a flexible array member not at the end of the structure.
Discard the initializer so that we do not die later. */
- if (TREE_CHAIN (constructor_fields) != NULL_TREE)
+ if (DECL_CHAIN (constructor_fields) != NULL_TREE)
constructor_type = NULL_TREE;
}
}
while (constructor_unfilled_fields
&& (!DECL_SIZE (constructor_unfilled_fields)
|| integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
- constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
+ constructor_unfilled_fields = DECL_CHAIN (constructor_unfilled_fields);
/* Do not warn if this level of the initializer uses member
designators; it is likely to be deliberate. */
|| (COMPLETE_TYPE_P (TREE_TYPE (field))
&& integer_zerop (TYPE_SIZE (TREE_TYPE (field)))
&& (TREE_CODE (constructor_type) == ARRAY_TYPE
- || TREE_CHAIN (field)))))
+ || DECL_CHAIN (field)))))
return;
if (semantic_type)
else if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
constructor_unfilled_fields
- = TREE_CHAIN (constructor_unfilled_fields);
+ = DECL_CHAIN (constructor_unfilled_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);
+ DECL_CHAIN (constructor_unfilled_fields);
}
else if (TREE_CODE (constructor_type) == UNION_TYPE)
constructor_unfilled_fields = 0;
if (fieldcode == ARRAY_TYPE
&& !require_constant_value
&& TYPE_SIZE (fieldtype) == NULL_TREE
- && TREE_CHAIN (constructor_fields) == NULL_TREE)
+ && DECL_CHAIN (constructor_fields) == NULL_TREE)
{
error_init ("non-static initialization of a flexible array member");
break;
it isn't now, so update. */
if (constructor_unfilled_fields == constructor_fields)
{
- constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+ constructor_unfilled_fields = DECL_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);
+ DECL_CHAIN (constructor_unfilled_fields);
}
}
- constructor_fields = TREE_CHAIN (constructor_fields);
+ constructor_fields = DECL_CHAIN (constructor_fields);
/* Skip any nameless bit fields at the beginning. */
while (constructor_fields != 0
&& DECL_C_BIT_FIELD (constructor_fields)
&& DECL_NAME (constructor_fields) == 0)
- constructor_fields = TREE_CHAIN (constructor_fields);
+ constructor_fields = DECL_CHAIN (constructor_fields);
}
else if (TREE_CODE (constructor_type) == UNION_TYPE)
{
directly output as a constructor. */
{
constructor_bit_index = DECL_SIZE (constructor_fields);
- constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+ constructor_unfilled_fields = DECL_CHAIN (constructor_fields);
}
constructor_fields = 0;
precision. */
bool may_need_excess_precision;
+ /* True means this is a boolean operation that converts both its
+ operands to truth-values. */
+ bool boolean_op = false;
+
if (location == UNKNOWN_LOCATION)
location = input_location;
op0 = c_common_truthvalue_conversion (location, op0);
op1 = c_common_truthvalue_conversion (location, op1);
converted = 1;
+ boolean_op = true;
}
if (code == TRUTH_ANDIF_EXPR)
{
Also set SHORT_SHIFT if shifting rightward. */
case RSHIFT_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+ if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+ {
+ result_type = type0;
+ converted = 1;
+ }
+ else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+ && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+ {
+ result_type = type0;
+ converted = 1;
+ }
+ else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
&& code1 == INTEGER_TYPE)
{
if (TREE_CODE (op1) == INTEGER_CST)
/* Use the type of the value to be shifted. */
result_type = type0;
- /* Convert the shift-count to an integer, regardless of size
- of value being shifted. */
- if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+ /* Convert the non vector shift-count to an integer, regardless
+ of size of value being shifted. */
+ if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+ && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = convert (integer_type_node, op1);
/* Avoid converting op1 to result_type later. */
converted = 1;
break;
case LSHIFT_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+ if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+ {
+ result_type = type0;
+ converted = 1;
+ }
+ else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+ && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+ {
+ result_type = type0;
+ converted = 1;
+ }
+ else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
&& code1 == INTEGER_TYPE)
{
if (TREE_CODE (op1) == INTEGER_CST)
/* Use the type of the value to be shifted. */
result_type = type0;
- /* Convert the shift-count to an integer, regardless of size
- of value being shifted. */
- if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+ /* Convert the non vector shift-count to an integer, regardless
+ of size of value being shifted. */
+ if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+ && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = convert (integer_type_node, op1);
/* Avoid converting op1 to result_type later. */
converted = 1;
if (shorten || common || short_compare)
{
result_type = c_common_type (type0, type1);
+ do_warn_double_promotion (result_type, type0, type1,
+ "implicit conversion from %qT to %qT "
+ "to match other operand of binary "
+ "expression",
+ location);
if (result_type == error_mark_node)
return error_mark_node;
}
if (build_type == NULL_TREE)
{
build_type = result_type;
- if (type0 != orig_type0 || type1 != orig_type1)
+ if ((type0 != orig_type0 || type1 != orig_type1)
+ && !boolean_op)
{
gcc_assert (may_need_excess_precision && common);
semantic_result_type = c_common_type (orig_type0, orig_type1);