Yeah, I am OK with this change, although riscv_subset_t may be able to
do further clean up/refactor, but I don't want to block you guys since
this is not super rush to do that.

Thanks :)

On Thu, Aug 14, 2025 at 5:19 PM Richard Sandiford
<richard.sandif...@arm.com> wrote:
>
> One of Alfie's FMV patches adds a hook that, in some cases,
> is used to silently query a target_version (with no diagnostics
> expected).  In the review, I'd suggested handling this using
> a location_t *, with null meaning "suppress diagnostics":
>
>    https://gcc.gnu.org/pipermail/gcc-patches/2025-August/692113.html
>
> This patch tries to propagate that through the RISC-V parsing code.
> I realise this isn't very elegant, sorry.
>
> I think riscv_compare_version_priority should also logically suppress
> diagnostics, since it's supposed to be a pure query function.  (From
> that point of view, advocating for this change for Alfie's patch might
> have been a bit unfair.)
>
> Tested as far as building riscv64-linux-gnu with --enable-werror-always.
> I'll rely on the CI for the real testing.
>
> WDYT?  Is the cure worse than the disease here?
>
> Richard
>
>
> gcc/
>         * config/riscv/riscv-protos.h
>         (riscv_process_target_version_attr): Change location_t argument
>         to location_t *.
>         * config/riscv/riscv-subset.h
>         (riscv_subset_list::riscv_subset_list): Change location_t argument
>         to location_t *.
>         (riscv_subset_list::parse): Likwise.
>         (riscv_subset_list::set_loc): Likewise.
>         (riscv_minimal_hwprobe_feature_bits): Likewise.
>         (riscv_subset_list::m_loc): Change type to location_t.
>         * common/config/riscv/riscv-common.cc
>         (riscv_subset_list::riscv_subset_list): Change location_t argument
>         to location_t *.
>         (riscv_subset_list::add): Suppress diagnostics when m_loc is null.
>         (riscv_subset_list::parsing_subset_version): Likewise.
>         (riscv_subset_list::parse_profiles): Likewise.
>         (riscv_subset_list::parse_base_ext): Likewise.
>         (riscv_subset_list::parse_single_std_ext): Likewise.
>         (riscv_subset_list::check_conflict_ext): Likewise.
>         (riscv_subset_list::parse_single_multiletter_ext): Likewise.
>         (riscv_subset_list::parse): Change location_t argument to location_t 
> *.
>         (riscv_subset_list::set_loc): Likewise.
>         (riscv_minimal_hwprobe_feature_bits): Likewise.
>         (riscv_parse_arch_string): Update call accordingly.
>         * config/riscv/riscv-target-attr.cc
>         (riscv_target_attr_parser::m_loc): Change type to location_t *.
>         (riscv_target_attr_parser::riscv_target_attr_parser): Change
>         location_t argument to location_t *.
>         (riscv_process_one_target_attr): Likewise.
>         (riscv_process_target_attr): Likewise.
>         (riscv_process_target_version_attr): Likewise.
>         (riscv_target_attr_parser::parse_arch): Suppress diagnostics when
>         m_loc is null.
>         (riscv_target_attr_parser::handle_arch): Likewise.
>         (riscv_target_attr_parser::handle_cpu): Likewise.
>         (riscv_target_attr_parser::handle_tune): Likewise.
>         (riscv_target_attr_parser::handle_priority): Likewise.
>         (riscv_option_valid_attribute_p): Update call accordingly.
>         (riscv_option_valid_version_attribute_p): Likewise.
>         * config/riscv/riscv.cc (parse_features_for_version): Add a
>         location_t * argument.
>         (dispatch_function_versions): Update call accordingly.
>         (riscv_compare_version_priority): Likewise, suppressing diagnostics.
> ---
>  gcc/common/config/riscv/riscv-common.cc | 169 +++++++++++++-----------
>  gcc/config/riscv/riscv-protos.h         |   2 +-
>  gcc/config/riscv/riscv-subset.h         |  13 +-
>  gcc/config/riscv/riscv-target-attr.cc   | 102 +++++++-------
>  gcc/config/riscv/riscv.cc               |  18 +--
>  5 files changed, 170 insertions(+), 134 deletions(-)
>
> diff --git a/gcc/common/config/riscv/riscv-common.cc 
> b/gcc/common/config/riscv/riscv-common.cc
> index f2ede074ac5..6582c15bae2 100644
> --- a/gcc/common/config/riscv/riscv-common.cc
> +++ b/gcc/common/config/riscv/riscv-common.cc
> @@ -378,7 +378,7 @@ riscv_subset_t::riscv_subset_t ()
>  {
>  }
>
> -riscv_subset_list::riscv_subset_list (const char *arch, location_t loc)
> +riscv_subset_list::riscv_subset_list (const char *arch, location_t *loc)
>    : m_arch (arch), m_loc (loc), m_head (NULL), m_tail (NULL), m_xlen (0),
>      m_subset_num (0), m_allow_adding_dup (false)
>  {
> @@ -584,47 +584,49 @@ riscv_subset_list::add (const char *subset, int 
> major_version,
>        else
>         {
>           /* The extension is already in the list.  */
> -         if (!m_allow_adding_dup
> -             || ext->major_version != major_version
> -             || ext->minor_version != minor_version)
> -           error_at (
> -             m_loc,
> -             "%<-march=%s%>: extension %qs appear more than one time",
> -             m_arch,
> -             subset);
> +         if (m_loc
> +             && (!m_allow_adding_dup
> +                 || ext->major_version != major_version
> +                 || ext->minor_version != minor_version))
> +           error_at (*m_loc, "%<-march=%s%>: extension %qs appear more "
> +                     "than one time", m_arch, subset);
>         }
>        return;
>      }
>    else if (strlen (subset) == 1 && !standard_extensions_p (subset))
>      {
> -      error_at (m_loc,
> -               "%<-march=%s%>: extension %qs is unsupported standard single "
> -               "letter extension",
> -               m_arch, subset);
> +      if (m_loc)
> +       error_at (*m_loc,
> +                 "%<-march=%s%>: extension %qs is unsupported standard "
> +                 "single letter extension",
> +                 m_arch, subset);
>        return;
>      }
>    else if (subset[0] == 'z' && !standard_extensions_p (subset))
>      {
> -      error_at (m_loc,
> -               "%<-march=%s%>: extension %qs starts with 'z' but is "
> -               "unsupported standard extension",
> -               m_arch, subset);
> +      if (m_loc)
> +       error_at (*m_loc,
> +                 "%<-march=%s%>: extension %qs starts with 'z' but is "
> +                 "unsupported standard extension",
> +                 m_arch, subset);
>        return;
>      }
>    else if (subset[0] == 's' && !standard_extensions_p (subset))
>      {
> -      error_at (m_loc,
> -               "%<-march=%s%>: extension %qs starts with 's' but is "
> -               "unsupported standard supervisor extension",
> -               m_arch, subset);
> +      if (m_loc)
> +       error_at (*m_loc,
> +                 "%<-march=%s%>: extension %qs starts with 's' but is "
> +                 "unsupported standard supervisor extension",
> +                 m_arch, subset);
>        return;
>      }
>    else if (subset[0] == 'x' && !standard_extensions_p (subset))
>      {
> -      error_at (m_loc,
> -               "%<-march=%s%>: extension %qs starts with 'x' but is "
> -               "unsupported non-standard extension",
> -               m_arch, subset);
> +      if (m_loc)
> +       error_at (*m_loc,
> +                 "%<-march=%s%>: extension %qs starts with 'x' but is "
> +                 "unsupported non-standard extension",
> +                 m_arch, subset);
>        return;
>      }
>
> @@ -886,15 +888,17 @@ riscv_subset_list::parsing_subset_version (const char 
> *ext,
>           {
>             if (!ISDIGIT (*(p+1)))
>               {
> -               error_at (m_loc, "%<-march=%s%>: expect number "
> -                         "after %<%dp%>", m_arch, version);
> +               if (m_loc)
> +                 error_at (*m_loc, "%<-march=%s%>: expect number "
> +                           "after %<%dp%>", m_arch, version);
>                 return NULL;
>               }
>             if (!major_p)
>               {
> -               error_at (m_loc, "%<-march=%s%>: for %<%s%dp%dp?%>, version "
> -                         "number with more than 2 level is not supported",
> -                         m_arch, ext, major, version);
> +               if (m_loc)
> +                 error_at (*m_loc, "%<-march=%s%>: for %<%s%dp%dp?%>, "
> +                           "version number with more than 2 level is not "
> +                           "supported", m_arch, ext, major, version);
>                 return NULL;
>               }
>             major = version;
> @@ -957,8 +961,9 @@ riscv_subset_list::parse_profiles (const char *arch)
>           /* If isn't '_' after profile, need to add it and mention the user. 
>  */
>           if (after_part[0] != '_')
>           {
> -           warning_at (m_loc, 0, "Should use \"%c\" to contact Profiles with 
> other "
> -                                 "extensions", '_');
> +           if (m_loc)
> +             warning_at (*m_loc, 0, "Should use \"%c\" to contact Profiles "
> +                         "with other extensions", '_');
>             return p_str + "_" + after_part;
>           }
>
> @@ -996,9 +1001,10 @@ riscv_subset_list::parse_base_ext (const char *p)
>      }
>    else
>      {
> -      error_at (m_loc, "%<-march=%s%>: ISA string must begin with rv32, 
> rv64,"
> -               " a supported RVA profile or refer to a supported CPU",
> -               m_arch);
> +      if (m_loc)
> +       error_at (*m_loc, "%<-march=%s%>: ISA string must begin with rv32, "
> +                 "rv64, a supported RVA profile or refer to a supported CPU",
> +                 m_arch);
>        return NULL;
>      }
>
> @@ -1021,8 +1027,9 @@ riscv_subset_list::parse_base_ext (const char *p)
>
>        if (m_xlen > 64)
>         {
> -         error_at (m_loc, "%<-march=%s%>: rv%de is not a valid base ISA",
> -                   m_arch, m_xlen);
> +         if (m_loc)
> +           error_at (*m_loc, "%<-march=%s%>: rv%de is not a valid base ISA",
> +                     m_arch, m_xlen);
>           return NULL;
>         }
>        break;
> @@ -1033,8 +1040,9 @@ riscv_subset_list::parse_base_ext (const char *p)
>                                   /* std_ext_p= */ true, &explicit_version_p);
>        if (major_version != 0 || minor_version != 0)
>         {
> -         warning_at (m_loc, 0, "version of %<g%> will be omitted, please "
> -                               "specify version for individual extension");
> +         if (m_loc)
> +           warning_at (*m_loc, 0, "version of %<g%> will be omitted, please "
> +                       "specify version for individual extension");
>         }
>
>        /* We have special rule for G, we disallow rv32gm2p but allow 
> rv32g_zicsr
> @@ -1052,8 +1060,9 @@ riscv_subset_list::parse_base_ext (const char *p)
>        break;
>
>      default:
> -      error_at (m_loc, "%<-march=%s%>: first ISA subset must be %<e%>, "
> -               "%<i%> or %<g%>", m_arch);
> +      if (m_loc)
> +       error_at (*m_loc, "%<-march=%s%>: first ISA subset must be %<e%>, "
> +                 "%<i%> or %<g%>", m_arch);
>        return NULL;
>      }
>    return p;
> @@ -1074,10 +1083,9 @@ riscv_subset_list::parse_single_std_ext (const char 
> *p, bool exact_single_p)
>  {
>    if (*p == 'x' || *p == 's' || *p == 'z')
>      {
> -      error_at (m_loc,
> -               "%<-march=%s%>: Not single-letter extension. "
> -               "%<%c%>",
> -               m_arch, *p);
> +      if (m_loc)
> +       error_at (*m_loc, "%<-march=%s%>: Not single-letter extension. 
> %<%c%>",
> +                 m_arch, *p);
>        return nullptr;
>      }
>
> @@ -1183,54 +1191,58 @@ riscv_subset_list::handle_combine_ext ()
>  void
>  riscv_subset_list::check_conflict_ext ()
>  {
> +  if (!m_loc)
> +    return;
> +
>    if (lookup ("zcf") && m_xlen == 64)
> -    error_at (m_loc, "%<-march=%s%>: zcf extension supports in rv32 only",
> +    error_at (*m_loc, "%<-march=%s%>: zcf extension supports in rv32 only",
>               m_arch);
>
>    if (lookup ("zilsd") && m_xlen == 64)
> -    error_at (m_loc, "%<-march=%s%>: zilsd extension supports in rv32 only",
> +    error_at (*m_loc, "%<-march=%s%>: zilsd extension supports in rv32 only",
>               m_arch);
>
>    if (lookup ("zclsd") && m_xlen == 64)
> -    error_at (m_loc, "%<-march=%s%>: zclsd extension supports in rv32 only",
> +    error_at (*m_loc, "%<-march=%s%>: zclsd extension supports in rv32 only",
>               m_arch);
>
>    if (lookup ("ssnpm") && m_xlen == 32)
> -    error_at (m_loc, "%<-march=%s%>: ssnpm extension supports in rv64 only",
> +    error_at (*m_loc, "%<-march=%s%>: ssnpm extension supports in rv64 only",
>               m_arch);
>
>    if (lookup ("smnpm") && m_xlen == 32)
> -    error_at (m_loc, "%<-march=%s%>: smnpm extension supports in rv64 only",
> +    error_at (*m_loc, "%<-march=%s%>: smnpm extension supports in rv64 only",
>               m_arch);
>
>    if (lookup ("smmpm") && m_xlen == 32)
> -    error_at (m_loc, "%<-march=%s%>: smmpm extension supports in rv64 only",
> +    error_at (*m_loc, "%<-march=%s%>: smmpm extension supports in rv64 only",
>               m_arch);
>
>    if (lookup ("sspm") && m_xlen == 32)
> -    error_at (m_loc, "%<-march=%s%>: sspm extension supports in rv64 only",
> +    error_at (*m_loc, "%<-march=%s%>: sspm extension supports in rv64 only",
>               m_arch);
>
>    if (lookup ("supm") && m_xlen == 32)
> -    error_at (m_loc, "%<-march=%s%>: supm extension supports in rv64 only",
> +    error_at (*m_loc, "%<-march=%s%>: supm extension supports in rv64 only",
>               m_arch);
>
>    if (lookup ("zfinx") && lookup ("f"))
> -    error_at (m_loc,
> +    error_at (*m_loc,
>               "%<-march=%s%>: z*inx conflicts with floating-point "
>               "extensions",
>               m_arch);
>
>    /* 'H' hypervisor extension requires base ISA with 32 registers.  */
>    if (lookup ("e") && lookup ("h"))
> -    error_at (m_loc, "%<-march=%s%>: h extension requires i extension", 
> m_arch);
> +    error_at (*m_loc, "%<-march=%s%>: h extension requires i extension",
> +             m_arch);
>
>    if (lookup ("zcd"))
>      {
>        if (lookup ("zcmt"))
> -       error_at (m_loc, "%<-march=%s%>: zcd conflicts with zcmt", m_arch);
> +       error_at (*m_loc, "%<-march=%s%>: zcd conflicts with zcmt", m_arch);
>        if (lookup ("zcmp"))
> -       error_at (m_loc, "%<-march=%s%>: zcd conflicts with zcmp", m_arch);
> +       error_at (*m_loc, "%<-march=%s%>: zcd conflicts with zcmp", m_arch);
>      }
>
>    if ((lookup ("v") || lookup ("zve32x")
> @@ -1238,9 +1250,9 @@ riscv_subset_list::check_conflict_ext ()
>          || lookup ("zve64f") || lookup ("zve64d")
>          || lookup ("zvl32b") || lookup ("zvl64b")
>          || lookup ("zvl128b") || lookup ("zvfh"))
> -        && lookup ("xtheadvector"))
> -    error_at (m_loc, "%<-march=%s%>: xtheadvector conflicts with vector "
> -                  "extension or its sub-extensions", m_arch);
> +      && lookup ("xtheadvector"))
> +    error_at (*m_loc, "%<-march=%s%>: xtheadvector conflicts with vector "
> +             "extension or its sub-extensions", m_arch);
>  }
>
>  /* Parsing function for multi-letter extensions.
> @@ -1336,8 +1348,9 @@ riscv_subset_list::parse_single_multiletter_ext (const 
> char *p,
>
>    if (strlen (subset) == 1)
>      {
> -      error_at (m_loc, "%<-march=%s%>: name of %s must be more than 1 
> letter",
> -               m_arch, ext_type_str);
> +      if (m_loc)
> +       error_at (*m_loc, "%<-march=%s%>: name of %s must be more "
> +                 "than 1 letter", m_arch, ext_type_str);
>        free (subset);
>        return NULL;
>      }
> @@ -1348,8 +1361,9 @@ riscv_subset_list::parse_single_multiletter_ext (const 
> char *p,
>
>    if (*p != '\0' && *p != '_')
>      {
> -      error_at (m_loc, "%<-march=%s%>: %s must separate with %<_%>",
> -               m_arch, ext_type_str);
> +      if (m_loc)
> +       error_at (*m_loc, "%<-march=%s%>: %s must separate with %<_%>",
> +                 m_arch, ext_type_str);
>        return NULL;
>      }
>
> @@ -1386,10 +1400,12 @@ riscv_subset_list::parse_single_ext (const char *p, 
> bool exact_single_p)
>      }
>  }
>
> -/* Parsing arch string to subset list, return NULL if parsing failed.  */
> +/* Parsing arch string to subset list, return NULL if parsing failed.
> +   If LOC is nonnull, report diagnostics against location *LOC, otherwise
> +   remain silent.  */
>
>  riscv_subset_list *
> -riscv_subset_list::parse (const char *arch, location_t loc)
> +riscv_subset_list::parse (const char *arch, location_t *loc)
>  {
>    if (riscv_subset_list::parse_failed)
>      return NULL;
> @@ -1412,8 +1428,9 @@ riscv_subset_list::parse (const char *arch, location_t 
> loc)
>         case 'e':
>         case 'i':
>         case 'g':
> -         error_at (loc, "%<-march=%s%>: i, e or g must be the first 
> extension",
> -                   arch);
> +         if (loc)
> +           error_at (*loc, "%<-march=%s%>: i, e or g must be "
> +                     "the first extension", arch);
>           goto fail;
>         default:
>           p = subset_list->parse_single_ext (p, /*exact_single_p=*/ false);
> @@ -1448,7 +1465,7 @@ riscv_subset_list::clone () const
>  }
>
>  void
> -riscv_subset_list::set_loc (location_t loc)
> +riscv_subset_list::set_loc (location_t *loc)
>  {
>    m_loc = loc;
>  }
> @@ -1622,12 +1639,15 @@ riscv_ext_is_subset (struct cl_target_option *opts,
>     The minimal feature bits refer to using the earliest extension that 
> appeared
>     in the Linux hwprobe to support the specified ISA string.  This ensures 
> that
>     older kernels, which may lack certain implied extensions, can still run 
> the
> -   FMV dispatcher correctly.  */
> +   FMV dispatcher correctly.
> +
> +   If LOC is nonnull, report any diagnostics against *LOC, otherwise remain
> +   silent.  */
>
>  bool
>  riscv_minimal_hwprobe_feature_bits (const char *isa,
>                                     struct riscv_feature_bits *res,
> -                                   location_t loc)
> +                                   location_t *loc)
>  {
>    riscv_subset_list *subset_list;
>    subset_list = riscv_subset_list::parse (isa, loc);
> @@ -1697,7 +1717,7 @@ riscv_parse_arch_string (const char *isa,
>                          location_t loc)
>  {
>    riscv_subset_list *subset_list;
> -  subset_list = riscv_subset_list::parse (isa, loc);
> +  subset_list = riscv_subset_list::parse (isa, &loc);
>    if (!subset_list)
>      return;
>
> @@ -1904,7 +1924,8 @@ riscv_multi_lib_info_t::parse (
>      }
>
>    multi_lib_info->subset_list =
> -    riscv_subset_list::parse (multi_lib_info->arch_str.c_str (), 
> input_location);
> +    riscv_subset_list::parse (multi_lib_info->arch_str.c_str (),
> +                             &input_location);
>
>    return true;
>  }
> @@ -2093,7 +2114,7 @@ riscv_compute_multilib (
>      return multilib_dir;
>
>    subset_list = riscv_subset_list::parse (riscv_current_arch_str.c_str (),
> -                                         input_location);
> +                                         &input_location);
>
>    /* Failed to parse -march, fallback to using what gcc use.  */
>    if (subset_list == NULL)
> diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
> index b4973251535..cf417e733fc 100644
> --- a/gcc/config/riscv/riscv-protos.h
> +++ b/gcc/config/riscv/riscv-protos.h
> @@ -837,7 +837,7 @@ riscv_option_valid_attribute_p (tree, tree, tree, int);
>  extern bool
>  riscv_option_valid_version_attribute_p (tree, tree, tree, int);
>  extern bool
> -riscv_process_target_version_attr (tree, location_t);
> +riscv_process_target_version_attr (tree, location_t *);
>  extern void
>  riscv_override_options_internal (struct gcc_options *);
>  extern void riscv_option_override (void);
> diff --git a/gcc/config/riscv/riscv-subset.h b/gcc/config/riscv/riscv-subset.h
> index a35537d7754..4cd860fee59 100644
> --- a/gcc/config/riscv/riscv-subset.h
> +++ b/gcc/config/riscv/riscv-subset.h
> @@ -52,8 +52,9 @@ private:
>    /* Original arch string.  */
>    const char *m_arch;
>
> -  /* Location of arch string, used for report error.  */
> -  location_t m_loc;
> +  /* A pointer to the location that should be used for diagnostics,
> +     or null if diagnostics should be suppressed.  */
> +  location_t *m_loc;
>
>    /* Head of subset info list.  */
>    riscv_subset_t *m_head;
> @@ -70,7 +71,7 @@ private:
>    /* Allow adding the same extension more than once.  */
>    bool m_allow_adding_dup;
>
> -  riscv_subset_list (const char *, location_t);
> +  riscv_subset_list (const char *, location_t *);
>
>    const char *parsing_subset_version (const char *, const char *, unsigned *,
>                                       unsigned *, bool, bool *);
> @@ -106,12 +107,12 @@ public:
>
>    riscv_subset_list *clone () const;
>
> -  static riscv_subset_list *parse (const char *, location_t);
> +  static riscv_subset_list *parse (const char *, location_t *);
>    const char *parse_single_ext (const char *, bool exact_single_p = true);
>
>    int match_score (riscv_subset_list *) const;
>
> -  void set_loc (location_t);
> +  void set_loc (location_t *);
>
>    void set_allow_adding_dup (bool v) { m_allow_adding_dup = v; }
>
> @@ -182,7 +183,7 @@ extern void
>  riscv_set_arch_by_subset_list (riscv_subset_list *, struct gcc_options *);
>  extern bool riscv_minimal_hwprobe_feature_bits (const char *,
>                                                 struct riscv_feature_bits *,
> -                                               location_t);
> +                                               location_t *);
>  extern bool
>  riscv_ext_is_subset (struct cl_target_option *, struct cl_target_option *);
>
> diff --git a/gcc/config/riscv/riscv-target-attr.cc 
> b/gcc/config/riscv/riscv-target-attr.cc
> index 8ad3025579b..5e01c921454 100644
> --- a/gcc/config/riscv/riscv-target-attr.cc
> +++ b/gcc/config/riscv/riscv-target-attr.cc
> @@ -34,7 +34,7 @@ namespace {
>  class riscv_target_attr_parser
>  {
>  public:
> -  riscv_target_attr_parser (location_t loc)
> +  riscv_target_attr_parser (location_t *loc)
>      : m_found_arch_p (false)
>      , m_found_tune_p (false)
>      , m_found_cpu_p (false)
> @@ -62,7 +62,7 @@ private:
>    bool m_found_cpu_p;
>    bool m_found_priority_p;
>    riscv_subset_list *m_subset_list;
> -  location_t m_loc;
> +  location_t *m_loc;
>    const  riscv_cpu_info *m_cpu_info;
>    const char *m_tune;
>    int m_priority;
> @@ -102,15 +102,17 @@ riscv_target_attr_parser::parse_arch (const char *str)
>      {
>        if (TARGET_64BIT && strncmp ("32", str + 2, strlen ("32")) == 0)
>         {
> -         error_at (m_loc, "unexpected arch for %<target()%> attribute: "
> -                   "must start with rv64 but found %qs", str);
> +         if (m_loc)
> +           error_at (*m_loc, "unexpected arch for %<target()%> attribute: "
> +                     "must start with rv64 but found %qs", str);
>           goto fail;
>         }
>
>        if (!TARGET_64BIT && strncmp ("64", str + 2, strlen ("64")) == 0)
>         {
> -         error_at (m_loc, "unexpected arch for %<target()%> attribute: "
> -                   "must start with rv32 but found %qs", str);
> +         if (m_loc)
> +           error_at (*m_loc, "unexpected arch for %<target()%> attribute: "
> +                     "must start with rv32 but found %qs", str);
>           goto fail;
>         }
>
> @@ -140,10 +142,9 @@ riscv_target_attr_parser::parse_arch (const char *str)
>         {
>           if (token[0] != '+')
>             {
> -             error_at (
> -               m_loc,
> -               "unexpected arch for %<target()%> attribute: must start "
> -               "with + or rv");
> +             if (*m_loc)
> +               error_at (*m_loc, "unexpected arch for %<target()%> "
> +                         "attribute: must start with + or rv");
>               goto fail;
>             }
>
> @@ -151,10 +152,9 @@ riscv_target_attr_parser::parse_arch (const char *str)
>           /* Check parse_single_ext has consume all string.  */
>           if (*result != '\0')
>             {
> -             error_at (
> -               m_loc,
> -               "unexpected arch for %<target()%> attribute: bad "
> -               "string found %qs", token);
> +             if (m_loc)
> +               error_at (*m_loc, "unexpected arch for %<target()%> "
> +                         "attribute: bad string found %qs", token);
>               goto fail;
>             }
>
> @@ -179,8 +179,8 @@ fail:
>  bool
>  riscv_target_attr_parser::handle_arch (const char *str)
>  {
> -  if (m_found_arch_p)
> -    error_at (m_loc, "%<target()%> attribute: arch appears more than once");
> +  if (m_found_arch_p && m_loc)
> +    error_at (*m_loc, "%<target()%> attribute: arch appears more than once");
>    m_found_arch_p = true;
>    return parse_arch (str);
>  }
> @@ -190,15 +190,16 @@ riscv_target_attr_parser::handle_arch (const char *str)
>  bool
>  riscv_target_attr_parser::handle_cpu (const char *str)
>  {
> -  if (m_found_cpu_p)
> -    error_at (m_loc, "%<target()%> attribute: cpu appears more than once");
> +  if (m_found_cpu_p && m_loc)
> +    error_at (*m_loc, "%<target()%> attribute: cpu appears more than once");
>
>    m_found_cpu_p = true;
>    const riscv_cpu_info *cpu_info = riscv_find_cpu (str);
>
>    if (!cpu_info)
>      {
> -      error_at (m_loc, "%<target()%> attribute: unknown CPU %qs", str);
> +      if (m_loc)
> +       error_at (*m_loc, "%<target()%> attribute: unknown CPU %qs", str);
>        return false;
>      }
>
> @@ -218,14 +219,15 @@ riscv_target_attr_parser::handle_cpu (const char *str)
>  bool
>  riscv_target_attr_parser::handle_tune (const char *str)
>  {
> -  if (m_found_tune_p)
> -    error_at (m_loc, "%<target()%> attribute: tune appears more than once");
> +  if (m_found_tune_p && m_loc)
> +    error_at (*m_loc, "%<target()%> attribute: tune appears more than once");
>    m_found_tune_p = true;
>    const struct riscv_tune_info *tune = riscv_parse_tune (str, true);
>
>    if (tune == nullptr)
>      {
> -      error_at (m_loc, "%<target()%> attribute: unknown TUNE %qs", str);
> +      if (m_loc)
> +       error_at (*m_loc, "%<target()%> attribute: unknown TUNE %qs", str);
>        return false;
>      }
>
> @@ -237,13 +239,15 @@ riscv_target_attr_parser::handle_tune (const char *str)
>  bool
>  riscv_target_attr_parser::handle_priority (const char *str)
>  {
> -  if (m_found_priority_p)
> -    error_at (m_loc, "%<target()%> attribute: priority appears more than 
> once");
> +  if (m_found_priority_p && m_loc)
> +    error_at (*m_loc, "%<target()%> attribute: priority appears "
> +             "more than once");
>    m_found_priority_p = true;
>
>    if (sscanf (str, "%d", &m_priority) != 1)
>      {
> -      error_at (m_loc, "%<target()%> attribute: invalid priority %qs", str);
> +      if (m_loc)
> +       error_at (*m_loc, "%<target()%> attribute: invalid priority %qs", 
> str);
>        return false;
>      }
>
> @@ -282,7 +286,7 @@ riscv_target_attr_parser::update_settings (struct 
> gcc_options *opts) const
>
>  static bool
>  riscv_process_one_target_attr (char *arg_str,
> -                              location_t loc,
> +                              location_t *loc,
>                                riscv_target_attr_parser &attr_parser,
>                                const struct riscv_attribute_info *attrs)
>  {
> @@ -290,7 +294,8 @@ riscv_process_one_target_attr (char *arg_str,
>
>    if (len == 0)
>      {
> -      error_at (loc, "malformed %<target()%> attribute");
> +      if (loc)
> +       error_at (*loc, "malformed %<target()%> attribute");
>        return false;
>      }
>
> @@ -302,10 +307,9 @@ riscv_process_one_target_attr (char *arg_str,
>
>    if (!arg)
>      {
> -      error_at (
> -       loc,
> -       "attribute %<target(\"%s\")%> does not accept an argument",
> -       str_to_check);
> +      if (loc)
> +       error_at (*loc, "attribute %<target(\"%s\")%> does not "
> +                 "accept an argument", str_to_check);
>        return false;
>      }
>
> @@ -324,7 +328,8 @@ riscv_process_one_target_attr (char *arg_str,
>        return (&attr_parser->*attr->handler) (arg);
>      }
>
> -  error_at (loc, "Got unknown attribute %<target(\"%s\")%>", str_to_check);
> +  if (loc)
> +    error_at (*loc, "Got unknown attribute %<target(\"%s\")%>", 
> str_to_check);
>    return false;
>  }
>
> @@ -347,11 +352,12 @@ num_occurrences_in_str (char c, char *str)
>  }
>
>  /* Parse the string in ARGS that contains the target attribute information
> -   and update the global target options space.  */
> +   and update the global target options space.  If LOC is nonnull, report
> +   diagnostics against location *LOC, otherwise remain silent.  */
>
>  bool
>  riscv_process_target_attr (const char *args,
> -                          location_t loc,
> +                          location_t *loc,
>                            const struct riscv_attribute_info *attrs)
>  {
>    size_t len = strlen (args);
> @@ -387,8 +393,8 @@ riscv_process_target_attr (const char *args,
>
>    if (num_attrs != num_semicolons + 1)
>      {
> -      error_at (loc, "malformed %<target(\"%s\")%> attribute",
> -               args);
> +      if (loc)
> +       error_at (*loc, "malformed %<target(\"%s\")%> attribute", args);
>        return false;
>      }
>
> @@ -399,11 +405,12 @@ riscv_process_target_attr (const char *args,
>  }
>
>  /* Parse the tree in ARGS that contains the target attribute information
> -   and update the global target options space.  */
> +   and update the global target options space.  If LOC is nonnull, report
> +   diagnostics against *LOC, otherwise remain silent.  */
>
>  static bool
>  riscv_process_target_attr (tree args,
> -                          location_t loc,
> +                          location_t *loc,
>                            const struct riscv_attribute_info *attrs)
>  {
>    if (TREE_CODE (args) == TREE_LIST)
> @@ -424,7 +431,8 @@ riscv_process_target_attr (tree args,
>
>    if (TREE_CODE (args) != STRING_CST)
>      {
> -      error_at (loc, "attribute %<target%> argument not a string");
> +      if (loc)
> +       error_at (*loc, "attribute %<target%> argument not a string");
>        return false;
>      }
>
> @@ -466,7 +474,7 @@ riscv_option_valid_attribute_p (tree fndecl, tree, tree 
> args, int)
>                               TREE_TARGET_OPTION 
> (target_option_default_node));
>
>    /* Now we can parse the attributes and set &global_options accordingly.  */
> -  ret = riscv_process_target_attr (args, loc, riscv_target_attrs);
> +  ret = riscv_process_target_attr (args, &loc, riscv_target_attrs);
>    if (ret)
>      {
>        riscv_override_options_internal (&global_options);
> @@ -481,16 +489,19 @@ riscv_option_valid_attribute_p (tree fndecl, tree, tree 
> args, int)
>  }
>
>  /* Parse the tree in ARGS that contains the target_version attribute
> -   information and update the global target options space.  */
> +   information and update the global target options space.  If LOC is 
> nonnull,
> +   report diagnostics against *LOC, otherwise remain silent.  */
>
>  bool
> -riscv_process_target_version_attr (tree args, location_t loc)
> +riscv_process_target_version_attr (tree args, location_t *loc)
>  {
>    if (TREE_CODE (args) == TREE_LIST)
>      {
>        if (TREE_CHAIN (args))
>         {
> -         error ("attribute %<target_version%> has multiple values");
> +         if (loc)
> +           error_at (*loc, "attribute %<target_version%> "
> +                     "has multiple values");
>           return false;
>         }
>        args = TREE_VALUE (args);
> @@ -498,7 +509,8 @@ riscv_process_target_version_attr (tree args, location_t 
> loc)
>
>    if (!args || TREE_CODE (args) != STRING_CST)
>      {
> -      error ("attribute %<target_version%> argument not a string");
> +      if (loc)
> +       error_at (*loc, "attribute %<target_version%> argument not a string");
>        return false;
>      }
>
> @@ -541,7 +553,7 @@ riscv_option_valid_version_attribute_p (tree fndecl, 
> tree, tree args, int)
>      cl_target_option_restore (&global_options, &global_options_set,
>                               TREE_TARGET_OPTION 
> (target_option_current_node));
>
> -  ret = riscv_process_target_version_attr (args, loc);
> +  ret = riscv_process_target_version_attr (args, &loc);
>
>    /* Set up any additional state.  */
>    if (ret)
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 4935367dd0e..e3b385b9150 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -13949,10 +13949,13 @@ riscv_c_mode_for_floating_type (enum tree_index ti)
>    return default_mode_for_floating_type (ti);
>  }
>
> -/* This parses the attribute arguments to target_version in DECL and modifies
> -   the feature mask and priority required to select those targets.  */
> +/* Parse the attribute arguments to target_version in DECL and modify
> +   the feature mask and priority required to select those targets.
> +   If LOC is nonnull, report diagnostics against *LOC, otherwise
> +   remain silent.  */
>  static void
>  parse_features_for_version (tree decl,
> +                           location_t *loc,
>                             struct riscv_feature_bits &res,
>                             int &priority)
>  {
> @@ -13983,14 +13986,12 @@ parse_features_for_version (tree decl,
>    cl_target_option_restore (&global_options, &global_options_set,
>                             default_opts);
>
> -  riscv_process_target_version_attr (TREE_VALUE (version_attr),
> -                                    DECL_SOURCE_LOCATION (decl));
> +  riscv_process_target_version_attr (TREE_VALUE (version_attr), loc);
>
>    priority = global_options.x_riscv_fmv_priority;
>    const char *arch_string = global_options.x_riscv_arch_string;
>    bool parse_res
> -    = riscv_minimal_hwprobe_feature_bits (arch_string, &res,
> -                                         DECL_SOURCE_LOCATION (decl));
> +    = riscv_minimal_hwprobe_feature_bits (arch_string, &res, loc);
>    gcc_assert (parse_res);
>
>    cl_target_option_restore (&global_options, &global_options_set,
> @@ -14047,8 +14048,8 @@ riscv_compare_version_priority (tree decl1, tree 
> decl2)
>    struct riscv_feature_bits mask1, mask2;
>    int prio1, prio2;
>
> -  parse_features_for_version (decl1, mask1, prio1);
> -  parse_features_for_version (decl2, mask2, prio2);
> +  parse_features_for_version (decl1, nullptr, mask1, prio1);
> +  parse_features_for_version (decl2, nullptr, mask2, prio2);
>
>    return compare_fmv_features (mask1, mask2, prio1, prio2);
>  }
> @@ -14351,6 +14352,7 @@ dispatch_function_versions (tree dispatch_decl,
>        version_info.version_decl = version_decl;
>        // Get attribute string, parse it and find the right features.
>        parse_features_for_version (version_decl,
> +                                 &DECL_SOURCE_LOCATION (version_decl),
>                                   version_info.features,
>                                   version_info.prio);
>        function_versions.push_back (version_info);
> --
> 2.43.0
>

Reply via email to