From: Alfie Richards Date: Tue, 30 Sep 2025 12:25:25 +0000 (+0000) Subject: c: fmv: Prevent FMV being combined with other cloning/renaming extensions. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=264a575765e0985fdc8a00b16c1d5bb4a46ed4db;p=thirdparty%2Fgcc.git c: fmv: Prevent FMV being combined with other cloning/renaming extensions. This patch adds exclusions and diagnostics to prevent function multi-versioning being used with omp simd pragmas and renaming extensions. This behaviour is forbidden by the ACLE as the expected behaviour is not clear. gcc/c-family/ChangeLog: * c-attribs.cc (attr_target_clones_exclusions): Add simd and omp exclusions. (attr_target_version_exclusions): New definition with simd and omp exclusions. (attr_omp_declare_simd_exclusions): New definition with target_version and clones exclusions. (attr_simd_exclusions): Ditto. (c_common_gnu_attributes): Add new target_version, simd, and omp declare simd variables. gcc/c/ChangeLog: * c-decl.cc (maybe_mark_function_versioned): Add diagnostic. * c-parser.cc (c_finish_omp_declare_simd): Add diagnostic. gcc/testsuite/ChangeLog: * gcc.target/aarch64/mv-error11.c: New test. * gcc.target/aarch64/mv-error12.c: New test. --- diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index df9ff9947a8..5bc5183f421 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -249,6 +249,29 @@ static const struct attribute_spec::exclusions attr_target_clones_exclusions[] = ATTR_EXCL ("always_inline", true, true, true), ATTR_EXCL ("target", TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE), + ATTR_EXCL ("omp declare simd", true, true, true), + ATTR_EXCL ("simd", true, true, true), + ATTR_EXCL (NULL, false, false, false), +}; + +static const struct attribute_spec::exclusions attr_target_version_exclusions[] = +{ + ATTR_EXCL ("omp declare simd", true, true, true), + ATTR_EXCL ("simd", true, true, true), + ATTR_EXCL (NULL, false, false, false), +}; + +static const struct attribute_spec::exclusions attr_omp_declare_simd_exclusions[] = +{ + ATTR_EXCL ("target_version", true, true, true), + ATTR_EXCL ("target_clones", true, true, true), + ATTR_EXCL (NULL, false, false, false), +}; + +static const struct attribute_spec::exclusions attr_simd_exclusions[] = +{ + ATTR_EXCL ("target_version", true, true, true), + ATTR_EXCL ("target_clones", true, true, true), ATTR_EXCL (NULL, false, false, false), }; @@ -536,7 +559,7 @@ const struct attribute_spec c_common_gnu_attributes[] = attr_target_exclusions }, { "target_version", 1, 1, true, false, false, false, handle_target_version_attribute, - NULL }, + attr_target_version_exclusions}, { "target_clones", 1, -1, true, false, false, false, handle_target_clones_attribute, attr_target_clones_exclusions }, @@ -563,7 +586,8 @@ const struct attribute_spec c_common_gnu_attributes[] = { "returns_nonnull", 0, 0, false, true, true, false, handle_returns_nonnull_attribute, NULL }, { "omp declare simd", 0, -1, true, false, false, false, - handle_omp_declare_simd_attribute, NULL }, + handle_omp_declare_simd_attribute, + attr_omp_declare_simd_exclusions }, { "omp declare variant base", 0, -1, true, false, false, false, handle_omp_declare_variant_attribute, NULL }, { "omp declare variant variant", 0, -1, true, false, false, false, @@ -572,7 +596,7 @@ const struct attribute_spec c_common_gnu_attributes[] = false, false, handle_omp_declare_variant_attribute, NULL }, { "simd", 0, 1, true, false, false, false, - handle_simd_attribute, NULL }, + handle_simd_attribute, attr_simd_exclusions }, { "omp declare target", 0, -1, true, false, false, false, handle_omp_declare_target_attribute, NULL }, { "omp declare target link", 0, 0, true, false, false, false, diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 825487529d0..632bbf057a3 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -2094,6 +2094,12 @@ maybe_mark_function_versioned (tree decl) { if (!DECL_FUNCTION_VERSIONED (decl)) { + /* Check if the name of the function has been overridden. */ + if (DECL_ASSEMBLER_NAME_SET_P (decl) + && IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))[0] == '*') + error_at (DECL_SOURCE_LOCATION (decl), + "cannot use function multiversioning on a renamed function"); + /* We need to insert function version now to make sure the correct pre-mangled assembler name is recorded. */ cgraph_node *node = cgraph_node::get_create (decl); diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index df44a915ed4..7c2452644bd 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -27776,6 +27776,13 @@ c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, clauses[0].type = CPP_EOF; return; } + if (DECL_FUNCTION_VERSIONED (fndecl)) + { + error_at (DECL_SOURCE_LOCATION (fndecl), + "%<#pragma omp declare %s%> cannot be used with function " + "multi-versioning", kind); + return; + } if (parms == NULL_TREE) parms = DECL_ARGUMENTS (fndecl); diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error11.c b/gcc/testsuite/gcc.target/aarch64/mv-error11.c new file mode 100644 index 00000000000..0fdd66012d3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/mv-error11.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0" } */ + +int fn () asm("name"); +int fn () { return 1; } /* { dg-error "cannot use function multiversioning on a renamed function" } */ +int fn [[gnu::target_version("sve")]] () { return 1; } + +int fn2 [[gnu::target_version("sve")]] () asm("name"); /* { dg-warning ".asm. declaration ignored due to conflict with previous rename" } */ diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error12.c b/gcc/testsuite/gcc.target/aarch64/mv-error12.c new file mode 100644 index 00000000000..45da85a67b9 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/mv-error12.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ +/* { dg-require-ifunc "" } */ + +#pragma omp declare simd +int fn [[gnu::target_version("sve")]] () { return 1; } /* { dg-error ".#pragma omp declare simd. cannot be used with function multi-versioning" } */ + +#pragma omp declare simd +int fn2 () { return 1; } + +int fn2 [[gnu::target_version("sve")]] (); /* { dg-warning "ignoring attribute .target_version. because it conflicts with attribute .omp declare simd." } */ + +int fn3 [[gnu::target_version("sve")]] [[gnu::simd]] () { return 1; } /* { dg-warning "ignoring attribute .simd. because it conflicts with attribute .target_version." } */