This is the mail archive of the gcc-patches@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]
Other format: [Raw text]

[4.5] PR c/c++/16202 The -Wsequence-point warning misses many important instances


The idea behind this patch was proposed by Tom Truscott. It fixes many
(all?) cases where -Wsequence-points failed.

I am submitting this now in case anyone wants to comment and to have
link from bugzilla.

Bootstrapped and regression tested on x86_64-unknown-linux-gnu with
--enable-languages=all

2008-10-24  Manuel López-Ibáñez  <manu@gcc.gnu.org>

	PR 16202
	* c-typeck.c (lvalue_p): Move declaration ...
	* c-common.h (lvalue_p): ... to here.
	* c-common.c (candidate_equal_p): New.
	(add_tlist): Use it.
	(merge_tlist): Use it.
	(warn_for_collisions_1): Likewise.
	(warning_candidate_p): Accept more candidates.
	(verify_tree): A warning candidate can be an expression. Use
	candidate_equal_p.
testsuite/
	* gcc.dg/sequence-pt-1.c: Remove XFAILs.
	* gcc.dg/sequence-pt-2.c: New.
	* gcc.dg/sequence-pt-3.c: New.
	* g++.dg/warn/sequence-pt-1.C: Remove XFAILs.
	* g++.dg/warn/sequence-pt-2.c: New.
	* g++.dg/warn/sequence-pt-3.c: New.
