cchen updated this revision to Diff 276589. cchen added a comment. Fix message and rebase
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/Parse/Parser.h 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/Parse/ParseOpenMP.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_messages.cpp
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_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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + {} +#pragma omp target data map(iarr[:2:d]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + {} +#pragma omp target map(iarr[:2:d]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-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]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + {} +#pragma omp target data map(alloc: iarr[:2:b]) // expected-error {{expected ']'}} expected-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 (Expr *Str = E->getStride()) { + Stride = getDerived().TransformExpr(Str); + 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 @@ -14692,7 +14692,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! @@ -14718,7 +14718,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! @@ -16475,7 +16475,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. @@ -16531,7 +16532,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."); @@ -16575,7 +16577,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 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/ParseOpenMP.cpp =================================================================== --- clang/lib/Parse/ParseOpenMP.cpp +++ clang/lib/Parse/ParseOpenMP.cpp @@ -2498,6 +2498,7 @@ /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { + OMPClauseKind = CKind; OMPClause *Clause = nullptr; bool ErrorFound = false; bool WrongDirective = false; Index: clang/lib/Parse/ParseExpr.cpp =================================================================== --- clang/lib/Parse/ParseExpr.cpp +++ clang/lib/Parse/ParseExpr.cpp @@ -1909,8 +1909,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); @@ -1924,10 +1924,22 @@ } if (Tok.is(tok::colon)) { // Consume ':' - ColonLoc = ConsumeToken(); - if (Tok.isNot(tok::r_square)) + ColonLocFirst = ConsumeToken(); + if (Tok.isNot(tok::r_square) && + (getLangOpts().OpenMP < 50 || + ((Tok.isNot(tok::colon) && getLangOpts().OpenMP >= 50)))) Length = ParseExpression(); } + if (getLangOpts().OpenMP >= 50 && + (OMPClauseKind == llvm::omp::Clause::OMPC_to || + OMPClauseKind == llvm::omp::Clause::OMPC_from) && + Tok.is(tok::colon)) { + // Consume ':' + ColonLocSecond = ConsumeToken(); + if (Tok.isNot(tok::r_square)) { + Stride = ParseExpression(); + } + } } else Idx = ParseExpression(); @@ -1937,10 +1949,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 @@ -7175,7 +7175,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); @@ -7190,7 +7190,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()) { @@ -7200,7 +7200,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); @@ -7273,7 +7273,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 @@ -4971,8 +4971,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/Parse/Parser.h =================================================================== --- clang/include/clang/Parse/Parser.h +++ clang/include/clang/Parse/Parser.h @@ -241,6 +241,9 @@ /// The "depth" of the template parameters currently being parsed. unsigned TemplateParameterDepth; + /// Current kind of OpenMP clause + OpenMPClauseKind OMPClauseKind = llvm::omp::OMPC_unknown; + /// RAII class that manages the template parameter depth. class TemplateParameterDepthRAII { unsigned &Depth; Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10064,6 +10064,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 @@ -17,46 +17,61 @@ #include "clang/AST/Expr.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 +104,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