This patch reports an error if the .md file has an unscoped
attribute that maps to more than one possible value.

I'll apply this once the port patches are in.


2019-07-05  Richard Sandiford  <richard.sandif...@arm.com>

gcc/
        * read-md.h (md_reader::record_potential_iterator_use): Add a
        file_location parameter.
        * read-rtl.c (attribute_use::loc): New field.
        (map_attr_string): Take a file_location parameter.  Report cases
        in which attributes map to multiple distinct values.
        (apply_attribute_uses): Update call accordingly.
        (md_reader::handle_overloaded_name): Likewise.
        (md_reader::apply_iterator_to_string): Likewise.  Skip empty
        nonnull strings.
        (record_attribute_use): Take a file_location parameter.
        Initialize attribute_use::loc.
        (md_reader::record_potential_iterator_use): Take a file_location
        parameter.  Update call to record_attribute_use.
        (rtx_reader::rtx_alloc_for_name): Update call accordingly.
        (rtx_reader::read_rtx_code): Likewise.
        (rtx_reader::read_rtx_operand): Likewise.  Record a location
        for implicitly-expanded empty strings.

Index: gcc/read-md.h
===================================================================
--- gcc/read-md.h       2019-07-05 15:08:52.698765764 +0100
+++ gcc/read-md.h       2019-07-05 15:09:08.694633872 +0100
@@ -211,8 +211,8 @@ struct mapping;
   rtx copy_rtx_for_iterators (rtx original);
   void read_conditions ();
   void record_potential_iterator_use (struct iterator_group *group,
-                                     rtx x, unsigned int index,
-                                     const char *name);
+                                     file_location loc, rtx x,
+                                     unsigned int index, const char *name);
   struct mapping *read_mapping (struct iterator_group *group, htab_t table);
   overloaded_name *handle_overloaded_name (rtx, vec<mapping *> *);
 
