Hi Sandra, hello world,
On Feburary 10, 2025, Sandra Loosemore wrote:
This patch adds functions for variant name mangling and context selector
merging that are shared by the C and C++ front ends.
The OpenMP specification says that name mangling is supposed to encode
the context selector for the variant, but also provides for no way to
reference these functions directly by name or from a different
compilation unit. It also gives no guidance on how dynamic selectors
might be encoded across compilation units.
In particular, OpenMP states that only function definitions are mangled,
not function declarations.
However, when I try it with the attached program, it fails with
'Error: symbol `_ZGIW3one' is already defined', i.e. mangling does not work.
The GCC implementation of this feature instead treats variant
functions as if they have no linkage and uses a simple counter to
generate names.
The assumption 'no linkage' breaks as soon as C++ modules are used
as the attached example program shows.
As the module name is encoded, I think using the simple counter per
TU should still work. Namely, with -fno-openmp, the one.cc part of
the example gives:
000000000000000b T initializer for module one0000000000000000 T
test@one() Thus, "test.ompvariant0@one()" should be fine as name. * * * TODO: * Handle mangling with C++
modules * Honor the visibility in the module (i.e. if 'export' it needs
to be callable from other TU) → just keep setting as is inside modules.
* * * Unrelated to mangling and visibility, but the following is wrongly
rejected: ----------------- #pragma omp begin declare variant
match(construct={parallel}) const char *test () { return "Parallel"; }
#pragma omp end declare variant -----------------
Namely, this fails with the bogus error:
error: no previous declaration of base function in this scope
However, OpenMP permits this: "For the purpose of call resolution, each
function definition that appears in the delimited code region is a
function variant for an assumed base function, with the same name and a
compatible prototype, that is declared elsewhere without an associated
declare variant directive." Obviously, if the base function is in no
(linked) TU defined, calling it will lead to a link time error. But
otherwise, having it only be defined in a different file / TU or later
in the same file or not at all is perfectly valid. Tobias PS: Note that
I tried the attached examples with OG14 with the assumption that it
doesn't differ from mainline + your patches in this regard. PPS: OpenMP
6.1 will add delimited declare variant also for Fortran.
// { dg-additional-options "-fmodules" }
// As C++20's modules aren't enabled by default (yet)
// Before r15-5112-gd9c3c3c85665b2, use -fmodules-ts instead of -fmodules
export module one;
export const char *
test ()
{
return "Default";
}
#if _OPENMP
#pragma omp begin declare variant match(construct={parallel})
export const char *
test ()
{
return "Parallel";
}
#pragma omp end declare variant
#endif
import one;
int
main ()
{
__builtin_printf ("%s\n", test ()); // "Default"
#pragma omp parallel if(0)
__builtin_printf ("%s\n", test ()); // "Parallel"
}