cchen updated this revision to Diff 274275.
cchen added a comment.
1. Remove a commit that is not on master branch
2. Add a rule in Sema to avoid non-contiguous array section for map clause
3. Add tests
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D82800/new/
https://reviews.llvm.org/D82800
Files:
clang/include/clang-c/Index.h
clang/include/clang/AST/ExprOpenMP.h
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/AST/StmtPrinter.cpp
clang/lib/CodeGen/CGExpr.cpp
clang/lib/CodeGen/CGOpenMPRuntime.cpp
clang/lib/Parse/ParseExpr.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/test/OpenMP/target_data_messages.c
clang/test/OpenMP/target_depend_messages.cpp
clang/test/OpenMP/target_enter_data_depend_messages.cpp
clang/test/OpenMP/target_exit_data_depend_messages.cpp
clang/test/OpenMP/target_map_messages.cpp
clang/test/OpenMP/target_parallel_depend_messages.cpp
clang/test/OpenMP/target_parallel_for_depend_messages.cpp
clang/test/OpenMP/target_parallel_for_simd_depend_messages.cpp
clang/test/OpenMP/target_simd_depend_messages.cpp
clang/test/OpenMP/target_teams_depend_messages.cpp
clang/test/OpenMP/target_teams_distribute_depend_messages.cpp
clang/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp
clang/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp
clang/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp
clang/test/OpenMP/target_update_ast_print.cpp
clang/test/OpenMP/target_update_depend_messages.cpp
clang/test/OpenMP/target_update_messages.cpp
clang/test/OpenMP/task_affinity_messages.cpp
clang/test/OpenMP/task_depend_messages.cpp
Index: clang/test/OpenMP/task_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/task_depend_messages.cpp
+++ clang/test/OpenMP/task_depend_messages.cpp
@@ -52,7 +52,7 @@
#pragma omp task depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
#pragma omp task depend (in : argv[-1:0]) // expected-error {{zero-length array section is not allowed in 'depend' clause}}
#pragma omp task depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
- #pragma omp task depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ #pragma omp task depend (in : argv[3:4:1]) // omp45-error {{expected ']'}} omp45-note {{to match this '['}}
#pragma omp task depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
#pragma omp task depend(in:argv[argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}}
#pragma omp task depend(in:argv[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
Index: clang/test/OpenMP/task_affinity_messages.cpp
===================================================================
--- clang/test/OpenMP/task_affinity_messages.cpp
+++ clang/test/OpenMP/task_affinity_messages.cpp
@@ -44,7 +44,7 @@
#pragma omp task affinity (argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
#pragma omp task affinity (argv[-1:0])
#pragma omp task affinity (argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
- #pragma omp task affinity (argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ #pragma omp task affinity (argv[3:4:1])
#pragma omp task affinity(a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
#pragma omp task affinity(argv[argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}}
#pragma omp task affinity(argv[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
Index: clang/test/OpenMP/target_update_messages.cpp
===================================================================
--- clang/test/OpenMP/target_update_messages.cpp
+++ clang/test/OpenMP/target_update_messages.cpp
@@ -1,6 +1,8 @@
-// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp -fopenmp-version=45 -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -fopenmp-version=50 -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized
-// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized
void xxx(int argc) {
int x; // expected-note {{initialize the variable 'x' to silence this warning}}
@@ -36,5 +38,11 @@
{
foo();
}
+
+ int iarr[5][5];
+#pragma omp target update to(iarr[0:][1:2:-1]) // omp50-error {{section stride is evaluated to a non-positive value -1}} omp45-error {{expected ']'}} omp45-note {{to match this '['}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+ {}
+#pragma omp target update from(iarr[0:][1:2:-1]) // omp50-error {{section stride is evaluated to a non-positive value -1}} omp45-error {{expected ']'}} omp45-note {{to match this '['}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+
return tmain(argc, argv);
}
Index: clang/test/OpenMP/target_update_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_update_depend_messages.cpp
+++ clang/test/OpenMP/target_update_depend_messages.cpp
@@ -54,7 +54,7 @@
#pragma omp target update to(z) depend(in : argv [0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
#pragma omp target update to(z) depend(in : argv [-1:0]) // expected-error {{zero-length array section is not allowed in 'depend' clause}}
#pragma omp target update to(z) depend(in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
-#pragma omp target update to(z) depend(in : argv [3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+#pragma omp target update to(z) depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
#pragma omp target update to(z) depend(in : a [0:1]) // expected-error {{subscripted value is not an array or pointer}}
#pragma omp target update to(z) depend(in : argv [argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}}
#pragma omp target update to(z) depend(in : argv [0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
@@ -101,7 +101,7 @@
#pragma omp target update to(z) depend(in : argv [0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
#pragma omp target update to(z) depend(in : argv [-1:0]) // expected-error {{zero-length array section is not allowed in 'depend' clause}}
#pragma omp target update to(z) depend(in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
-#pragma omp target update to(z) depend(in : argv [3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+#pragma omp target update to(z) depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
#pragma omp target update to(z) depend(in : a [0:1]) // expected-error {{subscripted value is not an array or pointer}}
#pragma omp target update to(z) depend(in : argv [argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}}
#pragma omp target update to(z) depend(in : argv [0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
Index: clang/test/OpenMP/target_update_ast_print.cpp
===================================================================
--- clang/test/OpenMP/target_update_ast_print.cpp
+++ clang/test/OpenMP/target_update_ast_print.cpp
@@ -20,6 +20,11 @@
#pragma omp target update to(([a][targ])p, a) if(l>5) device(l) nowait depend(inout:l)
#pragma omp target update from(b, ([a][targ])p) if(l<5) device(l-1) nowait depend(inout:l)
+
+ int arr[100][100];
+#pragma omp target update to(arr[2][0:1:2])
+
+#pragma omp target update from(arr[2][0:1:2])
return a + targ + (T)b;
}
// CHECK: static T a, *p;
@@ -37,6 +42,9 @@
// CHECK-NEXT: int l;
// CHECK-NEXT: #pragma omp target update to(([a][targ])p,a) if(l > 5) device(l) nowait depend(inout : l)
// CHECK-NEXT: #pragma omp target update from(b,([a][targ])p) if(l < 5) device(l - 1) nowait depend(inout : l)
+// CHECK: int arr[100][100];
+// CHECK-NEXT: #pragma omp target update to(arr[2][0:1:2])
+// CHECK-NEXT: #pragma omp target update from(arr[2][0:1:2])
int main(int argc, char **argv) {
static int a;
@@ -50,6 +58,11 @@
// CHECK-NEXT: #pragma omp target update to(a) if(f > 0.) device(n) nowait depend(in : n)
#pragma omp target update from(f) if(f<0.0) device(n+1) nowait depend(in:n)
// CHECK-NEXT: #pragma omp target update from(f) if(f < 0.) device(n + 1) nowait depend(in : n)
+#pragma omp target update to(argv[2][0:1:2])
+// CHECK-NEXT: #pragma omp target update to(argv[2][0:1:2])
+#pragma omp target update from(argv[2][0:1:2])
+// CHECK-NEXT: #pragma omp target update from(argv[2][0:1:2])
+
return foo(argc, f) + foo(argv[0][0], f) + a;
}
Index: clang/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp
+++ clang/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp
@@ -78,7 +78,7 @@
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute simd depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute simd depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+#pragma omp target teams distribute simd depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute simd depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
for (i = 0; i < argc; ++i) foo();
Index: clang/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp
+++ clang/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp
@@ -79,7 +79,7 @@
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for simd depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for simd depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+#pragma omp target teams distribute parallel for simd depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for simd depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
for (i = 0; i < argc; ++i) foo();
Index: clang/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp
+++ clang/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp
@@ -79,7 +79,7 @@
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute parallel for depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+#pragma omp target teams distribute parallel for depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute parallel for depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
for (i = 0; i < argc; ++i) foo();
Index: clang/test/OpenMP/target_teams_distribute_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_teams_distribute_depend_messages.cpp
+++ clang/test/OpenMP/target_teams_distribute_depend_messages.cpp
@@ -78,7 +78,7 @@
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
for (i = 0; i < argc; ++i) foo();
-#pragma omp target teams distribute depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+#pragma omp target teams distribute depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target teams distribute depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
for (i = 0; i < argc; ++i) foo();
Index: clang/test/OpenMP/target_teams_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_teams_depend_messages.cpp
+++ clang/test/OpenMP/target_teams_depend_messages.cpp
@@ -74,7 +74,7 @@
foo();
#pragma omp target teams depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
-#pragma omp target teams depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+#pragma omp target teams depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
foo();
#pragma omp target teams depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
foo();
Index: clang/test/OpenMP/target_simd_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_simd_depend_messages.cpp
+++ clang/test/OpenMP/target_simd_depend_messages.cpp
@@ -82,7 +82,7 @@
for (i = 0; i < argc; ++i) foo();
#pragma omp target simd depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
for (i = 0; i < argc; ++i) foo();
- #pragma omp target simd depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ #pragma omp target simd depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target simd depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
for (i = 0; i < argc; ++i) foo();
Index: clang/test/OpenMP/target_parallel_for_simd_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_parallel_for_simd_depend_messages.cpp
+++ clang/test/OpenMP/target_parallel_for_simd_depend_messages.cpp
@@ -82,7 +82,7 @@
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
for (i = 0; i < argc; ++i) foo();
- #pragma omp target parallel for simd depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ #pragma omp target parallel for simd depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for simd depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
for (i = 0; i < argc; ++i) foo();
Index: clang/test/OpenMP/target_parallel_for_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_parallel_for_depend_messages.cpp
+++ clang/test/OpenMP/target_parallel_for_depend_messages.cpp
@@ -82,7 +82,7 @@
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
for (i = 0; i < argc; ++i) foo();
- #pragma omp target parallel for depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ #pragma omp target parallel for depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
for (i = 0; i < argc; ++i) foo();
#pragma omp target parallel for depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
for (i = 0; i < argc; ++i) foo();
Index: clang/test/OpenMP/target_parallel_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_parallel_depend_messages.cpp
+++ clang/test/OpenMP/target_parallel_depend_messages.cpp
@@ -74,7 +74,7 @@
foo();
#pragma omp target parallel depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
- #pragma omp target parallel depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ #pragma omp target parallel depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
foo();
#pragma omp target parallel depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
foo();
Index: clang/test/OpenMP/target_map_messages.cpp
===================================================================
--- clang/test/OpenMP/target_map_messages.cpp
+++ clang/test/OpenMP/target_map_messages.cpp
@@ -550,6 +550,12 @@
#pragma omp target data map(tofrom, close: x) // expected-error {{incorrect map type modifier, expected 'always', 'close', or 'mapper'}} expected-error {{missing map type}}
#pragma omp target data map(close, tofrom: close, tofrom, x)
foo();
+
+ T marr[10][10], iarr[5];
+#pragma omp target data map(marr[10][0:2:2]) // le50-error 2 {{array section does not specify contiguous storage}} le45-error {{expected ']'}} le45-note {{to match this '['}}
+ {}
+#pragma omp target data map(iarr[:2:d]) // le50-error 2 {{array section does not specify contiguous storage}} le45-error {{expected ']'}} le45-note {{to match this '['}}
+ {}
return 0;
}
@@ -737,6 +743,13 @@
#pragma omp target map(release: a) // expected-error {{map type 'release' is not allowed for '#pragma omp target'}}
{}
+ int marr[10][10], iarr[5];
+
+#pragma omp target map(marr[10][0:2:2]) // le50-error {{array section does not specify contiguous storage}} le45-error {{expected ']'}} le45-note {{to match this '['}}
+ {}
+#pragma omp target map(iarr[:2:d]) // le50-error {{array section does not specify contiguous storage}} le45-error {{expected ']'}} le45-note {{to match this '['}}
+ {}
+
return tmain<int, 3>(argc)+tmain<from, 4>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<int, 4>' requested here}}
}
#endif
Index: clang/test/OpenMP/target_exit_data_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_exit_data_depend_messages.cpp
+++ clang/test/OpenMP/target_exit_data_depend_messages.cpp
@@ -76,7 +76,7 @@
foo();
#pragma omp target exit data map(from: i) depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
- #pragma omp target exit data map(from: i) depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ #pragma omp target exit data map(from : i) depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
foo();
#pragma omp target exit data map(from: i) depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
foo();
@@ -151,7 +151,7 @@
foo();
#pragma omp target exit data map(from: i) depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
- #pragma omp target exit data map(from: i) depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ #pragma omp target exit data map(from : i) depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
foo();
#pragma omp target exit data map(from: i) depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
foo();
Index: clang/test/OpenMP/target_enter_data_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_enter_data_depend_messages.cpp
+++ clang/test/OpenMP/target_enter_data_depend_messages.cpp
@@ -76,7 +76,7 @@
foo();
#pragma omp target enter data map(to: i) depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
- #pragma omp target enter data map(to: i) depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+#pragma omp target enter data map(to : i) depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
foo();
#pragma omp target enter data map(to: i) depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
foo();
@@ -149,9 +149,9 @@
foo();
#pragma omp target enter data map(to: i) depend (in : argv[-1:0]) // expected-error {{zero-length array section is not allowed in 'depend' clause}}
foo();
- #pragma omp target enter data map(to: i) depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ #pragma omp target enter data map(to: i) depend(in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
- #pragma omp target enter data map(to: i) depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ #pragma omp target enter data map(to : i) depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
foo();
#pragma omp target enter data map(to: i) depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
foo();
Index: clang/test/OpenMP/target_depend_messages.cpp
===================================================================
--- clang/test/OpenMP/target_depend_messages.cpp
+++ clang/test/OpenMP/target_depend_messages.cpp
@@ -80,7 +80,7 @@
foo();
#pragma omp target depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
foo();
- #pragma omp target depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
+ #pragma omp target depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
foo();
#pragma omp target depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
foo();
Index: clang/test/OpenMP/target_data_messages.c
===================================================================
--- clang/test/OpenMP/target_data_messages.c
+++ clang/test/OpenMP/target_data_messages.c
@@ -45,5 +45,12 @@
{
foo();
}
+
+ const int b = 5;
+ int marr[10][10], iarr[5];
+#pragma omp target data map(to: marr[10][0:2:2]) // omp50-error {{array section does not specify contiguous storage}} omp45-error {{expected ']'}} omp45-note {{to match this '['}}
+ {}
+#pragma omp target data map(alloc: iarr[:2:b]) // omp50-error {{array section does not specify contiguous storage}} omp45-error {{expected ']'}} omp45-note {{to match this '['}}
+ {}
return 0;
}
Index: clang/lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterStmt.cpp
+++ clang/lib/Serialization/ASTWriterStmt.cpp
@@ -797,7 +797,9 @@
Record.AddStmt(E->getBase());
Record.AddStmt(E->getLowerBound());
Record.AddStmt(E->getLength());
- Record.AddSourceLocation(E->getColonLoc());
+ Record.AddStmt(E->getStride());
+ Record.AddSourceLocation(E->getColonLocFirst());
+ Record.AddSourceLocation(E->getColonLocSecond());
Record.AddSourceLocation(E->getRBracketLoc());
Code = serialization::EXPR_OMP_ARRAY_SECTION;
}
Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -937,7 +937,9 @@
E->setBase(Record.readSubExpr());
E->setLowerBound(Record.readSubExpr());
E->setLength(Record.readSubExpr());
- E->setColonLoc(readSourceLocation());
+ E->setStride(Record.readSubExpr());
+ E->setColonLocFirst(readSourceLocation());
+ E->setColonLocSecond(readSourceLocation());
E->setRBracketLoc(readSourceLocation());
}
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -2436,10 +2436,13 @@
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildOMPArraySectionExpr(Expr *Base, SourceLocation LBracketLoc,
Expr *LowerBound,
- SourceLocation ColonLoc, Expr *Length,
+ SourceLocation ColonLocFirst,
+ SourceLocation ColonLocSecond,
+ Expr *Length, Expr *Stride,
SourceLocation RBracketLoc) {
return getSema().ActOnOMPArraySectionExpr(Base, LBracketLoc, LowerBound,
- ColonLoc, Length, RBracketLoc);
+ ColonLocFirst, ColonLocSecond,
+ Length, Stride, RBracketLoc);
}
/// Build a new array shaping expression.
@@ -10337,13 +10340,21 @@
return ExprError();
}
+ ExprResult Stride;
+ if (E->getStride()) {
+ Stride = getDerived().TransformExpr(E->getStride());
+ if (Stride.isInvalid())
+ return ExprError();
+ }
+
if (!getDerived().AlwaysRebuild() && Base.get() == E->getBase() &&
LowerBound.get() == E->getLowerBound() && Length.get() == E->getLength())
return E;
return getDerived().RebuildOMPArraySectionExpr(
- Base.get(), E->getBase()->getEndLoc(), LowerBound.get(), E->getColonLoc(),
- Length.get(), E->getRBracketLoc());
+ Base.get(), E->getBase()->getEndLoc(), LowerBound.get(),
+ E->getColonLocFirst(), E->getColonLocSecond(), Length.get(), Stride.get(),
+ E->getRBracketLoc());
}
template <typename Derived>
Index: clang/lib/Sema/SemaOpenMP.cpp
===================================================================
--- clang/lib/Sema/SemaOpenMP.cpp
+++ clang/lib/Sema/SemaOpenMP.cpp
@@ -14675,7 +14675,7 @@
if (Length == nullptr) {
// For array sections of the form [1:] or [:], we would need to analyze
// the lower bound...
- if (OASE->getColonLoc().isValid())
+ if (OASE->getColonLocFirst().isValid())
return false;
// This is an array subscript which has implicit length 1!
@@ -14701,7 +14701,7 @@
if (Length == nullptr) {
// For array sections of the form [1:] or [:], we would need to analyze
// the lower bound...
- if (OASE->getColonLoc().isValid())
+ if (OASE->getColonLocFirst().isValid())
return false;
// This is an array subscript which has implicit length 1!
@@ -16458,7 +16458,8 @@
// If this is an array subscript, it refers to the whole size if the size of
// the dimension is constant and equals 1. Also, an array section assumes the
// format of an array subscript if no colon is used.
- if (isa<ArraySubscriptExpr>(E) || (OASE && OASE->getColonLoc().isInvalid())) {
+ if (isa<ArraySubscriptExpr>(E) ||
+ (OASE && OASE->getColonLocFirst().isInvalid())) {
if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
return ATy->getSize().getSExtValue() != 1;
// Size can't be evaluated statically.
@@ -16514,7 +16515,8 @@
// An array subscript always refer to a single element. Also, an array section
// assumes the format of an array subscript if no colon is used.
- if (isa<ArraySubscriptExpr>(E) || (OASE && OASE->getColonLoc().isInvalid()))
+ if (isa<ArraySubscriptExpr>(E) ||
+ (OASE && OASE->getColonLocFirst().isInvalid()))
return false;
assert(OASE && "Expecting array section if not an array subscript.");
@@ -16558,7 +16560,7 @@
//
// We want to retrieve the member expression 'this->S';
-// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.2]
+// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
// If a list item is an array section, it must specify contiguous storage.
//
// For this restriction it is sufficient that we make sure only references
@@ -16789,6 +16791,19 @@
RelevantExpr = TE;
}
+ // Stride can only be null or one for map clause
+ if (CKind == OMPC_map && OASE->getStride()) {
+ Expr::EvalResult Result;
+ if (!OASE->getStride()->isValueDependent() &&
+ OASE->getStride()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
+ !Result.Val.getInt().isOneValue()) {
+ SemaRef.Diag(
+ OASE->getStride()->getExprLoc(),
+ diag::err_array_section_does_not_specify_contiguous_storage)
+ << OASE->getSourceRange();
+ }
+ }
+
// Record the component - we don't have any declaration associated.
Components.emplace_back(OASE, nullptr);
return RelevantExpr || Visit(E);
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -4560,7 +4560,8 @@
if (base && !base->getType().isNull() &&
base->getType()->isSpecificPlaceholderType(BuiltinType::OMPArraySection))
return ActOnOMPArraySectionExpr(base, lbLoc, idx, SourceLocation(),
- /*Length=*/nullptr, rbLoc);
+ SourceLocation(), /*Length*/ nullptr,
+ /*Stride=*/nullptr, rbLoc);
// Since this might be a postfix expression, get rid of ParenListExprs.
if (isa<ParenListExpr>(base)) {
@@ -4810,7 +4811,9 @@
ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
Expr *LowerBound,
- SourceLocation ColonLoc, Expr *Length,
+ SourceLocation ColonLocFirst,
+ SourceLocation ColonLocSecond,
+ Expr *Length, Expr *Stride,
SourceLocation RBLoc) {
if (Base->getType()->isPlaceholderType() &&
!Base->getType()->isSpecificPlaceholderType(
@@ -4838,15 +4841,25 @@
return ExprError();
Length = Result.get();
}
+ if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
+ ExprResult Result = CheckPlaceholderExpr(Stride);
+ if (Result.isInvalid())
+ return ExprError();
+ Result = DefaultLvalueConversion(Result.get());
+ if (Result.isInvalid())
+ return ExprError();
+ Stride = Result.get();
+ }
// Build an unanalyzed expression if either operand is type-dependent.
if (Base->isTypeDependent() ||
(LowerBound &&
(LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
- (Length && (Length->isTypeDependent() || Length->isValueDependent()))) {
- return new (Context)
- OMPArraySectionExpr(Base, LowerBound, Length, Context.DependentTy,
- VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
+ (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
+ (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
+ return new (Context) OMPArraySectionExpr(
+ Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
+ OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
}
// Perform default conversions.
@@ -4890,6 +4903,20 @@
Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
<< 1 << Length->getSourceRange();
}
+ if (Stride) {
+ ExprResult Res =
+ PerformOpenMPImplicitIntegerConversion(Stride->getExprLoc(), Stride);
+ if (Res.isInvalid())
+ return ExprError(Diag(Stride->getExprLoc(),
+ diag::err_omp_typecheck_section_not_integer)
+ << 1 << Stride->getSourceRange());
+ Stride = Res.get();
+
+ if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
+ Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
+ << 1 << Stride->getSourceRange();
+ }
// C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
// C++ [expr.sub]p1: The type "T" shall be a completely-defined object
@@ -4908,7 +4935,7 @@
if (LowerBound && !OriginalTy->isAnyPointerType()) {
Expr::EvalResult Result;
if (LowerBound->EvaluateAsInt(Result, Context)) {
- // OpenMP 4.5, [2.4 Array Sections]
+ // OpenMP 5.0, [2.1.5 Array Sections]
// The array section must be a subset of the original array.
llvm::APSInt LowerBoundValue = Result.Val.getInt();
if (LowerBoundValue.isNegative()) {
@@ -4922,7 +4949,7 @@
if (Length) {
Expr::EvalResult Result;
if (Length->EvaluateAsInt(Result, Context)) {
- // OpenMP 4.5, [2.4 Array Sections]
+ // OpenMP 5.0, [2.1.5 Array Sections]
// The length must evaluate to non-negative integers.
llvm::APSInt LengthValue = Result.Val.getInt();
if (LengthValue.isNegative()) {
@@ -4932,17 +4959,32 @@
return ExprError();
}
}
- } else if (ColonLoc.isValid() &&
+ } else if (ColonLocFirst.isValid() &&
(OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
!OriginalTy->isVariableArrayType()))) {
- // OpenMP 4.5, [2.4 Array Sections]
+ // OpenMP 5.0, [2.1.5 Array Sections]
// When the size of the array dimension is not known, the length must be
// specified explicitly.
- Diag(ColonLoc, diag::err_omp_section_length_undefined)
+ Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
<< (!OriginalTy.isNull() && OriginalTy->isArrayType());
return ExprError();
}
+ if (Stride) {
+ Expr::EvalResult Result;
+ if (Stride->EvaluateAsInt(Result, Context)) {
+ // OpenMP 5.0, [2.1.5 Array Sections]
+ // The stride must evaluate to a positive integer.
+ llvm::APSInt StrideValue = Result.Val.getInt();
+ if (!StrideValue.isStrictlyPositive()) {
+ Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
+ << StrideValue.toString(/*Radix=*/10, /*Signed=*/true)
+ << Stride->getSourceRange();
+ return ExprError();
+ }
+ }
+ }
+
if (!Base->getType()->isSpecificPlaceholderType(
BuiltinType::OMPArraySection)) {
ExprResult Result = DefaultFunctionArrayLvalueConversion(Base);
@@ -4950,9 +4992,9 @@
return ExprError();
Base = Result.get();
}
- return new (Context)
- OMPArraySectionExpr(Base, LowerBound, Length, Context.OMPArraySectionTy,
- VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
+ return new (Context) OMPArraySectionExpr(
+ Base, LowerBound, Length, Stride, Context.OMPArraySectionTy, VK_LValue,
+ OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
}
ExprResult Sema::ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc,
Index: clang/lib/Parse/ParseExpr.cpp
===================================================================
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -1845,8 +1845,8 @@
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
Loc = T.getOpenLocation();
- ExprResult Idx, Length;
- SourceLocation ColonLoc;
+ ExprResult Idx, Length, Stride;
+ SourceLocation ColonLocFirst, ColonLocSecond;
PreferredType.enterSubscript(Actions, Tok.getLocation(), LHS.get());
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
@@ -1860,10 +1860,19 @@
}
if (Tok.is(tok::colon)) {
// Consume ':'
- ColonLoc = ConsumeToken();
+ ColonLocFirst = ConsumeToken();
if (Tok.isNot(tok::r_square))
- Length = ParseExpression();
+ if (getLangOpts().OpenMP < 50 ||
+ ((Tok.isNot(tok::colon) && getLangOpts().OpenMP >= 50)))
+ Length = ParseExpression();
}
+ if (getLangOpts().OpenMP >= 50)
+ if (Tok.is(tok::colon)) {
+ // Consume ':'
+ ColonLocSecond = ConsumeToken();
+ if (Tok.isNot(tok::r_square))
+ Stride = ParseExpression();
+ }
} else
Idx = ParseExpression();
@@ -1873,10 +1882,11 @@
Idx = Actions.CorrectDelayedTyposInExpr(Idx);
Length = Actions.CorrectDelayedTyposInExpr(Length);
if (!LHS.isInvalid() && !Idx.isInvalid() && !Length.isInvalid() &&
- Tok.is(tok::r_square)) {
- if (ColonLoc.isValid()) {
- LHS = Actions.ActOnOMPArraySectionExpr(LHS.get(), Loc, Idx.get(),
- ColonLoc, Length.get(), RLoc);
+ !Stride.isInvalid() && Tok.is(tok::r_square)) {
+ if (ColonLocFirst.isValid() || ColonLocSecond.isValid()) {
+ LHS = Actions.ActOnOMPArraySectionExpr(
+ LHS.get(), Loc, Idx.get(), ColonLocFirst, ColonLocSecond,
+ Length.get(), Stride.get(), RLoc);
} else {
LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc,
Idx.get(), RLoc);
Index: clang/lib/CodeGen/CGOpenMPRuntime.cpp
===================================================================
--- clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7178,7 +7178,7 @@
// If there is no length associated with the expression and lower bound is
// not specified too, that means we are using the whole length of the
// base.
- if (!OAE->getLength() && OAE->getColonLoc().isValid() &&
+ if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
!OAE->getLowerBound())
return CGF.getTypeSize(BaseTy);
@@ -7193,7 +7193,7 @@
// If we don't have a length at this point, that is because we have an
// array section with a single element.
- if (!OAE->getLength() && OAE->getColonLoc().isInvalid())
+ if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
return ElemSize;
if (const Expr *LenExpr = OAE->getLength()) {
@@ -7203,7 +7203,7 @@
LenExpr->getExprLoc());
return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
}
- assert(!OAE->getLength() && OAE->getColonLoc().isValid() &&
+ assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
OAE->getLowerBound() && "expected array_section[lb:].");
// Size = sizetype - lb * elemtype;
llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
@@ -7276,7 +7276,7 @@
return false;
// An array section with no colon always refer to a single element.
- if (OASE->getColonLoc().isInvalid())
+ if (OASE->getColonLocFirst().isInvalid())
return false;
const Expr *Length = OASE->getLength();
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -3849,7 +3849,7 @@
else
ResultExprTy = BaseTy->getPointeeType();
llvm::Value *Idx = nullptr;
- if (IsLowerBound || E->getColonLoc().isInvalid()) {
+ if (IsLowerBound || E->getColonLocFirst().isInvalid()) {
// Requesting lower bound or upper bound, but without provided length and
// without ':' symbol for the default length -> length = 1.
// Idx = LowerBound ?: 0;
Index: clang/lib/AST/StmtPrinter.cpp
===================================================================
--- clang/lib/AST/StmtPrinter.cpp
+++ clang/lib/AST/StmtPrinter.cpp
@@ -1343,11 +1343,16 @@
OS << "[";
if (Node->getLowerBound())
PrintExpr(Node->getLowerBound());
- if (Node->getColonLoc().isValid()) {
+ if (Node->getColonLocFirst().isValid()) {
OS << ":";
if (Node->getLength())
PrintExpr(Node->getLength());
}
+ if (Node->getColonLocSecond().isValid()) {
+ OS << ":";
+ if (Node->getStride())
+ PrintExpr(Node->getStride());
+ }
OS << "]";
}
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -4940,8 +4940,11 @@
SourceLocation RBLoc);
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
- Expr *LowerBound, SourceLocation ColonLoc,
- Expr *Length, SourceLocation RBLoc);
+ Expr *LowerBound,
+ SourceLocation ColonLocFirst,
+ SourceLocation ColonLocSecond,
+ Expr *Length, Expr *Stride,
+ SourceLocation RBLoc);
ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc,
SourceLocation RParenLoc,
ArrayRef<Expr *> Dims,
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10052,6 +10052,8 @@
"array section must be a subset of the original array">;
def err_omp_section_length_negative : Error<
"section length is evaluated to a negative value %0">;
+def err_omp_section_stride_non_positive : Error<
+ "section stride is evaluated to a non-positive value %0">;
def err_omp_section_length_undefined : Error<
"section length is unspecified and cannot be inferred because subscripted value is %select{not an array|an array of unknown bound}0">;
def err_omp_wrong_linear_modifier : Error<
Index: clang/include/clang/AST/ExprOpenMP.h
===================================================================
--- clang/include/clang/AST/ExprOpenMP.h
+++ clang/include/clang/AST/ExprOpenMP.h
@@ -15,48 +15,64 @@
#include "clang/AST/ComputeDependence.h"
#include "clang/AST/Expr.h"
+#include "clang/Basic/SourceLocation.h"
namespace clang {
-/// OpenMP 4.0 [2.4, Array Sections].
+/// OpenMP 5.0 [2.1.5, Array Sections].
/// To specify an array section in an OpenMP construct, array subscript
/// expressions are extended with the following syntax:
/// \code
+/// [ lower-bound : length : stride ]
+/// [ lower-bound : length : ]
/// [ lower-bound : length ]
+/// [ lower-bound : : stride ]
+/// [ lower-bound : : ]
/// [ lower-bound : ]
+/// [ : length : stride ]
+/// [ : length : ]
/// [ : length ]
+/// [ : : stride ]
+/// [ : : ]
/// [ : ]
/// \endcode
/// The array section must be a subset of the original array.
/// Array sections are allowed on multidimensional arrays. Base language array
/// subscript expressions can be used to specify length-one dimensions of
/// multidimensional array sections.
-/// The lower-bound and length are integral type expressions. When evaluated
+/// Each of the lower-bound, length, and stride expressions if specified must be
+/// an integral type expressions of the base language. When evaluated
/// they represent a set of integer values as follows:
/// \code
-/// { lower-bound, lower-bound + 1, lower-bound + 2,... , lower-bound + length -
-/// 1 }
+/// { lower-bound, lower-bound + stride, lower-bound + 2 * stride,... ,
+/// lower-bound + ((length - 1) * stride) }
/// \endcode
/// The lower-bound and length must evaluate to non-negative integers.
+/// The stride must evaluate to a positive integer.
/// When the size of the array dimension is not known, the length must be
/// specified explicitly.
-/// When the length is absent, it defaults to the size of the array dimension
-/// minus the lower-bound.
-/// When the lower-bound is absent it defaults to 0.
+/// When the stride is absent it defaults to 1.
+/// When the length is absent it defaults to ⌈(size − lower-bound)/stride⌉,
+/// where size is the size of the array dimension. When the lower-bound is
+/// absent it defaults to 0.
class OMPArraySectionExpr : public Expr {
- enum { BASE, LOWER_BOUND, LENGTH, END_EXPR };
+ enum { BASE, LOWER_BOUND, LENGTH, STRIDE, END_EXPR };
Stmt *SubExprs[END_EXPR];
- SourceLocation ColonLoc;
+ SourceLocation ColonLocFirst;
+ SourceLocation ColonLocSecond;
SourceLocation RBracketLoc;
public:
- OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type,
- ExprValueKind VK, ExprObjectKind OK,
- SourceLocation ColonLoc, SourceLocation RBracketLoc)
- : Expr(OMPArraySectionExprClass, Type, VK, OK), ColonLoc(ColonLoc),
+ OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, Expr *Stride,
+ QualType Type, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation ColonLocFirst,
+ SourceLocation ColonLocSecond, SourceLocation RBracketLoc)
+ : Expr(OMPArraySectionExprClass, Type, VK, OK),
+ ColonLocFirst(ColonLocFirst), ColonLocSecond(ColonLocSecond),
RBracketLoc(RBracketLoc) {
SubExprs[BASE] = Base;
SubExprs[LOWER_BOUND] = LowerBound;
SubExprs[LENGTH] = Length;
+ SubExprs[STRIDE] = Stride;
setDependence(computeDependence(this));
}
@@ -89,13 +105,22 @@
/// Set length of the array section.
void setLength(Expr *E) { SubExprs[LENGTH] = E; }
+ /// Get stride of array section.
+ Expr *getStride() { return cast_or_null<Expr>(SubExprs[STRIDE]); }
+ const Expr *getStride() const { return cast_or_null<Expr>(SubExprs[STRIDE]); }
+ /// Set length of the array section.
+ void setStride(Expr *E) { SubExprs[STRIDE] = E; }
+
SourceLocation getBeginLoc() const LLVM_READONLY {
return getBase()->getBeginLoc();
}
SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }
- SourceLocation getColonLoc() const { return ColonLoc; }
- void setColonLoc(SourceLocation L) { ColonLoc = L; }
+ SourceLocation getColonLocFirst() const { return ColonLocFirst; }
+ void setColonLocFirst(SourceLocation L) { ColonLocFirst = L; }
+
+ SourceLocation getColonLocSecond() const { return ColonLocSecond; }
+ void setColonLocSecond(SourceLocation L) { ColonLocSecond = L; }
SourceLocation getRBracketLoc() const { return RBracketLoc; }
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
Index: clang/include/clang-c/Index.h
===================================================================
--- clang/include/clang-c/Index.h
+++ clang/include/clang-c/Index.h
@@ -2167,7 +2167,7 @@
*/
CXCursor_ObjCSelfExpr = 147,
- /** OpenMP 4.0 [2.4, Array Section].
+ /** OpenMP 5.0 [2.1.5, Array Section].
*/
CXCursor_OMPArraySectionExpr = 148,
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits