// RUN: %clang_cc1 -fsycl-is-host -std=c++17 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsycl-is-device -std=c++17 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsycl-is-host -std=c++20 -fsyntax-only -verify -DCPP20 %s // RUN: %clang_cc1 -fsycl-is-device -std=c++20 -fsyntax-only -verify -DCPP20 %s // Semantic tests for the sycl_external attribute. // expected-error@+1{{'clang::sycl_external' can only be applied to functions with external linkage}} [[clang::sycl_external]] static void func1() {} // expected-error@+2{{'clang::sycl_external' can only be applied to functions with external linkage}} namespace { [[clang::sycl_external]] void func2() {} } // expected-error@+2{{'clang::sycl_external' can only be applied to functions with external linkage}} namespace { struct S4 {}; } [[clang::sycl_external]] void func4(S4) {} // expected-error@+3{{'clang::sycl_external' can only be applied to functions with external linkage}} namespace { struct S5 {}; } template [[clang::sycl_external]] void func5(); template<> [[clang::sycl_external]] void func5() {} namespace { struct S6 {}; } template [[clang::sycl_external]] void func6() {} template void func6(); // FIXME: C++23 [temp.expl.spec]p12 states: // ... Similarly, attributes appearing in the declaration of a template // have no effect on an explicit specialization of that template. // Clang currently instantiates and propagates attributes from a function // template to its explicit specializations resulting in the following // spurious error. // expected-error@+3{{'clang::sycl_external' can only be applied to functions with external linkage}} namespace { struct S7 {}; } template [[clang::sycl_external]] void func7(); template<> void func7() {} // FIXME: The explicit function template specialization appears to trigger // instantiation of a declaration from the primary template without the // attribute leading to a spurious diagnostic that the sycl_external // attribute is not present on the first declaration. namespace { struct S8 {}; } template void func8(); template<> [[clang::sycl_external]] void func8() {} // expected-warning@-1{{'clang::sycl_external' attribute does not appear on the first declaration}} // expected-error@-2{{'clang::sycl_external' can only be applied to functions with external linkage}} // expected-note@-3{{previous declaration is here}} namespace { struct S9 {}; } struct T9 { using type = S9; }; template [[clang::sycl_external]] void func9() {} template [[clang::sycl_external]] void test_func9() { func9(); } template void test_func9(); // The first declaration of a SYCL external function is required to have this attribute. // expected-note@+1{{previous declaration is here}} int foo(); // expected-warning@+1{{'clang::sycl_external' attribute does not appear on the first declaration}} [[clang::sycl_external]] int foo(); // expected-note@+1{{previous declaration is here}} void goo(); // expected-warning@+1{{'clang::sycl_external' attribute does not appear on the first declaration}} [[clang::sycl_external]] void goo(); void goo() {} // expected-note@+1{{previous declaration is here}} void hoo() {} // expected-warning@+1{{'clang::sycl_external' attribute does not appear on the first declaration}} [[clang::sycl_external]] void hoo(); // expected-note@+1{{previous declaration is here}} void joo(); void use_joo() { joo(); } // expected-warning@+1{{'clang::sycl_external' attribute does not appear on the first declaration}} [[clang::sycl_external]] void joo(); // Subsequent declarations of a SYCL external function may optionally specify this attribute. [[clang::sycl_external]] int boo(); [[clang::sycl_external]] int boo(); // OK int boo(); // OK class C { [[clang::sycl_external]] void member(); }; // expected-error@+1{{'clang::sycl_external' cannot be applied to the 'main' function}} [[clang::sycl_external]] int main() { return 0; } // expected-error@+2{{'clang::sycl_external' cannot be applied to an explicitly deleted function}} class D { [[clang::sycl_external]] void mdel() = delete; }; // expected-error@+1{{'clang::sycl_external' cannot be applied to an explicitly deleted function}} [[clang::sycl_external]] void del() = delete; struct NonCopyable { ~NonCopyable() = delete; [[clang::sycl_external]] NonCopyable(const NonCopyable&) = default; }; class A { [[clang::sycl_external]] A() {} [[clang::sycl_external]] void mf() {} [[clang::sycl_external]] static void smf(); }; class B { public: [[clang::sycl_external]] virtual void foo() {} [[clang::sycl_external]] virtual void bar() = 0; }; [[clang::sycl_external]] void B::bar() {} [[clang::sycl_external]] constexpr int square(int x); // Devices that do not support the generic address space shall not specify // a raw pointer or reference type as the return type or as a parameter type. [[clang::sycl_external]] int *fun0(); [[clang::sycl_external]] int &fun1(); [[clang::sycl_external]] int &&fun2(); [[clang::sycl_external]] void fun3(int *); [[clang::sycl_external]] void fun4(int &); [[clang::sycl_external]] void fun5(int &&); template [[clang::sycl_external]] void fun6(T) {} template void fun6(int *); template<> [[clang::sycl_external]] void fun6(long *) {} #if CPP20 [[clang::sycl_external]] consteval int func(); #endif