This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: aliasing warnings [patch]


Jeffrey A Law wrote:
>   In message <199909240006.RAA28376@atrus.synopsys.com>you write:
>   > Someone mentioned that DEC's compiler issues warnings of this type
>   > and that's how the Perl team became aware of the issue.  The above
>   > approach seems like a clean way to get such warnings, for the case
>   > where all the code is in the same function.
>   > 
>   > The RMS variant (sure to be contoversial) would be to put a pointer with
>   > this tag into alias set 0 (it can alias everything).
> I haven't thought a lot about the implications of this, but at first glance
> it's not a bad idea.
> 
> It should achieve RMS's goal of having old broken code still work without a
> severe impact on most conforming code.
> 
> It's behavior should be consistent over time and we should be able to
> document the behavior.
> 
> I don't know how difficult this is from a technical standpoint, but it is
> probably worth some investigation.

Hmm... well, check this patch out.  It isn't necessary to add another
slot to every tree node, which is a relief.  It nails my test case
dead on, but generates a pile of complaints about libgcc which I'm not
sure if they're spurious or not yet.

Patch:
Index: c-typeck.c
===================================================================
RCS file: /cvs/egcs/egcs/gcc/c-typeck.c,v
retrieving revision 1.39
diff -u -p -r1.39 c-typeck.c
--- c-typeck.c	1999/09/22 05:51:44	1.39
+++ c-typeck.c	1999/09/25 20:45:08
@@ -1217,6 +1217,7 @@ build_indirect_ref (ptr, errorstring)
       else
 	{
 	  tree t = TREE_TYPE (type);
+	  tree orig_t, field = 0;
 	  register tree ref = build1 (INDIRECT_REF,
 				      TYPE_MAIN_VARIANT (t), pointer);
 
@@ -1228,16 +1229,44 @@ build_indirect_ref (ptr, errorstring)
 	  if (TREE_CODE (t) == VOID_TYPE && skip_evaluation == 0)
 	    warning ("dereferencing `void *' pointer");
 
-	  /* We *must* set TREE_READONLY when dereferencing a pointer to const,
-	     so that we get the proper error message if the result is used
-	     to assign to.  Also, &* is supposed to be a no-op.
-	     And ANSI C seems to specify that the type of the result
-	     should be the const type.  */
-	  /* A de-reference of a pointer to const is not a const.  It is valid
-	     to change it via some other pointer.  */
+	  /* If we are dereferencing a pointer through a cast to some
+	     other type, check that the type of the pointer and the
+	     type of the object pointed to are compatible alias-wise.  */
+
+	  orig_t = pointer;
+	  while (TREE_CODE_CLASS (TREE_CODE (orig_t)) == 'e'
+		 && TREE_CODE (orig_t) != ADDR_EXPR
+		 && TREE_CODE (orig_t) != REFERENCE_EXPR)
+	    orig_t = TREE_OPERAND (orig_t, 0);
+
+	  orig_t = TREE_TYPE (orig_t);
+
+	  if (TREE_CODE (t) == UNION_TYPE && !pedantic)
+	    {
+	      for (field = TYPE_FIELDS (type); field;
+		   field = TREE_CHAIN (field))
+		if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
+			       TYPE_MAIN_VARIANT (TREE_TYPE (orig_t))))
+		  break;
+	    }
+
+	  if (!(get_alias_set (t) == get_alias_set (orig_t)
+		|| TYPE_MAIN_VARIANT (t) == char_type_node
+		|| TYPE_MAIN_VARIANT (orig_t) == char_type_node
+		|| TREE_CODE (orig_t) == VOID_TYPE || field))
+	    warning ("dereferencing pointer to type T which points at value of type U");
+	  
+	  /* We *must* set TREE_READONLY when dereferencing a pointer
+	     to const, so that we get the proper error message if the
+	     result is used to assign to.  Also, &* is supposed to be
+	     a no-op.  And ANSI C seems to specify that the type of
+	     the result should be the const type.  */
+	  /* A de-reference of a pointer to const is not a const.  It
+	     is valid to change it via some other pointer.  */
 	  TREE_READONLY (ref) = TYPE_READONLY (t);
 	  TREE_SIDE_EFFECTS (ref)
-	    = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer) || flag_volatile;
+	    = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer)
+	      || flag_volatile;
 	  TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
 	  return ref;
 	}


Test case:

extern int printf(char *, ...);

double foo0(double d)
{
    double d2 = d;
    ((unsigned long *)&d2)[1] |= 0x80000000;
    return d2;
}

double foo1(double d)
{
    double d2 = d;
    unsigned long *l = (unsigned long *)&d2;

    l[1] |= 0x80000000;
    return d2;
}

double foo2(double d)
{
    union u
    {
	double D;
	unsigned long L[2];
    };
    double d2 = d;

    ((union u *)&d2)->L[1] |= 0x80000000;
    return d2;
}

int main(void)
{
    double x = 1.1234;
    double a, b, c;

    a = foo0(x);
    b = foo1(x);
    c = foo2(x);
    printf("%f %f %f %f\n", x, a, b, c);
    return 0;
}

Effect:

$ ./xgcc -B./ -O2 test.c
test.c: In function `foo0':
test.c:6: warning: dereferencing pointer to type T which points at value of type U
test.c: In function `foo1':
test.c:15: warning: dereferencing pointer to type T which points at value of type U
$ ./a.out
1.123400 1.123400 1.123400 -1.123400
$ ./xgcc -B./ -O2 -fno-strict-aliasing test.c
$ ./a.out
1.123400 -1.123400 -1.123400 -1.123400

The text of the warning is lame, but we're not going to be able to do
much better until we make cp/errors.c be usable by the C front end - I
may look at this but no promises.

zw

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]