Index: gcc/read-rtl.c
===================================================================
--- gcc/read-rtl.c      2019-07-01 09:37:05.780536545 +0100
+++ gcc/read-rtl.c      2019-07-05 15:09:08.694633872 +0100
@@ -106,6 +106,9 @@ struct attribute_use {
   /* The group that describes the use site.  */
   struct iterator_group *group;
 
+  /* The location at which the use occurs.  */
+  file_location loc;
+
   /* The name of the attribute, possibly with an "iterator:" prefix.  */
   const char *value;
 
@@ -361,10 +364,10 @@ find_subst_iter_by_attr (const char *att
 
 /* Map attribute string P to its current value.  Return null if the attribute
    isn't known.  If ITERATOR_OUT is nonnull, store the associated iterator
-   there.  */
+   there.  Report any errors against location LOC.  */
 
 static struct map_value *
-map_attr_string (const char *p, mapping **iterator_out = 0)
+map_attr_string (file_location loc, const char *p, mapping **iterator_out = 0)
 {
   const char *attr;
   struct mapping *iterator;
@@ -372,6 +375,8 @@ map_attr_string (const char *p, mapping
   struct mapping *m;
   struct map_value *v;
   int iterator_name_len;
+  struct map_value *res = NULL;
+  struct mapping *prev = NULL;
 
   /* Peel off any "iterator:" prefix.  Set ATTR to the start of the
      attribute name.  */
@@ -414,13 +419,22 @@ map_attr_string (const char *p, mapping
          for (v = m->values; v; v = v->next)
            if (v->number == iterator->current_value->number)
              {
+               if (res && strcmp (v->string, res->string) != 0)
+                 {
+                   error_at (loc, "ambiguous attribute '%s'; could be"
+                             " '%s' (via '%s:%s') or '%s' (via '%s:%s')",
+                             attr, res->string, prev->name, attr,
+                             v->string, iterator->name, attr);
+                   return v;
+                 }
                if (iterator_out)
                  *iterator_out = iterator;
-               return v;
+               prev = iterator;
+               res = v;
              }
        }
     }
-  return NULL;
+  return res;
 }
 
 /* Apply the current iterator values to STRING.  Return the new string
@@ -432,16 +446,17 @@ md_reader::apply_iterator_to_string (con
   char *base, *copy, *p, *start, *end;
   struct map_value *v;
 
-  if (string == 0)
+  if (string == 0 || string[0] == 0)
     return string;
 
+  file_location loc = get_md_ptr_loc (string)->loc;
   base = p = copy = ASTRDUP (string);
   while ((start = strchr (p, '<')) && (end = strchr (start, '>')))
     {
       p = start + 1;
 
       *end = 0;
-      v = map_attr_string (p);
+      v = map_attr_string (loc, p);
       *end = '>';
       if (v == 0)
        continue;
@@ -572,7 +587,7 @@ apply_attribute_uses (void)
 
   FOR_EACH_VEC_ELT (attribute_uses, i, ause)
     {
-      v = map_attr_string (ause->value);
+      v = map_attr_string (ause->loc, ause->value);
       if (!v)
        fatal_with_file_and_line ("unknown iterator value `%s'", ause->value);
       ause->group->apply_iterator (ause->x, ause->index,
@@ -656,6 +671,7 @@ md_reader::handle_overloaded_name (rtx o
 
   /* Remove the '@', so that no other code needs to worry about it.  */
   const char *name = XSTR (original, 0);
+  file_location loc = get_md_ptr_loc (name)->loc;
   copy_md_ptr_loc (name + 1, name);
   name += 1;
   XSTR (original, 0) = name;
@@ -672,7 +688,7 @@ md_reader::handle_overloaded_name (rtx o
     {
       *end = 0;
       mapping *iterator;
-      if (!map_attr_string (start + 1, &iterator))
+      if (!map_attr_string (loc, start + 1, &iterator))
        fatal_with_file_and_line ("unknown iterator `%s'", start + 1);
       *end = '>';
 
@@ -1126,24 +1142,25 @@ record_iterator_use (struct mapping *ite
   iterator_uses.safe_push (iuse);
 }
 
-/* Record that X uses attribute VALUE, which must match a built-in
-   value from group GROUP.  If the use is in an operand of X, INDEX
-   is the index of that operand, otherwise it is ignored.  */
+/* Record that X uses attribute VALUE at location LOC, where VALUE must
+   match a built-in value from group GROUP.  If the use is in an operand
+   of X, INDEX is the index of that operand, otherwise it is ignored.  */
 
 static void
-record_attribute_use (struct iterator_group *group, rtx x,
+record_attribute_use (struct iterator_group *group, file_location loc, rtx x,
                      unsigned int index, const char *value)
 {
-  struct attribute_use ause = {group, value, x, index};
+  struct attribute_use ause = {group, loc, value, x, index};
   attribute_uses.safe_push (ause);
 }
 
 /* Interpret NAME as either a built-in value, iterator or attribute
    for group GROUP.  X and INDEX are the values to pass to GROUP's
-   apply_iterator callback.  */
+   apply_iterator callback.  LOC is the location of the use.  */
 
 void
 md_reader::record_potential_iterator_use (struct iterator_group *group,
+                                         file_location loc,
                                          rtx x, unsigned int index,
                                          const char *name)
 {
@@ -1156,7 +1173,7 @@ md_reader::record_potential_iterator_use
       /* Copy the attribute string into permanent storage, without the
         angle brackets around it.  */
       obstack_grow0 (&m_string_obstack, name + 1, len - 2);
-      record_attribute_use (group, x, index,
+      record_attribute_use (group, loc, x, index,
                            XOBFINISH (&m_string_obstack, char *));
     }
   else
@@ -1540,7 +1557,8 @@ rtx_reader::rtx_alloc_for_name (const ch
       /* Pick the first possible code for now, and record the attribute
         use for later.  */
       rtx x = rtx_alloc (check_code_attribute (m));
-      record_attribute_use (&codes, x, 0, deferred_name);
+      record_attribute_use (&codes, get_current_location (),
+                           x, 0, deferred_name);
       return x;
     }
 
@@ -1639,8 +1657,8 @@ rtx_reader::read_rtx_code (const char *c
   c = read_skip_spaces ();
   if (c == ':')
     {
-      read_name (&name);
-      record_potential_iterator_use (&modes, return_rtx, 0, name.string);
+      file_location loc = read_name (&name);
+      record_potential_iterator_use (&modes, loc, return_rtx, 0, name.string);
     }
   else
     unread_char (c);
@@ -1862,6 +1880,7 @@ rtx_reader::read_rtx_operand (rtx return
                || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT
                || GET_CODE (return_rtx) == DEFINE_INSN_AND_REWRITE))
          {
+           const char *old_stringbuf = stringbuf;
            struct obstack *string_obstack = get_string_obstack ();
            char line_name[20];
            const char *read_md_filename = get_filename ();
@@ -1875,6 +1894,7 @@ rtx_reader::read_rtx_operand (rtx return
            sprintf (line_name, ":%d", get_lineno ());
            obstack_grow (string_obstack, line_name, strlen (line_name)+1);
            stringbuf = XOBFINISH (string_obstack, char *);
+           copy_md_ptr_loc (stringbuf, old_stringbuf);
          }
 
        /* Find attr-names in the string.  */
@@ -1946,10 +1966,13 @@ rtx_reader::read_rtx_operand (rtx return
     case 'i':
     case 'n':
     case 'p':
-      /* Can be an iterator or an integer constant.  */
-      read_name (&name);
-      record_potential_iterator_use (&ints, return_rtx, idx, name.string);
-      break;
+      {
+       /* Can be an iterator or an integer constant.  */
+       file_location loc = read_name (&name);
+       record_potential_iterator_use (&ints, loc, return_rtx, idx,
+                                      name.string);
+       break;
+      }
 
     case 'r':
       read_name (&name);

Reply via email to