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