================ @@ -0,0 +1,157 @@ +// 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 S6 {}; } +template<typename> +[[clang::sycl_external]] void func6() {} +template void func6<S6>(); +// expected-note@-1{{in instantiation of function template specialization 'func6<(anonymous namespace)::S6>' requested here}} + +// 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 2{{'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>() {} +// expected-note@-1{{in instantiation of function template specialization 'func7<(anonymous namespace)::S7>' requested here}} + +// 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}} + +// FIXME: The implicit instantiation of func9<S9>() is valid. +namespace { struct S9 {}; } +struct T9 { + using type = S9; +}; +// expected-error@+2{{'clang::sycl_external' can only be applied to functions with external linkage}} +template<typename> +[[clang::sycl_external]] void func9() {} +// expected-note@+3{{in instantiation of function template specialization 'func9<(anonymous namespace)::S9>' requested here}} +template<typename T> +[[clang::sycl_external]] void test_func9() { + func9<typename T::type>(); +} +// expected-note@+1{{in instantiation of function template specialization 'test_func9<T9>' requested here}} +template void test_func9<T9>(); // FIXME: don't diagnose implicit instantiation of func9<S9>(). + +// 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@+2{{previous definition is here}} +// expected-note@+1{{previous declaration is here}} +void hoo() {} +// expected-warning@+2{{attribute declaration must precede definition}} +// expected-warning@+1{{'clang::sycl_external' attribute does not appear on the first declaration}} +[[clang::sycl_external]] void hoo(); ---------------- tahonermann wrote:
The `attribute declaration must precede definition` warning is not desirable since we don't actually have such a requirement. The following addition to `checkNewAttributesAfterDef()` in `clang/lib/Sema/SemaDecl.cpp` will disable it. You'll see special handling there for the `sycl_kernel_entry_point` attribute as well. ``` diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 34f4e83e74e6..995283a344e4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3068,6 +3068,10 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { cast<SYCLKernelEntryPointAttr>(NewAttribute)->setInvalidAttr(); ++I; continue; + } else if (isa<SYCLExternalAttr>(NewAttribute)) { + // SYCLExternalAttr may be added after a definition. + ++I; + continue; } S.Diag(NewAttribute->getLocation(), ``` ```suggestion // 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(); ``` https://github.com/llvm/llvm-project/pull/140282 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits