// expected-note@-1 2 {{candidate template ignored: could not match 'DType' against 'HType'}}
// expected-note@-2 2 {{candidate template ignored: target attributes do not match}}
// Check explicit instantiation.
template __device__ __host__ DType overload_h_d(int a); // There's no HD template...
// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}}
template __device__ __host__ HType overload_h_d(int a); // There's no HD template...
// expected-error@-1 {{explicit instantiation of 'overload_h_d' does not refer to a function template, variable template, member function, member class, or static data member}}
template __device__ DType overload_h_d(int a); // OK. instantiates D
template __host__ HType overload_h_d(int a); // OK. instantiates H
// Check explicit specialization.
template <> __device__ __host__ DType overload_h_d(long a); // There's no HD template...
// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}}
template <> __device__ __host__ HType overload_h_d(long a); // There's no HD template...
// expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}}
template <> __device__ DType overload_h_d(long a); // OK. instantiates D
template <> __host__ HType overload_h_d(long a); // OK. instantiates H
// expected-error@-1 {{__device__ function 'overload_hd' cannot overload __host__ __device__ function 'overload_hd'}}
__device__ HDType overload_hd(int a); // OK.
// Verify that target attributes are taken into account when we
// explicitly specialize or instantiate function tempaltes.
template <> __host__ HType overload_hd(int a);
// expected-error@-1 {{no function template matches function template specialization 'overload_hd'}}
template __host__ HType overload_hd(long a);
// expected-error@-1 {{explicit instantiation of 'overload_hd' does not refer to a function template, variable template, member function, member class, or static data member}}
__host__ HType overload_hd(int a); // OK
template <typename T> __host__ T overload_h(T a); // expected-note {{previous declaration is here}}
template <typename T> __host__ __device__ T overload_h(T a);
// expected-error@-1 {{__host__ __device__ function 'overload_h' cannot overload __host__ function 'overload_h'}}
template <typename T> __device__ T overload_h(T a); // OK. D can overload H.
// constexpr functions are implicitly HD, but explicit
// instantiation/specialization must use target attributes as written.
template <typename T> constexpr T overload_ce_implicit_hd(T a) { return a+1; }
// expected-note@-1 3 {{candidate template ignored: target attributes do not match}}
// These will not match the template.
template __host__ __device__ int overload_ce_implicit_hd(int a);
// expected-error@-1 {{explicit instantiation of 'overload_ce_implicit_hd' does not refer to a function template, variable template, member function, member class, or static data member}}
template <> __host__ __device__ long overload_ce_implicit_hd(long a);
// expected-error@-1 {{no function template matches function template specialization 'overload_ce_implicit_hd'}}
template <> __host__ __device__ constexpr long overload_ce_implicit_hd(long a);
// expected-error@-1 {{no function template matches function template specialization 'overload_ce_implicit_hd'}}
// These should work, because template matching ignores the implicit
// HD attributes the compiler gives to constexpr functions/templates,
// so 'overload_ce_implicit_hd' template will match __host__ functions
// only.
template __host__ int overload_ce_implicit_hd(int a);
template <> __host__ long overload_ce_implicit_hd(long a);