This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PR c/84293] Unexpected strict-alias warning
- From: Nathan Sidwell <nathan at acm dot org>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Joseph Myers <joseph at codesourcery dot com>
- Date: Fri, 9 Feb 2018 07:50:15 -0500
- Subject: [PR c/84293] Unexpected strict-alias warning
- Authentication-results: sourceware.org; auth=none
This bug comes from python sources. It has some type-punning macros to
switch between representation, but these can cause unexpected
strict-alias warnings, even though the punning's context is a system
header file. (I guess that without macro expansion location information
we'd've thought the context was user code.)
As shown in the bug report, if the pun is spelt '(struct X *)&obj' we do
not warn, but if it is '(X_t *)&obj' we do. We also don't warn in
either case if we go via -save-temps. The patch changes things to not
warn in either spelling.
The problem is that strict_aliasing_warning uses input_location to
identifier the current code point. But that's not necessarily the
location of the above pun -- it can be the point where we use the pun.
We cannot just use the incoming EXPR's location, because we may well
have peeled some pieces off it, and we end up with the '&obj' fragment,
which in this case is located in the user source. It also turns out
that strict_aliasing_warning no longer uses the incoming 'otype'
argument, immediately doing:
STRIP_NOPS (expr);
otype = TREE_TYPE (expr);
So we may as well drop that arg, substituting a location_t from the caller.
That's what this patch does. The callers in the C & C++ FEs pass the
EXPR_LOCATION of the pointer being dereferenced, or converted, as
appropriate.
Joseph, are the C bits ok?
nathan
--
Nathan Sidwell
2018-02-09 Nathan Sidwell <nathan@acm.org>
PR c/84293
gcc/c/
* c-typeck.c (build_indirect_ref, build_c_cast): Pass expr location
to strict_aliasing_warning.
gcc/c-family/
* c-common.h (strict_aliasing_warning): Drop OTYPE arg, insert LOC
arg.
* c-warn.c (strict_aliasing_warning): Drop OTYPE arg, require LOC
arg. Adjust.
gcc/cp/
* typeck.c (cp_build_indirect_ref_1, build_reinterpret_cast_1):
Pass expr location to strict_aliasing_warning.
gcc/testsuite/
* c-c++-common/pr84293.h: New.
* c-c++-common/pr84293.c: New.
Index: gcc/c/c-typeck.c
===================================================================
--- gcc/c/c-typeck.c (revision 257480)
+++ gcc/c/c-typeck.c (working copy)
@@ -2524,7 +2524,7 @@ build_indirect_ref (location_t loc, tree
the backend. This only needs to be done at
warn_strict_aliasing > 2. */
if (warn_strict_aliasing > 2)
- if (strict_aliasing_warning (TREE_TYPE (TREE_OPERAND (pointer, 0)),
+ if (strict_aliasing_warning (EXPR_LOCATION (pointer),
type, TREE_OPERAND (pointer, 0)))
TREE_NO_WARNING (pointer) = 1;
}
@@ -5696,7 +5696,7 @@ build_c_cast (location_t loc, tree type,
"of different size");
if (warn_strict_aliasing <= 2)
- strict_aliasing_warning (otype, type, expr);
+ strict_aliasing_warning (EXPR_LOCATION (value), type, expr);
/* If pedantic, warn for conversions between function and object
pointer types, except for converting a null pointer constant
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h (revision 257480)
+++ gcc/c-family/c-common.h (working copy)
@@ -1260,7 +1260,7 @@ extern void warn_tautological_cmp (locat
extern void warn_logical_not_parentheses (location_t, enum tree_code, tree,
tree);
extern bool warn_if_unused_value (const_tree, location_t);
-extern bool strict_aliasing_warning (tree, tree, tree);
+extern bool strict_aliasing_warning (location_t, tree, tree);
extern void sizeof_pointer_memaccess_warning (location_t *, tree,
vec<tree, va_gc> *, tree *,
bool (*) (tree, tree));
Index: gcc/c-family/c-warn.c
===================================================================
--- gcc/c-family/c-warn.c (revision 257480)
+++ gcc/c-family/c-warn.c (working copy)
@@ -599,17 +599,21 @@ warn_if_unused_value (const_tree exp, lo
}
}
-/* Print a warning about casts that might indicate violation
- of strict aliasing rules if -Wstrict-aliasing is used and
- strict aliasing mode is in effect. OTYPE is the original
- TREE_TYPE of EXPR, and TYPE the type we're casting to. */
+/* Print a warning about casts that might indicate violation of strict
+ aliasing rules if -Wstrict-aliasing is used and strict aliasing
+ mode is in effect. LOC is the location of the expression being
+ cast, EXPR might be from inside it. TYPE is the type we're casting
+ to. */
bool
-strict_aliasing_warning (tree otype, tree type, tree expr)
+strict_aliasing_warning (location_t loc, tree type, tree expr)
{
+ if (loc == UNKNOWN_LOCATION)
+ loc = input_location;
+
/* Strip pointer conversion chains and get to the correct original type. */
STRIP_NOPS (expr);
- otype = TREE_TYPE (expr);
+ tree otype = TREE_TYPE (expr);
if (!(flag_strict_aliasing
&& POINTER_TYPE_P (type)
@@ -628,8 +632,9 @@ strict_aliasing_warning (tree otype, tre
if the cast breaks type based aliasing. */
if (!COMPLETE_TYPE_P (TREE_TYPE (type)) && warn_strict_aliasing == 2)
{
- warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
- "might break strict-aliasing rules");
+ warning_at (loc, OPT_Wstrict_aliasing,
+ "type-punning to incomplete type "
+ "might break strict-aliasing rules");
return true;
}
else
@@ -645,15 +650,17 @@ strict_aliasing_warning (tree otype, tre
&& !alias_set_subset_of (set2, set1)
&& !alias_sets_conflict_p (set1, set2))
{
- warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
- "pointer will break strict-aliasing rules");
+ warning_at (loc, OPT_Wstrict_aliasing,
+ "dereferencing type-punned "
+ "pointer will break strict-aliasing rules");
return true;
}
else if (warn_strict_aliasing == 2
&& !alias_sets_must_conflict_p (set1, set2))
{
- warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
- "pointer might break strict-aliasing rules");
+ warning_at (loc, OPT_Wstrict_aliasing,
+ "dereferencing type-punned "
+ "pointer might break strict-aliasing rules");
return true;
}
}
@@ -669,8 +676,9 @@ strict_aliasing_warning (tree otype, tre
if (!COMPLETE_TYPE_P (type)
|| !alias_sets_must_conflict_p (set1, set2))
{
- warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
- "pointer might break strict-aliasing rules");
+ warning_at (loc, OPT_Wstrict_aliasing,
+ "dereferencing type-punned "
+ "pointer might break strict-aliasing rules");
return true;
}
}
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c (revision 257480)
+++ gcc/cp/typeck.c (working copy)
@@ -3133,7 +3133,7 @@ cp_build_indirect_ref_1 (tree ptr, ref_o
the backend. This only needs to be done at
warn_strict_aliasing > 2. */
if (warn_strict_aliasing > 2)
- if (strict_aliasing_warning (TREE_TYPE (TREE_OPERAND (ptr, 0)),
+ if (strict_aliasing_warning (EXPR_LOCATION (ptr),
type, TREE_OPERAND (ptr, 0)))
TREE_NO_WARNING (ptr) = 1;
}
@@ -7331,7 +7331,7 @@ build_reinterpret_cast_1 (tree type, tre
expr = cp_build_addr_expr (expr, complain);
if (warn_strict_aliasing > 2)
- strict_aliasing_warning (TREE_TYPE (expr), type, expr);
+ strict_aliasing_warning (EXPR_LOCATION (expr), type, expr);
if (expr != error_mark_node)
expr = build_reinterpret_cast_1
@@ -7425,8 +7425,6 @@ build_reinterpret_cast_1 (tree type, tre
else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype))
|| (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
{
- tree sexpr = expr;
-
if (!c_cast_p
&& check_for_casting_away_constness (intype, type,
REINTERPRET_CAST_EXPR,
@@ -7444,11 +7442,9 @@ build_reinterpret_cast_1 (tree type, tre
warning (OPT_Wcast_align, "cast from %qH to %qI "
"increases required alignment of target type", intype, type);
- /* We need to strip nops here, because the front end likes to
- create (int *)&a for array-to-pointer decay, instead of &a[0]. */
- STRIP_NOPS (sexpr);
if (warn_strict_aliasing <= 2)
- strict_aliasing_warning (intype, type, sexpr);
+ /* strict_aliasing_warning STRIP_NOPs its expr. */
+ strict_aliasing_warning (EXPR_LOCATION (expr), type, expr);
return build_nop (type, expr);
}
Index: gcc/testsuite/c-c++-common/pr84293.c
===================================================================
--- gcc/testsuite/c-c++-common/pr84293.c (revision 0)
+++ gcc/testsuite/c-c++-common/pr84293.c (working copy)
@@ -0,0 +1,10 @@
+/* PR c/84293 unexpected warning from system header. */
+#include "./pr84293.h"
+struct typeobject thing;
+
+#pragma GCC diagnostic warning "-Wstrict-aliasing"
+void __attribute__ ((optimize (2))) init ()
+{
+ INCREF_TDEF (&thing);
+ INCREF_STAG (&thing);
+}
Index: gcc/testsuite/c-c++-common/pr84293.h
===================================================================
--- gcc/testsuite/c-c++-common/pr84293.h (revision 0)
+++ gcc/testsuite/c-c++-common/pr84293.h (working copy)
@@ -0,0 +1,7 @@
+/* PR c/84293 unexpected warning from system header expansion. */
+#pragma GCC system_header
+struct typeobject { unsigned refs; };
+typedef struct object { unsigned refs; } Object;
+
+#define INCREF_TDEF(op) (((Object*)(op))->refs++)
+#define INCREF_STAG(op) (((struct object*)(op))->refs++)