Skip to content
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14980,6 +14980,21 @@ StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation FactorLoc;
if (Expr *FactorVal = PartialClause->getFactor();
FactorVal && !FactorVal->containsErrors()) {
if (!VerifyPositiveIntegerConstantInClause(FactorVal, OMPC_partial,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question I have for @alexey-bataev and @shiltian is whether we should hoist the width-checking logic into VerifyPositiveIntegerConstantInClause() so that all callers of this function get the same checking instead of just loop unroll directives. Won't all the callers of this function have the same need to diagnose width mismatches? (Apologies for my OpenMP ignorance, maybe I'm wrong.)

/*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 {
Expand Down
21 changes: 19 additions & 2 deletions clang/test/OpenMP/unroll_messages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}

Expand Down