This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR c++/14024, missing aliasing-warnings for C++
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Dirk Mueller <dmueller at suse dot de>
- Date: Tue, 22 Nov 2005 15:40:28 +0100 (CET)
- Subject: [PATCH] Fix PR c++/14024, missing aliasing-warnings for C++
This enables the C++ frontend to warn about possible strict-aliasing
issues, like the C frontend does.
Bootstrapped and regtested on x86_64-unknown-linux-gnu.
Ok for mainline?
(This breaks libstdc++ and libjava compile with --enable-werror, as
there are aliasing issues in both of them. See f.i. PR24975, a
miscompilation of DLV because of libstdc++ aliasing issues)
Further tweaks to the strict_aliasing_warning function will follow
as separate patches.
Thanks,
Richard.
:ADDPATCH:
2005-11-22 Richard Guenther <rguenther@suse.de>
Dirk Mueller <dmueller@suse.de>
PR c++/14024
* c-common.h (strict_aliasing_warning): Declare.
* c-common.c (strict_aliasing_warning): New function,
split out from ...
* c-typeck.c (build_c_cast): ... here.
* typeck.c (build_reinterpret_cast_1): Use it.
* g++.dg/warn/Wstrict-aliasing-1.C: New testcase.
* g++.dg/warn/Wstrict-aliasing-2.C: Likewise.
* g++.dg/warn/Wstrict-aliasing-3.C: Likewise.
* g++.dg/warn/Wstrict-aliasing-4.C: Likewise.
* g++.dg/warn/Wstrict-aliasing-5.C: Likewise.
* g++.dg/warn/Wstrict-aliasing-6.C: Likewise.
Index: gcc/cp/typeck.c
===================================================================
*** gcc/cp/typeck.c (revision 107350)
--- gcc/cp/typeck.c (working copy)
*************** build_reinterpret_cast_1 (tree type, tre
*** 5019,5024 ****
--- 5019,5026 ----
else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
|| (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
{
+ tree sexpr = expr;
+
if (!c_cast_p)
check_for_casting_away_constness (intype, type, error,
"reinterpret_cast");
*************** build_reinterpret_cast_1 (tree type, tre
*** 5033,5038 ****
--- 5035,5045 ----
"target type",
intype, type);
+ /* We need to strip nops here, because the frontend likes to
+ create (int *)&a for array-to-pointer decay, instead of &a[0]. */
+ STRIP_NOPS (sexpr);
+ strict_aliasing_warning (intype, type, sexpr);
+
return fold_if_not_in_template (build_nop (type, expr));
}
else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
Index: gcc/c-typeck.c
===================================================================
*** gcc/c-typeck.c (revision 107350)
--- gcc/c-typeck.c (working copy)
*************** build_c_cast (tree type, tree expr)
*** 3447,3479 ****
warning (OPT_Wint_to_pointer_cast, "cast to pointer from integer "
"of different size");
! if (flag_strict_aliasing && warn_strict_aliasing
! && TREE_CODE (type) == POINTER_TYPE
! && TREE_CODE (otype) == POINTER_TYPE
! && TREE_CODE (expr) == ADDR_EXPR
! && (DECL_P (TREE_OPERAND (expr, 0))
! || TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF)
! && !VOID_TYPE_P (TREE_TYPE (type)))
! {
! /* Casting the address of an object to non void pointer. Warn
! if the cast breaks type based aliasing. */
! if (!COMPLETE_TYPE_P (TREE_TYPE (type)))
! warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
! "might break strict-aliasing rules");
! else
! {
! HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
! HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
!
! if (!alias_sets_conflict_p (set1, set2))
! warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
! "pointer will break strict-aliasing rules");
! else if (warn_strict_aliasing > 1
! && !alias_sets_might_conflict_p (set1, set2))
! warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
! "pointer might break strict-aliasing rules");
! }
! }
/* If pedantic, warn for conversions between function and object
pointer types, except for converting a null pointer constant
--- 3447,3453 ----
warning (OPT_Wint_to_pointer_cast, "cast to pointer from integer "
"of different size");
! strict_aliasing_warning (otype, type, expr);
/* If pedantic, warn for conversions between function and object
pointer types, except for converting a null pointer constant
Index: gcc/c-common.c
===================================================================
*** gcc/c-common.c (revision 107350)
--- gcc/c-common.c (working copy)
*************** unsigned_conversion_warning (tree result
*** 954,959 ****
--- 954,995 ----
}
}
+ /* 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. */
+
+ void
+ strict_aliasing_warning(tree otype, tree type, tree expr)
+ {
+ if (flag_strict_aliasing && warn_strict_aliasing
+ && POINTER_TYPE_P (type) && POINTER_TYPE_P (otype)
+ && TREE_CODE (expr) == ADDR_EXPR
+ && (DECL_P (TREE_OPERAND (expr, 0))
+ || TREE_CODE (TREE_OPERAND (expr, 0)) == COMPONENT_REF)
+ && !VOID_TYPE_P (TREE_TYPE (type)))
+ {
+ /* Casting the address of an object to non void pointer. Warn
+ if the cast breaks type based aliasing. */
+ if (!COMPLETE_TYPE_P (TREE_TYPE (type)))
+ warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
+ "might break strict-aliasing rules");
+ else
+ {
+ HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
+ HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
+
+ if (!alias_sets_conflict_p (set1, set2))
+ warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+ "pointer will break strict-aliasing rules");
+ else if (warn_strict_aliasing > 1
+ && !alias_sets_might_conflict_p (set1, set2))
+ warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+ "pointer might break strict-aliasing rules");
+ }
+ }
+ }
+
/* Nonzero if constant C has a value that is permissible
for type TYPE (an INTEGER_TYPE). */
Index: gcc/c-common.h
===================================================================
*** gcc/c-common.h (revision 107350)
--- gcc/c-common.h (working copy)
*************** extern void binary_op_error (enum tree_c
*** 649,654 ****
--- 649,655 ----
extern tree fix_string_type (tree);
struct varray_head_tag;
extern void constant_expression_warning (tree);
+ extern void strict_aliasing_warning(tree, tree, tree);
extern tree convert_and_check (tree, tree);
extern void overflow_warning (tree);
extern void unsigned_conversion_warning (tree, tree);
/* { dg-do compile } */
/* { dg-options "-Wstrict-aliasing=2 -O2" } */
double x;
int *foo(void)
{
return (int *)&x; /* { dg-warning "strict-aliasing" } */
}
/* { dg-do compile } */
/* { dg-options "-Wstrict-aliasing=2 -O2" } */
double x;
template <typename T>
T *foo(void)
{
return (T *)&x; /* { dg-bogus "strict-aliasing" } */
}
template double *foo<double>(void);
/* { dg-do compile } */
/* { dg-options "-Wstrict-aliasing=2 -O2" } */
double x;
template <typename T>
T *foo(void)
{
return (T *)&x; /* { dg-warning "strict-aliasing" } */
}
template int *foo<int>(void); /* { dg-warning "instantiated from here" } */
template char *foo<char>(void); /* { dg-bogus "instantiated from here" } */
/* { dg-do compile } */
/* { dg-options "-Wstrict-aliasing=2 -O2" } */
double x;
template <typename T>
T *foo(void)
{
int a[2];
float *y = (float *)a; /* { dg-bogus "strict-aliasing" } */
return (T *)&x; /* { dg-bogus "strict-aliasing" } */
}
/* { dg-do compile } */
/* { dg-options "-Wstrict-aliasing=2 -O2" } */
float foo ()
{
unsigned int MASK = 0x80000000;
return (float &) MASK; /* { dg-warning "strict-aliasing" } */
}
/* { dg-do compile } */
/* { dg-options "-Wstrict-aliasing=2 -O2" } */
int foo ()
{
char buf[8];
return *((int *)buf); /* { dg-warning "strict-aliasing" } */
}