================
@@ -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}}
----------------
erichkeane wrote:

I'm VERY much not a fan of how this is being displayed/printed here.  This is 
really kind of an awful way of presenting this information.  WE have planty of 
ways of printing argument lists, inventing a new one isn't a good idea.

@AaronBallman 

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