diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h --- a/clang/include/clang-c/Index.h +++ b/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, diff --git a/clang/include/clang/AST/ExprOpenMP.h b/clang/include/clang/AST/ExprOpenMP.h --- a/clang/include/clang/AST/ExprOpenMP.h +++ b/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(SubExprs[STRIDE]); } + const Expr *getStride() const { return cast_or_null(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; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/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< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/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 Dims, diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp --- a/clang/lib/AST/StmtPrinter.cpp +++ b/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 << "]"; } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/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; diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/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(); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp --- a/clang/lib/Parse/ParseExpr.cpp +++ b/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); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/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(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, diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/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(E) || (OASE && OASE->getColonLoc().isInvalid())) { + if (isa(E) || + (OASE && OASE->getColonLocFirst().isInvalid())) { if (const auto *ATy = dyn_cast(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(E) || (OASE && OASE->getColonLoc().isInvalid())) + if (isa(E) || + (OASE && OASE->getColonLocFirst().isInvalid())) return false; assert(OASE && "Expecting array section if not an array subscript."); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/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 diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/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()); } diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/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; } diff --git a/clang/test/OpenMP/target_depend_messages.cpp b/clang/test/OpenMP/target_depend_messages.cpp --- a/clang/test/OpenMP/target_depend_messages.cpp +++ b/clang/test/OpenMP/target_depend_messages.cpp @@ -80,7 +80,7 @@ foo(); #pragma omp target depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} foo(); - #pragma omp target depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + #pragma omp target depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} foo(); #pragma omp target depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} foo(); diff --git a/clang/test/OpenMP/target_enter_data_depend_messages.cpp b/clang/test/OpenMP/target_enter_data_depend_messages.cpp --- a/clang/test/OpenMP/target_enter_data_depend_messages.cpp +++ b/clang/test/OpenMP/target_enter_data_depend_messages.cpp @@ -76,7 +76,7 @@ foo(); #pragma omp target enter data map(to: i) depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} foo(); - #pragma omp target enter data map(to: i) depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} +#pragma omp target enter data map(to : i) depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} foo(); #pragma omp target enter data map(to: i) depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} foo(); @@ -149,9 +149,9 @@ foo(); #pragma omp target enter data map(to: i) depend (in : argv[-1:0]) // expected-error {{zero-length array section is not allowed in 'depend' clause}} foo(); - #pragma omp target enter data map(to: i) depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} + #pragma omp target enter data map(to: i) depend(in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} foo(); - #pragma omp target enter data map(to: i) depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + #pragma omp target enter data map(to : i) depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} foo(); #pragma omp target enter data map(to: i) depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} foo(); diff --git a/clang/test/OpenMP/target_exit_data_depend_messages.cpp b/clang/test/OpenMP/target_exit_data_depend_messages.cpp --- a/clang/test/OpenMP/target_exit_data_depend_messages.cpp +++ b/clang/test/OpenMP/target_exit_data_depend_messages.cpp @@ -76,7 +76,7 @@ foo(); #pragma omp target exit data map(from: i) depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} foo(); - #pragma omp target exit data map(from: i) depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + #pragma omp target exit data map(from : i) depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} foo(); #pragma omp target exit data map(from: i) depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} foo(); @@ -151,7 +151,7 @@ foo(); #pragma omp target exit data map(from: i) depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} foo(); - #pragma omp target exit data map(from: i) depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + #pragma omp target exit data map(from : i) depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} foo(); #pragma omp target exit data map(from: i) depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} foo(); diff --git a/clang/test/OpenMP/target_parallel_depend_messages.cpp b/clang/test/OpenMP/target_parallel_depend_messages.cpp --- a/clang/test/OpenMP/target_parallel_depend_messages.cpp +++ b/clang/test/OpenMP/target_parallel_depend_messages.cpp @@ -74,7 +74,7 @@ foo(); #pragma omp target parallel depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} foo(); - #pragma omp target parallel depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + #pragma omp target parallel depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} foo(); #pragma omp target parallel depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} foo(); diff --git a/clang/test/OpenMP/target_parallel_for_depend_messages.cpp b/clang/test/OpenMP/target_parallel_for_depend_messages.cpp --- a/clang/test/OpenMP/target_parallel_for_depend_messages.cpp +++ b/clang/test/OpenMP/target_parallel_for_depend_messages.cpp @@ -82,7 +82,7 @@ for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} for (i = 0; i < argc; ++i) foo(); - #pragma omp target parallel for depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + #pragma omp target parallel for depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/target_parallel_for_simd_depend_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_depend_messages.cpp --- a/clang/test/OpenMP/target_parallel_for_simd_depend_messages.cpp +++ b/clang/test/OpenMP/target_parallel_for_simd_depend_messages.cpp @@ -82,7 +82,7 @@ for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for simd depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} for (i = 0; i < argc; ++i) foo(); - #pragma omp target parallel for simd depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + #pragma omp target parallel for simd depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} for (i = 0; i < argc; ++i) foo(); #pragma omp target parallel for simd depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/target_simd_depend_messages.cpp b/clang/test/OpenMP/target_simd_depend_messages.cpp --- a/clang/test/OpenMP/target_simd_depend_messages.cpp +++ b/clang/test/OpenMP/target_simd_depend_messages.cpp @@ -82,7 +82,7 @@ for (i = 0; i < argc; ++i) foo(); #pragma omp target simd depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} for (i = 0; i < argc; ++i) foo(); - #pragma omp target simd depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + #pragma omp target simd depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} for (i = 0; i < argc; ++i) foo(); #pragma omp target simd depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/target_teams_depend_messages.cpp b/clang/test/OpenMP/target_teams_depend_messages.cpp --- a/clang/test/OpenMP/target_teams_depend_messages.cpp +++ b/clang/test/OpenMP/target_teams_depend_messages.cpp @@ -74,7 +74,7 @@ foo(); #pragma omp target teams depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} foo(); -#pragma omp target teams depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} +#pragma omp target teams depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} foo(); #pragma omp target teams depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} foo(); diff --git a/clang/test/OpenMP/target_teams_distribute_depend_messages.cpp b/clang/test/OpenMP/target_teams_distribute_depend_messages.cpp --- a/clang/test/OpenMP/target_teams_distribute_depend_messages.cpp +++ b/clang/test/OpenMP/target_teams_distribute_depend_messages.cpp @@ -78,7 +78,7 @@ for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} for (i = 0; i < argc; ++i) foo(); -#pragma omp target teams distribute depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} +#pragma omp target teams distribute depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_depend_messages.cpp @@ -79,7 +79,7 @@ for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute parallel for depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} for (i = 0; i < argc; ++i) foo(); -#pragma omp target teams distribute parallel for depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} +#pragma omp target teams distribute parallel for depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute parallel for depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_depend_messages.cpp @@ -79,7 +79,7 @@ for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute parallel for simd depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} for (i = 0; i < argc; ++i) foo(); -#pragma omp target teams distribute parallel for simd depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} +#pragma omp target teams distribute parallel for simd depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute parallel for simd depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp b/clang/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp --- a/clang/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp +++ b/clang/test/OpenMP/target_teams_distribute_simd_depend_messages.cpp @@ -78,7 +78,7 @@ for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute simd depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} for (i = 0; i < argc; ++i) foo(); -#pragma omp target teams distribute simd depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} +#pragma omp target teams distribute simd depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} for (i = 0; i < argc; ++i) foo(); #pragma omp target teams distribute simd depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} for (i = 0; i < argc; ++i) foo(); diff --git a/clang/test/OpenMP/target_update_ast_print.cpp b/clang/test/OpenMP/target_update_ast_print.cpp --- a/clang/test/OpenMP/target_update_ast_print.cpp +++ b/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; diff --git a/clang/test/OpenMP/target_update_depend_messages.cpp b/clang/test/OpenMP/target_update_depend_messages.cpp --- a/clang/test/OpenMP/target_update_depend_messages.cpp +++ b/clang/test/OpenMP/target_update_depend_messages.cpp @@ -54,7 +54,7 @@ #pragma omp target update to(z) depend(in : argv [0:-1]) // expected-error {{section length is evaluated to a negative value -1}} #pragma omp target update to(z) depend(in : argv [-1:0]) // expected-error {{zero-length array section is not allowed in 'depend' clause}} #pragma omp target update to(z) depend(in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} -#pragma omp target update to(z) depend(in : argv [3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} +#pragma omp target update to(z) depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} #pragma omp target update to(z) depend(in : a [0:1]) // expected-error {{subscripted value is not an array or pointer}} #pragma omp target update to(z) depend(in : argv [argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}} #pragma omp target update to(z) depend(in : argv [0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} @@ -101,7 +101,7 @@ #pragma omp target update to(z) depend(in : argv [0:-1]) // expected-error {{section length is evaluated to a negative value -1}} #pragma omp target update to(z) depend(in : argv [-1:0]) // expected-error {{zero-length array section is not allowed in 'depend' clause}} #pragma omp target update to(z) depend(in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} -#pragma omp target update to(z) depend(in : argv [3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} +#pragma omp target update to(z) depend(in : argv [3:4:1]) // omp4-error {{expected ']'}} omp4-note {{to match this '['}} #pragma omp target update to(z) depend(in : a [0:1]) // expected-error {{subscripted value is not an array or pointer}} #pragma omp target update to(z) depend(in : argv [argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}} #pragma omp target update to(z) depend(in : argv [0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} diff --git a/clang/test/OpenMP/target_update_messages.cpp b/clang/test/OpenMP/target_update_messages.cpp --- a/clang/test/OpenMP/target_update_messages.cpp +++ b/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); } diff --git a/clang/test/OpenMP/task_affinity_messages.cpp b/clang/test/OpenMP/task_affinity_messages.cpp --- a/clang/test/OpenMP/task_affinity_messages.cpp +++ b/clang/test/OpenMP/task_affinity_messages.cpp @@ -44,7 +44,7 @@ #pragma omp task affinity (argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}} #pragma omp task affinity (argv[-1:0]) #pragma omp task affinity (argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} - #pragma omp task affinity (argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + #pragma omp task affinity (argv[3:4:1]) #pragma omp task affinity(a[0:1]) // expected-error {{subscripted value is not an array or pointer}} #pragma omp task affinity(argv[argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}} #pragma omp task affinity(argv[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} diff --git a/clang/test/OpenMP/task_depend_messages.cpp b/clang/test/OpenMP/task_depend_messages.cpp --- a/clang/test/OpenMP/task_depend_messages.cpp +++ b/clang/test/OpenMP/task_depend_messages.cpp @@ -52,7 +52,7 @@ #pragma omp task depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}} #pragma omp task depend (in : argv[-1:0]) // expected-error {{zero-length array section is not allowed in 'depend' clause}} #pragma omp task depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} - #pragma omp task depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + #pragma omp task depend (in : argv[3:4:1]) // omp45-error {{expected ']'}} omp45-note {{to match this '['}} #pragma omp task depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}} #pragma omp task depend(in:argv[argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}} #pragma omp task depend(in:argv[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}