https://gcc.gnu.org/g:84628fdbe51da29cbe1459714eec81e0dbeecb17
commit r16-3212-g84628fdbe51da29cbe1459714eec81e0dbeecb17 Author: Richard Sandiford <richard.sandif...@arm.com> Date: Fri Aug 15 14:15:35 2025 +0100 RISC-V: Allow errors to be suppressed when parsing architectures 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.) 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. Diff: --- 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 f2ede074ac58..6582c15bae2e 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 b49732515352..cf417e733fc9 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 a35537d7754a..4cd860fee59b 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 8ad3025579b2..5e01c9214548 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 e9217dcb0433..9c3884903d84 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -13950,10 +13950,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) { @@ -13984,14 +13987,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, @@ -14048,8 +14049,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); } @@ -14352,6 +14353,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);