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;}
```

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);
 
-- 
2.34.1

Reply via email to