cchen created this revision.
cchen added a reviewer: ABataev.
Herald added subscribers: cfe-commits, sstefan1, arphaman, guansong, yaxunl.
Herald added a reviewer: jdoerfert.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

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_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_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,32 +52,60 @@
   #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: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}}
-  #pragma omp task depend(in:env[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
-  #pragma omp task depend(in : argv[ : argc][1 : argc - 1])
-  #pragma omp task depend(in : arr[0])
-  #pragma omp task depend(depobj:argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}
-  #pragma omp task depend(depobj : argv[ : argc][1 : argc - 1]) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected lvalue expression of 'omp_depend_t' type, not '<OpenMP array section type>'}}
-  #pragma omp task depend(depobj : arr[0]) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}}
-  #pragma omp task depend(in : ([ // expected-error {{expected variable name or 'this' in lambda capture list}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-  #pragma omp task depend(in : ([] // expected-error {{expected body of lambda expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-  #pragma omp task depend(in : ([]) // omp45-error {{expected body of lambda expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} omp50-error 2 {{expected expression}}
-  #pragma omp task depend(in : ([])a // omp45-error {{expected body of lambda expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} omp50-error {{expected expression}}
-  #pragma omp task depend(in : ([])a) // omp45-error {{expected body of lambda expression}} omp50-error {{expected expression}}
-  #pragma omp task depend(in : ([a])a) // omp45-error {{expected body of lambda expression}} omp50-error {{expected expression with a pointer to a complete type as a base of an array shaping operation}}
-  #pragma omp task depend(in : ([a])argc) // omp45-error {{expected body of lambda expression}} omp50-error {{expected expression with a pointer to a complete type as a base of an array shaping operation}}
-  #pragma omp task depend(in : ([-1][0])argv) // omp45-error {{expected variable name or 'this' in lambda capture list}} omp45-error {{expected ')'}} omp45-note {{to match this '('}} omp50-error {{array shaping dimension is evaluated to a non-positive value -1}} omp50-error {{array shaping dimension is evaluated to a non-positive value 0}}
-  #pragma omp task depend(iterator // expected-error {{expected ')'}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-note {{to match this '('}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected '(' after 'iterator'}} omp50-error {{expected ','}}
-  #pragma omp task depend(iterator():argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected ','}} omp50-error {{expected 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
-  #pragma omp task depend(iterator(argc // expected-error {{expected ')'}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-note {{to match this '('}} omp50-error {{unknown type name 'argc'}} omp50-error {{expected ')'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected ','}} omp50-note {{to match this '('}}
-  #pragma omp task depend(iterator(unsigned argc: // expected-error {{expected ')'}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-note {{to match this '('}} omp50-error {{expected '=' in iterator specifier}} omp50-error 2 {{expected expression}} omp50-error {{expected ',' or ')' after iterator specifier}} omp50-error {{expected ')'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected ','}} omp50-note {{to match this '('}}
-  #pragma omp task depend(iterator(unsigned argc = // expected-error {{expected ')'}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-note {{to match this '('}} omp50-error 2 {{expected expression}} omp50-error {{expected ',' or ')' after iterator specifier}} omp50-error {{expected ')'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected ','}} omp50-note {{to match this '('}}
-  #pragma omp task depend(iterator(vector argc = 0:2):argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected integral or pointer type as the iterator-type, not 'vector'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected ','}}
-  #pragma omp task depend(iterator(vector *argc = nullptr:nullptr+2:0), in:argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{invalid operands to binary expression ('nullptr_t' and 'int')}} omp50-error {{iterator step expression 0 evaluates to 0}}
-  #pragma omp task depend(iterator(vector *argc = 0:vector():argc), in:argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{converting 'vector' to incompatible type 'vector *'}}
+#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}}
+#pragma omp task depend(in \
+                        : env [0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
+#pragma omp task depend(in \
+                        : argv[:argc] [1:argc - 1])
+#pragma omp task depend(in \
+                        : arr[0])
+#pragma omp task depend(depobj \
+                        : argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}
+#pragma omp task depend(depobj \
+                        : argv[:argc] [1:argc - 1]) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected lvalue expression of 'omp_depend_t' type, not '<OpenMP array section type>'}}
+#pragma omp task depend(depobj \
+                        : arr[0]) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}}
+#pragma omp task depend(in \
+                        : ([ // expected-error {{expected variable name or 'this' in lambda capture list}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task depend(in \
+                        : ([] // expected-error {{expected body of lambda expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task depend(in \
+                        : ([]) // omp45-error {{expected body of lambda expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} omp50-error 2 {{expected expression}}
+#pragma omp task depend(in \
+                        : ([])a // omp45-error {{expected body of lambda expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} omp50-error {{expected expression}}
+#pragma omp task depend(in \
+                        : ([])a) // omp45-error {{expected body of lambda expression}} omp50-error {{expected expression}}
+#pragma omp task depend(in \
+                        : ([a])a) // omp45-error {{expected body of lambda expression}} omp50-error {{expected expression with a pointer to a complete type as a base of an array shaping operation}}
+#pragma omp task depend(in \
+                        : ([a])argc) // omp45-error {{expected body of lambda expression}} omp50-error {{expected expression with a pointer to a complete type as a base of an array shaping operation}}
+#pragma omp task depend(in \
+                        : ([-1][0])argv) // omp45-error {{expected variable name or 'this' in lambda capture list}} omp45-error {{expected ')'}} omp45-note {{to match this '('}} omp50-error {{array shaping dimension is evaluated to a non-positive value -1}} omp50-error {{array shaping dimension is evaluated to a non-positive value 0}}
+#pragma omp task depend(iterator // expected-error {{expected ')'}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-note {{to match this '('}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected '(' after 'iterator'}} omp50-error {{expected ','}}
+#pragma omp task depend(iterator() \
+                        : argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected ','}} omp50-error {{expected 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
+#pragma omp task depend(iterator(argc // expected-error {{expected ')'}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-note {{to match this '('}} omp50-error {{unknown type name 'argc'}} omp50-error {{expected ')'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected ','}} omp50-note {{to match this '('}}
+#pragma omp task depend(iterator(unsigned argc \
+                                 : // expected-error {{expected ')'}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-note {{to match this '('}} omp50-error {{expected '=' in iterator specifier}} omp50-error 2 {{expected expression}} omp50-error {{expected ',' or ')' after iterator specifier}} omp50-error {{expected ')'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected ','}} omp50-note {{to match this '('}}
+#pragma omp task depend(iterator(unsigned argc = // expected-error {{expected ')'}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-note {{to match this '('}} omp50-error 2 {{expected expression}} omp50-error {{expected ',' or ')' after iterator specifier}} omp50-error {{expected ')'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected ','}} omp50-note {{to match this '('}}
+#pragma omp task depend(iterator(vector argc = 0 : 2) \
+                        : argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected integral or pointer type as the iterator-type, not 'vector'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected ','}}
+#pragma omp task depend(iterator(vector *argc = nullptr \
+                                 : nullptr + 2 : 0),    \
+                        in                              \
+                        : argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{invalid operands to binary expression ('nullptr_t' and 'int')}} omp50-error {{iterator step expression 0 evaluates to 0}}
+#pragma omp task depend(iterator(vector *argc = 0 \
+                                 : vector()       \
+                                 : argc),         \
+                        in                        \
+                        : argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{converting 'vector' to incompatible type 'vector *'}}
   foo();
 #pragma omp task depend(iterator(unsigned argc = 0:10), in : argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}}
   argc = 0;
