Hi Nick, Jean,
Thanks for bringing this topic up. I must confess that I am not an expert in target and device handling in OpenMP and we have not yet finalized the approach for handling target regions.
But here is what I can share, the GPU folks from Nvidia/AMD and Johannes (who implemented this in Clang) can correct me here.
Vendors provide device libraries (https://docs.nvidia.com/cuda/libdevice-users-guide/__nv_sin.html) with math function support. The compiler can/should convert calls to the math library functions in a target region with calls to the device library functions. OpenMP provides the declare variant directive with which specialized variants of functions and the context in which these functions should be used can be specified. This mechanism can be used in a header file and each vendor can declare variants (with calls to their device library) for each math function. If the frontend supports OpenMP declare variant handling then the calls to math library functions are automatically converted to calls to device library functions.
For e.g: Clang has the following,
1) clang/lib/Headers/openmp_wrappers/math.h
#pragma omp begin declare variant match( \
device = {arch(nvptx, nvptx64)}, implementation = {extension(match_any)})
#define __CUDA__
#define __OPENMP_NVPTX__
#include <__clang_cuda_math.h>
#undef __OPENMP_NVPTX__
#undef __CUDA__
#pragma omp end declare variant
2) clang/lib/Headers/__clang_cuda_math.h
__DEVICE__ double sin(double __a) { return __nv_sin(__a); }
First, I can confirm this.
Second, I am unsure if this is "necessary" for Fortran as well.
One of the tricky parts for C/C++ is that we want to get the system math
headers and the device math headers as both might provide unique,
non-standard functions.
From the LLVM perspective, not all math functions have generic LLVM
intrinsics and you cannot always use the generic LLVM intrinsics as they
have requirements wrt. the floating point environment. There are usually
some target intrinsics, e.g., `@llvm.nvvm.fabs.f`, but I'm unsure if
everything has an `nvvm` intrinsic or if certain things remain function
calls. At the end, it hardly matters anyway.
If there is any question on how Clang handles this or just generic
things about this, please let me know 
Thanks,
Johannes