mv2 = TYPE_MAIN_VARIANT (pointed_to_2);
target = composite_type (mv1, mv2);
+ /* Strip array types to get correct qualifier for pointers to arrays */
+ quals1 = TYPE_QUALS_NO_ADDR_SPACE (strip_array_types (pointed_to_1));
+ quals2 = TYPE_QUALS_NO_ADDR_SPACE (strip_array_types (pointed_to_2));
+
/* For function types do not merge const qualifiers, but drop them
if used inconsistently. The middle-end uses these to mark const
and noreturn functions. */
- quals1 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_1);
- quals2 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_2);
-
if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
target_quals = (quals1 & quals2);
else
comp_target_types (location_t location, tree ttl, tree ttr)
{
int val;
+ int val_ped;
tree mvl = TREE_TYPE (ttl);
tree mvr = TREE_TYPE (ttr);
addr_space_t asl = TYPE_ADDR_SPACE (mvl);
if (!addr_space_superset (asl, asr, &as_common))
return 0;
- /* Do not lose qualifiers on element types of array types that are
- pointer targets by taking their TYPE_MAIN_VARIANT. */
- if (TREE_CODE (mvl) != ARRAY_TYPE)
- mvl = (TYPE_ATOMIC (mvl)
- ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvl), TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (mvl));
- if (TREE_CODE (mvr) != ARRAY_TYPE)
- mvr = (TYPE_ATOMIC (mvr)
- ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvr), TYPE_QUAL_ATOMIC)
- : TYPE_MAIN_VARIANT (mvr));
+ /* For pedantic record result of comptypes on arrays before losing
+ qualifiers on the element type below. */
+ val_ped = 1;
+
+ if (TREE_CODE (mvl) == ARRAY_TYPE
+ && TREE_CODE (mvr) == ARRAY_TYPE)
+ val_ped = comptypes (mvl, mvr);
+
+ /* Qualifiers on element types of array types that are
+ pointer targets are lost by taking their TYPE_MAIN_VARIANT. */
+
+ mvl = (TYPE_ATOMIC (strip_array_types (mvl))
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvl), TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mvl));
+
+ mvr = (TYPE_ATOMIC (strip_array_types (mvr))
+ ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvr), TYPE_QUAL_ATOMIC)
+ : TYPE_MAIN_VARIANT (mvr));
+
enum_and_int_p = false;
val = comptypes_check_enum_int (mvl, mvr, &enum_and_int_p);
+ if (val == 1 && val_ped != 1)
+ pedwarn (location, OPT_Wpedantic, "pointers to arrays with different qualifiers "
+ "are incompatible in ISO C");
+
if (val == 2)
pedwarn (location, OPT_Wpedantic, "types are not quite compatible");
else if (VOID_TYPE_P (TREE_TYPE (type1))
&& !TYPE_ATOMIC (TREE_TYPE (type1)))
{
+ if ((TREE_CODE (TREE_TYPE (type2)) == ARRAY_TYPE)
+ && (TYPE_QUALS (strip_array_types (TREE_TYPE (type2)))
+ & ~TYPE_QUALS (TREE_TYPE (type1))))
+ warning_at (colon_loc, OPT_Wdiscarded_array_qualifiers,
+ "pointer to array loses qualifier "
+ "in conditional expression");
+
if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
pedwarn (colon_loc, OPT_Wpedantic,
"ISO C forbids conditional expr between "
else if (VOID_TYPE_P (TREE_TYPE (type2))
&& !TYPE_ATOMIC (TREE_TYPE (type2)))
{
+ if ((TREE_CODE (TREE_TYPE (type1)) == ARRAY_TYPE)
+ && (TYPE_QUALS (strip_array_types (TREE_TYPE (type1)))
+ & ~TYPE_QUALS (TREE_TYPE (type2))))
+ warning_at (colon_loc, OPT_Wdiscarded_array_qualifiers,
+ "pointer to array loses qualifier "
+ "in conditional expression");
+
if (TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
pedwarn (colon_loc, OPT_Wpedantic,
"ISO C forbids conditional expr between "
/* This macro is used to emit diagnostics to ensure that all format
strings are complete sentences, visible to gettext and checked at
compile time. */
-#define WARN_FOR_ASSIGNMENT(LOCATION, PLOC, OPT, AR, AS, IN, RE) \
+#define PEDWARN_FOR_ASSIGNMENT(LOCATION, PLOC, OPT, AR, AS, IN, RE) \
do { \
switch (errtype) \
{ \
/* 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
+ compile time. It is the same as PEDWARN_FOR_ASSIGNMENT but with an
extra parameter to enumerate qualifiers. */
-
-#define WARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
+#define PEDWARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
do { \
switch (errtype) \
{ \
} \
} 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 PEDWARN_FOR_QUALIFIERS but uses
+ warning_at instead of pedwarn. */
+#define WARNING_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
+ do { \
+ switch (errtype) \
+ { \
+ case ic_argpass: \
+ if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS)) \
+ inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
+ ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \
+ "expected %qT but argument is of type %qT", \
+ type, rhstype); \
+ break; \
+ case ic_assign: \
+ warning_at (LOCATION, OPT, AS, QUALS); \
+ break; \
+ case ic_init: \
+ warning_at (LOCATION, OPT, IN, QUALS); \
+ break; \
+ case ic_return: \
+ warning_at (LOCATION, OPT, RE, QUALS); \
+ break; \
+ default: \
+ gcc_unreachable (); \
+ } \
+ } while (0)
+
if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
rhs = TREE_OPERAND (rhs, 0);
&& TREE_CODE (type) == ENUMERAL_TYPE
&& TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
{
- WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wc___compat,
- G_("enum conversion when passing argument "
- "%d of %qE is invalid in C++"),
- G_("enum conversion in assignment is "
- "invalid in C++"),
- G_("enum conversion in initialization is "
- "invalid in C++"),
- G_("enum conversion in return is "
- "invalid in C++"));
+ PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wc___compat,
+ G_("enum conversion when passing argument "
+ "%d of %qE is invalid in C++"),
+ G_("enum conversion in assignment is "
+ "invalid in C++"),
+ G_("enum conversion in initialization is "
+ "invalid in C++"),
+ G_("enum conversion in return is "
+ "invalid in C++"));
}
}
vice-versa. */
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
- WARN_FOR_QUALIFIERS (location, expr_loc,
- OPT_Wdiscarded_qualifiers,
- G_("passing argument %d of %qE "
- "makes %q#v qualified function "
- "pointer from unqualified"),
- G_("assignment makes %q#v qualified "
- "function pointer from "
- "unqualified"),
- G_("initialization makes %q#v qualified "
- "function pointer from "
- "unqualified"),
- G_("return makes %q#v qualified function "
- "pointer from unqualified"),
- TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
+ PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
+ G_("passing argument %d of %qE "
+ "makes %q#v qualified function "
+ "pointer from unqualified"),
+ G_("assignment makes %q#v qualified "
+ "function pointer from "
+ "unqualified"),
+ G_("initialization makes %q#v 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_QUALIFIERS (location, expr_loc,
- OPT_Wdiscarded_qualifiers,
- 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));
+ PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
+ 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));
memb = marginal_memb;
}
== c_common_signed_type (mvr))
&& TYPE_ATOMIC (mvl) == TYPE_ATOMIC (mvr)))
{
- if (pedantic
+ /* Warn about loss of qualifers from pointers to arrays with
+ qualifiers on the element type. */
+ if (TREE_CODE (ttr) == ARRAY_TYPE)
+ {
+ ttr = strip_array_types (ttr);
+ ttl = strip_array_types (ttl);
+
+ if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
+ & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
+ WARNING_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_array_qualifiers,
+ 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));
+ }
+ else if (pedantic
&& ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
||
(VOID_TYPE_P (ttr)
&& !null_pointer_constant
&& TREE_CODE (ttl) == FUNCTION_TYPE)))
- WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpedantic,
- G_("ISO C forbids passing argument %d of "
- "%qE between function pointer "
- "and %<void *%>"),
- G_("ISO C forbids assignment between "
- "function pointer and %<void *%>"),
- G_("ISO C forbids initialization between "
- "function pointer and %<void *%>"),
- G_("ISO C forbids return between function "
- "pointer and %<void *%>"));
+ PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpedantic,
+ G_("ISO C forbids passing argument %d of "
+ "%qE between function pointer "
+ "and %<void *%>"),
+ G_("ISO C forbids assignment between "
+ "function pointer and %<void *%>"),
+ G_("ISO C forbids initialization between "
+ "function pointer and %<void *%>"),
+ G_("ISO C forbids return between function "
+ "pointer and %<void *%>"));
/* Const and volatile mean something different for function types,
so the usual warnings are not appropriate. */
else if (TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttl) != FUNCTION_TYPE)
{
+ /* Don't warn about loss of qualifier for conversions from
+ qualified void* to pointers to arrays with corresponding
+ qualifier on the element type. */
+ if (!pedantic)
+ ttl = strip_array_types (ttl);
+
/* Assignments between atomic and non-atomic objects are OK. */
if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
{
- WARN_FOR_QUALIFIERS (location, expr_loc,
- OPT_Wdiscarded_qualifiers,
- 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));
+ PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
+ 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. */
;
/* If there is a mismatch, do warn. */
else if (warn_pointer_sign)
- WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpointer_sign,
- G_("pointer targets in passing argument "
- "%d of %qE differ in signedness"),
- G_("pointer targets in assignment "
- "differ in signedness"),
- G_("pointer targets in initialization "
- "differ in signedness"),
- G_("pointer targets in return differ "
- "in signedness"));
+ PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpointer_sign,
+ G_("pointer targets in passing argument "
+ "%d of %qE differ in signedness"),
+ G_("pointer targets in assignment "
+ "differ in signedness"),
+ G_("pointer targets in initialization "
+ "differ in signedness"),
+ G_("pointer targets in return differ "
+ "in signedness"));
}
else if (TREE_CODE (ttl) == FUNCTION_TYPE
&& TREE_CODE (ttr) == FUNCTION_TYPE)
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_QUALIFIERS (location, expr_loc,
- OPT_Wdiscarded_qualifiers,
- G_("passing argument %d of %qE makes "
- "%q#v qualified function pointer "
- "from unqualified"),
- G_("assignment makes %q#v qualified function "
- "pointer from unqualified"),
- G_("initialization makes %q#v qualified "
- "function pointer from unqualified"),
- G_("return makes %q#v qualified function "
- "pointer from unqualified"),
- TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
+ PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
+ G_("passing argument %d of %qE makes "
+ "%q#v qualified function pointer "
+ "from unqualified"),
+ G_("assignment makes %q#v qualified function "
+ "pointer from unqualified"),
+ G_("initialization makes %q#v qualified "
+ "function pointer from unqualified"),
+ G_("return makes %q#v qualified function "
+ "pointer from unqualified"),
+ TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
}
}
else
/* Avoid warning about the volatile ObjC EH puts on decls. */
if (!objc_ok)
- WARN_FOR_ASSIGNMENT (location, expr_loc,
- OPT_Wincompatible_pointer_types,
- G_("passing argument %d of %qE from "
- "incompatible pointer type"),
- G_("assignment from incompatible pointer type"),
- G_("initialization from incompatible "
- "pointer type"),
- G_("return from incompatible pointer type"));
+ PEDWARN_FOR_ASSIGNMENT (location, expr_loc,
+ OPT_Wincompatible_pointer_types,
+ G_("passing argument %d of %qE from "
+ "incompatible pointer type"),
+ G_("assignment from incompatible pointer type"),
+ G_("initialization from incompatible "
+ "pointer type"),
+ G_("return from incompatible pointer type"));
return convert (type, rhs);
}
or one that results from arithmetic, even including
a cast to integer type. */
if (!null_pointer_constant)
- WARN_FOR_ASSIGNMENT (location, expr_loc,
- OPT_Wint_conversion,
- G_("passing argument %d of %qE makes "
- "pointer from integer without a cast"),
- G_("assignment makes pointer from integer "
- "without a cast"),
- G_("initialization makes pointer from "
- "integer without a cast"),
- G_("return makes pointer from integer "
- "without a cast"));
+ PEDWARN_FOR_ASSIGNMENT (location, expr_loc,
+ OPT_Wint_conversion,
+ G_("passing argument %d of %qE makes "
+ "pointer from integer without a cast"),
+ G_("assignment makes pointer from integer "
+ "without a cast"),
+ G_("initialization makes pointer from "
+ "integer without a cast"),
+ G_("return makes pointer from integer "
+ "without a cast"));
return convert (type, rhs);
}
else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
{
- WARN_FOR_ASSIGNMENT (location, expr_loc,
- OPT_Wint_conversion,
- G_("passing argument %d of %qE makes integer "
- "from pointer without a cast"),
- G_("assignment makes integer from pointer "
- "without a cast"),
- G_("initialization makes integer from pointer "
- "without a cast"),
- G_("return makes integer from pointer "
- "without a cast"));
+ PEDWARN_FOR_ASSIGNMENT (location, expr_loc,
+ OPT_Wint_conversion,
+ G_("passing argument %d of %qE makes integer "
+ "from pointer without a cast"),
+ G_("assignment makes integer from pointer "
+ "without a cast"),
+ G_("initialization makes integer from pointer "
+ "without a cast"),
+ G_("return makes integer from pointer "
+ "without a cast"));
return convert (type, rhs);
}
else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)