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]

(Improved patch) Re: New feature, warning on n=n++ etc.


Here is Michael's patch with fixes for things that I caught that didn't
meet GNU coding standards and revised against the current EGCS tree.  

Hopefully, this will make it easier to evaluate.

RJL



Index: c-typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-typeck.c,v
retrieving revision 1.18
diff -u -p -r1.18 c-typeck.c
--- c-typeck.c	1998/06/19 22:27:35	1.18
+++ c-typeck.c	1998/07/09 06:21:39
@@ -3847,6 +3847,109 @@ build_c_cast (type, expr)
   return value;
 }
 
+/* Recursive Check for un-defined sytax, note lhs && rhs have
+   no meaning ! ie. n++=n; is equaly invalid to n=n++; */
+void
+check_modify_expr (lhs, rhs)
+     tree lhs, rhs;
+{
+  tree identifierName;   /* a VAR_DECL name on the lhs, that could
+			    be the same as one on the rhs */
+  identifierName = NULL_TREE;
+
+  if ((lhs == NULL_TREE) || (rhs == NULL_TREE))
+    return;
+
+  switch (TREE_CODE(rhs))
+    {
+    case (VAR_DECL):
+      identifierName = DECL_NAME(rhs);
+      break;	  
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+      {
+	tree var_decl = TREE_OPERAND(rhs,0);
+	if (TREE_CODE(var_decl)==VAR_DECL)
+	  identifierName=DECL_NAME(var_decl);
+      }
+      break;
+    case TREE_LIST:
+      {
+	tree parm = TREE_CHAIN(rhs);
+	int lp = 0;
+	/* Now scan all the list. eg. indices of multi dimensional array */
+	while (parm)
+	  {
+	    check_modify_expr(lhs, TREE_VALUE(parm));
+	    parm = TREE_CHAIN(parm);
+	  }
+      }
+      return;
+    case NOP_EXPR:
+      return;
+    case MODIFY_EXPR:
+      /* First check for form a = b = a++ by checking rhs */
+      check_modify_expr (lhs, TREE_OPERAND(rhs, 1));
+      /* Then check for a = (a = 1) + 2 */
+      identifierName = DECL_NAME(TREE_OPERAND(rhs,0));
+      break;
+    default: /* We don't know what to do... pray check_modify_expr removes loops in the tree */
+      switch (TREE_CODE_CLASS(TREE_CODE(rhs)))
+	{
+	case 'r':
+	case '<':	
+	case '2':
+	case 'b':
+	case '1':
+	case 'e':
+	case 's':
+	case 'x':
+	  {
+	    int lp;
+	    int max = get_max_tree_operands(rhs);
+	    for (lp=0;lp<max;lp++)
+	      check_modify_expr(lhs, TREE_OPERAND(rhs,lp));
+	    return;
+	  }
+	default:
+	  return;
+	}
+      break;
+    }
+  if (identifierName != NULL_TREE)
+    {
+      switch (TREE_CODE(lhs))
+	{
+	  /* perhaps this variable was incremented on the rhs */
+	case VAR_DECL:
+	  if (TREE_CODE(rhs)!=VAR_DECL)
+	    if (DECL_NAME(lhs)==identifierName)
+	      warning ("operation on '%s' may be undefined", IDENTIFIER_POINTER(DECL_NAME(lhs)));
+	  break;
+	case PREDECREMENT_EXPR:
+	case PREINCREMENT_EXPR:
+	case POSTDECREMENT_EXPR:
+	case POSTINCREMENT_EXPR:
+	  {
+	    tree var_decl = TREE_OPERAND(lhs,0);
+	    if (TREE_CODE(var_decl)==VAR_DECL)
+	      if (identifierName==DECL_NAME(var_decl))
+		warning ("operation on '%s' may be undefined", IDENTIFIER_POINTER(DECL_NAME(var_decl)));
+	  }
+	  break;
+	case NULL_TREE:
+	  return;
+	default:
+	  /* to save duplicating tree traversal code swap args, and recurse */
+	  check_modify_expr(rhs, lhs);
+	  break;
+	}
+    }
+}
+
+
 /* Build an assignment expression of lvalue LHS from value RHS.
    MODIFYCODE is the code for a binary operator that we use
    to combine the old value of LHS with RHS to get the new value.
@@ -4001,6 +4104,11 @@ build_modify_expr (lhs, modifycode, rhs)
 				   NULL_TREE, NULL_TREE, 0);
   if (TREE_CODE (newrhs) == ERROR_MARK)
     return error_mark_node;
+
+  if (warn_undefined)
+    check_modify_expr(lhs,rhs);
+
+  /* Scan operands */
 
   result = build (MODIFY_EXPR, lhstype, lhs, newrhs);
   TREE_SIDE_EFFECTS (result) = 1;
Index: toplev.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/toplev.c,v
retrieving revision 1.84
diff -u -p -r1.84 toplev.c
--- toplev.c	1998/07/08 12:15:55	1.84
+++ toplev.c	1998/07/09 06:21:44
@@ -880,6 +880,7 @@ char *lang_options[] =
   "-Wno-nested-externs",
   "-Wparentheses",
   "-Wno-parentheses",
+  "-Wundefined",
   "-Wpointer-arith",
   "-Wno-pointer-arith",
   "-Wredundant-decls",
Index: tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.h,v
retrieving revision 1.45
diff -u -p -r1.45 tree.h
--- tree.h	1998/07/07 00:05:23	1.45
+++ tree.h	1998/07/09 06:21:47
@@ -2282,3 +2282,8 @@ extern void dwarf2out_begin_prologue	PRO
    code for a function definition.  */
 
 extern void dwarf2out_end_epilogue	PROTO((void));
+
+extern int get_max_tree_operands	PROTO((tree));
+
+
+
Index: tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.c,v
retrieving revision 1.36
diff -u -p -r1.36 tree.c
--- tree.c	1998/07/07 00:05:24	1.36
+++ tree.c	1998/07/09 06:21:52
@@ -4915,7 +4915,34 @@ get_set_constructor_bits (init, buffer, 
     }
   return non_const_bits;
 }
+
+/* Return the maximum valid number of operands that are used solely for
+  the parse tree. NB. Some tree codes have RTL, not trees, as operands. */
 
+int
+get_max_tree_operands (exp)
+     tree exp;
+{
+  if (exp==NULL_TREE)
+    return 0;
+
+  switch (TREE_CODE (exp))
+    {
+    case CALL_EXPR:
+      return 2;
+    case METHOD_CALL_EXPR:
+      return 3;
+    case WITH_CLEANUP_EXPR:
+      return 1;
+    case RTL_EXPR:
+      return 0;
+    case OP_IDENTIFIER:
+      return 0;
+    default:
+      return tree_code_length[(int) TREE_CODE(exp)];
+    } 
+}
+
 /* Expand (the constant part of) a SET_TYPE CONSTRUCTOR node.
    The result is placed in BUFFER (which is an array of bytes).
    If the constructor is constant, NULL_TREE is returned.
Index: c-decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-decl.c,v
retrieving revision 1.39
diff -u -p -r1.39 c-decl.c
--- c-decl.c	1998/07/08 12:15:56	1.39
+++ c-decl.c	1998/07/09 06:22:01
@@ -585,6 +585,10 @@ int warn_sign_compare = -1;
 
 int warn_multichar = 1;
 
+/* Nonzero means warn about use of explictly undefined constructs */
+
+int warn_undefined = 0;
+
 /* Nonzero means `$' can be in an identifier.  */
 
 #ifndef DOLLARS_IN_IDENTIFIERS
@@ -772,6 +776,8 @@ c_decode_option (argc, argv)
     warn_return_type = 1;
   else if (!strcmp (p, "-Wno-return-type"))
     warn_return_type = 0;
+  else if (!strcmp(p, "-Wundefined"))
+    warn_undefined = 1;
   else if (!strcmp (p, "-Wcomment"))
     ; /* cpp handles this one.  */
   else if (!strcmp (p, "-Wno-comment"))
@@ -829,6 +835,7 @@ c_decode_option (argc, argv)
       warn_format = 1;
       warn_char_subscripts = 1;
       warn_parentheses = 1;
+      warn_undefined = 1;
       warn_missing_braces = 1;
       /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn
 	 it off only if it's not explicit.  */
