================
@@ -0,0 +1,541 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fsyntax-only 
-fsycl-is-host -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -fsyntax-only 
-fsycl-is-device -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 -fsyntax-only 
-fsycl-is-host -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 -fsyntax-only 
-fsycl-is-device -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -fsyntax-only 
-fsycl-is-host -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -fsyntax-only 
-fsycl-is-device -verify %s
+
+// Test overload resolution for implicit calls to sycl_kernel_launch<KN>(...)
+// synthesized for functions declared with the sycl_kernel_entry_point
+// attribute.
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Valid declarations.
+////////////////////////////////////////////////////////////////////////////////
+
+// A unique kernel name type is required for each declared kernel entry point.
+template<int, int = 0> struct KN;
+
+// A generic kernel object type.
+template<int, int = 0>
+struct KT {
+  void operator()() const;
+};
+
+
+// sycl_kernel_launch as function template at namespace scope.
+namespace ok1 {
+  template<typename KN, typename... Ts>
+  void sycl_kernel_launch(const char *, Ts...);
+  [[clang::sycl_kernel_entry_point(KN<1>)]]
+  void skep(KT<1> k) {
+    k();
+  }
+}
+
+// sycl_kernel_launch as function template at namespace scope with default
+// template arguments and default function arguments..
+namespace ok2 {
+  template<typename KN, typename T = int>
+  void sycl_kernel_launch(const char *, KT<2>, T = 2);
+  [[clang::sycl_kernel_entry_point(KN<2>)]]
+  void skep(KT<2> k) {
+    k();
+  }
+}
+
+// sycl_kernel_launch as overload set.
+namespace ok3 {
+  template<typename KN>
+  void sycl_kernel_launch(const char *);
+  template<typename KN, typename... Ts>
+  void sycl_kernel_launch(const char *, Ts...);
+  [[clang::sycl_kernel_entry_point(KN<3>)]]
+  void skep(KT<3> k) {
+    k();
+  }
+}
+
+// sycl_kernel_launch as static member function template.
+namespace ok4 {
+  struct handler {
+  private:
+    template<typename KN, typename... Ts>
+    static void sycl_kernel_launch(const char *, Ts...);
+  public:
+    [[clang::sycl_kernel_entry_point(KN<4,0>)]]
+    static void skep(KT<4,0> k) {
+      k();
+    }
+    [[clang::sycl_kernel_entry_point(KN<4,1>)]]
+    void skep(KT<4,1> k) {
+      k();
+    }
+  };
+}
+
+// sycl_kernel_launch as non-static member function template.
+namespace ok5 {
+  struct handler {
+  private:
+    template<typename KN, typename... Ts>
+    void sycl_kernel_launch(const char *, Ts...);
+  public:
+    [[clang::sycl_kernel_entry_point(KN<5>)]]
+    void skep(KT<5> k) {
+      k();
+    }
+  };
+}
+
+#if __cplusplus >= 202302L
+// sycl_kernel_launch as non-static member function template with explicit
+// object parameter.
+namespace ok6 {
+  struct handler {
+  private:
+    template<typename KN, typename... Ts>
+    void sycl_kernel_launch(this handler self, const char *, Ts...);
+  public:
+    [[clang::sycl_kernel_entry_point(KN<6>)]]
+    void skep(KT<6> k) {
+      k();
+    }
+  };
+}
+#endif
+
+// sycl_kernel_launch as variable template.
+namespace ok7 {
+  template<typename KN>
+  struct launcher {
+    template<typename... Ts>
+    void operator()(const char *, Ts...);
+  };
+  template<typename KN>
+  launcher<KN> sycl_kernel_launch;
+  [[clang::sycl_kernel_entry_point(KN<7>)]]
+  void skep(KT<7> k) {
+    k();
+  }
+}
+
+#if __cplusplus >= 202302L
+// sycl_kernel_launch as variable template with static call operator template.
+namespace ok8 {
+  template<typename KN>
+  struct launcher {
+    template<typename... Ts>
+    static void operator()(const char *, Ts...);
+  };
+  template<typename KN>
+  launcher<KN> sycl_kernel_launch;
+  [[clang::sycl_kernel_entry_point(KN<8>)]]
+  void skep(KT<8> k) {
+    k();
+  }
+}
+#endif
+
+#if __cplusplus >= 202302L
+// sycl_kernel_launch as variable template with call operator template with
+// explicit object parameter.
+namespace ok9 {
+  template<typename KN>
+  struct launcher {
+    template<typename... Ts>
+    void operator()(this launcher self, const char *, Ts...);
+  };
+  template<typename KN>
+  launcher<KN> sycl_kernel_launch;
+  [[clang::sycl_kernel_entry_point(KN<9>)]]
+  void skep(KT<9> k) {
+    k();
+  }
+}
+#endif
+
+// sycl_kernel_launch as base class non-static member function template.
+namespace ok10 {
+  template<typename Derived>
+  struct base_handler {
+  protected:
+    template<typename KN, typename... Ts>
+    void sycl_kernel_launch(const char *, Ts...);
+  };
+  struct handler : protected base_handler<handler> {
+  public:
+    [[clang::sycl_kernel_entry_point(KN<10>)]]
+    void skep(KT<10> k) {
+      k();
+    }
+  };
+}
+
+// sycl_kernel_launch with non-reference parameters.
+namespace ok11 {
+  template<typename KN, typename... Ts>
+  void sycl_kernel_launch(const char *, Ts...);
+  struct move_only {
+    move_only(move_only&&) = default;
+  };
+  [[clang::sycl_kernel_entry_point(KN<11>)]]
+  void skep(KT<11> k, move_only) {
+    k();
+  }
+}
+
+// sycl_kernel_launch with forward reference parameters.
+namespace ok12 {
+  template<typename KN, typename... Ts>
+  void sycl_kernel_launch(const char *, Ts &&...);
+  struct non_copyable {
+    non_copyable(const non_copyable&) = delete;
+  };
+  struct non_moveable {
+    non_moveable(non_moveable&&) = delete;
+  };
+  struct move_only {
+    move_only(move_only&&) = default;
+  };
+  [[clang::sycl_kernel_entry_point(KN<12>)]]
+  void skep(KT<12> k, non_copyable, non_moveable, move_only) {
+    k();
+  }
+}
+
+// ADL for sycl_kernel_launch.
+namespace ok13 {
+  template<typename KN, typename KT, typename T>
+  [[clang::sycl_kernel_entry_point(KN)]]
+  void skep(KT k, T t) {
+    k();
+  }
+  namespace nested {
+    template<typename KN, typename... Ts>
+    void sycl_kernel_launch(const char *, Ts...);
+    struct S13 {};
+  }
+  template void skep<KN<13>>(KT<13>, nested::S13);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Invalid declarations.
+////////////////////////////////////////////////////////////////////////////////
+
+// A unique kernel name type is required for each declared kernel entry point.
+template<int, int = 0> struct BADKN;
+
+// A generic kernel object type.
+template<int, int = 0>
+struct BADKT {
+  void operator()() const;
+};
+
+
+// Undeclared sycl_kernel_launch identifier from non-template function.
+namespace bad1 {
+  // expected-error@+3 {{use of undeclared identifier 'sycl_kernel_launch'}}
+  // expected-note-re@+1 {{in implicit call to 'sycl_kernel_launch' with 
template argument 'BADKN<1>' and function arguments (lvalue of type 'const 
char[{{[0-9]*}}]', xvalue of type 'BADKT<1>') required here}}
+  [[clang::sycl_kernel_entry_point(BADKN<1>)]]
+  void skep(BADKT<1> k) {
+    k();
+  }
+}
+
+// Undeclared sycl_kernel_launch identifier from function template.
+namespace bad2 {
+  // expected-error@+4 {{use of undeclared identifier 'sycl_kernel_launch'}}
+  // expected-note-re@+2 {{in implicit call to 'sycl_kernel_launch' with 
template argument 'BADKN<2>' and function arguments (lvalue of type 'const 
char[{{[0-9]*}}]', xvalue of type 'BADKT<2>') required here}}
+  template<typename KN, typename KT>
+  [[clang::sycl_kernel_entry_point(KN)]]
+  void skep(KT k) {
+    k();
+  }
+  // expected-note@+1 {{in instantiation of function template specialization 
'bad2::skep<BADKN<2>, BADKT<2>>' requested here}}
+  template void skep<BADKN<2>>(BADKT<2>);
+}
+
+// No matching function for call to sycl_kernel_launch; not a template.
+namespace bad3 {
+  // expected-note@+1 {{declared as a non-template here}}
+  void sycl_kernel_launch(const char *, BADKT<3>);
+  // expected-error@+3 {{'sycl_kernel_launch' does not refer to a template}}
+  // expected-note@+1 {{in implicit call to 'sycl_kernel_launch' with template 
argument 'BADKN<3>' required here}}
+  [[clang::sycl_kernel_entry_point(BADKN<3>)]]
+  void skep(BADKT<3> k) {
+    k();
+  }
+}
+
+// No matching function for call to sycl_kernel_launch; not enough arguments.
+namespace bad4 {
+  // expected-note@+2 {{candidate function template not viable: requires 2 
arguments, but 1 was provided}}
+  template<typename KN, typename KT>
+  void sycl_kernel_launch(const char *, KT);
+  // expected-error@+4 {{no matching function for call to 
'sycl_kernel_launch'}}
+  // expected-note-re@+2 {{in implicit call to 'sycl_kernel_launch' with 
template argument 'BADKN<4>' and function arguments (lvalue of type 'const 
char[{{[0-9]*}}]') required here}}
+  template<typename KN>
+  [[clang::sycl_kernel_entry_point(KN)]]
+  void skep() {}
+  // expected-note@+1 {{in instantiation of function template specialization 
'bad4::skep<BADKN<4>>' requested here}}
+  template void skep<BADKN<4>>();
+}
+
+// No matching function for call to sycl_kernel_launch; too many arguments.
+namespace bad5 {
+  // expected-note@+2 {{candidate function template not viable: requires 2 
arguments, but 3 were provided}}
+  template<typename KN, typename KT>
+  void sycl_kernel_launch(const char *, KT);
+  // expected-error@+4 {{no matching function for call to 
'sycl_kernel_launch'}}
+  // expected-note-re@+2 {{in implicit call to 'sycl_kernel_launch' with 
template argument 'BADKN<5>' and function arguments (lvalue of type 'const 
char[{{[0-9]*}}]', xvalue of type 'BADKT<5>', xvalue of type 'int') required 
here}}
----------------
tahonermann wrote:

I recognize that this is novel and I welcome suggestions for how to do better.

The reason I went with this approach is because there is no source line to 
refer to, so a diagnostic can't reference a line of code for the (SYCL RT) 
programmer to refer to in order to understand how arguments are passed. 
Debugging an overload resolution failure requires knowing the number of 
arguments, their types, and their value categories. The diagnostic notes for 
candidates don't necessarily suffice on their own to understand what is going 
wrong without this additional information.

https://github.com/llvm/llvm-project/pull/152403
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to