Skip to content

Commit a1fa5cc

Browse files
committed
[clang][OpenMP] 6.0: detect privatization of array section/assumed-size array
According to the OpenMP 6.0 specification, array sections with no length and unknown size are considered assumed-size arrays. As of pull request llvm#148048 these types of array sections are allowed and can be specified in clauses that allow array sections as list items. However, only two clauses explicitly allow array sections that are assumed-size arrays: - 'map' and 'use_device_addr'. The other clauses that accept array sections do not explicitly accept assumed-size arrays: - inclusive, exclusive, has_device_addr, in_reduction, task_reduction, reduction These cases should generate an error. See OpenMP 6.0 specification section 7.4 List Item Privatization, Restrictions, p. 222, L15 Assumed-size arrays must not be privatized For OpenMP 6.0, function getPrivateItem() now checks for array section list items that are assumed-size arrays and generates an error if they are not allowed for the clause. Testing - Updated LIT tests for assumed-size array sections to ensure these clauses generate an error: inclusive, exclusive, has_device_addr, in_reduction, task_reduction, reduction and that this clause is accepted (codegen test): use_device_addr - check-all - OpenMP_VV (sollve_vv)
1 parent 313b52f commit a1fa5cc

7 files changed

+1064
-232
lines changed

clang/lib/Sema/SemaOpenMP.cpp

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2780,7 +2780,7 @@ void SemaOpenMP::EndOpenMPClause() {
27802780
static std::pair<ValueDecl *, bool>
27812781
getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
27822782
SourceRange &ERange, bool AllowArraySection = false,
2783-
StringRef DiagType = "");
2783+
bool AllowAssumedSizeArray = false, StringRef DiagType = "");
27842784

27852785
/// Check consistency of the reduction clauses.
27862786
static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
@@ -5148,11 +5148,10 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
51485148
return ErrorFound;
51495149
}
51505150

5151-
static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5152-
SourceLocation &ELoc,
5153-
SourceRange &ERange,
5154-
bool AllowArraySection,
5155-
StringRef DiagType) {
5151+
static std::pair<ValueDecl *, bool>
5152+
getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
5153+
SourceRange &ERange, bool AllowArraySection,
5154+
bool AllowAssumedSizeArray, StringRef DiagType) {
51565155
if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
51575156
RefExpr->containsUnexpandedParameterPack())
51585157
return std::make_pair(nullptr, true);
@@ -5162,6 +5161,20 @@ static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
51625161
// OpenMP [2.9.3.3, Restrictions, p.1]
51635162
// A variable that is part of another variable (as an array or
51645163
// structure element) cannot appear in a private clause.
5164+
//
5165+
// OpenMP [6.0]
5166+
// 5.2.5 Array Sections, p. 166, L28-29
5167+
// When the length is absent and the size of the dimension is not known,
5168+
// the array section is an assumed-size array.
5169+
// 2 Glossary, p. 23, L4-6
5170+
// assumed-size array
5171+
// For C/C++, an array section for which the length is absent and the
5172+
// size of the dimensions is not known.
5173+
// 5.2.5 Array Sections, p. 168, L11
5174+
// An assumed-size array can appear only in clauses for which it is
5175+
// explicitly allowed.
5176+
// 7.4 List Item Privatization, Restrictions, p. 222, L15
5177+
// Assumed-size arrays must not be privatized.
51655178
RefExpr = RefExpr->IgnoreParens();
51665179
enum {
51675180
NoArrayExpr = -1,
@@ -5177,6 +5190,17 @@ static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
51775190
IsArrayExpr = ArraySubscript;
51785191
} else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
51795192
Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5193+
if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5194+
OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5195+
QualType BaseType = ArraySectionExpr::getBaseOriginalType(Base);
5196+
if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5197+
!BaseType->isVariableArrayType())) {
5198+
S.Diag(OASE->getColonLocFirst(),
5199+
diag::err_omp_section_length_undefined)
5200+
<< (!BaseType.isNull() && BaseType->isArrayType());
5201+
return std::make_pair(nullptr, false);
5202+
}
5203+
}
51805204
while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
51815205
Base = TempOASE->getBase()->IgnoreParenImpCasts();
51825206
while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
@@ -17320,9 +17344,10 @@ static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
1732017344
SourceLocation ELoc;
1732117345
SourceRange ERange;
1732217346
Expr *RefExpr = InteropVarExpr;
17323-
auto Res =
17324-
getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
17325-
/*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17347+
auto Res = getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
17348+
/*AllowArraySection=*/false,
17349+
/*AllowAssumedSizeArray=*/false,
17350+
/*DiagType=*/"omp_interop_t");
1732617351

1732717352
if (Res.second) {
1732817353
// It will be analyzed later.
@@ -23506,7 +23531,8 @@ SemaOpenMP::ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
2350623531
SourceRange ERange;
2350723532
Expr *SimpleRefExpr = RefExpr;
2350823533
auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23509-
/*AllowArraySection=*/true);
23534+
/*AllowArraySection=*/true,
23535+
/*AllowAssumedSizeArray=*/true);
2351023536
if (Res.second) {
2351123537
// It will be analyzed later.
2351223538
MVLI.ProcessedVarList.push_back(RefExpr);

clang/test/OpenMP/scan_messages.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22

33
// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 %s
44

5+
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=60 -ferror-limit 150 %s
6+
7+
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=60 -ferror-limit 150 %s
8+
59
template <class T>
6-
T tmain() {
10+
T tfoobar(T ub[]) {
711
static T argc;
12+
T *ptr;
813
#pragma omp for
914
for (int i = 0; i < 10; ++i) {
1015
#pragma omp scan // expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
@@ -83,12 +88,23 @@ T tmain() {
8388
label1 : {
8489
#pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}}
8590
}}
91+
#pragma omp simd reduction(inscan, +: argc)
92+
for (int i = 0; i < 10; ++i) {
93+
#pragma omp scan inclusive(ptr[0:], argc) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
94+
;
95+
}
96+
#pragma omp simd reduction(inscan, +: argc)
97+
for (int i = 0; i < 10; ++i) {
98+
#pragma omp scan exclusive(argc, ub[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
99+
;
100+
}
86101

87102
return T();
88103
}
89104

90-
int main() {
105+
int foobar(int ub[]) {
91106
static int argc;
107+
int *ptr;
92108
#pragma omp simd reduction(inscan, +: argc)
93109
for (int i = 0; i < 10; ++i) {
94110
#pragma omp scan inclusive(argc) inclusive(argc) // expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
@@ -177,6 +193,16 @@ label1 : {
177193
#pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}}
178194
}
179195
}
196+
#pragma omp simd reduction(inscan, +: argc)
197+
for (int i = 0; i < 10; ++i) {
198+
#pragma omp scan inclusive(ptr[0:], argc) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
199+
;
200+
}
201+
#pragma omp simd reduction(inscan, +: argc)
202+
for (int i = 0; i < 10; ++i) {
203+
#pragma omp scan exclusive(argc, ub[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
204+
;
205+
}
180206

181-
return tmain<int>(); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}}
207+
return tfoobar<int>(ub); // expected-note {{in instantiation of function template specialization 'tfoobar<int>' requested here}}
182208
}

0 commit comments

Comments
 (0)