// Tests without serialization: // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-device \ // RUN: -ast-dump %s \ // RUN: | FileCheck --match-full-lines %s // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-host \ // RUN: -ast-dump %s \ // RUN: | FileCheck --match-full-lines %s // // Tests with serialization: // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-device \ // RUN: -emit-pch -o %t %s // RUN: %clang_cc1 -x c++ -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-device \ // RUN: -include-pch %t -ast-dump-all /dev/null \ // RUN: | sed -e "s/ //" -e "s/ imported//" \ // RUN: | FileCheck --match-full-lines %s // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-host \ // RUN: -emit-pch -o %t %s // RUN: %clang_cc1 -x c++ -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-host \ // RUN: -include-pch %t -ast-dump-all /dev/null \ // RUN: | sed -e "s/ //" -e "s/ imported//" \ // RUN: | FileCheck --match-full-lines %s // These tests validate the AST produced for functions declared with the // sycl_kernel_entry_point attribute. // CHECK: TranslationUnitDecl {{.*}} // A unique kernel name type is required for each declared kernel entry point. template struct KN; [[clang::sycl_kernel_entry_point(KN<1>)]] void skep1() { } // CHECK: |-FunctionDecl {{.*}} skep1 'void ()' // CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KN<1> using KN2 = KN<2>; [[clang::sycl_kernel_entry_point(KN2)]] void skep2() { } // CHECK: |-FunctionDecl {{.*}} skep2 'void ()' // CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KN2 template using KNT = KN; [[clang::sycl_kernel_entry_point(KNT<3>)]] void skep3() { } // CHECK: |-FunctionDecl {{.*}} skep3 'void ()' // CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KNT<3> template [[clang::sycl_kernel_entry_point(KNT)]] void skep4(F f) { f(); } // CHECK: |-FunctionTemplateDecl {{.*}} skep4 // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} KNT // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} F // CHECK-NEXT: | |-FunctionDecl {{.*}} skep4 'void (F)' // CHECK: | | `-SYCLKernelEntryPointAttr {{.*}} KNT void test_skep4() { skep4>([]{}); } // CHECK: | `-FunctionDecl {{.*}} used skep4 'void ((lambda at {{.*}}))' implicit_instantiation // CHECK-NEXT: | |-TemplateArgument type 'KN<4>' // CHECK: | |-TemplateArgument type '(lambda at {{.*}})' // CHECK: | `-SYCLKernelEntryPointAttr {{.*}} struct KN<4> // CHECK-NEXT: |-FunctionDecl {{.*}} test_skep4 'void ()' template [[clang::sycl_kernel_entry_point(KNT)]] void skep5(T) { } // CHECK: |-FunctionTemplateDecl {{.*}} skep5 // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} KNT // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} T // CHECK-NEXT: | |-FunctionDecl {{.*}} skep5 'void (T)' // CHECK: | | `-SYCLKernelEntryPointAttr {{.*}} KNT // Checks for the explicit template instantiation declaration below. // CHECK: | `-FunctionDecl {{.*}} skep5 'void (int)' explicit_instantiation_definition // CHECK-NEXT: | |-TemplateArgument type 'KN<5, 4>' // CHECK: | |-TemplateArgument type 'int' // CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KN<5, 4> // FIXME: C++23 [temp.expl.spec]p12 states: // FIXME: ... Similarly, attributes appearing in the declaration of a template // FIXME: have no effect on an explicit specialization of that template. // FIXME: Clang currently instantiates and propagates attributes from a function // FIXME: template to its explicit specializations resulting in the following // FIXME: explicit specialization having an attribute incorrectly attached. template<> void skep5>(short) { } // CHECK: |-FunctionDecl {{.*}} prev {{.*}} skep5 'void (short)' explicit_specialization // CHECK-NEXT: | |-TemplateArgument type 'KN<5, 1>' // CHECK: | |-TemplateArgument type 'short' // CHECK: | `-SYCLKernelEntryPointAttr {{.*}} Inherited struct KN<5, 1> template<> [[clang::sycl_kernel_entry_point(KN<5,2>)]] void skep5>(long) { } // CHECK: |-FunctionDecl {{.*}} prev {{.*}} skep5 'void (long)' explicit_specialization // CHECK-NEXT: | |-TemplateArgument type 'KN<5, 2>' // CHECK: | |-TemplateArgument type 'long' // CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KN<5, 2> // FIXME: C++23 [temp.expl.spec]p12 states: // FIXME: ... Similarly, attributes appearing in the declaration of a template // FIXME: have no effect on an explicit specialization of that template. // FIXME: Clang currently instantiates a function template specialization from // FIXME: the function template declaration and links it as a previous // FIXME: declaration of an explicit specialization. The instantiated // FIXME: declaration includes attributes instantiated from the function // FIXME: template declaration. When the instantiated declaration and the // FIXME: explicit specialization both specify a sycl_kernel_entry_point // FIXME: attribute with different kernel name types, a spurious diagnostic // FIXME: is issued. The following test case is incorrectly diagnosed as // FIXME: having conflicting kernel name types (KN<5,3> vs the incorrectly // FIXME: inherited KN<5,-1>). #if 0 template<> [[clang::sycl_kernel_entry_point(KN<5,3>)]] void skep5>(long long) { } // FIXME-CHECK: |-FunctionDecl {{.*}} prev {{.*}} skep5 'void (long long)' explicit_specialization // FIXME-CHECK-NEXT: | |-TemplateArgument type 'KN<5, -1>' // FIXME-CHECK: | |-TemplateArgument type 'long long' // FIXME-CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KN<5, 3> #endif template void skep5>(int); // Checks are located with the primary template declaration above. // Ensure that matching attributes from multiple declarations are ok. [[clang::sycl_kernel_entry_point(KN<6>)]] void skep6(); [[clang::sycl_kernel_entry_point(KN<6>)]] void skep6() { } // CHECK: |-FunctionDecl {{.*}} skep6 'void ()' // CHECK-NEXT: | `-SYCLKernelEntryPointAttr {{.*}} KN<6> // CHECK-NEXT: |-FunctionDecl {{.*}} prev {{.*}} skep6 'void ()' // CHECK: | `-SYCLKernelEntryPointAttr {{.*}} KN<6> // Ensure that matching attributes from the same declaration are ok. [[clang::sycl_kernel_entry_point(KN<7>), clang::sycl_kernel_entry_point(KN<7>)]] void skep7() { } // CHECK: |-FunctionDecl {{.*}} skep7 'void ()' // CHECK: | |-SYCLKernelEntryPointAttr {{.*}} KN<7> // CHECK-NEXT: | `-SYCLKernelEntryPointAttr {{.*}} KN<7> void the_end() {} // CHECK: `-FunctionDecl {{.*}} the_end 'void ()'