Index: clang/test/OpenMP/task_affinity_messages.cpp
===================================================================
--- clang/test/OpenMP/task_affinity_messages.cpp
+++ clang/test/OpenMP/task_affinity_messages.cpp
@@ -44,29 +44,37 @@
   #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(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}}
-  #pragma omp task affinity(env[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
-  #pragma omp task affinity(argv[ : argc][1 : argc - 1])
-  #pragma omp task affinity(arr[0])
-  #pragma omp task affinity(([ // expected-error {{expected variable name or 'this' in lambda capture list}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-  #pragma omp task affinity(([] // expected-error {{expected body of lambda expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-  #pragma omp task affinity(([]) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expected expression}}
-  #pragma omp task affinity(([])a // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
-  #pragma omp task affinity(([])a) // expected-error {{expected expression}}
-  #pragma omp task affinity(([a])a) // expected-error {{expected expression with a pointer to a complete type as a base of an array shaping operation}}
-  #pragma omp task affinity(([a])argc) // expected-error {{expected expression with a pointer to a complete type as a base of an array shaping operation}}
-  #pragma omp task affinity(([-1][0])argv) // expected-error {{array shaping dimension is evaluated to a non-positive value -1}} expected-error {{array shaping dimension is evaluated to a non-positive value 0}}
-  #pragma omp task affinity(iterator // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected '(' after 'iterator'}} expected-error {{expected expression}}
-  #pragma omp task affinity(iterator():argc)
-  #pragma omp task affinity(iterator(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown type name 'argc'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
-  #pragma omp task affinity(iterator(unsigned argc: // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected '=' in iterator specifier}} expected-error 2 {{expected expression}} expected-error {{expected ',' or ')' after iterator specifier}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
-  #pragma omp task affinity(iterator(unsigned argc = // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expected expression}} expected-error {{expected ',' or ')' after iterator specifier}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
-  #pragma omp task affinity(iterator(vector argc = 0:2):argc) // expected-error {{expected integral or pointer type as the iterator-type, not 'vector'}} expected-error {{expected expression}}
-  #pragma omp task affinity(iterator(vector *argc = nullptr:nullptr+2:0):argc) // expected-error {{invalid operands to binary expression ('nullptr_t' and 'int')}} expected-error {{iterator step expression 0 evaluates to 0}} expected-error {{expected expression}}
-  #pragma omp task affinity(iterator(vector *argc = 0:vector():argc):argc) // expected-error {{converting 'vector' to incompatible type 'vector *'}} expected-error {{expected expression}}
+#pragma omp task affinity(argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}}
+#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}}
+#pragma omp task affinity(env [0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
+#pragma omp task affinity(argv[:argc] [1:argc - 1])
+#pragma omp task affinity(arr[0])
+#pragma omp task affinity(([ // expected-error {{expected variable name or 'this' in lambda capture list}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task affinity(([] // expected-error {{expected body of lambda expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task affinity(([]) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expected expression}}
+#pragma omp task affinity(([])a // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+#pragma omp task affinity(([])a) // expected-error {{expected expression}}
+#pragma omp task affinity(([a])a) // expected-error {{expected expression with a pointer to a complete type as a base of an array shaping operation}}
+#pragma omp task affinity(([a])argc) // expected-error {{expected expression with a pointer to a complete type as a base of an array shaping operation}}
+#pragma omp task affinity(([-1][0])argv) // expected-error {{array shaping dimension is evaluated to a non-positive value -1}} expected-error {{array shaping dimension is evaluated to a non-positive value 0}}
+#pragma omp task affinity(iterator // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected '(' after 'iterator'}} expected-error {{expected expression}}
+#pragma omp task affinity(iterator() \
+                          : argc)
+#pragma omp task affinity(iterator(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown type name 'argc'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+#pragma omp task affinity(iterator(unsigned argc \
+                                   : // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected '=' in iterator specifier}} expected-error 2 {{expected expression}} expected-error {{expected ',' or ')' after iterator specifier}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+#pragma omp task affinity(iterator(unsigned argc = // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expected expression}} expected-error {{expected ',' or ')' after iterator specifier}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}}
+#pragma omp task affinity(iterator(vector argc = 0 : 2) \
+                          : argc) // expected-error {{expected integral or pointer type as the iterator-type, not 'vector'}} expected-error {{expected expression}}
+#pragma omp task affinity(iterator(vector *argc = nullptr \
+                                   : nullptr + 2 : 0)     \
+                          : argc) // expected-error {{invalid operands to binary expression ('nullptr_t' and 'int')}} expected-error {{iterator step expression 0 evaluates to 0}} expected-error {{expected expression}}
+#pragma omp task affinity(iterator(vector *argc = 0 \
+                                   : vector()       \
+                                   : argc)          \
+                          : argc) // expected-error {{converting 'vector' to incompatible type 'vector *'}} expected-error {{expected expression}}
   foo();
 #pragma omp task affinity(iterator(i = 0:10, i = 0:10) : argv[i]) // expected-error {{redefinition of 'i'}} expected-note {{previous definition is here}}
   i = 0; // expected-error {{use of undeclared identifier 'i'}}
