Index: clang/include/clang/AST/OpenMPClause.h =================================================================== --- clang/include/clang/AST/OpenMPClause.h +++ clang/include/clang/AST/OpenMPClause.h @@ -4758,6 +4758,9 @@ /// Number of loops, associated with the depend clause. unsigned NumLoops = 0; + /// True if the 'omp_all_memory' reserved locator is present. + bool IsOmpAllMemory = false; + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. @@ -4766,22 +4769,24 @@ /// \param N Number of the variables in the clause. /// \param NumLoops Number of loops that is associated with this depend /// clause. + /// \param IsOmpAllMemory True if the 'omp_all_memory' locator is present. OMPDependClause(SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N, unsigned NumLoops) + SourceLocation EndLoc, unsigned N, unsigned NumLoops, + bool IsOmpAllMemory) : OMPVarListClause(llvm::omp::OMPC_depend, StartLoc, LParenLoc, EndLoc, N), - NumLoops(NumLoops) {} + NumLoops(NumLoops), IsOmpAllMemory(IsOmpAllMemory) {} /// Build an empty clause. /// /// \param N Number of variables. /// \param NumLoops Number of loops that is associated with this depend /// clause. - explicit OMPDependClause(unsigned N, unsigned NumLoops) + explicit OMPDependClause(unsigned N, unsigned NumLoops, bool IsOmpAllMemory) : OMPVarListClause(llvm::omp::OMPC_depend, SourceLocation(), SourceLocation(), SourceLocation(), N), - NumLoops(NumLoops) {} + NumLoops(NumLoops), IsOmpAllMemory(IsOmpAllMemory) {} /// Set dependency kind. void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; } @@ -4795,6 +4800,9 @@ /// Sets optional dependency modifier. void setModifier(Expr *DepModifier); + /// Sets whether 'omp_all_memory' is present in clause. + void setIsOmpAllMemory(bool OmpAllMemory) { IsOmpAllMemory = OmpAllMemory; } + public: /// Creates clause with a list of variables \a VL. /// @@ -4808,12 +4816,14 @@ /// \param VL List of references to the variables. /// \param NumLoops Number of loops that is associated with this depend /// clause. + /// \param IsOmpAllMemory True if 'omp_all_memory' is present. static OMPDependClause *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *DepModifier, OpenMPDependClauseKind DepKind, SourceLocation DepLoc, SourceLocation ColonLoc, - ArrayRef VL, unsigned NumLoops); + ArrayRef VL, unsigned NumLoops, + bool IsOmpAllMemory); /// Creates an empty clause with \a N variables. /// @@ -4821,8 +4831,9 @@ /// \param N The number of variables. /// \param NumLoops Number of loops that is associated with this depend /// clause. + /// \param IsOmpAllMemory True if 'omp_all_memory' is present. static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N, - unsigned NumLoops); + unsigned NumLoops, bool IsOmpAllMemory); /// Get dependency type. OpenMPDependClauseKind getDependencyKind() const { return DepKind; } @@ -4842,6 +4853,9 @@ /// Get number of loops associated with the clause. unsigned getNumLoops() const { return NumLoops; } + /// Get whether 'omp_all_memory' is present in clause. + bool getIsOmpAllMemory() const { return IsOmpAllMemory; } + /// Set the loop data for the depend clauses with 'sink|source' kind of /// dependency. void setLoopData(unsigned NumLoop, Expr *Cnt); Index: clang/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticParseKinds.td +++ clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1464,6 +1464,12 @@ def err_omp_expected_colon : Error<"missing ':' in %0">; def err_omp_expected_context_selector : Error<"expected valid context selector in %0">; +def err_omp_requires_out_inout_depend_type : Error< + "reserved locator 'omp_all_memory' requires 'out' or 'inout' " + "dependency types">; +def warn_omp_more_one_omp_all_memory : Warning< + "reserved locator 'omp_all_memory' cannot be specified more than once">, + InGroup; // Pragma loop support. def err_pragma_loop_missing_argument : Error< Index: clang/include/clang/Parse/Parser.h =================================================================== --- clang/include/clang/Parse/Parser.h +++ clang/include/clang/Parse/Parser.h @@ -3350,6 +3350,7 @@ SmallVector MotionModifiersLoc; bool IsMapTypeImplicit = false; SourceLocation ExtraModifierLoc; + bool IsOmpAllMemory = false; }; /// Parses clauses with list. Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -11441,7 +11441,7 @@ ArrayRef MapTypeModifiersLoc, bool IsMapTypeImplicit, SourceLocation ExtraModifierLoc, ArrayRef MotionModifiers, - ArrayRef MotionModifiersLoc); + ArrayRef MotionModifiersLoc, bool IsOmpAllMemory); /// Called on well-formed 'inclusive' clause. OMPClause *ActOnOpenMPInclusiveClause(ArrayRef VarList, SourceLocation StartLoc, @@ -11536,7 +11536,8 @@ ActOnOpenMPDependClause(Expr *DepModifier, OpenMPDependClauseKind DepKind, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef VarList, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc); + SourceLocation LParenLoc, SourceLocation EndLoc, + bool IsOmpAllMemory); /// Called on well-formed 'device' clause. OMPClause *ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, Index: clang/lib/AST/OpenMPClause.cpp =================================================================== --- clang/lib/AST/OpenMPClause.cpp +++ clang/lib/AST/OpenMPClause.cpp @@ -1037,20 +1037,20 @@ return new (C) OMPDepobjClause(); } -OMPDependClause * -OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc, - Expr *DepModifier, OpenMPDependClauseKind DepKind, - SourceLocation DepLoc, SourceLocation ColonLoc, - ArrayRef VL, unsigned NumLoops) { +OMPDependClause *OMPDependClause::Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, Expr *DepModifier, OpenMPDependClauseKind DepKind, + SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef VL, + unsigned NumLoops, bool IsOmpAllMemory) { void *Mem = C.Allocate( totalSizeToAlloc(VL.size() + /*depend-modifier*/ 1 + NumLoops), alignof(OMPDependClause)); - OMPDependClause *Clause = new (Mem) - OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops); + OMPDependClause *Clause = new (Mem) OMPDependClause( + StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops, IsOmpAllMemory); Clause->setVarRefs(VL); Clause->setDependencyKind(DepKind); Clause->setDependencyLoc(DepLoc); + Clause->setIsOmpAllMemory(IsOmpAllMemory); Clause->setColonLoc(ColonLoc); Clause->setModifier(DepModifier); for (unsigned I = 0 ; I < NumLoops; ++I) @@ -1059,11 +1059,12 @@ } OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N, - unsigned NumLoops) { + unsigned NumLoops, + bool IsOmpAllMemory) { void *Mem = C.Allocate(totalSizeToAlloc(N + /*depend-modifier*/ 1 + NumLoops), alignof(OMPDependClause)); - return new (Mem) OMPDependClause(N, NumLoops); + return new (Mem) OMPDependClause(N, NumLoops, IsOmpAllMemory); } void OMPDependClause::setLoopData(unsigned NumLoop, Expr *Cnt) { @@ -2185,9 +2186,12 @@ } OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Node->getDependencyKind()); - if (!Node->varlist_empty()) { + if (!Node->varlist_empty() || Node->getIsOmpAllMemory()) OS << " :"; - VisitOMPClauseList(Node, ' '); + VisitOMPClauseList(Node, ' '); + if (Node->getIsOmpAllMemory()) { + OS << (Node->varlist_empty() ? " " : ","); + OS << "omp_all_memory"; } OS << ")"; } Index: clang/lib/Parse/ParseOpenMP.cpp =================================================================== --- clang/lib/Parse/ParseOpenMP.cpp +++ clang/lib/Parse/ParseOpenMP.cpp @@ -4356,14 +4356,26 @@ Tok.isNot(tok::annot_pragma_openmp_end))) { ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope); ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); - // Parse variable - ExprResult VarExpr = - Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); - if (VarExpr.isUsable()) { - Vars.push_back(VarExpr.get()); + if (getLangOpts().OpenMP >= 51 && Kind == OMPC_depend && + Tok.is(tok::identifier) && + Tok.getIdentifierInfo()->isStr("omp_all_memory")) { + if (Data.ExtraModifier != OMPC_DEPEND_out && + Data.ExtraModifier != OMPC_DEPEND_inout) + Diag(Tok, diag::err_omp_requires_out_inout_depend_type); + else if (Data.IsOmpAllMemory) + Diag(Tok, diag::warn_omp_more_one_omp_all_memory); + Data.IsOmpAllMemory = true; + ConsumeToken(); } else { - SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, - StopBeforeMatch); + // Parse variable + ExprResult VarExpr = + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); + if (VarExpr.isUsable()) { + Vars.push_back(VarExpr.get()); + } else { + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, + StopBeforeMatch); + } } // Skip ',' if any IsComma = Tok.is(tok::comma); @@ -4485,5 +4497,5 @@ Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, Data.IsMapTypeImplicit, Data.ExtraModifierLoc, Data.MotionModifiers, - Data.MotionModifiersLoc); + Data.MotionModifiersLoc, Data.IsOmpAllMemory); } Index: clang/lib/Sema/SemaOpenMP.cpp =================================================================== --- clang/lib/Sema/SemaOpenMP.cpp +++ clang/lib/Sema/SemaOpenMP.cpp @@ -16923,7 +16923,7 @@ ArrayRef MapTypeModifiersLoc, bool IsMapTypeImplicit, SourceLocation ExtraModifierLoc, ArrayRef MotionModifiers, - ArrayRef MotionModifiersLoc) { + ArrayRef MotionModifiersLoc, bool IsOmpAllMemory) { SourceLocation StartLoc = Locs.StartLoc; SourceLocation LParenLoc = Locs.LParenLoc; SourceLocation EndLoc = Locs.EndLoc; @@ -16989,7 +16989,8 @@ "Unexpected depend modifier."); Res = ActOnOpenMPDependClause( DepModOrTailExpr, static_cast(ExtraModifier), - ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc); + ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc, + IsOmpAllMemory); break; case OMPC_map: assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown && @@ -19628,11 +19629,10 @@ return OMPDepobjClause::Create(Context, StartLoc, LParenLoc, EndLoc, Depobj); } -OMPClause * -Sema::ActOnOpenMPDependClause(Expr *DepModifier, OpenMPDependClauseKind DepKind, - SourceLocation DepLoc, SourceLocation ColonLoc, - ArrayRef VarList, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) { +OMPClause *Sema::ActOnOpenMPDependClause( + Expr *DepModifier, OpenMPDependClauseKind DepKind, SourceLocation DepLoc, + SourceLocation ColonLoc, ArrayRef VarList, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, bool IsOmpAllMemory) { if (DSAStack->getCurrentDirective() == OMPD_ordered && DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) { Diag(DepLoc, diag::err_omp_unexpected_clause_value) @@ -19879,12 +19879,12 @@ << 1 << DSAStack->getParentLoopControlVariable(VarList.size() + 1); } if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink && - Vars.empty()) + !IsOmpAllMemory && Vars.empty()) return nullptr; - auto *C = OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, - DepModifier, DepKind, DepLoc, ColonLoc, - Vars, TotalDepCount.getZExtValue()); + auto *C = OMPDependClause::Create( + Context, StartLoc, LParenLoc, EndLoc, DepModifier, DepKind, DepLoc, + ColonLoc, Vars, TotalDepCount.getZExtValue(), IsOmpAllMemory); if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) && DSAStack->isParentOrderedRegion()) DSAStack->addDoacrossDependClause(C, OpsOffs); Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -1904,10 +1904,11 @@ RebuildOMPDependClause(Expr *DepModifier, OpenMPDependClauseKind DepKind, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef VarList, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) { + SourceLocation LParenLoc, SourceLocation EndLoc, + bool IsOmpAllMemory) { return getSema().ActOnOpenMPDependClause(DepModifier, DepKind, DepLoc, ColonLoc, VarList, StartLoc, - LParenLoc, EndLoc); + LParenLoc, EndLoc, IsOmpAllMemory); } /// Build a new OpenMP 'device' clause. @@ -10014,7 +10015,7 @@ return getDerived().RebuildOMPDependClause( DepModifier, C->getDependencyKind(), C->getDependencyLoc(), C->getColonLoc(), Vars, C->getBeginLoc(), C->getLParenLoc(), - C->getEndLoc()); + C->getEndLoc(), C->getIsOmpAllMemory()); } template Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -11827,7 +11827,8 @@ case llvm::omp::OMPC_depend: { unsigned NumVars = Record.readInt(); unsigned NumLoops = Record.readInt(); - C = OMPDependClause::CreateEmpty(Context, NumVars, NumLoops); + C = OMPDependClause::CreateEmpty(Context, NumVars, NumLoops, + Record.readBool()); break; } case llvm::omp::OMPC_device: Index: clang/lib/Serialization/ASTWriter.cpp =================================================================== --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -6575,6 +6575,7 @@ void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) { Record.push_back(C->varlist_size()); Record.push_back(C->getNumLoops()); + Record.writeBool(C->getIsOmpAllMemory()); Record.AddSourceLocation(C->getLParenLoc()); Record.AddStmt(C->getModifier()); Record.push_back(C->getDependencyKind()); Index: clang/test/OpenMP/task_ast_print.cpp =================================================================== --- clang/test/OpenMP/task_ast_print.cpp +++ clang/test/OpenMP/task_ast_print.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ast-print %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s -// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ast-print %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=51 -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=51 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s // expected-no-diagnostics #ifndef HEADER @@ -188,6 +188,18 @@ // CHECK-NEXT: foo(); // CHECK-NEXT: #pragma omp task in_reduction(+: arr1) #pragma omp task in_reduction(+: arr1) + foo(); + // CHECK-NEXT: foo(); + // CHECK-NEXT: #pragma omp task depend(out : arr,omp_all_memory) +#pragma omp task depend(out: omp_all_memory, arr) + foo(); + // CHECK-NEXT: foo(); + // CHECK-NEXT: #pragma omp task depend(inout : b,arr,a,x,omp_all_memory) +#pragma omp task depend(inout: b, arr, omp_all_memory, a, x) + foo(); + // CHECK-NEXT: foo(); + // CHECK-NEXT: #pragma omp task depend(inout : omp_all_memory) +#pragma omp task depend(inout: omp_all_memory) foo(); // CHECK-NEXT: foo(); return tmain(b, &b) + tmain(x, &x); Index: clang/test/OpenMP/task_depend_messages.cpp =================================================================== --- clang/test/OpenMP/task_depend_messages.cpp +++ clang/test/OpenMP/task_depend_messages.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-version=45 -fopenmp -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=50 -fopenmp -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized -// RUN: %clang_cc1 -verify=expected,omp51 -fopenmp-version=51 -fopenmp -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp51,omp51warn -fopenmp-version=51 -fopenmp -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized // RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-version=45 -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=50 -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized -// RUN: %clang_cc1 -verify=expected,omp51 -fopenmp-version=51 -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp51,omp51warn -fopenmp-version=51 -fopenmp-simd -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized typedef void *omp_depend_t; @@ -85,6 +85,10 @@ argc = 0; #pragma omp task depend(iterator(i = 0:10, i = 0:10), in : argv[i]) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp45-error {{use of undeclared identifier 'i'}} omp50-error {{redefinition of 'i'}} omp50-note {{previous definition is here}} omp51-error {{redefinition of 'i'}} omp51-note {{previous definition is here}} i = 0; // expected-error {{use of undeclared identifier 'i'}} - +#pragma omp task depend(in: argc, omp_all_memory) // omp45-error {{use of undeclared identifier 'omp_all_memory'}} omp50-error {{use of undeclared identifier 'omp_all_memory'}} omp51-error {{reserved locator 'omp_all_memory' requires 'out' or 'inout' dependency types}} +#pragma omp task depend(out: omp_all_memory, argc, omp_all_memory) // omp45-error {{use of undeclared identifier 'omp_all_memory'}} omp45-error {{use of undeclared identifier 'omp_all_memory'}} omp50-error {{use of undeclared identifier 'omp_all_memory'}} omp50-error {{use of undeclared identifier 'omp_all_memory'}} omp51warn-warning {{reserved locator 'omp_all_memory' cannot be specified more than once}} + // expected-error@+1 {{use of undeclared identifier 'omp_all_memory'}} +#pragma omp task depend(out: argc) private(argc) allocate(argc, omp_all_memory) + argc = 0; return 0; }