diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 5935897980b2d..5791711295677 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1393,7 +1393,7 @@ def IntelReqdSubGroupSize: InheritableAttr { let Spellings = [GNU<"intel_reqd_sub_group_size">, CXX11<"intel", "reqd_sub_group_size">]; let Args = [ExprArgument<"Value">]; - let Subjects = SubjectList<[Function, CXXMethod], ErrorDiag>; + let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [IntelReqdSubGroupSizeDocs]; let LangOpts = [OpenCL, SYCLIsDevice, SYCLIsHost]; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 51e6ef2dda01a..59fd9fe76e5ac 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10210,6 +10210,16 @@ class Sema final { template void addIntelTripleArgAttr(Decl *D, const AttributeCommonInfo &CI, Expr *XDimExpr, Expr *YDimExpr, Expr *ZDimExpr); + void AddIntelReqdSubGroupSize(Decl *D, const AttributeCommonInfo &CI, + Expr *E); + IntelReqdSubGroupSizeAttr * + MergeIntelReqdSubGroupSizeAttr(Decl *D, const IntelReqdSubGroupSizeAttr &A); + void AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *E); + SYCLIntelNumSimdWorkItemsAttr * + MergeSYCLIntelNumSimdWorkItemsAttr(Decl *D, + const SYCLIntelNumSimdWorkItemsAttr &A); + /// AddAlignedAttr - Adds an aligned attribute to a particular declaration. void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, bool IsPackExpansion); @@ -13068,16 +13078,14 @@ void Sema::addIntelSingleArgAttr(Decl *D, const AttributeCommonInfo &CI, return; E = ICE.get(); int32_t ArgInt = ArgVal.getSExtValue(); - if (CI.getParsedKind() == ParsedAttr::AT_IntelReqdSubGroupSize || - CI.getParsedKind() == ParsedAttr::AT_IntelFPGAMaxReplicates) { + if (CI.getParsedKind() == ParsedAttr::AT_IntelFPGAMaxReplicates) { if (ArgInt <= 0) { Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer) << CI << /*positive*/ 0; return; } } - if (CI.getParsedKind() == ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim || - CI.getParsedKind() == ParsedAttr::AT_SYCLIntelNumSimdWorkItems) { + if (CI.getParsedKind() == ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim) { if (ArgInt < 0) { Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer) << CI << /*non-negative*/ 1; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index b50ad820d280c..3b4844146ceca 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2618,6 +2618,10 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, NewAttr = S.mergeEnforceTCBAttr(D, *TCBA); else if (const auto *TCBLA = dyn_cast(Attr)) NewAttr = S.mergeEnforceTCBLeafAttr(D, *TCBLA); + else if (const auto *A = dyn_cast(Attr)) + NewAttr = S.MergeIntelReqdSubGroupSizeAttr(D, *A); + else if (const auto *A = dyn_cast(Attr)) + NewAttr = S.MergeSYCLIntelNumSimdWorkItemsAttr(D, *A); else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr)) NewAttr = cast(Attr->clone(S.Context)); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 0558baa1e4ece..1b3028b5a9c38 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3209,65 +3209,148 @@ static void handleWorkGroupSizeHint(Sema &S, Decl *D, const ParsedAttr &AL) { WGSize[1], WGSize[2])); } -// Handles intel_reqd_sub_group_size. -static void handleSubGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { - if (S.LangOpts.SYCLIsHost) +void Sema::AddIntelReqdSubGroupSize(Decl *D, const AttributeCommonInfo &CI, + Expr *E) { + if (LangOpts.SYCLIsHost) return; - Expr *E = AL.getArgAsExpr(0); + if (!E->isValueDependent()) { + // Validate that we have an integer constant expression and then store the + // converted constant expression into the semantic attribute so that we + // don't have to evaluate it again later. + llvm::APSInt ArgVal; + ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal); + if (Res.isInvalid()) + return; + E = Res.get(); - if (D->getAttr()) - S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; + // This attribute requires a strictly positive value. + if (ArgVal <= 0) { + Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer) + << CI << /*positive*/ 0; + return; + } + + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + // If the other attribute argument is instantiation dependent, we won't + // have converted it to a constant expression yet and thus we test + // whether this is a null pointer. + const auto *DeclExpr = dyn_cast(DeclAttr->getValue()); + if (DeclExpr && ArgVal != DeclExpr->getResultAsAPSInt()) { + Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI; + Diag(DeclAttr->getLoc(), diag::note_previous_attribute); + return; + } + } + } - S.addIntelSingleArgAttr(D, AL, E); + D->addAttr(::new (Context) IntelReqdSubGroupSizeAttr(Context, CI, E)); } -// Handles num_simd_work_items. -static void handleNumSimdWorkItemsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (D->isInvalidDecl()) - return; +IntelReqdSubGroupSizeAttr * +Sema::MergeIntelReqdSubGroupSizeAttr(Decl *D, + const IntelReqdSubGroupSizeAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + const auto *DeclExpr = dyn_cast(DeclAttr->getValue()); + const auto *MergeExpr = dyn_cast(A.getValue()); + if (DeclExpr && MergeExpr && + DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + return nullptr; + } + } + return ::new (Context) IntelReqdSubGroupSizeAttr(Context, A, A.getValue()); +} +static void handleIntelReqdSubGroupSize(Sema &S, Decl *D, + const ParsedAttr &AL) { Expr *E = AL.getArgAsExpr(0); + S.AddIntelReqdSubGroupSize(D, AL, E); +} - if (D->getAttr()) - S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; - - S.CheckDeprecatedSYCLAttributeSpelling(AL); - +void Sema::AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, + const AttributeCommonInfo &CI, + Expr *E) { if (!E->isValueDependent()) { + // Validate that we have an integer constant expression and then store the + // converted constant expression into the semantic attribute so that we + // don't have to evaluate it again later. llvm::APSInt ArgVal; - ExprResult ICE = S.VerifyIntegerConstantExpression(E, &ArgVal); - - if (ICE.isInvalid()) + ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal); + if (Res.isInvalid()) return; + E = Res.get(); - E = ICE.get(); - int64_t NumSimdWorkItems = ArgVal.getSExtValue(); - - if (NumSimdWorkItems == 0) { - S.Diag(E->getExprLoc(), diag::err_attribute_argument_is_zero) - << AL << E->getSourceRange(); + // This attribute requires a strictly positive value. + if (ArgVal <= 0) { + Diag(E->getExprLoc(), diag::err_attribute_requires_positive_integer) + << CI << /*positive*/ 0; return; } - if (const auto *A = D->getAttr()) { - ASTContext &Ctx = S.getASTContext(); - Optional XDimVal = A->getXDimVal(Ctx); - Optional YDimVal = A->getYDimVal(Ctx); - Optional ZDimVal = A->getZDimVal(Ctx); - - if (!(XDimVal->getZExtValue() % NumSimdWorkItems == 0 || - YDimVal->getZExtValue() % NumSimdWorkItems == 0 || - ZDimVal->getZExtValue() % NumSimdWorkItems == 0)) { - S.Diag(AL.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) - << AL << A; - S.Diag(A->getLocation(), diag::note_conflicting_attribute); + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + // If the other attribute argument is instantiation dependent, we won't + // have converted it to a constant expression yet and thus we test + // whether this is a null pointer. + const auto *DeclExpr = dyn_cast(DeclAttr->getValue()); + if (DeclExpr && ArgVal != DeclExpr->getResultAsAPSInt()) { + Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI; + Diag(DeclAttr->getLoc(), diag::note_previous_attribute); + return; + } + } + + // If the declaration has an [[intel::reqd_work_group_size]] attribute, + // check to see if can be evenly divided by the num_simd_work_items attr. + if (const auto *DeclAttr = D->getAttr()) { + Optional XDimVal = DeclAttr->getXDimVal(Context); + Optional YDimVal = DeclAttr->getYDimVal(Context); + Optional ZDimVal = DeclAttr->getZDimVal(Context); + + if (!(*XDimVal % ArgVal == 0 || *YDimVal % ArgVal == 0 || + *ZDimVal % ArgVal == 0)) { + Diag(CI.getLoc(), diag::err_sycl_num_kernel_wrong_reqd_wg_size) + << CI << DeclAttr; + Diag(DeclAttr->getLocation(), diag::note_conflicting_attribute); return; } } } - S.addIntelSingleArgAttr(D, AL, E); + D->addAttr(::new (Context) SYCLIntelNumSimdWorkItemsAttr(Context, CI, E)); +} + +SYCLIntelNumSimdWorkItemsAttr *Sema::MergeSYCLIntelNumSimdWorkItemsAttr( + Decl *D, const SYCLIntelNumSimdWorkItemsAttr &A) { + // Check to see if there's a duplicate attribute with different values + // already applied to the declaration. + if (const auto *DeclAttr = D->getAttr()) { + const auto *DeclExpr = dyn_cast(DeclAttr->getValue()); + const auto *MergeExpr = dyn_cast(A.getValue()); + if (DeclExpr && MergeExpr && + DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) { + Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A; + Diag(A.getLoc(), diag::note_previous_attribute); + return nullptr; + } + } + return ::new (Context) + SYCLIntelNumSimdWorkItemsAttr(Context, A, A.getValue()); +} + +static void handleSYCLIntelNumSimdWorkItemsAttr(Sema &S, Decl *D, + const ParsedAttr &A) { + S.CheckDeprecatedSYCLAttributeSpelling(A); + + Expr *E = A.getArgAsExpr(0); + S.AddSYCLIntelNumSimdWorkItemsAttr(D, A, E); } // Handles use_stall_enable_clusters @@ -8848,10 +8931,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleWorkGroupSize(S, D, AL); break; case ParsedAttr::AT_IntelReqdSubGroupSize: - handleSubGroupSize(S, D, AL); + handleIntelReqdSubGroupSize(S, D, AL); break; case ParsedAttr::AT_SYCLIntelNumSimdWorkItems: - handleNumSimdWorkItemsAttr(S, D, AL); + handleSYCLIntelNumSimdWorkItemsAttr(S, D, AL); break; case ParsedAttr::AT_SYCLIntelSchedulerTargetFmaxMhz: handleSchedulerTargetFmaxMhzAttr(S, D, AL); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index fb17e6ac68888..53c3dc2d7317d 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -643,6 +643,26 @@ static void instantiateSYCLIntelLoopFuseAttr( S.addSYCLIntelLoopFuseAttr(New, *Attr, Result.getAs()); } +static void instantiateIntelReqdSubGroupSize( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const IntelReqdSubGroupSizeAttr *A, Decl *New) { + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ExprResult Result = S.SubstExpr(A->getValue(), TemplateArgs); + if (!Result.isInvalid()) + S.AddIntelReqdSubGroupSize(New, *A, Result.getAs()); +} + +static void instantiateSYCLIntelNumSimdWorkItemsAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const SYCLIntelNumSimdWorkItemsAttr *A, Decl *New) { + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ExprResult Result = S.SubstExpr(A->getValue(), TemplateArgs); + if (!Result.isInvalid()) + S.AddSYCLIntelNumSimdWorkItemsAttr(New, *A, Result.getAs()); +} + template static void instantiateIntelSYCLFunctionAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, @@ -834,14 +854,14 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, } if (const auto *IntelReqdSubGroupSize = dyn_cast(TmplAttr)) { - instantiateIntelSYCLFunctionAttr( - *this, TemplateArgs, IntelReqdSubGroupSize, New); + instantiateIntelReqdSubGroupSize(*this, TemplateArgs, + IntelReqdSubGroupSize, New); continue; } if (const auto *SYCLIntelNumSimdWorkItems = dyn_cast(TmplAttr)) { - instantiateIntelSYCLFunctionAttr( - *this, TemplateArgs, SYCLIntelNumSimdWorkItems, New); + instantiateSYCLIntelNumSimdWorkItemsAttr(*this, TemplateArgs, + SYCLIntelNumSimdWorkItems, New); continue; } if (const auto *SYCLIntelSchedulerTargetFmaxMhz = diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 30fd396ff95e7..b42dda69af890 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -71,7 +71,7 @@ // CHECK-NEXT: IBAction (SubjectMatchRule_objc_method_is_instance) // CHECK-NEXT: IFunc (SubjectMatchRule_function) // CHECK-NEXT: InitPriority (SubjectMatchRule_variable) -// CHECK-NEXT: IntelReqdSubGroupSize (SubjectMatchRule_function, SubjectMatchRule_function_is_member) +// CHECK-NEXT: IntelReqdSubGroupSize (SubjectMatchRule_function) // CHECK-NEXT: InternalLinkage (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record) // CHECK-NEXT: LTOVisibilityPublic (SubjectMatchRule_record) // CHECK-NEXT: Leaf (SubjectMatchRule_function) diff --git a/clang/test/SemaOpenCL/invalid-kernel-attrs.cl b/clang/test/SemaOpenCL/invalid-kernel-attrs.cl index 47f751370943b..dbb3ca192db5d 100644 --- a/clang/test/SemaOpenCL/invalid-kernel-attrs.cl +++ b/clang/test/SemaOpenCL/invalid-kernel-attrs.cl @@ -39,7 +39,8 @@ kernel __attribute__((intel_reqd_sub_group_size(0))) void kernel15() {} // expec kernel __attribute__((intel_reqd_sub_group_size(-1))) void kernel16() {} // expected-error {{'intel_reqd_sub_group_size' attribute requires a positive integral compile time constant expression}} -kernel __attribute__((intel_reqd_sub_group_size(8))) __attribute__((intel_reqd_sub_group_size(16))) void kernel17() {} //expected-warning{{attribute 'intel_reqd_sub_group_size' is already applied with different parameters}} +kernel __attribute__((intel_reqd_sub_group_size(8))) __attribute__((intel_reqd_sub_group_size(16))) void kernel17() {} //expected-warning{{attribute 'intel_reqd_sub_group_size' is already applied with different parameters}} \ + // expected-note {{previous attribute is here}} __kernel __attribute__((work_group_size_hint(8,-16,32))) void neg1() {} //expected-error{{'work_group_size_hint' attribute requires a non-negative integral compile time constant expression}} __kernel __attribute__((reqd_work_group_size(8, 16, -32))) void neg2() {} //expected-warning{{implicit conversion changes signedness: 'int' to 'unsigned long long'}} diff --git a/clang/test/SemaSYCL/num_simd_work_items_device.cpp b/clang/test/SemaSYCL/num_simd_work_items_device.cpp index 96c7db29de8ea..93a339da09190 100644 --- a/clang/test/SemaSYCL/num_simd_work_items_device.cpp +++ b/clang/test/SemaSYCL/num_simd_work_items_device.cpp @@ -8,7 +8,7 @@ queue q; #ifndef __SYCL_DEVICE_ONLY__ struct FuncObj { - [[intel::num_simd_work_items(42)]] // expected-no-diagnostics + [[intel::num_simd_work_items(42)]] void operator()() const {} }; @@ -26,6 +26,12 @@ void foo() { }); } +[[intel::num_simd_work_items(12)]] void bar(); +[[intel::num_simd_work_items(12)]] void bar() {} // OK + +[[intel::num_simd_work_items(12)]] void baz(); // expected-note {{previous attribute is here}} +[[intel::num_simd_work_items(100)]] void baz(); // expected-warning {{attribute 'num_simd_work_items' is already applied with different parameters}} + #else // __SYCL_DEVICE_ONLY__ [[intel::num_simd_work_items(2)]] void func_do_not_ignore() {} @@ -63,7 +69,7 @@ struct TRIFuncObjBad4 { }; struct TRIFuncObjBad5 { - [[intel::num_simd_work_items(0)]] // expected-error{{'num_simd_work_items' attribute must be greater than 0}} + [[intel::num_simd_work_items(0)]] // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} [[intel::reqd_work_group_size(5, 5, 5)]] void operator()() const {} }; @@ -98,7 +104,7 @@ struct TRIFuncObjBad9 { struct TRIFuncObjBad10 { [[intel::reqd_work_group_size(5, 5, 5)]] - [[intel::num_simd_work_items(0)]] // expected-error{{'num_simd_work_items' attribute must be greater than 0}} + [[intel::num_simd_work_items(0)]] // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} void operator()() const {} }; @@ -116,12 +122,12 @@ struct TRIFuncObjBad12 { struct TRIFuncObjBad13 { [[intel::reqd_work_group_size(0)]] // expected-error{{'reqd_work_group_size' attribute must be greater than 0}} - [[intel::num_simd_work_items(0)]] // expected-error{{'num_simd_work_items' attribute must be greater than 0}} + [[intel::num_simd_work_items(0)]] // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} void operator()() const {} }; struct TRIFuncObjBad14 { - [[intel::num_simd_work_items(0)]] // expected-error{{'num_simd_work_items' attribute must be greater than 0}} + [[intel::num_simd_work_items(0)]] // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} [[intel::reqd_work_group_size(0)]] // expected-error{{'reqd_work_group_size' attribute must be greater than 0}} void operator()() const {} }; @@ -145,7 +151,7 @@ struct TRIFuncObjBad17 { }; struct TRIFuncObjBad18 { - [[intel::num_simd_work_items(-1)]] // expected-error{{'num_simd_work_items' attribute requires a non-negative integral compile time constant expression}} + [[intel::num_simd_work_items(-1)]] // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} [[intel::reqd_work_group_size(-1)]] // expected-warning{{implicit conversion changes signedness: 'int' to 'unsigned long long'}} void operator()() const {} }; @@ -366,10 +372,10 @@ int main() { [[intel::num_simd_work_items(0)]] int Var = 0; // expected-error{{'num_simd_work_items' attribute only applies to functions}} h.single_task( - []() [[intel::num_simd_work_items(0)]]{}); // expected-error{{'num_simd_work_items' attribute must be greater than 0}} + []() [[intel::num_simd_work_items(0)]]{}); // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} h.single_task( - []() [[intel::num_simd_work_items(-42)]]{}); // expected-error{{'num_simd_work_items' attribute requires a non-negative integral compile time constant expression}} + []() [[intel::num_simd_work_items(-42)]]{}); // expected-error{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} h.single_task(TRIFuncObjBad1()); @@ -408,7 +414,8 @@ int main() { h.single_task(TRIFuncObjBad18()); h.single_task( - []() [[intel::num_simd_work_items(1), intel::num_simd_work_items(2)]]{}); // expected-warning{{attribute 'num_simd_work_items' is already applied with different parameters}} + []() [[intel::num_simd_work_items(1), intel::num_simd_work_items(2)]]{}); // expected-warning{{attribute 'num_simd_work_items' is already applied with different parameters}} \ + // expected-note {{previous attribute is here}} #endif // TRIGGER_ERROR }); return 0; diff --git a/clang/test/SemaSYCL/reqd-sub-group-size-device.cpp b/clang/test/SemaSYCL/reqd-sub-group-size-device.cpp index 6a23a54421813..95fe5fe0f0e4e 100644 --- a/clang/test/SemaSYCL/reqd-sub-group-size-device.cpp +++ b/clang/test/SemaSYCL/reqd-sub-group-size-device.cpp @@ -10,6 +10,12 @@ queue q; // expected-note@-1 {{conflicting attribute is here}} [[intel::reqd_sub_group_size(32)]] void baz() {} // expected-note {{conflicting attribute is here}} +[[intel::reqd_sub_group_size(12)]] void bar(); +[[intel::reqd_sub_group_size(12)]] void bar() {} // OK + +[[intel::reqd_sub_group_size(12)]] void quux(); // expected-note {{previous attribute is here}} +[[intel::reqd_sub_group_size(100)]] void quux(); // expected-warning {{attribute 'reqd_sub_group_size' is already applied with different parameters}} + class Functor16 { public: [[intel::reqd_sub_group_size(16)]] void operator()() const {} 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 f308cb4f9e1d9..2185fd3b1107d 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,8 +5,9 @@ // Test that checks wrong function template instantiation and ensures that the type // is checked properly when instantiating from the template definition. template -// expected-error@+2{{integral constant expression must have integral or unscoped enumeration type, not 'S'}} -// expected-error@+1{{integral constant expression must have integral or unscoped enumeration type, not 'float'}} +// expected-error@+3{{integral constant expression must have integral or unscoped enumeration type, not 'S'}} +// expected-error@+2{{integral constant expression must have integral or unscoped enumeration type, not 'float'}} +// expected-error@+1{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} [[intel::num_simd_work_items(Ty{})]] void func() {} struct S {}; @@ -15,6 +16,7 @@ void test() { 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(); } @@ -33,7 +35,7 @@ constexpr int bar() { return 0; } template class KernelFunctor { public: - // expected-error@+1{{'num_simd_work_items' attribute requires a non-negative integral compile time constant expression}} + // expected-error@+1{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} [[intel::num_simd_work_items(SIZE)]] void operator()() {} }; @@ -55,14 +57,23 @@ int main() { // Test that checks template parameter support on function. template -// expected-error@+1{{'num_simd_work_items' attribute requires a non-negative integral compile time constant expression}} +// expected-error@+1{{'num_simd_work_items' attribute requires a positive integral compile time constant expression}} [[intel::num_simd_work_items(N)]] void func3() {} +template +[[intel::num_simd_work_items(4)]] void func4(); // expected-note {{previous attribute is here}} + +template +[[intel::num_simd_work_items(N)]] void func4() {} // expected-warning {{attribute 'num_simd_work_items' is already applied with different parameters}} + int check() { // no error expected func3<8>(); //expected-note@+1{{in instantiation of function template specialization 'func3<-1>' requested here}} func3<-1>(); + + func4<6>(); //expected-note {{in instantiation of function template specialization 'func4<6>' requested here}} + 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 a8af66f7f47e1..e6cf8a05eefe8 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 @@ -60,11 +60,20 @@ 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() {} +template +[[intel::reqd_sub_group_size(4)]] void func4(); // expected-note {{previous attribute is here}} + +template +[[intel::reqd_sub_group_size(N)]] void func4() {} // expected-warning {{attribute 'reqd_sub_group_size' is already applied with different parameters}} + int check() { // no error expected func3<12>(); //expected-note@+1{{in instantiation of function template specialization 'func3<-1>' requested here}} func3<-1>(); + + func4<6>(); //expected-note {{in instantiation of function template specialization 'func4<6>' requested here}} + return 0; }