Index: clang/test/OpenMP/target_update_messages.cpp
===================================================================
--- clang/test/OpenMP/target_update_messages.cpp
+++ clang/test/OpenMP/target_update_messages.cpp
@@ -54,5 +54,9 @@
   {}
 #pragma omp target update from(dptr[0:2][2:4][1:2]) // le45-error {{array section does not specify contiguous storage}} le50-error 2 {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}} le45-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
 
+  int iarr[5][5];
+#pragma omp target update to(marr [0:] [1:2:-1]) // le50-error {{section stride is evaluated to a non-positive value -1}} le45-error {{expected ']'}} le45-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(marr [0:] [1:2:-1]) // le50-error {{section stride is evaluated to a non-positive value -1}} le45-error {{expected ']'}} le45-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,8 @@
 #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}}
@@ -100,8 +101,10 @@
 #pragma omp target update to(z) depend(in : argv [argc:argc] // expected-error {{expected ')'}} expected-note {{to match this '('}}
 #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[:]) // 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]) // 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
@@ -63,6 +63,8 @@
 
 #pragma omp target update from(marr[:1][:2][0])
 
+#pragma omp target update from(marr [1:1:1] [0:2:] [1:0])
+
 // OMP5: marr[10][10][10];
 // OMP5-NEXT: #pragma omp target update to(marr[2][0:2][0:2])
 // OMP5-NEXT: #pragma omp target update from(marr[2][0:2][0:2])
