[PATCH] Fix PR c++/14024, missing aliasing-warnings for C++

Richard Guenther rguenther@suse.de
Tue Nov 22 14:40:00 GMT 2005


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" } */
}





More information about the Gcc-patches mailing list