On 3/2/2026 01:49, Yangyu Chen wrote:
This commit implements the function TARGET_CHECK_TARGET_CLONE_VERSION
for the RISC-V architecture by changing the error to a warning when an
unsupported target clone version is encountered.

This allows the compiler to compatible with future extensions without
failing the build. And also helps for future APIs that need real
implementation of TARGET_CHECK_TARGET_CLONE_VERSION for RISC-V that
no longer always return true.

Signed-off-by: Yangyu Chen <[email protected]>
---
  gcc/config/riscv/riscv-target-attr.cc | 50 +++++++++++++++------------
  gcc/config/riscv/riscv.cc             | 21 +++++------
  2 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/gcc/config/riscv/riscv-target-attr.cc 
b/gcc/config/riscv/riscv-target-attr.cc
index 99af5308fea4..ad5e5a052196 100644
--- a/gcc/config/riscv/riscv-target-attr.cc
+++ b/gcc/config/riscv/riscv-target-attr.cc
@@ -149,18 +149,18 @@ riscv_target_attr_parser::parse_arch (const char *str)
          if (token[0] != '+')
            {
              if (*m_loc)
-               error_at (*m_loc, "unexpected arch for %<target()%> "
-                         "attribute: must start with + or rv");
+               warning_at (*m_loc, 0, "unexpected arch for %<target()%> "
+                           "attribute: must start with + or rv");
              goto fail;
            }
const char *result = m_subset_list->parse_single_ext (token + 1);
          /* Check parse_single_ext has consume all string.  */
-         if (*result != '\0')
+         if (result == nullptr || *result != '\0')

I noticed that this patch was marked Deferred by RISC-V Maintainers. But there is also a bugfix for the target_clones attribute with a pattern like "arch=+unparseable_string". This will result in a nullptr de-reference here. For example, without this fix, if we try to compile such code:

```c
__attribute__((target_clones("default", "arch=+randomstring")))
void foo() {

}
```

We will get:

```console
during IPA pass: targetclone
foo-2.c:2:6: internal compiler error: Segmentation fault
    2 | void foo() {
      |      ^~~
0x7f0f50a40a4f ???
        ./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
0x7f0f50a29f74 __libc_start_call_main
        ../sysdeps/nptl/libc_start_call_main.h:58
0x7f0f50a2a026 __libc_start_main_impl
        ../csu/libc-start.c:360
Please submit a full bug report, with preprocessed source (by using -freport-bug).
Please include the complete backtrace with any bug report.
See <file:///usr/share/doc/gcc-15/README.Bugs> for instructions.
```

My opinion is to fix this and replace the error to warning in GCC-16. But if it's not feasible, waiting for GCC-17 is OK. No matter what the option is, we still need to address the nullptr de-reference issue here for GCC-15 and GCC-16.

Thanks,
Yangyu Chen

            {
              if (m_loc)
-               error_at (*m_loc, "unexpected arch for %<target()%> "
-                         "attribute: bad string found %qs", token);
+               warning_at (*m_loc, 0, "unexpected arch for %<target()%> "
+                           "attribute: bad string found %qs", token);
              goto fail;
            }
@@ -186,7 +186,8 @@ bool
  riscv_target_attr_parser::handle_arch (const char *str)
  {
    if (m_found_arch_p && m_loc)
-    error_at (*m_loc, "%<target()%> attribute: arch appears more than once");
+    warning_at (*m_loc, 0,
+               "%<target()%> attribute: arch appears more than once");
    m_found_arch_p = true;
    return parse_arch (str);
  }
