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);