diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10173,7 +10173,8 @@ /// Checks that the specified declaration matches requirements for the linear /// decls. bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, - OpenMPLinearClauseKind LinKind, QualType Type); + OpenMPLinearClauseKind LinKind, QualType Type, + bool IsDeclareSimd = false); /// Called on well-formed '\#pragma omp declare simd' after parsing of /// the associated method/function. diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5269,7 +5269,8 @@ E->containsUnexpandedParameterPack()) continue; (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind, - PVD->getOriginalType()); + PVD->getOriginalType(), + /*IsDeclareSimd=*/true); continue; } } @@ -5289,7 +5290,7 @@ E->isInstantiationDependent() || E->containsUnexpandedParameterPack()) continue; (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind, - E->getType()); + E->getType(), /*IsDeclareSimd=*/true); continue; } Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) @@ -14547,8 +14548,8 @@ } bool Sema::CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, - OpenMPLinearClauseKind LinKind, - QualType Type) { + OpenMPLinearClauseKind LinKind, QualType Type, + bool IsDeclareSimd) { const auto *VD = dyn_cast_or_null(D); // A variable must not have an incomplete type or a reference type. if (RequireCompleteType(ELoc, Type, diag::err_omp_linear_incomplete_type)) @@ -14564,8 +14565,10 @@ // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions] // A variable that is privatized must not have a const-qualified type // unless it is of class type with a mutable member. This restriction does - // not apply to the firstprivate clause. - if (rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc)) + // not apply to the firstprivate clause, nor to the linear clause on + // declarative directives (like declare simd). + if (!IsDeclareSimd && + rejectConstNotMutableType(*this, D, Type, OMPC_linear, ELoc)) return true; // A list item must be of integral or pointer type. diff --git a/clang/test/OpenMP/declare_simd_codegen.cpp b/clang/test/OpenMP/declare_simd_codegen.cpp --- a/clang/test/OpenMP/declare_simd_codegen.cpp +++ b/clang/test/OpenMP/declare_simd_codegen.cpp @@ -114,6 +114,9 @@ #pragma omp declare simd notinbranch double foo(double x) { return 0; } +#pragma omp declare simd notinbranch linear(i) +double constlinear(const int i) { return 0.0; } + // CHECK-DAG: define {{.+}}@_Z5add_1Pf( // CHECK-DAG: define {{.+}}@_Z1hIiEvPT_S1_S1_S1_( // CHECK-DAG: define {{.+}}@_Z1hIfEvPT_S1_S1_S1_( @@ -131,6 +134,7 @@ // CHECK-DAG: define {{.+}}@_Z3fooPffi( // CHECK-DAG: define {{.+}}@_Z3food( // CHECK-DAG: declare {{.+}}@_Z5add_2Pf( +// CHECK-DAG: declare {{.+}}@_Z11constlineari() // CHECK-DAG: "_ZGVbM4l8__Z5add_1Pf" // CHECK-DAG: "_ZGVbN4l8__Z5add_1Pf" @@ -320,6 +324,11 @@ // CHECK-DAG: "_ZGVdN4v__Z3food" // CHECK-DAG: "_ZGVeN8v__Z3food" +// CHECK-DAG: "_ZGVbN2l__Z11constlineari" +// CHECK-DAG: "_ZGVcN4l__Z11constlineari" +// CHECK-DAG: "_ZGVdN4l__Z11constlineari" +// CHECK-DAG: "_ZGVeN8l__Z11constlineari" + // CHECK-NOT: "_ZGV{{.+}}__Z1fRA_i #endif