@@ -197,7 +198,8 @@ bool
  riscv_target_attr_parser::handle_cpu (const char *str)
  {
    if (m_found_cpu_p && m_loc)
-    error_at (*m_loc, "%<target()%> attribute: cpu appears more than once");
+    warning_at (*m_loc, 0,
+               "%<target()%> attribute: cpu appears more than once");
m_found_cpu_p = true;
    const riscv_cpu_info *cpu_info = riscv_find_cpu (str);
@@ -205,7 +207,7 @@ riscv_target_attr_parser::handle_cpu (const char *str)
    if (!cpu_info)
      {
        if (m_loc)
-       error_at (*m_loc, "%<target()%> attribute: unknown CPU %qs", str);
+       warning_at (*m_loc, 0, "%<target()%> attribute: unknown CPU %qs", str);
        return false;
      }
@@ -226,14 +228,15 @@ bool
  riscv_target_attr_parser::handle_tune (const char *str)
  {
    if (m_found_tune_p && m_loc)
-    error_at (*m_loc, "%<target()%> attribute: tune appears more than once");
+    warning_at (*m_loc, 0,
+               "%<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)
      {
        if (m_loc)
-       error_at (*m_loc, "%<target()%> attribute: unknown TUNE %qs", str);
+       warning_at (*m_loc, 0, "%<target()%> attribute: unknown TUNE %qs", str);
        return false;
      }
@@ -246,14 +249,15 @@ bool
  riscv_target_attr_parser::handle_priority (const char *str)
  {
    if (m_found_priority_p && m_loc)
-    error_at (*m_loc, "%<target()%> attribute: priority appears "
+    warning_at (*m_loc, 0, "%<target()%> attribute: priority appears "
              "more than once");
    m_found_priority_p = true;
if (sscanf (str, "%d", &m_priority) != 1)
      {
        if (m_loc)
-       error_at (*m_loc, "%<target()%> attribute: invalid priority %qs", str);
+       warning_at (*m_loc, 0, "%<target()%> attribute: invalid priority %qs",
+                   str);
        return false;
      }
@@ -315,7 +319,7 @@ riscv_process_one_target_attr (char *arg_str,
    if (len == 0)
      {
        if (loc)
-       error_at (*loc, "malformed %<target()%> attribute");
+       warning_at (*loc, 0, "malformed %<target()%> attribute");
        return false;
      }
@@ -333,8 +337,9 @@ riscv_process_one_target_attr (char *arg_str,
        if (*arg == '\0')
        {
          if (loc)
-           error_at (*loc, "attribute %<target(\"%s\")%> has empty argument",
-                     str_to_check);
+           warning_at (*loc, 0,
+                       "attribute %<target(\"%s\")%> has empty argument",
+                       str_to_check);
          return false;
        }
      }
@@ -349,7 +354,7 @@ riscv_process_one_target_attr (char *arg_str,
        if (attr->requires_arg && !arg)
        {
          if (loc)
-           error_at (*loc, "attribute %<target(\"%s\")%> expects "
+           warning_at (*loc, 0, "attribute %<target(\"%s\")%> expects "
                      "an argument", str_to_check);
          return false;
        }
@@ -357,7 +362,7 @@ riscv_process_one_target_attr (char *arg_str,
        if (!attr->requires_arg && arg)
        {
          if (loc)
-           error_at (*loc, "attribute %<target(\"%s\")%> does not "
+           warning_at (*loc, 0, "attribute %<target(\"%s\")%> does not "
                      "accept an argument", str_to_check);
          return false;
        }
@@ -366,7 +371,7 @@ riscv_process_one_target_attr (char *arg_str,
      }
if (loc)
-    error_at (*loc, "unknown attribute %<target(\"%s\")%>", str_to_check);
+    warning_at (*loc, 0, "unknown attribute %<target(\"%s\")%>", str_to_check);
    return false;
  }
@@ -432,7 +437,7 @@ riscv_process_target_str (string_slice args,
    if (num_attrs != num_semicolons + 1)
      {
        if (loc)
-       error_at (*loc, "malformed %<target(\"%B\")%> attribute", &args);
+       warning_at (*loc, 0, "malformed %<target(\"%B\")%> attribute", &args);
        return false;
      }
@@ -470,7 +475,7 @@ riscv_process_target_attr (tree args,
    if (TREE_CODE (args) != STRING_CST)
      {
        if (loc)
-       error_at (*loc, "attribute %<target%> argument not a string");
+       warning_at (*loc, 0, "attribute %<target%> argument not a string");
        return false;
      }
@@ -549,7 +554,7 @@ riscv_process_target_version_attr (tree args, location_t *loc)
        if (TREE_CHAIN (args))
        {
          if (loc)
-           error_at (*loc, "attribute %<target_version%> "
+           warning_at (*loc, 0, "attribute %<target_version%> "
                      "has multiple values");
          return false;
        }
@@ -559,7 +564,8 @@ riscv_process_target_version_attr (tree args, location_t 
*loc)
    if (!args || TREE_CODE (args) != STRING_CST)
      {
        if (loc)
-       error_at (*loc, "attribute %<target_version%> argument not a string");
+       warning_at (*loc, 0,
+                   "attribute %<target_version%> argument not a string");
        return false;
      }
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 32e72128f049..a84e6d7b4831 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -14876,7 +14876,7 @@ riscv_bitint_type_info (int n, struct bitint_info *info)
     priority required to select those targets.
     If LOC is nonnull, report diagnostics against *LOC, otherwise
     remain silent.  */
-static void
+static bool
  parse_features_for_version (string_slice version_str,
                            location_t *loc,
                            struct riscv_feature_bits &res,
@@ -14887,7 +14887,7 @@ parse_features_for_version (string_slice version_str,
      {
        res.length = 0;
        priority = 0;
-      return;
+      return true;
      }
struct cl_target_option cur_target;
@@ -14899,7 +14899,13 @@ parse_features_for_version (string_slice version_str,
    cl_target_option_restore (&global_options, &global_options_set,
                            default_opts);
- riscv_process_target_version_str (version_str, loc);
+  bool ret = riscv_process_target_version_str (version_str, loc);
+  if (!ret)
+    {
+      cl_target_option_restore (&global_options, &global_options_set,
+                               &cur_target);
+    return false;
+    }
priority = global_options.x_riscv_fmv_priority;
    const char *arch_string = global_options.x_riscv_arch_string;
@@ -14909,6 +14915,7 @@ parse_features_for_version (string_slice version_str,
cl_target_option_restore (&global_options, &global_options_set,
                            &cur_target);
+  return true;
  }
/* Compare priorities of two feature masks. Return:
@@ -15003,13 +15010,7 @@ riscv_check_target_clone_version (string_slice str, 
location_t *loc_p)
    struct riscv_feature_bits mask;
    int prio;
- /* Currently it is not possible to parse without emitting errors on failure
-     so do not reject on a failed parse, as this would then emit two
-     diagnostics.  Instead let errors be emitted which will halt
-     compilation.  */
-  parse_features_for_version (str, loc_p, mask, prio);
-
-  return true;
+  return parse_features_for_version (str, loc_p, mask, prio);
  }
/* Implement TARGET_MANGLE_DECL_ASSEMBLER_NAME, to add function multiversioning

Reply via email to