This is a reimplementation of get_target_clone_attr_len,
get_attr_str, and separate_attrs using string_slice and auto_vec to make
memory management and use simpler.
gcc/c-family/ChangeLog:
* c-attribs.cc (handle_target_clones_attribute): Change to use
get_clone_versions.
gcc/ChangeLog:
* tree.cc (get_clone_versions): New function.
(get_clone_attr_versions): New function.
* tree.h (get_clone_versions): New function.
(get_clone_attr_versions): New function.
---
gcc/c-family/c-attribs.cc | 2 +-
gcc/tree.cc | 40 +++++++++++++++++++++++++++++++++++++++
gcc/tree.h | 5 +++++
3 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index f3181e7b57c..642d724f6c6 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -6129,7 +6129,7 @@ handle_target_clones_attribute (tree *node, tree name, tree ARG_UNUSED (args),
}
}
- if (get_target_clone_attr_len (args) == -1)
+ if (get_clone_attr_versions (args).length () == 1)
{
warning (OPT_Wattributes,
"single %<target_clones%> attribute is ignored");
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 05f679edc09..346522d01c0 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -15299,6 +15299,46 @@ get_target_clone_attr_len (tree arglist)
return str_len_sum;
}
+/* Returns an auto_vec of string_slices containing the version strings from
+ ARGLIST. DEFAULT_COUNT is incremented for each default version found. */
+
+auto_vec<string_slice>
+get_clone_attr_versions (const tree arglist, int *default_count)
+{
+ gcc_assert (TREE_CODE (arglist) == TREE_LIST);
+ auto_vec<string_slice> versions;
+
+ static const char separator_str[] = {TARGET_CLONES_ATTR_SEPARATOR, 0};
+ string_slice separators = string_slice (separator_str);
+
+ for (tree arg = arglist; arg; arg = TREE_CHAIN (arg))
+ {
+ string_slice str = string_slice (TREE_STRING_POINTER (TREE_VALUE (arg)));
+ for (string_slice attr = string_slice::strtok (&str, separators);
+ attr.is_valid (); attr = string_slice::strtok (&str, separators))
+ {
+ attr = attr.strip ();
+ if (attr == string_slice ("default") && default_count)
+ (*default_count)++;
+ versions.safe_push (attr);
+ }
+ }
+ return versions;
+}
+
+/* Returns an auto_vec of string_slices containing the version strings from
+ the target_clone attribute from DECL. DEFAULT_COUNT is incremented for each
+ default version found. */
+auto_vec<string_slice>
+get_clone_versions (const tree decl, int *default_count)
+{
+ tree attr = lookup_attribute ("target_clones", DECL_ATTRIBUTES (decl));
+ if (!attr)
+ return auto_vec<string_slice> ();
+ tree arglist = TREE_VALUE (attr);
+ return get_clone_attr_versions (arglist, default_count);
+}
+
void
tree_cc_finalize (void)
{
diff --git a/gcc/tree.h b/gcc/tree.h
index 21f3cd5525c..aea1cf078a0 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-core.h"
#include "options.h"
+#include "vec.h"
/* Convert a target-independent built-in function code to a combined_fn. */
@@ -7035,5 +7036,9 @@ extern unsigned fndecl_dealloc_argno (tree);
extern tree get_attr_nonstring_decl (tree, tree * = NULL);
extern int get_target_clone_attr_len (tree);
+auto_vec<string_slice>
+get_clone_versions (const tree, int * = NULL);
+auto_vec<string_slice>
+get_clone_attr_versions (const tree, int * = NULL);
#endif /* GCC_TREE_H */