For constraints there are operand modifiers and constraint qualifiers. Operand modifiers apply to all alternatives and must appear, in traditional syntax before the first alternative. Constraint qualifiers, on the other hand must appear in each alternative to which they apply.
There's no easy way to validate the distinction in the traditional md format, but when using the new compact format we can enforce some semantic checking of these characters to avoid some potentially surprising code generation. gcc/ * gensupport.cc (conlist::conlist): Pass a location to the constructor. Only allow skipping of non-alpha-numeric characters when parsing a number and only allow '=', '+' or '%'. Add some error checking when parsing an operand number. (parse_section_layout): Pass the location to the conlist constructor. (parse_section): Allow an optional list of forbidden characters. If specified, reject strings containing them. (convert_syntax): Reject '=', '+' or '%' in an alternative. --- gcc/gensupport.cc | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/gcc/gensupport.cc b/gcc/gensupport.cc index 80f1976faf1..ac0132860a9 100644 --- a/gcc/gensupport.cc +++ b/gcc/gensupport.cc @@ -656,7 +656,7 @@ public: i.e. if rtx is the relevant match_operand or match_scratch then [ns..ns + len) should equal itoa (XINT (rtx, 0)), and if set_attr then [ns..ns + len) should equal XSTR (rtx, 0). */ - conlist (const char *ns, unsigned int len, bool numeric) + conlist (const char *ns, unsigned int len, bool numeric, file_location loc) { /* Trim leading whitespaces. */ while (len > 0 && ISBLANK (*ns)) @@ -670,16 +670,26 @@ public: if (!ISBLANK (ns[i])) break; - /* Parse off any modifiers. */ - while (len > 0 && !ISALNUM (*ns)) - { - con += *(ns++); - len--; - } + /* Only numeric values can have modifiers. */ + if (numeric) + /* Parse off any modifiers. */ + while (len > 0 && !ISALNUM (*ns)) + { + if (*ns != '=' && *ns != '+' && *ns != '%') + error_at (loc, "`%c` is not a valid operand modifier", *ns); + con += *(ns++); + len--; + } name.assign (ns, len); if (numeric) - idx = strtol (name.c_str (), (char **)NULL, 10); + { + char *endstr; + /* There should only be a numeric value now... */ + idx = strtol (name.c_str (), &endstr, 10); + if (*endstr != '\0') + error_at (loc, "operand number expected, found %s", name.c_str ()); + } } /* Adds a character to the end of the string. */ @@ -832,7 +842,7 @@ parse_section_layout (file_location loc, const char **templ, const char *label, *templ += len; if (val == ',') (*templ)++; - list.push_back (conlist (name_start, len, numeric)); + list.push_back (conlist (name_start, len, numeric, loc)); } } } @@ -845,7 +855,8 @@ parse_section_layout (file_location loc, const char **templ, const char *label, static void parse_section (const char **templ, unsigned int n_elems, unsigned int alt_no, - vec_conlist &list, file_location loc, const char *name) + vec_conlist &list, file_location loc, const char *name, + const char *invalid_chars = NULL) { unsigned int i; @@ -856,6 +867,10 @@ parse_section (const char **templ, unsigned int n_elems, unsigned int alt_no, { if (**templ == 0 || **templ == '\n') fatal_at (loc, "missing ']'"); + if (invalid_chars + && strchr (invalid_chars, **templ)) + error_at (loc, "'%c' is not permitted in an alternative for a %s", + **templ, name); list[i].add (**templ); if (**templ == ',') { @@ -981,7 +996,7 @@ convert_syntax (rtx x, file_location loc) /* Parse the constraint list, then the attribute list. */ if (tconvec.size () > 0) parse_section (&templ, tconvec.size (), alt_no, tconvec, loc, - "constraint"); + "constraint", "=+%"); if (attrvec.size () > 0) { -- 2.43.0