diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 116341f4b66d5..a68588879d63a 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11700,6 +11700,8 @@ def err_omp_negative_expression_in_clause : Error< "argument to '%0' clause must be a %select{non-negative|strictly positive}1 integer value">; def err_omp_large_expression_in_clause : Error< "argument to '%0' clause requires a value that can be represented by a 64-bit">; +def err_omp_unroll_factor_width_mismatch : Error< + "unroll factor has width %0 but the iteration variable %1 is only %2 bits wide">; def err_omp_not_integral : Error< "expression must have integral or unscoped enumeration " "type, not %0">; diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 7d800c446b595..6cfdd9072c0d9 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -14980,6 +14980,21 @@ StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef Clauses, SourceLocation FactorLoc; if (Expr *FactorVal = PartialClause->getFactor(); FactorVal && !FactorVal->containsErrors()) { + if (!VerifyPositiveIntegerConstantInClause(FactorVal, OMPC_partial, + /*StrictlyPositive=*/true, + /*SuppressExprDiags=*/false) + .isUsable()) + return StmtError(); + // Check that the iterator variable’s type can hold the factor’s bit-width + unsigned FactorValWidth = + FactorVal->getIntegerConstantExpr(Context)->getActiveBits(); + unsigned IteratorVWidth = Context.getTypeSize(OrigVar->getType()); + if (FactorValWidth > IteratorVWidth) { + Diag(FactorVal->getExprLoc(), diag::err_omp_unroll_factor_width_mismatch) + << FactorValWidth << OrigVar->getType() << IteratorVWidth; + return StmtError(); + } + Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue(); FactorLoc = FactorVal->getExprLoc(); } else { diff --git a/clang/test/OpenMP/unroll_messages.cpp b/clang/test/OpenMP/unroll_messages.cpp index 17d5ed83e162f..ba9ec35899dcd 100644 --- a/clang/test/OpenMP/unroll_messages.cpp +++ b/clang/test/OpenMP/unroll_messages.cpp @@ -58,8 +58,25 @@ void func(int n) { // expected-error@+1 {{argument to 'partial' clause must be a strictly positive integer value}} #pragma omp unroll partial(0) for (int i = 0; i < n; ++i) {} - - // expected-error@+1 {{directive '#pragma omp unroll' cannot contain more than one 'partial' clause}} + + // expected-error@+1 {{unroll factor has width 36 but the iteration variable 'int' is only 32 bits wide}} + #pragma omp unroll partial(0xFFFFFFFFF) + for (int i = 0; i < 10; i++) {} + + // expected-error@+2 {{integer literal is too large to be represented in any integer type}} + // expected-error@+1 {{argument to 'partial' clause must be a strictly positive integer value}} + #pragma omp unroll partial(0x10000000000000000) + for (int i = 0; i < 10; i++) {} + + // expected-error@+1 {{unroll factor has width 12 but the iteration variable 'char' is only 8 bits wide}} + #pragma omp unroll partial(0xFFF) + for (char i = 0; i < 10; i++) {} + + // expected-error@+1 {{unroll factor has width 20 but the iteration variable 'short' is only 16 bits wide}} + #pragma omp unroll partial(0xFFFFF) + for (short i = 0; i < 10; i++) {} + + // expected-error@+1 {{directive '#pragma omp unroll' cannot contain more than one 'partial' clause}} #pragma omp unroll partial partial for (int i = 0; i < n; ++i) {}