> On Oct 31, 2024, at 18:14, Kito Cheng <kito.ch...@gmail.com> wrote:
>
>> diff --git a/gcc/config/riscv/riscv-target-attr.cc
>> b/gcc/config/riscv/riscv-target-attr.cc
>> index 087fbae77b0..4c85ad60b72 100644
>> --- a/gcc/config/riscv/riscv-target-attr.cc
>> +++ b/gcc/config/riscv/riscv-target-attr.cc
>> @@ -239,10 +239,6 @@ riscv_target_attr_parser::update_settings (struct
>> gcc_options *opts) const
>> {
>> std::string local_arch = m_subset_list->to_string (true);
>> const char* local_arch_str = local_arch.c_str ();
>> - struct cl_target_option *default_opts
>> - = TREE_TARGET_OPTION (target_option_default_node);
>> - if (opts->x_riscv_arch_string != default_opts->x_riscv_arch_string)
>> - free (CONST_CAST (void *, (const void *) opts->x_riscv_arch_string));
>
> Could you give a little more context why you decide to remove those logics?
>
That's because when we have target_version features, the riscv_arch_string
may need to be stored in the DECL_FUNCTION_SPECIFIC_TARGET. If we
free the arch string, it may have use-after-free bugs. I came across
this bug even without ASAN.
I know that if we didn't free it, it might cause a memory leak. But
for GCC, it’s OK, I think. It's also complex to add something like
std::shared_ptr or std::string to the global options.
If this explanation is OK, I will add a comment about this in this
source file.
>> opts->x_riscv_arch_string = xstrdup (local_arch_str);
>>
>> riscv_set_arch_by_subset_list (m_subset_list, opts);
>> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
>> index 3ac40234345..947864fc3a6 100644
>> --- a/gcc/config/riscv/riscv.cc
>> +++ b/gcc/config/riscv/riscv.cc
>> @@ -12574,6 +12574,127 @@ riscv_c_mode_for_floating_type (enum tree_index ti)
>> return default_mode_for_floating_type (ti);
>> }
>>
>> +/* This parses the attribute arguments to target_version in DECL and
>> modifies
>> + the feature mask and priority required to select those targets. */
>> +static void
>> +parse_features_for_version (tree decl,
>> + struct riscv_feature_bits &res,
>> + int &priority)
>> +{
>> + tree version_attr = lookup_attribute ("target_version",
>> + DECL_ATTRIBUTES (decl));
>> + if (version_attr == NULL_TREE)
>> + {
>> + res.length = 0;
>> + priority = 0;
>> + return;
>> + }
>> +
>> + const char *version_string = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE
>> + (version_attr)));
>> + gcc_assert (version_string != NULL);
>> + if (strcmp (version_string, "default") == 0)
>> + {
>> + res.length = 0;
>> + priority = 0;
>> + return;
>> + }
>> + struct cl_target_option cur_target;
>> + cl_target_option_save (&cur_target, &global_options,
>> + &global_options_set);
>> + /* Always set to default option before parsing "arch=+..." */
>> + struct cl_target_option *default_opts
>> + = TREE_TARGET_OPTION (target_option_default_node);
>> + cl_target_option_restore (&global_options, &global_options_set,
>> + default_opts);
>> +
>> + riscv_process_target_attr (version_string,
>> + DECL_SOURCE_LOCATION (decl));
>
> Is it possible to just use DECL_FUNCTION_SPECIFIC_TARGET (decl) here
> rather than parse and apply that globally?
For DECL_FUNCTION_SPECIFIC_TARGET, the answer is no.
That's because the function may not be versioned when calling from
TARGET_OPTION_FUNCTION_VERSIONS.
You can check this by applying this assert and running the test in
the final patch to see the stack dump:
```diff
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 20c6bf4f2e4..1b39c33c518 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -12692,6 +12692,7 @@ parse_features_for_version (tree decl,
struct riscv_feature_bits &res,
int &priority)
{
+ gcc_assert (decl != NULL && DECL_FUNCTION_VERSIONED (decl));
tree version_attr = lookup_attribute ("target_version",
DECL_ATTRIBUTES (decl));
if (version_attr == NULL_TREE)
```
```console
test2.cpp:5:10: internal compiler error: in parse_features_for_version, at
config/riscv/riscv.cc:12695
5 | void foo() {}
| ^
0x30dd120 internal_error(char const*, ...)
../.././gcc/gcc/diagnostic-global-context.cc:518
0xd2ca07 fancy_abort(char const*, int, char const*)
../.././gcc/gcc/diagnostic.cc:1693
0xc5713d parse_features_for_version
../.././gcc/gcc/config/riscv/riscv.cc:12695
0x1a9b51f riscv_compare_version_priority(tree_node*, tree_node*)
../.././gcc/gcc/config/riscv/riscv.cc:12790
0x1a9b69a riscv_common_function_versions(tree_node*, tree_node*)
../.././gcc/gcc/config/riscv/riscv.cc:12808
0x1a9b69a riscv_common_function_versions(tree_node*, tree_node*)
../.././gcc/gcc/config/riscv/riscv.cc:12801
0xdf1a9e decls_match(tree_node*, tree_node*, bool)
../.././gcc/gcc/cp/decl.cc:1213
0xe1d5bd find_last_decl
../.././gcc/gcc/cp/decl2.cc:1752
0xe1d5bd cplus_decl_attributes(tree_node**, tree_node*, int)
../.././gcc/gcc/cp/decl2.cc:1888 <http://decl2.cc:1888/>
```