================
@@ -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

Reply via email to