Hi,
here is updated patch that replaces 'C' by '1'...'9' so we still have
place to specify size.
As discussed on IRC, this seems better alternative.

Bootstrapped/regtested x86_64-linux, OK?

Honza

gcc/ChangeLog:

2020-11-12  Jan Hubicka  <hubi...@ucw.cz>

        * attr-fnspec.h: Update topleve comment.
        (attr_fnspec::arg_direct_p): Accept 1...9.
        (attr_fnspec::arg_maybe_written_p): Reject 1...9.
        (attr_fnspec::arg_copied_to_arg_p): New member function.
        * builtins.c (builtin_fnspec): Update fnspec of block copy.
        * tree-ssa-alias.c (attr_fnspec::verify): Update.

diff --git a/gcc/attr-fnspec.h b/gcc/attr-fnspec.h
index 28135328437..766414a2520 100644
--- a/gcc/attr-fnspec.h
+++ b/gcc/attr-fnspec.h
@@ -41,6 +41,9 @@
                written and does not escape
      'w' or 'W' specifies that the memory pointed to by the parameter does not
                escape
+     '1'....'9' specifies that the memory pointed to by the parameter is
+               copied to memory pointed to by different parameter
+               (as in memcpy).
      '.'       specifies that nothing is known.
    The uppercase letter in addition specifies that the memory pointed to
    by the parameter is not dereferenced.  For 'r' only read applies
@@ -51,8 +54,8 @@
      ' '        nothing is known
      't'       the size of value written/read corresponds to the size of
                of the pointed-to type of the argument type
-     '1'...'9'  the size of value written/read is given by the specified
-               argument
+     '1'...'9'  specifies the size of value written/read is given by the
+               specified argument
  */
 
 #ifndef ATTR_FNSPEC_H
@@ -122,7 +125,8 @@ public:
   {
     unsigned int idx = arg_idx (i);
     gcc_checking_assert (arg_specified_p (i));
-    return str[idx] == 'R' || str[idx] == 'O' || str[idx] == 'W';
+    return str[idx] == 'R' || str[idx] == 'O'
+          || str[idx] == 'W' || (str[idx] >= '1' && str[idx] <= '9');
   }
 
   /* True if argument is used.  */
@@ -161,6 +165,7 @@ public:
     unsigned int idx = arg_idx (i);
     gcc_checking_assert (arg_specified_p (i));
     return str[idx] != 'r' && str[idx] != 'R'
+          && (str[idx] < '1' || str[idx] > '9')
           && str[idx] != 'x' && str[idx] != 'X';
   }
 
@@ -190,6 +195,21 @@ public:
     return str[idx + 1] == 't';
   }
 
+  /* Return true if memory pointer to by argument is copied to a memory
+     pointed to by a different argument (as in memcpy).
+     In this case set ARG.  */
+  bool
+  arg_copied_to_arg_p (unsigned int i, unsigned int *arg)
+  {
+    unsigned int idx = arg_idx (i);
+    gcc_checking_assert (arg_specified_p (i));
+    if (str[idx] < '1' || str[idx] > '9')
+      return false;
+    *arg = str[idx] - '1';
+    return true;
+  }
+
+
   /* True if the argument does not escape.  */
   bool
   arg_noescape_p (unsigned int i)
@@ -230,7 +250,7 @@ public:
     return str[1] != 'c' && str[1] != 'C';
   }
 
-  /* Return true if all memory written by the function 
+  /* Return true if all memory written by the function
      is specified by fnspec.  */
   bool
   global_memory_written_p ()
diff --git a/gcc/builtins.c b/gcc/builtins.c
index da25343beb1..4ec1766cffd 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -12939,16 +12939,16 @@ builtin_fnspec (tree callee)
         argument.  */
       case BUILT_IN_STRCAT:
       case BUILT_IN_STRCAT_CHK:
-       return "1cW R ";
+       return "1cW 1 ";
       case BUILT_IN_STRNCAT:
       case BUILT_IN_STRNCAT_CHK:
-       return "1cW R3";
+       return "1cW 13";
       case BUILT_IN_STRCPY:
       case BUILT_IN_STRCPY_CHK:
-       return "1cO R ";
+       return "1cO 1 ";
       case BUILT_IN_STPCPY:
       case BUILT_IN_STPCPY_CHK:
-       return ".cO R ";
+       return ".cO 1 ";
       case BUILT_IN_STRNCPY:
       case BUILT_IN_MEMCPY:
       case BUILT_IN_MEMMOVE:
@@ -12957,15 +12957,15 @@ builtin_fnspec (tree callee)
       case BUILT_IN_STRNCPY_CHK:
       case BUILT_IN_MEMCPY_CHK:
       case BUILT_IN_MEMMOVE_CHK:
-       return "1cO3R3";
+       return "1cO313";
       case BUILT_IN_MEMPCPY:
       case BUILT_IN_MEMPCPY_CHK:
-       return ".cO3R3";
+       return ".cO313";
       case BUILT_IN_STPNCPY:
       case BUILT_IN_STPNCPY_CHK:
-       return ".cO3R3";
+       return ".cO313";
       case BUILT_IN_BCOPY:
-       return ".cR3O3";
+       return ".c23O3";
       case BUILT_IN_BZERO:
        return ".cO2";
       case BUILT_IN_MEMCMP:
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index e64011d04df..b1e8e5b5352 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -3797,6 +3797,8 @@ attr_fnspec::verify ()
       default:
        err = true;
     }
+  if (err)
+    internal_error ("invalid fn spec attribute \"%s\"", str);
 
   /* Now check all parameters.  */
   for (unsigned int i = 0; arg_specified_p (i); i++)
@@ -3813,21 +3815,28 @@ attr_fnspec::verify ()
          case 'w':
          case 'W':
          case '.':
+           if ((str[idx + 1] >= '1' && str[idx + 1] <= '9')
+               || str[idx + 1] == 't')
+             {
+               if (str[idx] != 'r' && str[idx] != 'R'
+                   && str[idx] != 'w' && str[idx] != 'W'
+                   && str[idx] != 'o' && str[idx] != 'O')
+                 err = true;
+               if (str[idx] != 't'
+                   /* Size specified is scalar, so it should be described
+                      by ". " if specified at all.  */
+                   && (arg_specified_p (str[idx + 1] - '1')
+                       && str[arg_idx (str[idx + 1] - '1')] != '.'))
+                 err = true;
+             }
+           else if (str[idx + 1] != ' ')
+             err = true;
            break;
          default:
-           err = true;
+           if (str[idx] < '1' || str[idx] > '9')
+             err = true;
        }
-      if ((str[idx + 1] >= '1' && str[idx + 1] <= '9')
-         || str[idx + 1] == 't')
-       {
-         if (str[idx] != 'r' && str[idx] != 'R'
-             && str[idx] != 'w' && str[idx] != 'W'
-             && str[idx] != 'o' && str[idx] != 'O')
-           err = true;
-       }
-      else if (str[idx + 1] != ' ')
-       err = true;
+      if (err)
+       internal_error ("invalid fn spec attribute \"%s\" arg %i", str, i);
     }
-  if (err)
-    internal_error ("invalid fn spec attribute \"%s\"", str);
 }

Reply via email to