On 5/29/25 8:52 AM, Alfie Richards wrote:
Adds the target_version and target_clones attributes to diagnostic messages
for target_version semantics.

This is because the target_version/target_clones attributes affect the identity
of the decls, so need to be represented in diagnostics for them.

After this change diagnostics look like:

```
test.c:5:7: error: redefinition of ‘[[target_version("sve")]] foo’
     5 | float foo () {return 2;}
       |       ^~~
test.c:2:7: note: previous definition of ‘[[target_version("sve")]] foo’ with 
type ‘float(void)’
     2 | float foo () {return 1;}
```

It would be better to print this information after the identifier, to match standard attribute syntax; attributes generally appertain to the thing immediately to their left. Except attributes at the very beginning of the declaration, but that doesn't apply here because we only see the identifier.

This only affects targets which use target_version (aarch64 and riscv).

gcc/c-family/ChangeLog:

        * c-pretty-print.cc (pp_c_function_target_version): New function.
        (pp_c_function_target_clones): New function.
        * c-pretty-print.h (pp_c_function_target_version): New function.
        (pp_c_function_target_clones): New function.

gcc/c/ChangeLog:

        * c-objc-common.cc (c_tree_printer): Add printing of target_clone and
        target_version in decl diagnostics.

gcc/cp/ChangeLog:

        * cxx-pretty-print.h (pp_cxx_function_target_version): New macro.
        (pp_cxx_function_target_clones): Ditto.
        * error.cc (dump_function_decl): Add printing of target_clone and
        target_version in decl diagnostics.
---
  gcc/c-family/c-pretty-print.cc | 65 ++++++++++++++++++++++++++++++++++
  gcc/c-family/c-pretty-print.h  |  2 ++
  gcc/c/c-objc-common.cc         |  6 ++++
  gcc/cp/cxx-pretty-print.h      |  4 +++
  gcc/cp/error.cc                |  3 ++
  5 files changed, 80 insertions(+)

diff --git a/gcc/c-family/c-pretty-print.cc b/gcc/c-family/c-pretty-print.cc
index fad6b5eb9b0..1cb71d99b16 100644
--- a/gcc/c-family/c-pretty-print.cc
+++ b/gcc/c-family/c-pretty-print.cc
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "function.h"
  #include "basic-block.h"
  #include "gimple.h"
+#include "tm.h"
/* The pretty-printer code is primarily designed to closely follow
     (GNU) C and C++ grammars.  That is to be contrasted with spaghetti
@@ -3054,6 +3055,70 @@ pp_c_tree_decl_identifier (c_pretty_printer *pp, tree t)
    pp_c_identifier (pp, name);
  }
+/* Prints "[version: VERSION]" for a versioned function decl.
+   This only works for target_version.  */
+void
+pp_c_function_target_version (c_pretty_printer *pp, tree t)
+{
+  if (TARGET_HAS_FMV_TARGET_ATTRIBUTE)
+    return;
+
+  string_slice version = get_target_version (t);
+  if (!version.is_valid ())
+    return;
+
+  pp_c_left_bracket (pp);
+  pp_c_left_bracket (pp);
+  pp_string (pp, "target_version");
+  pp_c_left_paren (pp);
+  pp_doublequote (pp);
+  pp_string_n (pp, version.begin (), version.size ());
+  pp_doublequote (pp);
+  pp_c_right_paren (pp);
+  pp_c_right_bracket (pp);
+  pp_c_right_bracket (pp);
+  pp_c_whitespace (pp);
+}
+
+/* Prints "[clones: VERSION, +]" for a versioned function decl.
+   This only works for target_version.  */
+void
+pp_c_function_target_clones (c_pretty_printer *pp, tree t)
+{
+  /* Only print for target_version semantics.
+     This is because for target FMV semantics a target_clone always defines
+     the entire FMV set.  target_version semantics can mix target_clone and
+     target_version decls in the definition of a FMV set and so the
+     target_clone becomes a part of the identity of the declaration.  */
+  if (TARGET_HAS_FMV_TARGET_ATTRIBUTE)
+    return;
+
+  auto_vec<string_slice> versions = get_clone_versions (t, NULL, false);
+  if (versions.is_empty ())
+    return;
+
+  string_slice final_version = versions.pop ();
+  pp_c_left_bracket (pp);
+  pp_c_left_bracket (pp);
+  pp_string (pp, "target_clones");
+  pp_c_left_paren (pp);
+  for (string_slice version : versions)
+    {
+      pp_doublequote (pp);
+      pp_string_n (pp, version.begin (), version.size ());
+      pp_doublequote (pp);
+      pp_string (pp, ",");
+      pp_c_whitespace (pp);
+    }
+  pp_doublequote (pp);
+  pp_string_n (pp, final_version.begin (), final_version.size ());
+  pp_doublequote (pp);
+  pp_c_right_paren (pp);
+  pp_c_right_bracket (pp);
+  pp_c_right_bracket (pp);
+  pp_c_whitespace (pp);
+}
+
  #if CHECKING_P
