From bef85bd0c86d65d435368d60aae12b4839c282f1 Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Sun, 24 Jan 2021 22:07:20 -0800 Subject: [PATCH 1/3] [SYCL] Add new test cases for FPGA attributes Template parameter support was added for 1. [[intel::max_global_work_dim)]] attribute on https://github.com/intel/llvm/pull/2816 2. [[intel::num_simd_work_items()]] attribute on https://github.com/intel/llvm/pull/2510 3. [[intel::reqd_sub_group_size()]] attribute on https://github.com/intel/llvm/pull/1807 This patch adds the following new test cases that were not there before to improve the support: 1. Test that checks wrong function template instantiation and ensures that the type is checked properly when instantiating from the template definition. 2. Test that checks expression is not a constant expression. 3. Test that checks expression is a constant expression. 4. Test that checks template parameter support on function. NOTE: No change in compiler. All new test cases have already been supported. Signed-off-by: Soumi Manna --- .../CodeGenSYCL/intel-max-global-work-dim.cpp | 8 ++++ .../test/CodeGenSYCL/num-simd-work-items.cpp | 9 +++++ .../test/CodeGenSYCL/reqd-sub-group-size.cpp | 8 ++++ ...ice-intel-max-global-work-dim-template.cpp | 39 +++++++++++++++++++ ...cl-device-num_simd_work_items-template.cpp | 39 +++++++++++++++++++ ...cl-device-reqd-sub-group-size-template.cpp | 39 +++++++++++++++++++ 6 files changed, 142 insertions(+) diff --git a/clang/test/CodeGenSYCL/intel-max-global-work-dim.cpp b/clang/test/CodeGenSYCL/intel-max-global-work-dim.cpp index 35f0e4d19cf11..e9e380455fe84 100644 --- a/clang/test/CodeGenSYCL/intel-max-global-work-dim.cpp +++ b/clang/test/CodeGenSYCL/intel-max-global-work-dim.cpp @@ -16,6 +16,9 @@ class Functor { [[intel::max_global_work_dim(SIZE)]] void operator()() const {} }; +template +[[intel::max_global_work_dim(N)]] void func() {} + int main() { q.submit([&](handler &h) { Foo boo; @@ -26,6 +29,10 @@ int main() { Functor<2> f; h.single_task(f); + + h.single_task([]() { + func<2>(); + }); }); return 0; } @@ -33,5 +40,6 @@ int main() { // CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_name1"() #0 {{.*}} !max_global_work_dim ![[NUM1:[0-9]+]] // CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_name2"() #0 {{.*}} !max_global_work_dim ![[NUM2:[0-9]+]] // CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_name3"() #0 {{.*}} !max_global_work_dim ![[NUM2]] +// CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_name4"() #0 {{.*}} !max_global_work_dim ![[NUM2]] // CHECK: ![[NUM1]] = !{i32 1} // CHECK: ![[NUM2]] = !{i32 2} diff --git a/clang/test/CodeGenSYCL/num-simd-work-items.cpp b/clang/test/CodeGenSYCL/num-simd-work-items.cpp index 4620ead8b7896..7a5f3892171fd 100644 --- a/clang/test/CodeGenSYCL/num-simd-work-items.cpp +++ b/clang/test/CodeGenSYCL/num-simd-work-items.cpp @@ -16,6 +16,9 @@ class Functor { [[intel::num_simd_work_items(SIZE)]] void operator()() const {} }; +template +[[intel::num_simd_work_items(N)]] void func() {} + int main() { q.submit([&](handler &h) { Foo boo; @@ -26,6 +29,10 @@ int main() { Functor<2> f; h.single_task(f); + + h.single_task([]() { + func<4>(); + }); }); return 0; } @@ -33,6 +40,8 @@ int main() { // CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_name1"() #0 {{.*}} !num_simd_work_items ![[NUM1:[0-9]+]] // CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_name2"() #0 {{.*}} !num_simd_work_items ![[NUM42:[0-9]+]] // CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_name3"() #0 {{.*}} !num_simd_work_items ![[NUM2:[0-9]+]] +// CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_name4"() #0 {{.*}} !num_simd_work_items ![[NUM4:[0-9]+]] // CHECK: ![[NUM1]] = !{i32 1} // CHECK: ![[NUM42]] = !{i32 42} // CHECK: ![[NUM2]] = !{i32 2} +// CHECK: ![[NUM4]] = !{i32 4} diff --git a/clang/test/CodeGenSYCL/reqd-sub-group-size.cpp b/clang/test/CodeGenSYCL/reqd-sub-group-size.cpp index 2bd724421a84e..8325beb99e8f3 100644 --- a/clang/test/CodeGenSYCL/reqd-sub-group-size.cpp +++ b/clang/test/CodeGenSYCL/reqd-sub-group-size.cpp @@ -25,6 +25,9 @@ class Functor2 { [[intel::reqd_sub_group_size(SIZE)]] void operator()() const {} }; +template +[[intel::reqd_sub_group_size(N)]] void func() {} + int main() { q.submit([&](handler &h) { Functor16 f16; @@ -38,6 +41,10 @@ int main() { Functor2<2> f2; h.single_task(f2); + + h.single_task([]() { + func<2>(); + }); }); return 0; } @@ -46,6 +53,7 @@ int main() { // CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_name2"() #0 {{.*}} !intel_reqd_sub_group_size ![[SGSIZE8:[0-9]+]] // CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_name3"() #0 {{.*}} !intel_reqd_sub_group_size ![[SGSIZE4:[0-9]+]] // CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_name4"() #0 {{.*}} !intel_reqd_sub_group_size ![[SGSIZE2:[0-9]+]] +// CHECK: define {{.*}}spir_kernel void @{{.*}}kernel_name5"() #0 {{.*}} !intel_reqd_sub_group_size ![[SGSIZE2]] // CHECK: ![[SGSIZE16]] = !{i32 16} // CHECK: ![[SGSIZE8]] = !{i32 8} // CHECK: ![[SGSIZE4]] = !{i32 4} diff --git a/clang/test/SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp b/clang/test/SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp index 9b8600f99a76d..563be50e52c36 100644 --- a/clang/test/SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp @@ -2,6 +2,28 @@ // Test that checkes template parameter support for 'max_global_work_dim' attribute on sycl device. +// Test that checks wrong function template instantiation and ensures that the type +// is checked properly when instantiating from the template definition. +template +// expected-error@+1{{'max_global_work_dim' attribute requires an integer constant}} +[[intel::max_global_work_dim(Ty{})]] void func() {} + +struct S {}; +void var() { + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); +} + +// Test that checks expression is not a constant expression. +int foo(); +// expected-error@+1{{'max_global_work_dim' attribute requires an integer constant}} +[[intel::max_global_work_dim(foo() + 1)]] void func1(); + +// Test that checks expression is a constant expression. +constexpr int bar() { return 0; } +[[intel::max_global_work_dim(bar() + 2)]] void func2(); // OK + +// Test that checks template parameter suppport on member function of class template. template class KernelFunctor { public: @@ -23,3 +45,20 @@ int main() { // CHECK: SubstNonTypeTemplateParmExpr {{.*}} // CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} // CHECK-NEXT: IntegerLiteral{{.*}}2{{$}} + +// Test that checks template parameter support on function. +template +[[intel::max_global_work_dim(N)]] void func3() {} + +int check() { + func3<2>(); + return 0; +} + +// CHECK: FunctionTemplateDecl {{.*}} {{.*}} func3 +// CHECK: NonTypeTemplateParmDecl {{.*}} {{.*}} referenced 'int' depth 0 index 0 N +// CHECK: FunctionDecl {{.*}} {{.*}} func3 'void ()' +// CHECK: SYCLIntelMaxGlobalWorkDimAttr {{.*}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}2{{$}} diff --git a/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp b/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp index 4f4f9286b5d72..e957d38fcd4ac 100644 --- a/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp @@ -2,6 +2,28 @@ // Test that checkes template parameter support for 'num_simd_work_items' attribute on sycl device. +// Test that checks wrong function template instantiation and ensures that the type +// is checked properly when instantiating from the template definition. +template +// expected-error@+1{{'num_simd_work_items' attribute requires an integer constant}} +[[intel::num_simd_work_items(Ty{})]] void func() {} + +struct S {}; +void var() { + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); +} + +// Test that checks expression is not a constant expression. +int foo(); +// expected-error@+1{{'num_simd_work_items' attribute requires an integer constant}} +[[intel::num_simd_work_items(foo() + 12)]] void func1(); + +// Test that checks expression is a constant expression. +constexpr int bar() { return 0; } +[[intel::num_simd_work_items(bar() + 12)]] void func2(); // OK + +// Test that checks template parameter suppport on member function of class template. template class KernelFunctor { public: @@ -23,3 +45,20 @@ int main() { // CHECK: SubstNonTypeTemplateParmExpr {{.*}} // CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} // CHECK-NEXT: IntegerLiteral{{.*}}10{{$}} + +// Test that checks template parameter support on function. +template +[[intel::num_simd_work_items(N)]] void func3() {} + +int check() { + func3<8>(); + return 0; +} + +// CHECK: FunctionTemplateDecl {{.*}} {{.*}} func3 +// CHECK: NonTypeTemplateParmDecl {{.*}} {{.*}} referenced 'int' depth 0 index 0 N +// CHECK: FunctionDecl {{.*}} {{.*}} func3 'void ()' +// CHECK: SYCLIntelNumSimdWorkItemsAttr {{.*}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} diff --git a/clang/test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp b/clang/test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp index 4c4a376cf4591..e274a6d2da19e 100644 --- a/clang/test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp @@ -2,6 +2,28 @@ // Test that checkes template parameter support for 'reqd_sub_group_size' attribute on sycl device. +// Test that checks wrong function template instantiation and ensures that the type +// is checked properly when instantiating from the template definition. +template +// expected-error@+1{{'reqd_sub_group_size' attribute requires an integer constant}} +[[intel::reqd_sub_group_size(Ty{})]] void func() {} + +struct S {}; +void var() { + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); +} + +// Test that checks expression is not a constant expression. +int foo(); +// expected-error@+1{{'reqd_sub_group_size' attribute requires an integer constant}} +[[intel::reqd_sub_group_size(foo() + 12)]] void func1(); + +// Test that checks expression is a constant expression. +constexpr int bar() { return 0; } +[[intel::reqd_sub_group_size(bar() + 12)]] void func2(); // OK + +// Test that checks template parameter suppport on member function of class template. template class KernelFunctor { public: @@ -23,3 +45,20 @@ int main() { // CHECK: SubstNonTypeTemplateParmExpr {{.*}} // CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} // CHECK-NEXT: IntegerLiteral{{.*}}10{{$}} + +// Test that checks template parameter support on function. +template +[[intel::reqd_sub_group_size(N)]] void func3() {} + +int check() { + func3<12>(); + return 0; +} + +// CHECK: FunctionTemplateDecl {{.*}} {{.*}} func3 +// CHECK: NonTypeTemplateParmDecl {{.*}} {{.*}} referenced 'int' depth 0 index 0 N +// CHECK: FunctionDecl {{.*}} {{.*}} func3 'void ()' +// CHECK: IntelReqdSubGroupSizeAttr {{.*}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}12{{$}} From eaabb183e721b1183cca0c5437fc601aaf2b74b5 Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Mon, 25 Jan 2021 11:56:12 -0800 Subject: [PATCH 2/3] Fix typos Signed-off-by: Soumi Manna --- .../SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp | 2 +- .../SemaSYCL/sycl-device-intel-max-work-group-size-template.cpp | 2 +- .../sycl-device-intel-reqd-work-group-size-template.cpp | 2 +- .../test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp | 2 +- .../test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp | 2 +- .../test/SemaSYCL/sycl-device-reqd-work-group-size-template.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/test/SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp b/clang/test/SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp index 563be50e52c36..ab7531246028e 100644 --- a/clang/test/SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp @@ -23,7 +23,7 @@ int foo(); constexpr int bar() { return 0; } [[intel::max_global_work_dim(bar() + 2)]] void func2(); // OK -// Test that checks template parameter suppport on member function of class template. +// Test that checks template parameter support on member function of class template. template class KernelFunctor { public: diff --git a/clang/test/SemaSYCL/sycl-device-intel-max-work-group-size-template.cpp b/clang/test/SemaSYCL/sycl-device-intel-max-work-group-size-template.cpp index 50cc361c19796..ae1797a991612 100644 --- a/clang/test/SemaSYCL/sycl-device-intel-max-work-group-size-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-intel-max-work-group-size-template.cpp @@ -24,7 +24,7 @@ int foo(); constexpr int bar() { return 0; } [[intel::max_work_group_size(bar() + 12, bar() + 12, bar() + 12)]] void func2(); // OK -// Test that checks template parameter suppport on member function of class template. +// Test that checks template parameter support on member function of class template. template class KernelFunctor { public: diff --git a/clang/test/SemaSYCL/sycl-device-intel-reqd-work-group-size-template.cpp b/clang/test/SemaSYCL/sycl-device-intel-reqd-work-group-size-template.cpp index c297f4e15e091..409f017e50f74 100644 --- a/clang/test/SemaSYCL/sycl-device-intel-reqd-work-group-size-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-intel-reqd-work-group-size-template.cpp @@ -24,7 +24,7 @@ int foo(); constexpr int bar() { return 0; } [[intel::reqd_work_group_size(bar() + 12, bar() + 12, bar() + 12)]] void func2(); // OK -// Test that checks template parameter suppport on member function of class template. +// Test that checks template parameter support on member function of class template. template class KernelFunctor { public: diff --git a/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp b/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp index e957d38fcd4ac..99e1732c67c00 100644 --- a/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp @@ -23,7 +23,7 @@ int foo(); constexpr int bar() { return 0; } [[intel::num_simd_work_items(bar() + 12)]] void func2(); // OK -// Test that checks template parameter suppport on member function of class template. +// Test that checks template parameter support on member function of class template. template class KernelFunctor { public: diff --git a/clang/test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp b/clang/test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp index e274a6d2da19e..cd914905b983c 100644 --- a/clang/test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp @@ -23,7 +23,7 @@ int foo(); constexpr int bar() { return 0; } [[intel::reqd_sub_group_size(bar() + 12)]] void func2(); // OK -// Test that checks template parameter suppport on member function of class template. +// Test that checks template parameter support on member function of class template. template class KernelFunctor { public: diff --git a/clang/test/SemaSYCL/sycl-device-reqd-work-group-size-template.cpp b/clang/test/SemaSYCL/sycl-device-reqd-work-group-size-template.cpp index b981f524b2b0b..7fe5c4a6a827f 100644 --- a/clang/test/SemaSYCL/sycl-device-reqd-work-group-size-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-reqd-work-group-size-template.cpp @@ -24,7 +24,7 @@ int foo(); constexpr int bar() { return 0; } [[cl::reqd_work_group_size(bar() + 12, bar() + 12, bar() + 12)]] void func2(); // OK -// Test that checks template parameter suppport on member function of class template. +// Test that checks template parameter support on member function of class template. template class KernelFunctor { public: From f0112fca4ca1d0ad458e4d9e4222ec56efb74dcb Mon Sep 17 00:00:00 2001 From: Soumi Manna Date: Mon, 25 Jan 2021 22:15:37 -0800 Subject: [PATCH 3/3] Add new test cases Signed-off-by: Soumi Manna --- ...l-device-intel-max-global-work-dim-template.cpp | 12 ++++++++++-- .../sycl-device-num_simd_work_items-template.cpp | 14 ++++++++++++-- .../sycl-device-reqd-sub-group-size-template.cpp | 14 ++++++++++++-- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/clang/test/SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp b/clang/test/SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp index ab7531246028e..ce49d6344897c 100644 --- a/clang/test/SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-intel-max-global-work-dim-template.cpp @@ -5,13 +5,17 @@ // Test that checks wrong function template instantiation and ensures that the type // is checked properly when instantiating from the template definition. template -// expected-error@+1{{'max_global_work_dim' attribute requires an integer constant}} +// expected-error@+1 2{{'max_global_work_dim' attribute requires an integer constant}} [[intel::max_global_work_dim(Ty{})]] void func() {} struct S {}; -void var() { +void test() { //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} func(); + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); + // no error expected + func(); // OK } // Test that checks expression is not a constant expression. @@ -48,10 +52,14 @@ int main() { // Test that checks template parameter support on function. template +// expected-error@+1{{'max_global_work_dim' attribute requires a non-negative integral compile time constant expression}} [[intel::max_global_work_dim(N)]] void func3() {} int check() { + // no error expected func3<2>(); + //expected-note@+1{{in instantiation of function template specialization 'func3<-1>' requested here}} + func3<-1>(); return 0; } diff --git a/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp b/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp index 99e1732c67c00..f29d050d4b49e 100644 --- a/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-num_simd_work_items-template.cpp @@ -5,13 +5,18 @@ // Test that checks wrong function template instantiation and ensures that the type // is checked properly when instantiating from the template definition. template -// expected-error@+1{{'num_simd_work_items' attribute requires an integer constant}} +// expected-error@+2{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} +// expected-error@+1 2{{'num_simd_work_items' attribute requires an integer constant}} [[intel::num_simd_work_items(Ty{})]] void func() {} struct S {}; -void var() { +void test() { //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} func(); + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); } // Test that checks expression is not a constant expression. @@ -36,6 +41,7 @@ int main() { KernelFunctor<-1>(); // no error expected KernelFunctor<10>(); + return 0; } // CHECK: ClassTemplateDecl {{.*}} {{.*}} KernelFunctor @@ -48,10 +54,14 @@ int main() { // Test that checks template parameter support on function. template +// expected-error@+1{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} [[intel::num_simd_work_items(N)]] void func3() {} int check() { + // no error expected func3<8>(); + //expected-note@+1{{in instantiation of function template specialization 'func3<-1>' requested here}} + func3<-1>(); return 0; } diff --git a/clang/test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp b/clang/test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp index cd914905b983c..ae41e6bead1dc 100644 --- a/clang/test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp +++ b/clang/test/SemaSYCL/sycl-device-reqd-sub-group-size-template.cpp @@ -5,13 +5,18 @@ // Test that checks wrong function template instantiation and ensures that the type // is checked properly when instantiating from the template definition. template -// expected-error@+1{{'reqd_sub_group_size' attribute requires an integer constant}} +// expected-error@+2{{'reqd_sub_group_size' attribute requires a positive integral compile time constant expression}} +// expected-error@+1 2{{'reqd_sub_group_size' attribute requires an integer constant}} [[intel::reqd_sub_group_size(Ty{})]] void func() {} struct S {}; -void var() { +void test() { //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} func(); + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); } // Test that checks expression is not a constant expression. @@ -36,6 +41,7 @@ int main() { KernelFunctor<-1>(); // no error expected KernelFunctor<10>(); + return 0; } // CHECK: ClassTemplateDecl {{.*}} {{.*}} KernelFunctor @@ -48,10 +54,14 @@ int main() { // Test that checks template parameter support on function. template +// expected-error@+1{{'reqd_sub_group_size' attribute requires a positive integral compile time constant expression}} [[intel::reqd_sub_group_size(N)]] void func3() {} int check() { + // no error expected func3<12>(); + //expected-note@+1{{in instantiation of function template specialization 'func3<-1>' requested here}} + func3<-1>(); return 0; }