#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "rtl.h"
#include "tree.h"
#include "langhooks.h"
#include "c-tree.h"
#include "c-lang.h"
-#include "tm_p.h"
#include "flags.h"
#include "output.h"
-#include "expr.h"
#include "toplev.h"
#include "intl.h"
-#include "ggc.h"
#include "target.h"
#include "tree-iterator.h"
+#include "bitmap.h"
#include "gimple.h"
-#include "tree-flow.h"
/* Possible cases of implicit bad conversions. Used to select
diagnostic messages in convert_for_assignment. */
static bool null_pointer_constant_p (const_tree);
static tree qualify_type (tree, tree);
-static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *);
+static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *,
+ bool *);
static int comp_target_types (location_t, tree, tree);
-static int function_types_compatible_p (const_tree, const_tree, bool *);
-static int type_lists_compatible_p (const_tree, const_tree, bool *);
+static int function_types_compatible_p (const_tree, const_tree, bool *,
+ bool *);
+static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
static tree lookup_field (tree, tree);
static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
tree);
static void readonly_warning (tree, enum lvalue_use);
static int lvalue_or_else (const_tree, enum lvalue_use);
static void record_maybe_used_decl (tree);
-static int comptypes_internal (const_tree, const_tree, bool *);
+static int comptypes_internal (const_tree, const_tree, bool *, bool *);
\f
/* Return true if EXP is a null pointer constant, false otherwise. */
&& 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
const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
int val;
- val = comptypes_internal (type1, type2, NULL);
+ val = comptypes_internal (type1, type2, NULL, NULL);
free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
return val;
const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
int val;
- val = comptypes_internal (type1, type2, enum_and_int_p);
+ val = comptypes_internal (type1, type2, enum_and_int_p, NULL);
+ free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+
+ return val;
+}
+
+/* Like comptypes, but if it returns nonzero for different types, it
+ sets *DIFFERENT_TYPES_P to true. */
+
+int
+comptypes_check_different_types (tree type1, tree type2,
+ bool *different_types_p)
+{
+ const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
+ int val;
+
+ val = comptypes_internal (type1, type2, NULL, different_types_p);
free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
return val;
but a warning may be needed if you use them together. If
ENUM_AND_INT_P is not NULL, and one type is an enum and the other a
compatible integer type, then this sets *ENUM_AND_INT_P to true;
- *ENUM_AND_INT_P is never set to false. This differs from
- comptypes, in that we don't free the seen types. */
+ *ENUM_AND_INT_P is never set to false. If DIFFERENT_TYPES_P is not
+ NULL, and the types are compatible but different enough not to be
+ permitted in C1X typedef redeclarations, then this sets
+ *DIFFERENT_TYPES_P to true; *DIFFERENT_TYPES_P is never set to
+ false, but may or may not be set if the types are incompatible.
+ This differs from comptypes, in that we don't free the seen
+ types. */
static int
-comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
+comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
+ bool *different_types_p)
{
const_tree t1 = type1;
const_tree t2 = type2;
if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE)
{
t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
- if (enum_and_int_p != NULL && TREE_CODE (t2) != VOID_TYPE)
- *enum_and_int_p = true;
+ if (TREE_CODE (t2) != VOID_TYPE)
+ {
+ if (enum_and_int_p != NULL)
+ *enum_and_int_p = true;
+ if (different_types_p != NULL)
+ *different_types_p = true;
+ }
}
else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE)
{
t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
- if (enum_and_int_p != NULL && TREE_CODE (t1) != VOID_TYPE)
- *enum_and_int_p = true;
+ if (TREE_CODE (t1) != VOID_TYPE)
+ {
+ if (enum_and_int_p != NULL)
+ *enum_and_int_p = true;
+ if (different_types_p != NULL)
+ *different_types_p = true;
+ }
}
if (t1 == t2)
break;
val = (TREE_TYPE (t1) == TREE_TYPE (t2)
? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
- enum_and_int_p));
+ enum_and_int_p, different_types_p));
break;
case FUNCTION_TYPE:
- val = function_types_compatible_p (t1, t2, enum_and_int_p);
+ val = function_types_compatible_p (t1, t2, enum_and_int_p,
+ different_types_p);
break;
case ARRAY_TYPE:
/* Target types must match incl. qualifiers. */
if (TREE_TYPE (t1) != TREE_TYPE (t2)
&& 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
- enum_and_int_p)))
+ enum_and_int_p,
+ different_types_p)))
return 0;
+ if (different_types_p != NULL
+ && (d1 == 0) != (d2 == 0))
+ *different_types_p = true;
/* Sizes must match unless one is missing or variable. */
if (d1 == 0 || d2 == 0 || d1 == d2)
break;
d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
+ if (different_types_p != NULL
+ && d1_variable != d2_variable)
+ *different_types_p = true;
if (d1_variable || d2_variable)
break;
if (d1_zero && d2_zero)
break;
if (attrval != 2)
- return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
- val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
+ return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
+ different_types_p);
+ val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
+ different_types_p);
}
break;
case VECTOR_TYPE:
val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
&& comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
- enum_and_int_p));
+ enum_and_int_p, different_types_p));
break;
default:
compatible. If the two types are not the same (which has been
checked earlier), this can only happen when multiple translation
units are being compiled. See C99 6.2.7 paragraph 1 for the exact
- rules. ENUM_AND_INT_P is as in comptypes_internal. */
+ rules. ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
+ comptypes_internal. */
static int
tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
- bool *enum_and_int_p)
+ bool *enum_and_int_p, bool *different_types_p)
{
tree s1, s2;
bool needs_warning = false;
/* 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;
if (DECL_NAME (s1) != DECL_NAME (s2))
break;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
- enum_and_int_p);
+ enum_and_int_p, different_types_p);
if (result != 1 && !DECL_NAME (s1))
break;
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;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
- enum_and_int_p);
+ enum_and_int_p,
+ different_types_p);
if (result != 1 && !DECL_NAME (s1))
continue;
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)
|| DECL_NAME (s1) != DECL_NAME (s2))
break;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
- enum_and_int_p);
+ enum_and_int_p, different_types_p);
if (result == 0)
break;
if (result == 2)
Otherwise, if one type specifies only the number of arguments,
the other must specify that number of self-promoting arg types.
Otherwise, the argument types must match.
- ENUM_AND_INT_P is as in comptypes_internal. */
+ ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in comptypes_internal. */
static int
function_types_compatible_p (const_tree f1, const_tree f2,
- bool *enum_and_int_p)
+ bool *enum_and_int_p, bool *different_types_p)
{
tree args1, args2;
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
if (TYPE_VOLATILE (ret2))
ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
- val = comptypes_internal (ret1, ret2, enum_and_int_p);
+ val = comptypes_internal (ret1, ret2, enum_and_int_p, different_types_p);
if (val == 0)
return 0;
args1 = TYPE_ARG_TYPES (f1);
args2 = TYPE_ARG_TYPES (f2);
+ if (different_types_p != NULL
+ && (args1 == 0) != (args2 == 0))
+ *different_types_p = true;
+
/* An unspecified parmlist matches any specified parmlist
whose argument types don't need default promotions. */
If they don't match, ask for a warning (but no error). */
if (TYPE_ACTUAL_ARG_TYPES (f1)
&& 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
- enum_and_int_p))
+ enum_and_int_p, different_types_p))
val = 2;
return val;
}
return 0;
if (TYPE_ACTUAL_ARG_TYPES (f2)
&& 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
- enum_and_int_p))
+ enum_and_int_p, different_types_p))
val = 2;
return val;
}
/* Both types have argument lists: compare them and propagate results. */
- val1 = type_lists_compatible_p (args1, args2, enum_and_int_p);
+ val1 = type_lists_compatible_p (args1, args2, enum_and_int_p,
+ different_types_p);
return val1 != 1 ? val1 : val;
}
/* Check two lists of types for compatibility, returning 0 for
incompatible, 1 for compatible, or 2 for compatible with
- warning. ENUM_AND_INT_P is as in comptypes_internal. */
+ warning. ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
+ comptypes_internal. */
static int
type_lists_compatible_p (const_tree args1, const_tree args2,
- bool *enum_and_int_p)
+ bool *enum_and_int_p, bool *different_types_p)
{
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
int val = 1;
means there is supposed to be an argument
but nothing is specified about what type it has.
So match anything that self-promotes. */
+ if (different_types_p != NULL
+ && (a1 == 0) != (a2 == 0))
+ *different_types_p = true;
if (a1 == 0)
{
if (c_type_promotes_to (a2) != a2)
else if (TREE_CODE (a1) == ERROR_MARK
|| TREE_CODE (a2) == ERROR_MARK)
;
- else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p)))
+ else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p,
+ different_types_p)))
{
+ if (different_types_p != NULL)
+ *different_types_p = true;
/* Allow wait (union {union wait *u; int *i} *)
and wait (union wait *) to be compatible. */
if (TREE_CODE (a1) == UNION_TYPE
{
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_CODE (mv3) != ARRAY_TYPE)
mv3 = TYPE_MAIN_VARIANT (mv3);
- if (comptypes_internal (mv3, mv2, enum_and_int_p))
+ if (comptypes_internal (mv3, mv2, enum_and_int_p,
+ different_types_p))
break;
}
if (memb == 0)
{
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
&& TREE_CODE (mv3) != ARRAY_TYPE)
mv3 = TYPE_MAIN_VARIANT (mv3);
- if (comptypes_internal (mv3, mv1, enum_and_int_p))
+ if (comptypes_internal (mv3, mv1, enum_and_int_p,
+ different_types_p))
break;
}
if (memb == 0)
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:
return exp;
}
\f
-/* Look up COMPONENT in a structure or union DECL.
+/* Look up COMPONENT in a structure or union TYPE.
If the component name is not found, returns NULL_TREE. Otherwise,
the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
unions, the list steps down the chain to the component. */
static tree
-lookup_field (tree decl, tree component)
+lookup_field (tree type, tree component)
{
- tree type = TREE_TYPE (decl);
tree field;
/* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{
- tree anon = lookup_field (field, component);
+ tree anon = lookup_field (TREE_TYPE (field), component);
if (anon)
return tree_cons (NULL_TREE, field, anon);
}
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
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
{
- tree anon = lookup_field (field, component);
+ tree anon = lookup_field (TREE_TYPE (field), component);
if (anon)
return tree_cons (NULL_TREE, field, anon);
return error_mark_node;
}
- field = lookup_field (datum, component);
+ field = lookup_field (type, component);
if (!field)
{
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;
/* 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. */
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;
}
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,
+ 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));
}
/* 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. */
void
set_init_label (tree fieldname, struct obstack * braced_init_obstack)
{
- tree tail;
+ tree field;
if (set_designator (0, braced_init_obstack))
return;
return;
}
- for (tail = TYPE_FIELDS (constructor_type); tail;
- tail = TREE_CHAIN (tail))
- {
- if (DECL_NAME (tail) == fieldname)
- break;
- }
+ field = lookup_field (constructor_type, fieldname);
- if (tail == 0)
+ if (field == 0)
error ("unknown field %qE specified in initializer", fieldname);
else
- {
- constructor_fields = tail;
- designator_depth++;
- designator_erroneous = 0;
- if (constructor_range_stack)
- push_range_stack (NULL_TREE, braced_init_obstack);
- }
+ do
+ {
+ constructor_fields = TREE_VALUE (field);
+ designator_depth++;
+ designator_erroneous = 0;
+ if (constructor_range_stack)
+ push_range_stack (NULL_TREE, braced_init_obstack);
+ field = TREE_CHAIN (field);
+ if (field)
+ {
+ if (set_designator (0, braced_init_obstack))
+ return;
+ }
+ }
+ while (field != NULL_TREE);
}
\f
/* Add a new initializer to the tree of pending initializers. PURPOSE
|| (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;
tree
c_process_expr_stmt (location_t loc, tree expr)
{
+ tree exprv;
+
if (!expr)
return NULL_TREE;
&& warn_unused_value)
emit_side_effect_warnings (loc, expr);
- if (DECL_P (expr) || handled_component_p (expr))
- mark_exp_read (expr);
+ exprv = expr;
+ while (TREE_CODE (exprv) == COMPOUND_EXPR)
+ exprv = TREE_OPERAND (exprv, 1);
+ if (DECL_P (exprv) || handled_component_p (exprv))
+ mark_exp_read (exprv);
/* If the expression is not of a type to which we cannot assign a line
number, wrap the thing in a no-op NOP_EXPR. */