Author: Alexey Bataev Date: 2020-03-03T13:59:32-05:00 New Revision: 82f7c207f51b28c834d71bbb3b0f818f51c8b090
URL: https://github.com/llvm/llvm-project/commit/82f7c207f51b28c834d71bbb3b0f818f51c8b090 DIFF: https://github.com/llvm/llvm-project/commit/82f7c207f51b28c834d71bbb3b0f818f51c8b090.diff LOG: [OPENMP50]Support 'update' clause for 'depobj' directive. Added basic support (parsing/sema/serialization) for 'update' clause in 'depobj' directive. Added: Modified: clang/include/clang/AST/OpenMPClause.h clang/include/clang/Basic/OpenMPKinds.def clang/include/clang/Sema/Sema.h clang/lib/AST/OpenMPClause.cpp clang/lib/Basic/OpenMPKinds.cpp clang/lib/Parse/ParseOpenMP.cpp clang/lib/Sema/SemaOpenMP.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp clang/test/OpenMP/depobj_ast_print.cpp clang/test/OpenMP/depobj_messages.cpp Removed: ################################################################################ diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index fa727837a802..086c6a232de7 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -1763,18 +1763,94 @@ class OMPWriteClause : public OMPClause { /// #pragma omp atomic update /// \endcode /// In this example directive '#pragma omp atomic' has 'update' clause. -class OMPUpdateClause : public OMPClause { -public: +/// Also, this class represents 'update' clause in '#pragma omp depobj' +/// directive. +/// +/// \code +/// #pragma omp depobj(a) update(in) +/// \endcode +/// In this example directive '#pragma omp depobj' has 'update' clause with 'in' +/// dependence kind. +class OMPUpdateClause final + : public OMPClause, + private llvm::TrailingObjects<OMPUpdateClause, SourceLocation, + OpenMPDependClauseKind> { + friend class OMPClauseReader; + friend TrailingObjects; + + /// true if extended version of the clause for 'depobj' directive. + bool IsExtended = false; + + /// Define the sizes of each trailing object array except the last one. This + /// is required for TrailingObjects to work properly. + size_t numTrailingObjects(OverloadToken<SourceLocation>) const { + // 2 locations: for '(' and argument location. + return IsExtended ? 2 : 0; + } + + /// Sets the the location of '(' in clause for 'depobj' directive. + void setLParenLoc(SourceLocation Loc) { + assert(IsExtended && "Expected extended clause."); + *getTrailingObjects<SourceLocation>() = Loc; + } + + /// Sets the the location of '(' in clause for 'depobj' directive. + void setArgumentLoc(SourceLocation Loc) { + assert(IsExtended && "Expected extended clause."); + *std::next(getTrailingObjects<SourceLocation>(), 1) = Loc; + } + + /// Sets the dependence kind for the clause for 'depobj' directive. + void setDependencyKind(OpenMPDependClauseKind DK) { + assert(IsExtended && "Expected extended clause."); + *getTrailingObjects<OpenMPDependClauseKind>() = DK; + } + /// Build 'update' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - OMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc) - : OMPClause(OMPC_update, StartLoc, EndLoc) {} + OMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc, + bool IsExtended) + : OMPClause(OMPC_update, StartLoc, EndLoc), IsExtended(IsExtended) {} /// Build an empty clause. - OMPUpdateClause() - : OMPClause(OMPC_update, SourceLocation(), SourceLocation()) {} + OMPUpdateClause(bool IsExtended) + : OMPClause(OMPC_update, SourceLocation(), SourceLocation()), + IsExtended(IsExtended) {} + +public: + /// Creates clause for 'atomic' directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + static OMPUpdateClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc); + + /// Creates clause for 'depobj' directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param ArgumentLoc Location of the argument. + /// \param DK Dependence kind. + /// \param EndLoc Ending location of the clause. + static OMPUpdateClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ArgumentLoc, + OpenMPDependClauseKind DK, + SourceLocation EndLoc); + + /// Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param IsExtended true if extended clause for 'depobj' directive must be + /// created. + static OMPUpdateClause *CreateEmpty(const ASTContext &C, bool IsExtended); + + /// Checks if the clause is the extended clauses for 'depobj' directive. + bool isExtended() const { return IsExtended; } child_range children() { return child_range(child_iterator(), child_iterator()); @@ -1791,6 +1867,24 @@ class OMPUpdateClause : public OMPClause { return const_child_range(const_child_iterator(), const_child_iterator()); } + /// Gets the the location of '(' in clause for 'depobj' directive. + SourceLocation getLParenLoc() const { + assert(IsExtended && "Expected extended clause."); + return *getTrailingObjects<SourceLocation>(); + } + + /// Gets the the location of argument in clause for 'depobj' directive. + SourceLocation getArgumentLoc() const { + assert(IsExtended && "Expected extended clause."); + return *std::next(getTrailingObjects<SourceLocation>(), 1); + } + + /// Gets the dependence kind in clause for 'depobj' directive. + OpenMPDependClauseKind getDependencyKind() const { + assert(IsExtended && "Expected extended clause."); + return *getTrailingObjects<OpenMPDependClauseKind>(); + } + static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_update; } diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 388204c3c193..dbc0d1cec2c7 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -1086,6 +1086,7 @@ OPENMP_FLUSH_CLAUSE(release) // Clauses allowed for OpenMP directive 'depobj'. OPENMP_DEPOBJ_CLAUSE(depend) OPENMP_DEPOBJ_CLAUSE(destroy) +OPENMP_DEPOBJ_CLAUSE(update) #undef OPENMP_DEPOBJ_CLAUSE #undef OPENMP_FLUSH_CLAUSE diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 9a3fc9585c98..2304a9718567 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10293,6 +10293,12 @@ class Sema final { SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// Called on well-formed 'update' clause. + OMPClause *ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); OMPClause *ActOnOpenMPSingleExprWithArgClause( OpenMPClauseKind Kind, ArrayRef<unsigned> Arguments, Expr *Expr, diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 2bd02a0cda4f..00d43425c270 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -330,6 +330,39 @@ const Expr *OMPOrderedClause::getLoopCounter(unsigned NumLoop) const { return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop]; } +OMPUpdateClause *OMPUpdateClause::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (C) OMPUpdateClause(StartLoc, EndLoc, /*IsExtended=*/false); +} + +OMPUpdateClause * +OMPUpdateClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ArgumentLoc, + OpenMPDependClauseKind DK, SourceLocation EndLoc) { + void *Mem = + C.Allocate(totalSizeToAlloc<SourceLocation, OpenMPDependClauseKind>(2, 1), + alignof(OMPUpdateClause)); + auto *Clause = + new (Mem) OMPUpdateClause(StartLoc, EndLoc, /*IsExtended=*/true); + Clause->setLParenLoc(LParenLoc); + Clause->setArgumentLoc(ArgumentLoc); + Clause->setDependencyKind(DK); + return Clause; +} + +OMPUpdateClause *OMPUpdateClause::CreateEmpty(const ASTContext &C, + bool IsExtended) { + if (!IsExtended) + return new (C) OMPUpdateClause(/*IsExtended=*/false); + void *Mem = + C.Allocate(totalSizeToAlloc<SourceLocation, OpenMPDependClauseKind>(2, 1), + alignof(OMPUpdateClause)); + auto *Clause = new (Mem) OMPUpdateClause(/*IsExtended=*/true); + Clause->IsExtended = true; + return Clause; +} + void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) { assert(VL.size() == varlist_size() && "Number of private copies is not the same as the preallocated buffer"); @@ -1349,8 +1382,14 @@ void OMPClausePrinter::VisitOMPReadClause(OMPReadClause *) { OS << "read"; } void OMPClausePrinter::VisitOMPWriteClause(OMPWriteClause *) { OS << "write"; } -void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *) { +void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *Node) { OS << "update"; + if (Node->isExtended()) { + OS << "("; + OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), + Node->getDependencyKind()); + OS << ")"; + } } void OMPClausePrinter::VisitOMPCaptureClause(OMPCaptureClause *) { diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 8de233c19135..5ecc24647e7c 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -149,6 +149,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, #define OPENMP_ORDER_KIND(Name) .Case(#Name, OMPC_ORDER_##Name) #include "clang/Basic/OpenMPKinds.def" .Default(OMPC_ORDER_unknown); + case OMPC_update: + return llvm::StringSwitch<OpenMPDependClauseKind>(Str) +#define OPENMP_DEPEND_KIND(Name) .Case(#Name, OMPC_DEPEND_##Name) +#include "clang/Basic/OpenMPKinds.def" + .Default(OMPC_DEPEND_unknown); case OMPC_unknown: case OMPC_threadprivate: case OMPC_if: @@ -176,7 +181,6 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_depobj: case OMPC_read: case OMPC_write: - case OMPC_update: case OMPC_capture: case OMPC_seq_cst: case OMPC_acq_rel: @@ -365,6 +369,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, #include "clang/Basic/OpenMPKinds.def" } llvm_unreachable("Invalid OpenMP 'order' clause type"); + case OMPC_update: + switch (Type) { + case OMPC_DEPEND_unknown: + return "unknown"; +#define OPENMP_DEPEND_KIND(Name) \ + case OMPC_DEPEND_##Name: \ + return #Name; +#include "clang/Basic/OpenMPKinds.def" + } + llvm_unreachable("Invalid OpenMP 'depend' clause type"); case OMPC_unknown: case OMPC_threadprivate: case OMPC_if: @@ -392,7 +406,6 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_depobj: case OMPC_read: case OMPC_write: - case OMPC_update: case OMPC_capture: case OMPC_seq_cst: case OMPC_acq_rel: diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 56e88d15f8fa..27b88b331199 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -2447,7 +2447,6 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_mergeable: case OMPC_read: case OMPC_write: - case OMPC_update: case OMPC_capture: case OMPC_seq_cst: case OMPC_acq_rel: @@ -2476,6 +2475,17 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, Clause = ParseOpenMPClause(CKind, WrongDirective); break; + case OMPC_update: + if (!FirstClause) { + Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; + ErrorFound = true; + } + + Clause = (DKind == OMPD_depobj) + ? ParseOpenMPSimpleClause(CKind, WrongDirective) + : ParseOpenMPClause(CKind, WrongDirective); + break; case OMPC_private: case OMPC_firstprivate: case OMPC_lastprivate: @@ -2593,10 +2603,13 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. /// /// default-clause: -/// 'default' '(' 'none' | 'shared' ') +/// 'default' '(' 'none' | 'shared' ')' /// /// proc_bind-clause: -/// 'proc_bind' '(' 'master' | 'close' | 'spread' ') +/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')' +/// +/// update-clause: +/// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' ')' /// OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, bool ParseOnly) { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index ecabb3aefd20..48352e63399e 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -12077,6 +12077,10 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( Res = ActOnOpenMPOrderClause(static_cast<OpenMPOrderClauseKind>(Argument), ArgumentLoc, StartLoc, LParenLoc, EndLoc); break; + case OMPC_update: + Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument), + ArgumentLoc, StartLoc, LParenLoc, EndLoc); + break; case OMPC_if: case OMPC_final: case OMPC_num_threads: @@ -12106,7 +12110,6 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_depobj: case OMPC_read: case OMPC_write: - case OMPC_update: case OMPC_capture: case OMPC_seq_cst: case OMPC_acq_rel: @@ -12238,6 +12241,23 @@ OMPClause *Sema::ActOnOpenMPOrderClause(OpenMPOrderClauseKind Kind, OMPOrderClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); } +OMPClause *Sema::ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, + SourceLocation KindKwLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + if (Kind == OMPC_DEPEND_unknown) { + unsigned Except[] = {OMPC_DEPEND_source, OMPC_DEPEND_sink}; + Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) + << getListOfPossibleValues(OMPC_depend, /*First=*/0, + /*Last=*/OMPC_DEPEND_unknown, Except) + << getOpenMPClauseName(OMPC_update); + return nullptr; + } + return OMPUpdateClause::Create(Context, StartLoc, LParenLoc, KindKwLoc, Kind, + EndLoc); +} + OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -12601,7 +12621,7 @@ OMPClause *Sema::ActOnOpenMPWriteClause(SourceLocation StartLoc, OMPClause *Sema::ActOnOpenMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc) { - return new (Context) OMPUpdateClause(StartLoc, EndLoc); + return OMPUpdateClause::Create(Context, StartLoc, EndLoc); } OMPClause *Sema::ActOnOpenMPCaptureClause(SourceLocation StartLoc, diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 865a666ce8f4..b5ca1e1841ac 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11657,7 +11657,7 @@ OMPClause *OMPClauseReader::readClause() { C = new (Context) OMPWriteClause(); break; case OMPC_update: - C = new (Context) OMPUpdateClause(); + C = OMPUpdateClause::CreateEmpty(Context, Record.readInt()); break; case OMPC_capture: C = new (Context) OMPCaptureClause(); @@ -11938,7 +11938,13 @@ void OMPClauseReader::VisitOMPReadClause(OMPReadClause *) {} void OMPClauseReader::VisitOMPWriteClause(OMPWriteClause *) {} -void OMPClauseReader::VisitOMPUpdateClause(OMPUpdateClause *) {} +void OMPClauseReader::VisitOMPUpdateClause(OMPUpdateClause *C) { + if (C->isExtended()) { + C->setLParenLoc(Record.readSourceLocation()); + C->setArgumentLoc(Record.readSourceLocation()); + C->setDependencyKind(Record.readEnum<OpenMPDependClauseKind>()); + } +} void OMPClauseReader::VisitOMPCaptureClause(OMPCaptureClause *) {} diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index bf59bca29e8c..bf893c7ff3bf 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -6141,7 +6141,14 @@ void OMPClauseWriter::VisitOMPReadClause(OMPReadClause *) {} void OMPClauseWriter::VisitOMPWriteClause(OMPWriteClause *) {} -void OMPClauseWriter::VisitOMPUpdateClause(OMPUpdateClause *) {} +void OMPClauseWriter::VisitOMPUpdateClause(OMPUpdateClause *C) { + Record.push_back(C->isExtended() ? 1 : 0); + if (C->isExtended()) { + Record.AddSourceLocation(C->getLParenLoc()); + Record.AddSourceLocation(C->getArgumentLoc()); + Record.writeEnum(C->getDependencyKind()); + } +} void OMPClauseWriter::VisitOMPCaptureClause(OMPCaptureClause *) {} diff --git a/clang/test/OpenMP/depobj_ast_print.cpp b/clang/test/OpenMP/depobj_ast_print.cpp index 9d1d408c058c..8b6586ca2b26 100644 --- a/clang/test/OpenMP/depobj_ast_print.cpp +++ b/clang/test/OpenMP/depobj_ast_print.cpp @@ -19,14 +19,17 @@ T tmain(T argc) { static T a; #pragma omp depobj(a) depend(in:argc) #pragma omp depobj(argc) destroy +#pragma omp depobj(argc) update(inout) return argc; } // CHECK: static T a; // CHECK-NEXT: #pragma omp depobj (a) depend(in : argc){{$}} // CHECK-NEXT: #pragma omp depobj (argc) destroy{{$}} +// CHECK-NEXT: #pragma omp depobj (argc) update(inout){{$}} // CHECK: static void *a; // CHECK-NEXT: #pragma omp depobj (a) depend(in : argc){{$}} // CHECK-NEXT: #pragma omp depobj (argc) destroy{{$}} +// CHECK-NEXT: #pragma omp depobj (argc) update(inout){{$}} int main(int argc, char **argv) { static omp_depend_t a; @@ -35,8 +38,10 @@ int main(int argc, char **argv) { // CHECK-NEXT: omp_depend_t b; #pragma omp depobj(a) depend(out:argc, argv) #pragma omp depobj(b) destroy +#pragma omp depobj(b) update(mutexinoutset) // CHECK-NEXT: #pragma omp depobj (a) depend(out : argc,argv) // CHECK-NEXT: #pragma omp depobj (b) destroy +// CHECK-NEXT: #pragma omp depobj (b) update(mutexinoutset) (void)tmain(a), tmain(b); return 0; } diff --git a/clang/test/OpenMP/depobj_messages.cpp b/clang/test/OpenMP/depobj_messages.cpp index b820a0eb517d..7b1529a69652 100644 --- a/clang/test/OpenMP/depobj_messages.cpp +++ b/clang/test/OpenMP/depobj_messages.cpp @@ -26,7 +26,7 @@ T tmain(T argc) { #pragma omp depobj(x) depend(in:s) } while (argc) -#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} +#pragma omp depobj(x)update(inout) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}} while (argc) { #pragma omp depobj(x) depend(in:s) } @@ -143,14 +143,23 @@ label1 : { ; #pragma omp depobj(x) seq_cst // expected-error {{unexpected OpenMP clause 'seq_cst' in directive '#pragma omp depobj'}} #pragma omp depobj(x) depend(in: x) +#pragma omp depobj(x) update // expected-error {{expected '(' after 'update'}} +#pragma omp depobj(x) update( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'update'}} +#pragma omp depobj(x) update(x // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'update'}} #pragma omp depobj(x) destroy destroy // expected-error {{directive '#pragma omp depobj' cannot contain more than one 'destroy' clause}} +#pragma omp depobj(x) update(in) update(in) // expected-error {{directive '#pragma omp depobj' cannot contain more than one 'update' clause}} #pragma omp depobj(x) depend(in: x) destroy // expected-error {{exactly one of 'depend', 'destroy', or 'update' clauses is expected}} #pragma omp depobj(x) destroy depend(in: x) // expected-error {{exactly one of 'depend', 'destroy', or 'update' clauses is expected}} +#pragma omp depobj(x) depend(in: x) update(mutexinoutset) // expected-error {{exactly one of 'depend', 'destroy', or 'update' clauses is expected}} +#pragma omp depobj(x) update(inout) destroy // expected-error {{exactly one of 'depend', 'destroy', or 'update' clauses is expected}} #pragma omp depobj(x) (x) depend(in: x) // expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} +#pragma omp depobj(x) (x) update(in) // expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} #pragma omp depobj(x) depend(in: x) depend(out:x) // expected-error {{exactly one of 'depend', 'destroy', or 'update' clauses is expected}} #pragma omp depend(out:x) depobj(x) // expected-error {{expected an OpenMP directive}} #pragma omp destroy depobj(x) // expected-error {{expected an OpenMP directive}} +#pragma omp update(out) depobj(x) // expected-error {{expected an OpenMP directive}} #pragma omp depobj depend(in:x) (x) // expected-error {{expected depobj expression}} expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} #pragma omp depobj destroy (x) // expected-error {{expected depobj expression}} expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} +#pragma omp depobj update(in) (x) // expected-error {{expected depobj expression}} expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} return tmain(argc); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits