function-template-overload.cu 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s
  2. // RUN: %clang_cc1 -std=c++11 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s
  3. #include "Inputs/cuda.h"
  4. struct HType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'DType'}}
  5. struct DType {}; // expected-note-re 6 {{candidate constructor {{.*}} not viable: no known conversion from 'HType'}}
  6. struct HDType {};
  7. template <typename T> __host__ HType overload_h_d(T a) { return HType(); }
  8. // expected-note@-1 2 {{candidate template ignored: could not match 'HType' against 'DType'}}
  9. // expected-note@-2 2 {{candidate template ignored: target attributes do not match}}
  10. template <typename T> __device__ DType overload_h_d(T a) { return DType(); }
  11. // expected-note@-1 2 {{candidate template ignored: could not match 'DType' against 'HType'}}
  12. // expected-note@-2 2 {{candidate template ignored: target attributes do not match}}
  13. // Check explicit instantiation.
  14. template __device__ __host__ DType overload_h_d(int a); // There's no HD template...
  15. // 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}}
  16. template __device__ __host__ HType overload_h_d(int a); // There's no HD template...
  17. // 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}}
  18. template __device__ DType overload_h_d(int a); // OK. instantiates D
  19. template __host__ HType overload_h_d(int a); // OK. instantiates H
  20. // Check explicit specialization.
  21. template <> __device__ __host__ DType overload_h_d(long a); // There's no HD template...
  22. // expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}}
  23. template <> __device__ __host__ HType overload_h_d(long a); // There's no HD template...
  24. // expected-error@-1 {{no function template matches function template specialization 'overload_h_d'}}
  25. template <> __device__ DType overload_h_d(long a); // OK. instantiates D
  26. template <> __host__ HType overload_h_d(long a); // OK. instantiates H
  27. // Can't overload HD template with H or D template, though
  28. // non-template functions are OK.
  29. template <typename T> __host__ __device__ HDType overload_hd(T a) { return HDType(); }
  30. // expected-note@-1 {{previous declaration is here}}
  31. // expected-note@-2 2 {{candidate template ignored: could not match 'HDType' against 'HType'}}
  32. template <typename T> __device__ HDType overload_hd(T a);
  33. // expected-error@-1 {{__device__ function 'overload_hd' cannot overload __host__ __device__ function 'overload_hd'}}
  34. __device__ HDType overload_hd(int a); // OK.
  35. // Verify that target attributes are taken into account when we
  36. // explicitly specialize or instantiate function templates.
  37. template <> __host__ HType overload_hd(int a);
  38. // expected-error@-1 {{no function template matches function template specialization 'overload_hd'}}
  39. template __host__ HType overload_hd(long a);
  40. // 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}}
  41. __host__ HType overload_hd(int a); // OK
  42. template <typename T> __host__ T overload_h(T a); // expected-note {{previous declaration is here}}
  43. template <typename T> __host__ __device__ T overload_h(T a);
  44. // expected-error@-1 {{__host__ __device__ function 'overload_h' cannot overload __host__ function 'overload_h'}}
  45. template <typename T> __device__ T overload_h(T a); // OK. D can overload H.
  46. template <typename T> __host__ HType overload_h_d2(T a) { return HType(); }
  47. template <typename T> __host__ __device__ HDType overload_h_d2(T a) { return HDType(); }
  48. template <typename T1, typename T2 = int> __device__ DType overload_h_d2(T1 a) { T1 x; T2 y; return DType(); }
  49. // constexpr functions are implicitly HD, but explicit
  50. // instantiation/specialization must use target attributes as written.
  51. template <typename T> constexpr T overload_ce_implicit_hd(T a) { return a+1; }
  52. // expected-note@-1 3 {{candidate template ignored: target attributes do not match}}
  53. // These will not match the template.
  54. template __host__ __device__ int overload_ce_implicit_hd(int a);
  55. // 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}}
  56. template <> __host__ __device__ long overload_ce_implicit_hd(long a);
  57. // expected-error@-1 {{no function template matches function template specialization 'overload_ce_implicit_hd'}}
  58. template <> __host__ __device__ constexpr long overload_ce_implicit_hd(long a);
  59. // expected-error@-1 {{no function template matches function template specialization 'overload_ce_implicit_hd'}}
  60. // These should work, because template matching ignores the implicit
  61. // HD attributes the compiler gives to constexpr functions/templates,
  62. // so 'overload_ce_implicit_hd' template will match __host__ functions
  63. // only.
  64. template __host__ int overload_ce_implicit_hd(int a);
  65. template <> __host__ long overload_ce_implicit_hd(long a);
  66. template float overload_ce_implicit_hd(float a);
  67. template <> float* overload_ce_implicit_hd(float *a);
  68. template <> constexpr double overload_ce_implicit_hd(double a) { return a + 3.0; };
  69. __host__ void hf() {
  70. overload_hd(13);
  71. overload_ce_implicit_hd('h'); // Implicitly instantiated
  72. overload_ce_implicit_hd(1.0f); // Explicitly instantiated
  73. overload_ce_implicit_hd(2.0); // Explicitly specialized
  74. HType h = overload_h_d(10);
  75. HType h2i = overload_h_d2<int>(11);
  76. HType h2ii = overload_h_d2<int>(12);
  77. // These should be implicitly instantiated from __host__ template returning HType.
  78. DType d = overload_h_d(20); // expected-error {{no viable conversion from 'HType' to 'DType'}}
  79. DType d2i = overload_h_d2<int>(21); // expected-error {{no viable conversion from 'HType' to 'DType'}}
  80. DType d2ii = overload_h_d2<int>(22); // expected-error {{no viable conversion from 'HType' to 'DType'}}
  81. }
  82. __device__ void df() {
  83. overload_hd(23);
  84. overload_ce_implicit_hd('d'); // Implicitly instantiated
  85. overload_ce_implicit_hd(1.0f); // Explicitly instantiated
  86. overload_ce_implicit_hd(2.0); // Explicitly specialized
  87. // These should be implicitly instantiated from __device__ template returning DType.
  88. HType h = overload_h_d(10); // expected-error {{no viable conversion from 'DType' to 'HType'}}
  89. HType h2i = overload_h_d2<int>(11); // expected-error {{no viable conversion from 'DType' to 'HType'}}
  90. HType h2ii = overload_h_d2<int>(12); // expected-error {{no viable conversion from 'DType' to 'HType'}}
  91. DType d = overload_h_d(20);
  92. DType d2i = overload_h_d2<int>(21);
  93. DType d2ii = overload_h_d2<int>(22);
  94. }