Summary
The declare variant directive declares a specialized variant of a base function and specifies the
context in which that specialized variant is used. The declare variant directive is a declarative
directive.
Syntax
The syntax of the declare variant directive is as follows:
and where variant-proc-name is the name of a function variant that is a base language identifier.
Description
The declare variant directive declares a base function to have the specified function variant. The context
selector in the match clause is associated with the variant.
The begindeclarevariant directive associates the context selector in the match clause with each
function definition in declaration-definition-seq.
For the purpose of call resolution, each function definition that appears between a begindeclarevariant
directive and its paired enddeclarevariant directive 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.
If a declare variant directive appears between a begindeclarevariant directive and its paired
enddeclarevariant directive the effective context selectors of the outer directive are appended to
the context selector of the inner directive to form the effective context selector of the inner directive. If a
trait-set-selector is present on both directives, the trait-selector list of the outer directive is appended to the
trait-selector list of the inner directive after equivalent trait-selectors have been removed from the outer list.
Restrictions that apply to explicitly specified context selectors also apply to effective context selectors
constructed through this process.
The symbol name of a function definition that appears between a begindeclarevariant directive
and its paired enddeclarevariant directive shall be determined through the base language rules
after the name of the function has been augmented with a string that shall be determined according to the
effective context selector of the begindeclarevariant directive. The symbol names of
two definitions of a function shall be equal if and only if their effective context selectors are
equivalent.
If the context selector of a begindeclarevariant directive contains traits in the device or
implementation set that are known never to be compatible with an OpenMP context during the current
compilation, the preprocessed code that follows the begindeclarevariant directive up to the
matching enddeclarevariant directive shall be elided.
The OpenMP context for a direct call to a given base function is defined according to Section 2.3.1. If a
declare variant directive for the base function is visible at the call site and the static part of the context
selector that is associated with the declared function variant is compatible with the OpenMP context of the
call according to the matching rules defined in Section 2.3.3 then the variant is a replacement candidate to
be called instead of the base function. Replacement candidates are ordered in decreasing order of the score
associated with the context selector. If two replacement candidates have the same score then their order is
implementation defined.
The list of dynamic replacement candidates is the prefix of the sorted list of replacement candidates up to
and including the first candidate for which the corresponding context selector is static.
The first dynamic replacement candidate for which the corresponding context selector is compatible,
according to the matching rules defined in Section 2.3.3, is called instead of the base function. If no
compatible candidate exists then the base function is called.
Expressions that appear in the context selector of a match clause are evaluated if no prior dynamic
replacement candidate has a compatible context selector, and the number of times each expression is
evaluated is implementation defined. All variables referenced by these expressions are considered to be
referenced at the call site.
For calls to constexpr base functions that are evaluated in constant expressions, whether any variant
replacement occurs is implementation defined.
For indirect function calls that can be determined to call a particular base function, whether any variant
replacement occurs is unspecified.
For each adjust_args clause that is present on the selected variant the adjustment operation specified by
adjust-op will be applied to each of the arguments specified in the clause before being passed to the selected
variant.
If the adjust-op modifier is need_device_ptr, the arguments are converted to corresponding device
pointers of the default device. If an argument has the is_device_ptr property in its interoperabilityrequirementset then the argument will be passed as is. Otherwise, the argument will be converted in the
same manner that a use_device_ptr clause on a targetdata construct converts its pointer list
items into device pointers. If the argument cannot be converted into a device pointer then the NULL value
will be passed as the argument.
If the adjust-op modifier is nothing, the argument is passed to the selected variant without being
modified.
If an append_args clause is present on the matching directive then additional arguments
are passed in the call. The arguments are constructed according to any specified append-op
modifiers and are passed in the same order in which they are specified in the append_args
clause.
The interop operation constructs an argument of type omp_interop_t from the interoperabilityrequirementset of the encountering task.
The interop operation constructs an argument of type omp_interop_kind from the interoperabilityrequirementset of the encountering task.
The argument is constructed as if an interop construct with an init clause of interop-types was
specified. If the interoperabilityrequirementset contains one or more properties that could be used as
clauses for an interop construct of the interop-type type, the behavior is as if the corresponding clauses
would also be part of the aforementioned interop construct and those properties will be removed from
the interoperabilityrequirementset.
This argument is destroyed after the call to the selected variant returns, as if an interop construct with a
destroy clause was used with the same clauses that were used to initialize the argument.
Any differences that the specific OpenMP context requires in the prototype of the variant from the base
function prototype are implementation defined.
For the declarevariant directive, any expressions in the match clause are interpreted as if they
appeared in the scope of arguments of the base function.
Different declare variant directives may be specified for different declarations of the same base
function.
The function variant is determined by base language standard name lookup rules ([basic.lookup]) of
variant-func-id using the argument types at the call site after implementation-defined changes have been
made according to the OpenMP context.
For the declarevariant directive, the variant-func-id and any expressions in the match
clause are interpreted as if they appeared at the scope of the trailing return type of the base
function.
For the begindeclarevariant directive, any expressions in the match clause are interpreted at the
location of the directive.
The procedure to which base-proc-name refers is resolved at the location of the directive according to the
establishment rules for procedure names in the base language.
Restrictions
Restrictions to the declare variant directive are as follows:
Calling
functions
that
a
declare
variant
directive
determined
to
be
a
function
variant
directly
in
an
OpenMP
context
that
is
different
from
the
one
that
the
construct
selector
set
of
the
context
selector
specifies
is
non-conforming.
If
a
function
is
determined
to
be
a
function
variant
through
more
than
one
declare
variant
directive
then
the
construct
selector
set
of
their
context
selectors
must
be
the
same.
A
function
determined
to
be
a
function
variant
may
not
be
specified
as
a
base
function
in
another
declare
variant
directive.
All
variables
that
are
referenced
in
an
expression
that
appears
in
the
context
selector
of
a
match
clause
must
be
accessible
at
a
call
site
to
the
base
function
according
to
the
base
language
rules.
At
most
one
match
clause
can
appear
on
a
declarevariant
directive.
At
most
one
append_args
clause
can
appear
on
a
declarevariant
directive.
Each
argument
can
only
appear
in
a
single
adjust_args
clause
for
each
declarevariant
directive.
An
adjust_args
clause
or
append_args
clause
can
only
be
specified
if
the
dispatch
selector
of
the
construct
selector
set
appears
in
the
match
clause.
∙ The type of the function variant must be compatible with the type of the base function after the
implementation-defined transformation for its OpenMP context.
∙ Only the match clause can appear on a begindeclarevariant directive.
∙ The match clause of a begindeclarevariant directive may not contain a simdtrait-selector-name.
∙ Matching pairs of begindeclarevariant and enddeclarevariant directives shall either
encompass disjoint source ranges or they shall be perfectly nested.
∙ The declare variant directive cannot be specified for a virtual, defaulted or deleted function.
∙ The declare variant directive cannot be specified for a constructor or destructor.
∙ The declare variant directive cannot be specified for an immediate function.
∙ The function that a declare variant directive determined to be a function variant may not be an immediate
function.
∙ A match clause that appears on a begindeclaretarget directive must not contain a dynamic
context selector that references the this pointer.
∙ If an expression in the context selector that appears in a match clause references the this pointer, the
base function must be a non-static member function.
∙base-proc-name must not be a generic name, an entry name, the name of a procedure pointer, a dummy
procedure or a statement function.
∙ If base-proc-name is omitted then the declarevariant directive must appear in an interface block
or the specification part of a procedure.
∙ Any declarevariant directive must appear in the specification part of a subroutine subprogram,
function subprogram, or interface body to which it applies.
∙ If the directive is specified for a procedure that is declared via a procedure declaration statement, the
base-proc-name must be specified.
∙ The procedure base-proc-name must have an accessible explicit interface at the location of the
directive.
∙ Each argument that appears in a need_device_ptradjust-op must be of type C_PTR in the dummy
argument declaration.