Index: gcc/testsuite/gcc.dg/sequence-pt-1.c
===================================================================
--- gcc/testsuite/gcc.dg/sequence-pt-1.c	(revision 141322)
+++ gcc/testsuite/gcc.dg/sequence-pt-1.c	(working copy)
@@ -28,14 +28,14 @@ foo (int a, int b, int n, int p, int *pt
   a = ++a + b; /* { dg-warning "undefined" "sequence point warning" } */
   a = a-- + b; /* { dg-warning "undefined" "sequence point warning" } */
   ap[n] = bp[n++]; /* { dg-warning "undefined" "sequence point warning" } */
   ap[--n] = bp[n]; /* { dg-warning "undefined" "sequence point warning" } */
   ap[++n] = bp[--n]; /* { dg-warning "undefined" "sequence point warning" } */
-  cp[n][n] = cp[n][n]++; /* { dg-warning "undefined" "sequence point warning" { xfail *-*-* } } */
+  cp[n][n] = cp[n][n]++; /* { dg-warning "undefined" "sequence point warning" } */
   cp[n][p] = cp[n][n++]; /* { dg-warning "undefined" "sequence point warning" } */
   *ptr++ = (size_t)ptr++; /* { dg-warning "undefined" "sequence point warning" } */
-  sptr->a = sptr->a++; /* { dg-warning "undefined" "sequence point warning" { xfail *-*-* } } */
+  sptr->a = sptr->a++; /* { dg-warning "undefined" "sequence point warning" } */
   sptr->a = (size_t)(sptr++); /* { dg-warning "undefined" "sequence point warning" } */
   *ptr++ = fn (*ptr); /* { dg-warning "undefined" "sequence point warning" } */
   a = b = a++; /* { dg-warning "undefined" "sequence point warning" } */
   b = a = --b; /* { dg-warning "undefined" "sequence point warning" } */
   a = 1 + (a = 1); /* { dg-warning "undefined" "sequence point warning" } */
Index: gcc/testsuite/gcc.dg/sequence-pt-3.c
===================================================================
--- gcc/testsuite/gcc.dg/sequence-pt-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/sequence-pt-3.c	(revision 0)
@@ -0,0 +1,15 @@
+/* More sequence point warning tests  */
+/* { dg-do compile } */
+/* { dg-options "-Wsequence-point" } */
+
+void bar(int i, int j)
+{
+  return;
+}
+
+void foo (int i)
+{
+   int a = i-i++; (void)a; /* { dg-warning "undefined" "sequence point warning" } */
+
+   bar (i--, i++); /* { dg-warning "undefined" "sequence point warning" } */
+}
Index: gcc/testsuite/gcc.dg/sequence-pt-2.c
===================================================================
--- gcc/testsuite/gcc.dg/sequence-pt-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/sequence-pt-2.c	(revision 0)
@@ -0,0 +1,46 @@
+/* More sequence point warning tests  */
+/* { dg-do compile } */
+/* { dg-options "-Wsequence-point" } */
+
+struct s { struct s *nxt; int v; } q;
+    
+int x[10];
+    
+int foo(int *p)
+{
+  int i = 0;
+
+  /* Test general-lvalue sequence point warnings  */
+  (*p) = (*p)++; /* { dg-warning "undefined" "sequence point warning" } */
+  p[3] = p[3]++; /* { dg-warning "undefined" "sequence point warning" } */
+  p[i] = p[i]++; /* { dg-warning "undefined" "sequence point warning" } */
+  x[3] = x[3]++; /* { dg-warning "undefined" "sequence point warning" } */
+  q.nxt->nxt->v = q.nxt->nxt->v++; /* { dg-warning "undefined" "sequence point warning" } */
+
+  /* test expressions that appear elsewhere in the C grammar */
+
+  { int a = i-i++; (void)a;} /* { dg-warning "undefined" "sequence point warning" } */
+
+  if ((i-i++) != 0) /* { dg-warning "undefined" "sequence point warning" } */
+    return i-i++; /* { dg-warning "undefined" "sequence point warning" } */
+
+  for (i-i++;;)  /* { dg-warning "undefined" "sequence point warning" } */
+    ;
+
+  for (; (i-i++) != 0; )  /* { dg-warning "undefined" "sequence point warning" } */
+    ;
+
+  for (;;i-i++)  /* { dg-warning "undefined" "sequence point warning" } */
+    ;
+
+  while ((i-i++) != 0)  /* { dg-warning "undefined" "sequence point warning" } */
+    ;
+
+  do {} while ((i-i++) != 0);  /* { dg-warning "undefined" "sequence point warning" } */
+
+  switch (i-i++) {  /* { dg-warning "undefined" "sequence point warning" } */
+  case 0: return 1;
+  }
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/warn/sequence-pt-1.C
===================================================================
--- gcc/testsuite/g++.dg/warn/sequence-pt-1.C	(revision 141322)
+++ gcc/testsuite/g++.dg/warn/sequence-pt-1.C	(working copy)
@@ -28,14 +28,14 @@ foo (int a, int b, int n, int p, int *pt
   a = ++a + b; /* { dg-warning "undefined" "sequence point warning" } */
   a = a-- + b; /* { dg-warning "undefined" "sequence point warning" } */
   ap[n] = bp[n++]; /* { dg-warning "undefined" "sequence point warning" } */
   ap[--n] = bp[n]; /* { dg-warning "undefined" "sequence point warning" } */
   ap[++n] = bp[--n]; /* { dg-warning "undefined" "sequence point warning" } */
-  cp[n][n] = cp[n][n]++; /* { dg-warning "undefined" "sequence point warning" { xfail *-*-* } } */
+  cp[n][n] = cp[n][n]++; /* { dg-warning "undefined" "sequence point warning" } */
   cp[n][p] = cp[n][n++]; /* { dg-warning "undefined" "sequence point warning" } */
   *ptr++ = (size_t)ptr++; /* { dg-warning "undefined" "sequence point warning" } */
-  sptr->a = sptr->a++; /* { dg-warning "undefined" "sequence point warning" { xfail *-*-* } } */
+  sptr->a = sptr->a++; /* { dg-warning "undefined" "sequence point warning" } */
   sptr->a = (size_t)(sptr++); /* { dg-warning "undefined" "sequence point warning" } */
   *ptr++ = fn (*ptr); /* { dg-warning "undefined" "sequence point warning" } */
   a = b = a++; /* { dg-warning "undefined" "sequence point warning" } */
   b = a = --b; /* { dg-warning "undefined" "sequence point warning" } */
   a = 1 + (a = 1); /* { dg-warning "undefined" "sequence point warning" } */
Index: gcc/testsuite/g++.dg/warn/sequence-pt-2.c
===================================================================
--- gcc/testsuite/g++.dg/warn/sequence-pt-2.c	(revision 0)
+++ gcc/testsuite/g++.dg/warn/sequence-pt-2.c	(revision 0)
@@ -0,0 +1,46 @@
+/* More sequence point warning tests  */
+/* { dg-do compile } */
+/* { dg-options "-Wsequence-point" } */
+
+struct s { struct s *nxt; int v; } q;
+    
+int x[10];
+    
+int foo(int *p)
+{
+  int i = 0;
+
+  /* Test general-lvalue sequence point warnings  */
+  (*p) = (*p)++; /* { dg-warning "undefined" "sequence point warning" } */
+  p[3] = p[3]++; /* { dg-warning "undefined" "sequence point warning" } */
+  p[i] = p[i]++; /* { dg-warning "undefined" "sequence point warning" } */
+  x[3] = x[3]++; /* { dg-warning "undefined" "sequence point warning" } */
+  q.nxt->nxt->v = q.nxt->nxt->v++; /* { dg-warning "undefined" "sequence point warning" } */
+
+  /* test expressions that appear elsewhere in the C grammar */
+
+  { int a = i-i++; (void)a;} /* { dg-warning "undefined" "sequence point warning" } */
+
+  if ((i-i++) != 0) /* { dg-warning "undefined" "sequence point warning" } */
+    return i-i++; /* { dg-warning "undefined" "sequence point warning" } */
+
+  for (i-i++;;)  /* { dg-warning "undefined" "sequence point warning" } */
+    ;
+
+  for (; (i-i++) != 0; )  /* { dg-warning "undefined" "sequence point warning" } */
+    ;
+
+  for (;;i-i++)  /* { dg-warning "undefined" "sequence point warning" } */
+    ;
+
+  while ((i-i++) != 0)  /* { dg-warning "undefined" "sequence point warning" } */
+    ;
+
+  do {} while ((i-i++) != 0);  /* { dg-warning "undefined" "sequence point warning" } */
+
+  switch (i-i++) {  /* { dg-warning "undefined" "sequence point warning" } */
+  case 0: return 1;
+  }
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/warn/sequence-pt-3.c
===================================================================
--- gcc/testsuite/g++.dg/warn/sequence-pt-3.c	(revision 0)
+++ gcc/testsuite/g++.dg/warn/sequence-pt-3.c	(revision 0)
@@ -0,0 +1,15 @@
+/* More sequence point warning tests  */
+/* { dg-do compile } */
+/* { dg-options "-Wsequence-point" } */
+
+void bar(int i, int j)
+{
+  return;
+}
+
+void foo (int i)
+{
+   int a = i-i++; (void)a; /* { dg-warning "undefined" "sequence point warning" } */
+
+   bar (i--, i++); /* { dg-warning "undefined" "sequence point warning" } */
+}
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 141322)
+++ gcc/c-typeck.c	(working copy)
@@ -101,11 +101,10 @@ static void add_pending_init (tree, tree
 static void set_nonincremental_init (void);
 static void set_nonincremental_init_from_string (tree);
 static tree find_init_member (tree);
 static void readonly_error (tree, enum lvalue_use);
 static int lvalue_or_else (const_tree, enum lvalue_use);
-static int lvalue_p (const_tree);
 static void record_maybe_used_decl (tree);
 static int comptypes_internal (const_tree, const_tree);
 
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
@@ -3256,11 +3255,11 @@ build_unary_op (location_t location,
 
 /* Return nonzero if REF is an lvalue valid for this language.
    Lvalues can be assigned, unless their type has TYPE_READONLY.
    Lvalues can have their address taken, unless they have C_DECL_REGISTER.  */
 
-static int
+int
 lvalue_p (const_tree ref)
 {
   const enum tree_code code = TREE_CODE (ref);
 
   switch (code)
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 141322)
+++ gcc/c-common.c	(working copy)
@@ -1828,10 +1828,11 @@ static struct tlist_cache *save_expr_cac
 
 static void add_tlist (struct tlist **, struct tlist *, tree, int);
 static void merge_tlist (struct tlist **, struct tlist *, int);
 static void verify_tree (tree, struct tlist **, struct tlist **, tree);
 static int warning_candidate_p (tree);
+static int candidate_equal_p (tree, tree);
 static void warn_for_collisions (struct tlist *);
 static void warn_for_collisions_1 (tree, tree, struct tlist *, int);
 static struct tlist *new_tlist (struct tlist *, tree, tree);
 
 /* Create a new struct tlist and fill in its fields.  */
@@ -1855,11 +1856,11 @@ add_tlist (struct tlist **to, struct tli
   while (add)
     {
       struct tlist *next = add->next;
       if (!copy)
 	add->next = *to;
-      if (!exclude_writer || add->writer != exclude_writer)
+      if (!exclude_writer || !candidate_equal_p (add->writer, exclude_writer))
 	*to = copy ? new_tlist (*to, add->expr, add->writer) : add;
       add = next;
     }
 }
 
@@ -1882,11 +1883,11 @@ merge_tlist (struct tlist **to, struct t
       int found = 0;
       struct tlist *tmp2;
       struct tlist *next = add->next;
 
       for (tmp2 = *to; tmp2; tmp2 = tmp2->next)
-	if (tmp2->expr == add->expr)
+	if (candidate_equal_p (tmp2->expr, add->expr))
 	  {
 	    found = 1;
 	    if (!tmp2->writer)
 	      tmp2->writer = add->writer;
 	  }
@@ -1910,19 +1911,18 @@ warn_for_collisions_1 (tree written, tre
 {
   struct tlist *tmp;
 
   /* Avoid duplicate warnings.  */
   for (tmp = warned_ids; tmp; tmp = tmp->next)
-    if (tmp->expr == written)
+    if (candidate_equal_p (tmp->expr, written))
       return;
 
   while (list)
     {
-      if (list->expr == written
-	  && list->writer != writer
-	  && (!only_writes || list->writer)
-	  && DECL_NAME (list->expr))
+      if (candidate_equal_p (list->expr, written)
+	  && !candidate_equal_p (list->writer, writer)
+	  && (!only_writes || list->writer))
 	{
 	  warned_ids = new_tlist (warned_ids, written, NULL_TREE);
 	  warning_at (EXPR_HAS_LOCATION (writer)
 		      ? EXPR_LOCATION (writer) : input_location,
 		      OPT_Wsequence_point, "operation on %qE may be undefined",
@@ -1950,11 +1950,21 @@ warn_for_collisions (struct tlist *list)
 /* Return nonzero if X is a tree that can be verified by the sequence point
    warnings.  */
 static int
 warning_candidate_p (tree x)
 {
-  return TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == PARM_DECL;
+  /* !VOID_TYPE_P (TREE_TYPE (x)) is workaround for cp/tree.c
+     (lvalue_p) crash on TRY/CATCH. */
+  return !(DECL_P (x) && DECL_ARTIFICIAL (x))
+    && TREE_TYPE (x) && !VOID_TYPE_P (TREE_TYPE (x)) && lvalue_p (x);
+}
+
+/* Return nonzero if X and Y appear to be the same candidate (or NULL) */
+static int
+candidate_equal_p (tree x, tree y)
+{
+  return (x == y) || (x && y && operand_equal_p (x, y, 0));
 }
 
 /* Walk the tree X, and record accesses to variables.  If X is written by the
    parent tree, WRITER is the parent.
    We store accesses in one of the two lists: PBEFORE_SP, and PNO_SP.  If this
@@ -1996,14 +2006,11 @@ verify_tree (tree x, struct tlist **pbef
  restart:
   code = TREE_CODE (x);
   cl = TREE_CODE_CLASS (code);
 
   if (warning_candidate_p (x))
-    {
-      *pno_sp = new_tlist (*pno_sp, x, writer);
-      return;
-    }
+    *pno_sp = new_tlist (*pno_sp, x, writer);
 
   switch (code)
     {
     case CONSTRUCTOR:
       return;
@@ -2112,11 +2119,11 @@ verify_tree (tree x, struct tlist **pbef
 
     case SAVE_EXPR:
       {
 	struct tlist_cache *t;
 	for (t = save_expr_cache; t; t = t->next)
-	  if (t->expr == x)
+	  if (candidate_equal_p (t->expr, x))
 	    break;
 
 	if (!t)
 	  {
 	    t = XOBNEW (&tlist_obstack, struct tlist_cache);
Index: gcc/c-common.h
===================================================================
--- gcc/c-common.h	(revision 141322)
+++ gcc/c-common.h	(working copy)
@@ -848,10 +848,11 @@ extern tree finish_label_address_expr (t
 
 /* Same function prototype, but the C and C++ front ends have
    different implementations.  Used in c-common.c.  */
 extern tree lookup_label (tree);
 extern tree lookup_name (tree);
+extern int lvalue_p (const_tree);
 
 extern bool vector_targets_convertible_p (const_tree t1, const_tree t2);
 extern bool vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note);
 
 extern rtx c_expand_expr (tree, rtx, enum machine_mode, int, rtx *);

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