Kito Cheng <kito.ch...@gmail.com> writes:
> 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!  Now pushed.  The precommit CI seems to be struggling at
the moment, so please let me know if you see any fallout.

Richard

> 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