@@ -80,6 +82,7 @@
 // OMP5-NEXT: #pragma omp target update from(marr[:1][3:2][:2])
 // OMP5-NEXT: #pragma omp target update to(marr[:1][:2][0])
 // OMP5-NEXT: #pragma omp target update from(marr[:1][:2][0])
+// OMP5-NEXT: #pragma omp target update from(marr[1:1:1][0:2:][1:0])
 #endif
 
   return a + targ + (T)b;
@@ -131,6 +134,8 @@
 // OMP5-NEXT: #pragma omp target update to(marr[:1][:2][0])
 #pragma omp target update from(marr[:1][:2][0])
 // OMP5-NEXT: #pragma omp target update from(marr[:1][:2][0])
+#pragma omp target update from(marr [1:1:1] [0:2:] [1:0])
+// OMP5-NEXT: #pragma omp target update from(marr[1:1:1][0:2:][1:0])
 #endif
 
   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,8 @@
   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,8 @@
   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,8 @@
   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,8 @@
   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,8 @@
   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,8 @@
   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,8 @@
   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,8 @@
   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,8 @@
   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_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,9 @@
   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();
@@ -149,9 +151,13 @@
   foo();
   #pragma omp target exit data map(from: i) depend (in : argv[-1:0]) // expected-error {{zero-length array section is not allowed in 'depend' clause}}
   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}}
+#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,9 @@
   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 +151,13 @@
   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,8 @@
   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/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
@@ -14676,7 +14676,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!
@@ -14702,7 +14702,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!
@@ -16459,7 +16459,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.
@@ -16515,7 +16516,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.");
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) {
+    auto 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
@@ -7192,7 +7192,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);
 
@@ -7207,7 +7207,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()) {
@@ -7217,7 +7217,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);
@@ -7294,7 +7294,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();
@@ -7890,6 +7890,11 @@
         if (!OASE)
           continue;
 
+        llvm::errs() << "DEBUG in CGOpenMPRuntime.cpp\n";
+        OASE->getLowerBound()->dump();
+        OASE->getLength()->dump();
+        OASE->getStride()->dump();
+
         // Offset
         const Expr *OffsetExpr = nullptr;
         OffsetExpr = OASE->getLowerBound();
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -3843,7 +3843,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
@@ -4924,8 +4924,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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to