namespace selftest {
diff --git a/gcc/c-family/c-pretty-print.h b/gcc/c-family/c-pretty-print.h
index c8fb6789991..5dc1cdff513 100644
--- a/gcc/c-family/c-pretty-print.h
+++ b/gcc/c-family/c-pretty-print.h
@@ -138,6 +138,8 @@ void pp_c_ws_string (c_pretty_printer *, const char *);
  void pp_c_identifier (c_pretty_printer *, const char *);
  void pp_c_string_literal (c_pretty_printer *, tree);
  void pp_c_integer_constant (c_pretty_printer *, tree);
+void pp_c_function_target_version (c_pretty_printer *, tree);
+void pp_c_function_target_clones (c_pretty_printer *, tree);
void print_c_tree (FILE *file, tree t, dump_flags_t); diff --git a/gcc/c/c-objc-common.cc b/gcc/c/c-objc-common.cc
index 2016eaebf17..84a4ee5fc17 100644
--- a/gcc/c/c-objc-common.cc
+++ b/gcc/c/c-objc-common.cc
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "c-tree.h"
  #include "intl.h"
  #include "c-family/c-pretty-print.h"
+#include "tree-core.h"
  #include "tree-pretty-print.h"
  #include "tree-pretty-print-markup.h"
  #include "gimple-pretty-print.h"
@@ -353,6 +354,11 @@ c_tree_printer (pretty_printer *pp, text_info *text, const 
char *spec,
      case 'F':
        if (DECL_NAME (t))
        {
+         if (TREE_CODE (t) == FUNCTION_DECL)
+           {
+             pp_c_function_target_version (cpp, t);
+             pp_c_function_target_clones (cpp, t);
+           }
          pp_identifier (cpp, lang_hooks.decl_printable_name (t, 2));
          return true;
        }
diff --git a/gcc/cp/cxx-pretty-print.h b/gcc/cp/cxx-pretty-print.h
index 86e0ce7d85f..836c7478a42 100644
--- a/gcc/cp/cxx-pretty-print.h
+++ b/gcc/cp/cxx-pretty-print.h
@@ -83,6 +83,10 @@ public:
  #define pp_cxx_identifier(PP, I)      pp_c_identifier (PP, I)
  #define pp_cxx_tree_identifier(PP, T) \
    pp_c_tree_identifier (PP, T)
+#define pp_cxx_function_target_version(PP, T) \
+  pp_c_function_target_version (PP, T)
+#define pp_cxx_function_target_clones(PP, T) \
+  pp_c_function_target_clones (PP, T)
void pp_cxx_begin_template_argument_list (cxx_pretty_printer *);
  void pp_cxx_end_template_argument_list (cxx_pretty_printer *);
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index d52dad3db29..489f52f3523 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -1913,6 +1913,9 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int 
flags)
        }
      }
+ pp_cxx_function_target_version (pp, t);
+  pp_cxx_function_target_clones (pp, t);
+
    if (DECL_NAME (t) && LAMBDA_FUNCTION_P (t))
      return dump_lambda_function (pp, t, template_parms, template_args, flags);

Reply via email to