diff options
author | Martin Uecker <uecker@eecs.berkeley.edu> | 2014-12-19 16:29:16 -0800 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2014-12-20 00:29:16 +0000 |
commit | 768952be25c2fc50bce51a5658377934d49f473f (patch) | |
tree | 0a8c1f437c3f3ba1a17e373c8796d2e79deb28f7 /gcc/c | |
parent | 189486b85833690ab1ff75c604645ea3d22aa1e1 (diff) | |
download | gcc-768952be25c2fc50bce51a5658377934d49f473f.zip gcc-768952be25c2fc50bce51a5658377934d49f473f.tar.gz gcc-768952be25c2fc50bce51a5658377934d49f473f.tar.bz2 |
invoke.texi: Document -Wdiscarded-array-qualifiers.
2014-12-20 Martin Uecker <uecker@eecs.berkeley.edu>
* doc/invoke.texi: Document -Wdiscarded-array-qualifiers.
* doc/extend.texi: Document new behavior for pointers to arrays
with qualifiers.
c/
* c-typeck.c: New behavious for pointers to arrays with qualifiers
(common-pointer-type): For pointers to arrays take qualifiers from
element type.
(build_conditional_expr): Add warnings for lost qualifiers.
(comp-target-types): Allow pointers to arrays with different qualifiers.
(convert-for-assignment): Adapt warnings for discarded qualifiers. Add
WARNING_FOR_QUALIFIERS macro and rename WARN_FOR_QUALIFIERS
to PEDWARN_FOR_QUALIFIERS.
c-family/
* c.opt (Wdiscarded-array-qualifiers): New option.
testsuite/
* gcc.dg/Wwrite-strings-1.c: Change dg-warning.
* gcc.dg/array-quals-1.c: Use -Wno-discarded-array-qualifiers.
* gcc.dg/array-quals-2.c: Change dg-options, dg-warning.
* gcc.dg/pointer-array-atomic.c: New test.
* gcc.dg/pointer-array-quals-1.c: New test.
* gcc.dg/pointer-array-quals-2.c: New test (-pedantic-errors).
* gcc.dg/qual-component-1.c: Change dg-options, dg-warnings.
From-SVN: r218985
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 328 |
2 files changed, 217 insertions, 122 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index ad9b8bc..1661747 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,14 @@ +2014-12-20 Martin Uecker <uecker@eecs.berkeley.edu> + + * c-typeck.c: New behavious for pointers to arrays with qualifiers + (common-pointer-type): For pointers to arrays take qualifiers from + element type. + (build_conditional_expr): Add warnings for lost qualifiers. + (comp-target-types): Allow pointers to arrays with different qualifiers. + (convert-for-assignment): Adapt warnings for discarded qualifiers. Add + WARNING_FOR_QUALIFIERS macro and rename WARN_FOR_QUALIFIERS + to PEDWARN_FOR_QUALIFIERS. + 2014-12-17 Jakub Jelinek <jakub@redhat.com> PR sanitizer/64289 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index ca9d512..abd452a 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -673,12 +673,13 @@ common_pointer_type (tree t1, tree t2) 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 @@ -1224,6 +1225,7 @@ static int 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); @@ -1235,19 +1237,32 @@ comp_target_types (location_t location, tree ttl, tree ttr) 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"); @@ -4609,6 +4624,13 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, 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 " @@ -4619,6 +4641,13 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, 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 " @@ -5661,7 +5690,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, /* 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) \ { \ @@ -5688,10 +5717,9 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, /* 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) \ { \ @@ -5716,6 +5744,35 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, } \ } 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); @@ -5758,15 +5815,15 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, && 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++")); } } @@ -5921,34 +5978,34 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, 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; } @@ -6096,42 +6153,69 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, == 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. */ @@ -6140,15 +6224,15 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, ; /* 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) @@ -6159,31 +6243,31 @@ convert_for_assignment (location_t location, location_t expr_loc, tree 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); } @@ -6200,31 +6284,31 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, 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) |