\begin{ccppspecific}[4ex]
\section{C/C++ Attributes}
\label{sec:attributes}
\index{directive syntax!attribute, C/C++}
\index{attribute syntax, C/C++}

OpenMP directives for C/C++ can also be specified with 
the \kcode{directive} extension for the C23 and C++11 standard \plc{attributes}.
%https://en.cppreference.com/w/cpp/language/attributes

The example below shows two ways to parallelize a \bcode{for} loop using the \kcode{\#pragma} syntax.
The first pragma uses the combined \kcode{parallel for} directive, and the second
applies the uncombined closely nested directives, \kcode{parallel} and \kcode{for}, directly to the same statement. 
These are labeled PRAG 1-3.

Using the attribute syntax, the same construct in PRAG 1
is applied in two different ways in attribute form, as shown in the ATTR 1 and ATTR 2 sections.
In ATTR 1 the attribute syntax is used with the \kcode{omp ::} namespace form.
In ATTR 2 the attribute syntax is used with the \kcode{using omp :} namespace
form available for C++ only.

Next, parallelization is attempted by applying directives using two different syntaxes.
For ATTR 3 and PRAG 4, the loop parallelization will fail to compile because multiple directives that
apply to the same statement must all use either the attribute syntax or the pragma syntax.
The lines have been commented out and labeled INVALID.

While multiple attributes may be applied to the same statement,
compilation may fail if the ordering of the directive matters.
For the ATTR 4-5 loop parallelization, the \kcode{parallel} directive precedes 
the \kcode{for} directive, but the compiler may reorder consecutive attributes.
If the directives are reversed, compilation will fail.

The attribute directive of the ATTR 6 section resolves the previous problem (in ATTR 4-5).
Here, the \kcode{sequence} attribute is used to apply ordering to the
directives of ATTR 4-5, using the \kcode{omp ::} namespace qualifier. (The
\kcode{using omp :} namespace form is not available for the \kcode{sequence} attribute.) 
Note, for the \kcode{sequence} attribute a comma must separate the \kcode{directive} extensions.


The last 3 pairs of sections (PRAG DECL 1-2, 3-4, and 5-6) show cases where 
directive ordering does not matter for \kcode{declare simd} directives. 

In section PRAG DECL 1-2, the two loops use different SIMD forms of the \ucode{P} function
(one with \kcode{simdlen(\ucode{4})} and the other with \kcode{simdlen(\ucode{8})}), 
as prescribed by the two different \kcode{declare simd} directives
applied to the \ucode{P} function definitions (at the beginning of the code). 
The directives use the pragma syntax, and order is not important. 
For the next set of loops 
(PRAG DECL 3-4) that use the \ucode{Q} function, the attribute syntax is 
used for the \kcode{declare simd} directives. 
The result is compliant code since directive order is irrelevant.
Sections ATTR DECL 5-6 are included for completeness. Here, the attribute 
form of the \kcode{simd} directive is used for loops calling the \ucode{Q} function, 
in combination with the attribute form of the \kcode{declare simd} 
directives declaring the variants for \ucode{Q}.

\topmarker{C/C++}
\cppnexample[6.0]{directive_syntax_attribute}{1}

\topmarker{C/C++}
The following code snippets show how to use the \kcode{omp::decl} attribute
as an alternative way for specifying declarative directives.
The \kcode{omp::decl} attribute can be embedded in the base
language declarations as shown for variables in Cases 1 and 2, 
for function in Case 3, and for C++ template in Case 4.
The variable and function name lists are implied from where
the attributes are specified.

In Case 1, the prefix attribute applies
to all variables (\ucode{u} and \ucode{v}) in the declaration;
in Case 2, the postfix attribute applies to the associated variable
(\ucode{a} as the directive argument for the \kcode{declare_target} directive,
and \ucode{b} as the clause argument for the \kcode{link} clause
on \kcode{declare_target});
in Case 3, the prefix attribute applies to the function (\ucode{f}).
The comma to separate directive name (\kcode{declare_target}) and 
clause name (\kcode{link}) in
the \kcode{omp::decl} attribute specifier in Case 2 is optional.

Case 4 shows the use of \kcode{omp::decl(declare_target)} for 
a C++ template function definition
and its equivalent using the delimited
\kcode{begin}/\kcode{end declare_target} pragma form.

\cppnexample[6.0]{directive_syntax_attribute}{2}
\end{ccppspecific}