Index: c-iterate.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-iterate.c,v
retrieving revision 1.5
diff -u -p -r1.5 c-iterate.c
--- c-iterate.c	1998/06/19 22:01:27	1.5
+++ c-iterate.c	1998/07/09 06:22:02
@@ -1,5 +1,5 @@
 /* Build expressions with type checking for C compiler.
-   Copyright (C) 1987, 88, 89, 92, 93, 96, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 89, 92, 93, 96-98 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -240,26 +240,8 @@ collect_iterators (exp, list)
 	case 'e':
 	case 'r':
 	  {
-	    int num_args = tree_code_length[(int) TREE_CODE (exp)];
+	    int num_args = get_max_tree_operands (exp);
 	    int i;
-
-	    /* Some tree codes have RTL, not trees, as operands.  */
-	    switch (TREE_CODE (exp))
-	      {
-	      case CALL_EXPR:
-		num_args = 2;
-		break;
-	      case METHOD_CALL_EXPR:
-		num_args = 3;
-		break;
-	      case WITH_CLEANUP_EXPR:
-		num_args = 1;
-		break;
-	      case RTL_EXPR:
-		return list;
-	      default:
-		break;
-	      }
 		
 	    for (i = 0; i < num_args; i++)
 	      list = collect_iterators (TREE_OPERAND (exp, i), list);
Index: c-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-tree.h,v
retrieving revision 1.10
diff -u -p -r1.10 c-tree.h
--- c-tree.h	1998/07/06 21:53:21	1.10
+++ c-tree.h	1998/07/09 06:22:03
@@ -1,5 +1,6 @@
 /* Definitions for C parsing and type checking.
-   Copyright (C) 1987, 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998 
+   Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -504,6 +505,10 @@ extern int warn_missing_braces;
 /* Warn about comparison of signed and unsigned values.  */
 
 extern int warn_sign_compare;
+
+/* Warn about explictly undefined behavior. */
+
+extern int warn_undefined;
 
 /* Warn about multicharacter constants.  */
 



Michael Meeks wrote:

> 	A first attempt, at a first submission to egcs. I have signed a
> copyright assignment, posted it to RMS and recieved a reply confirming
> this.
> 
> 	The feature is to catch probably undefined syntax. The following
> cases are flagged, where Fail denotes a warning.
> 
>   a = a++ ; /* Fail */
>   a = --a ; /* Fail */
>   a = ++a + b ; /* Fail */
>   a = a-- + b ; /* Fail */
>   a = (a++ && 4) ; /* shouldn't Fail but does */
>   a[n]=b[n++] ; /* Fail */
>   a[--n]=b[n] ; /* Fail */
>   a[++n]=b[--n] ; /* Fail */
>   c[n][n]=c[n][n]++ ; /* should fail but doesn't */
>   c[n][p]=c[n][n++] ; /* Fail */ /* if [n][n] then fails twice */
>   *ptr++ = (int)ptr++ ; /* Fail */
>   ptr->a = ptr->a++ ; /* should fail but doesn't */
>   ptr->a = (int)(ptr++) ; /* Fail */
>   len = sprintf (ans, "%d", len++) ;    /* Fail */
>   *ptr++ = fn(*ptr) ; /* should fail but doesn't */
>   a = b = a++ ;   /* Fail */
>   b = a = --b ;   /* Fail */
>   a = 1 + (a=1) ; /* Fail */
>   a = (a=b) ;     /* Fail */
>   a = (a=b) + 1 ; /* Fail */
> 
> 	A changelog entry might look like : ?
> 
> Tue Jun 16 19:41:18 1998  Michael Meeks  (michael@imaginator.com)
> 
> 	* c-toplev.c: Added -Wundefined to lang_options.
> 	* c-decl.c (c_decode_option): Added -Wundefined, added warn_undefined
> 	to -Wall.
> 	* c-iterate.c (collect_iterators): Broke out operand classification code
> 	into get_max_tree_operands.
> 	* tree.c (get_max_tree_operands): Returns max. valid number of operands
> 	used solely in parse tree.
> 	* tree.h: appended prototype.
> 	* c-typeck.c (build_modify_expr): Added call to check_modify_expr
> 	(check_modify_expr): Created, checks and warns for some undefined syntax.


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