blob: ebda94e7d5030776ad1bcf6ae7c7bd24109b0d6f [file] [log] [blame] [edit]
// 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<typename> [[clang::sycl_external]] void func5();
template<> [[clang::sycl_external]] void func5<S5>() {}
namespace { struct S6 {}; }
template<typename>
[[clang::sycl_external]] void func6() {}
template void func6<S6>();
// 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<typename>
[[clang::sycl_external]] void func7();
template<> void func7<S7>() {}
// 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<typename>
void func8();
template<> [[clang::sycl_external]] void func8<S8>() {}
// 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<typename>
[[clang::sycl_external]] void func9() {}
template<typename T>
[[clang::sycl_external]] void test_func9() {
func9<typename T::type>();
}
template void test_func9<T9>();
// 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<typename T>
[[clang::sycl_external]] void fun6(T) {}
template void fun6(int *);
template<> [[clang::sycl_external]] void fun6<long*>(long *) {}
#if CPP20
[[clang::sycl_external]] consteval int func();
#endif