This post assumes and requires that you have read the introductory post to this series which also includes a table of content. With that out of the way let’s look at restrictions around function declarators and calls.
For a function declarator with restrict(amp) (or restrict(amp, cpu)), besides the obvious rules that its return type and parameter types must be supported for amp, there are some extra rules as following:
· It is not allowed to have a trailing ellipsis (…) in its parameter list;
· It is not allowed to have an exception specification (including the empty throw() and __declspec(nothrow));
· It is not allowed to have extern”C” linkage when it has multiple restriction specifiers;
· It is not allowed to be virtual;
Variadic functions require direct support from the C runtime, which is not amp-compatible in C++ AMP v1. In addition, C++ AMP does not support exception handling, therefore, an exception cannot be thrown inside an amp restricted function, and neither can the function have exception specifications. The empty exception specification is harmless, but we disallow it for consistency. The limitation on extern “C” linkage is due to the fact that the current C++ AMP implementation generates multiple symbols for a function with multiple restriction specifiers, which cannot be done for extern “C” functions since they do not have C++ decorated names and thus those symbols cannot be differentiated. Finally, the non-virtual requirement is due to the lack of hardware function call support.
Within an amp-restricted function, the target of a function-like invocation (e.g., functions, member functions, object constructors & destructors, operators) must be amp-restricted too. Following the amp type restrictions, we know that it cannot be a virtual function or a function pointer/pointer to member function either. In addition, due to the lack of hardware stack and function call support, it is not allowed for a function to recursively invoke itself directly or via other functions indirectly.