diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 3ef504b70937..f0dddf729309 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -1875,6 +1875,46 @@ public: } }; +/// This represents 'acq_rel' clause in the '#pragma omp atomic|flush' +/// directives. +/// +/// \code +/// #pragma omp flush acq_rel +/// \endcode +/// In this example directive '#pragma omp flush' has 'acq_rel' clause. +class OMPAcqRelClause : public OMPClause { +public: + /// Build 'ack_rel' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + OMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_acq_rel, StartLoc, EndLoc) {} + + /// Build an empty clause. + OMPAcqRelClause() + : OMPClause(OMPC_acq_rel, SourceLocation(), SourceLocation()) {} + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + child_range used_children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range used_children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_acq_rel; + } +}; + /// This represents clause 'private' in the '#pragma omp ...' directives. /// /// \code diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 55245039e84f..d8e6fb6e0254 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -3121,6 +3121,11 @@ bool RecursiveASTVisitor::VisitOMPSeqCstClause(OMPSeqCstClause *) { return true; } +template +bool RecursiveASTVisitor::VisitOMPAcqRelClause(OMPAcqRelClause *) { + return true; +} + template bool RecursiveASTVisitor::VisitOMPThreadsClause(OMPThreadsClause *) { return true; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 104a2a575481..bd5bfa3e122b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9656,6 +9656,8 @@ def note_omp_atomic_capture: Note< "%select{expected assignment expression|expected compound statement|expected exactly two expression statements|expected in right hand side of the first expression}0">; def err_omp_atomic_several_clauses : Error< "directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause">; +def err_omp_atomic_several_mem_order_clauses : Error< + "directive '#pragma omp atomic' cannot contain more than one 'seq_cst' or 'acq_rel' clause">; def note_omp_atomic_previous_clause : Note< "'%0' clause used here">; def err_omp_target_contains_not_only_teams : Error< @@ -9894,6 +9896,10 @@ def err_omp_one_defaultmap_each_category: Error< def err_omp_lastprivate_conditional_non_scalar : Error< "expected list item of scalar type in 'lastprivate' clause with 'conditional' modifier" >; +def err_omp_flush_order_clause_and_list : Error< + "'flush' directive with memory order clause '%0' cannot have the list">; +def note_omp_flush_order_clause_here : Note< + "memory order clause '%0' is specified here">; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 20b5b8a4eb25..0d7d952a49d6 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -215,6 +215,9 @@ #ifndef OPENMP_ORDER_KIND #define OPENMP_ORDER_KIND(Name) #endif +#ifndef OPENMP_FLUSH_CLAUSE +#define OPENMP_FLUSH_CLAUSE(Name) +#endif // OpenMP context selector sets. OPENMP_CONTEXT_SELECTOR_SET(implementation) @@ -254,6 +257,7 @@ OPENMP_CLAUSE(write, OMPWriteClause) OPENMP_CLAUSE(update, OMPUpdateClause) OPENMP_CLAUSE(capture, OMPCaptureClause) OPENMP_CLAUSE(seq_cst, OMPSeqCstClause) +OPENMP_CLAUSE(acq_rel, OMPAcqRelClause) OPENMP_CLAUSE(depend, OMPDependClause) OPENMP_CLAUSE(device, OMPDeviceClause) OPENMP_CLAUSE(threads, OMPThreadsClause) @@ -486,6 +490,7 @@ OPENMP_ATOMIC_CLAUSE(write) OPENMP_ATOMIC_CLAUSE(update) OPENMP_ATOMIC_CLAUSE(capture) OPENMP_ATOMIC_CLAUSE(seq_cst) +OPENMP_ATOMIC_CLAUSE(acq_rel) // Clauses allowed for OpenMP directive 'target'. OPENMP_TARGET_CLAUSE(if) @@ -1082,6 +1087,10 @@ OPENMP_LASTPRIVATE_KIND(conditional) // Type of the 'order' clause. OPENMP_ORDER_KIND(concurrent) +// Clauses allowed for OpenMP directive 'flush'. +OPENMP_FLUSH_CLAUSE(acq_rel) + +#undef OPENMP_FLUSH_CLAUSE #undef OPENMP_ORDER_KIND #undef OPENMP_LASTPRIVATE_KIND #undef OPENMP_CONTEXT_SELECTOR diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 1d953c8fa65f..99cfd2411ab7 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10327,6 +10327,9 @@ public: /// Called on well-formed 'seq_cst' clause. OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc); + /// Called on well-formed 'acq_rel' clause. + OMPClause *ActOnOpenMPAcqRelClause(SourceLocation StartLoc, + SourceLocation EndLoc); /// Called on well-formed 'threads' clause. OMPClause *ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc); diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index c7e7f339d499..b1f9ad17f708 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -116,6 +116,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) { case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_acq_rel: case OMPC_depend: case OMPC_threads: case OMPC_simd: @@ -190,6 +191,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_acq_rel: case OMPC_depend: case OMPC_device: case OMPC_threads: @@ -1334,6 +1336,10 @@ void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) { OS << "seq_cst"; } +void OMPClausePrinter::VisitOMPAcqRelClause(OMPAcqRelClause *) { + OS << "acq_rel"; +} + void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) { OS << "threads"; } diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 4625374cc4c4..a39bc9af3b03 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -517,6 +517,8 @@ void OMPClauseProfiler::VisitOMPCaptureClause(const OMPCaptureClause *) {} void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {} +void OMPClauseProfiler::VisitOMPAcqRelClause(const OMPAcqRelClause *) {} + void OMPClauseProfiler::VisitOMPThreadsClause(const OMPThreadsClause *) {} void OMPClauseProfiler::VisitOMPSIMDClause(const OMPSIMDClause *) {} diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 3204e22004a6..8937e879af2b 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -214,6 +214,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_acq_rel: case OMPC_device: case OMPC_threads: case OMPC_simd: @@ -426,6 +427,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_acq_rel: case OMPC_device: case OMPC_threads: case OMPC_simd: @@ -577,9 +579,22 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, } break; case OMPD_flush: - return CKind == OMPC_flush; + if (CKind == OMPC_flush) + return true; + if (OpenMPVersion < 50) + return false; + switch (CKind) { +#define OPENMP_FLUSH_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } break; case OMPD_atomic: + if (OpenMPVersion < 50 && CKind == OMPC_acq_rel) + return false; switch (CKind) { #define OPENMP_ATOMIC_CLAUSE(Name) \ case OMPC_##Name: \ diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 827ea213bf4e..b315421d51f3 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -21,6 +21,7 @@ #include "clang/AST/OpenMPClause.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/PrettyStackTrace.h" #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" using namespace clang; @@ -4434,6 +4435,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, case OMPC_collapse: case OMPC_default: case OMPC_seq_cst: + case OMPC_acq_rel: case OMPC_shared: case OMPC_linear: case OMPC_aligned: @@ -4483,8 +4485,9 @@ void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) { bool IsSeqCst = S.getSingleClause(); OpenMPClauseKind Kind = OMPC_unknown; for (const OMPClause *C : S.clauses()) { - // Find first clause (skip seq_cst clause, if it is first). - if (C->getClauseKind() != OMPC_seq_cst) { + // Find first clause (skip seq_cst|acq_rel clause, if it is first). + if (C->getClauseKind() != OMPC_seq_cst && + C->getClauseKind() != OMPC_acq_rel) { Kind = C->getClauseKind(); break; } diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index ed2e52a66453..8ac0471b1806 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -1720,7 +1720,6 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { DeclarationNameInfo DirName; StmtResult Directive = StmtError(); bool HasAssociatedStatement = true; - bool FlushHasClause = false; switch (DKind) { case OMPD_threadprivate: { @@ -1831,13 +1830,6 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { break; } case OMPD_flush: - if (PP.LookAhead(0).is(tok::l_paren)) { - FlushHasClause = true; - // Push copy of the current token back to stream to properly parse - // pseudo-clause OMPFlushClause. - PP.EnterToken(Tok, /*IsReinject*/ true); - } - LLVM_FALLTHROUGH; case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -1897,6 +1889,10 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { case OMPD_target_teams_distribute_parallel_for: case OMPD_target_teams_distribute_parallel_for_simd: case OMPD_target_teams_distribute_simd: { + // Special processing for flush clause. + Token FlushTok; + if (DKind == OMPD_flush) + FlushTok = Tok; ConsumeToken(); // Parse directive name of the 'critical' directive if any. if (DKind == OMPD_critical) { @@ -1926,6 +1922,15 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); while (Tok.isNot(tok::annot_pragma_openmp_end)) { + bool FlushHasClause = false; + if (DKind == OMPD_flush && Tok.is(tok::l_paren)) { + FlushHasClause = true; + // Push copy of the current token back to stream to properly parse + // pseudo-clause OMPFlushClause. + PP.EnterToken(Tok, /*IsReinject*/ true); + PP.EnterToken(FlushTok, /*IsReinject*/ true); + ConsumeAnyToken(); + } OpenMPClauseKind CKind = Tok.isAnnotation() ? OMPC_unknown @@ -2084,7 +2089,8 @@ bool Parser::ParseOpenMPSimpleVarList( /// thread_limit-clause | priority-clause | grainsize-clause | /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | /// from-clause | is_device_ptr-clause | task_reduction-clause | -/// in_reduction-clause | allocator-clause | allocate-clause +/// in_reduction-clause | allocator-clause | allocate-clause | +/// acq_rel-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -2193,6 +2199,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_acq_rel: case OMPC_threads: case OMPC_simd: case OMPC_nogroup: diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index df76b42ad7d4..aa619710c4ef 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -4987,6 +4987,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective( case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_acq_rel: case OMPC_depend: case OMPC_threads: case OMPC_simd: @@ -8562,7 +8563,21 @@ StmtResult Sema::ActOnOpenMPTaskgroupDirective(ArrayRef Clauses, StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef Clauses, SourceLocation StartLoc, SourceLocation EndLoc) { - assert(Clauses.size() <= 1 && "Extra clauses in flush directive"); + OMPFlushClause *FC = nullptr; + OMPClause *OrderClause = nullptr; + for (OMPClause *C : Clauses) { + if (C->getClauseKind() == OMPC_flush) + FC = cast(C); + else + OrderClause = C; + } + if (FC && OrderClause) { + Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list) + << getOpenMPClauseName(OrderClause->getClauseKind()); + Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here) + << getOpenMPClauseName(OrderClause->getClauseKind()); + return StmtError(); + } return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses); } @@ -8901,6 +8916,8 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef Clauses, // longjmp() and throw() must not violate the entry/exit criteria. OpenMPClauseKind AtomicKind = OMPC_unknown; SourceLocation AtomicKindLoc; + OpenMPClauseKind MemOrderKind = OMPC_unknown; + SourceLocation MemOrderLoc; for (const OMPClause *C : Clauses) { if (C->getClauseKind() == OMPC_read || C->getClauseKind() == OMPC_write || C->getClauseKind() == OMPC_update || @@ -8915,6 +8932,18 @@ StmtResult Sema::ActOnOpenMPAtomicDirective(ArrayRef Clauses, AtomicKindLoc = C->getBeginLoc(); } } + if (C->getClauseKind() == OMPC_seq_cst || + C->getClauseKind() == OMPC_acq_rel) { + if (MemOrderKind != OMPC_unknown) { + Diag(C->getBeginLoc(), diag::err_omp_atomic_several_mem_order_clauses) + << SourceRange(C->getBeginLoc(), C->getEndLoc()); + Diag(MemOrderLoc, diag::note_omp_atomic_previous_clause) + << getOpenMPClauseName(MemOrderKind); + } else { + MemOrderKind = C->getClauseKind(); + MemOrderLoc = C->getBeginLoc(); + } + } } Stmt *Body = CS->getCapturedStmt(); @@ -10841,6 +10870,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_acq_rel: case OMPC_depend: case OMPC_threads: case OMPC_simd: @@ -11553,6 +11583,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause( case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_acq_rel: case OMPC_depend: case OMPC_threads: case OMPC_simd: @@ -11975,6 +12006,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause( case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_acq_rel: case OMPC_depend: case OMPC_device: case OMPC_threads: @@ -12175,6 +12207,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause( case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_acq_rel: case OMPC_depend: case OMPC_device: case OMPC_threads: @@ -12348,6 +12381,9 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind, case OMPC_seq_cst: Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc); break; + case OMPC_acq_rel: + Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc); + break; case OMPC_threads: Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc); break; @@ -12461,6 +12497,11 @@ OMPClause *Sema::ActOnOpenMPSeqCstClause(SourceLocation StartLoc, return new (Context) OMPSeqCstClause(StartLoc, EndLoc); } +OMPClause *Sema::ActOnOpenMPAcqRelClause(SourceLocation StartLoc, + SourceLocation EndLoc) { + return new (Context) OMPAcqRelClause(StartLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc) { return new (Context) OMPThreadsClause(StartLoc, EndLoc); @@ -12617,6 +12658,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause( case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_acq_rel: case OMPC_device: case OMPC_threads: case OMPC_simd: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index c00c06e7f003..bd0df005f60b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -8804,6 +8804,13 @@ TreeTransform::TransformOMPSeqCstClause(OMPSeqCstClause *C) { return C; } +template +OMPClause * +TreeTransform::TransformOMPAcqRelClause(OMPAcqRelClause *C) { + // No need to rebuild this clause, no template-dependent parameters. + return C; +} + template OMPClause * TreeTransform::TransformOMPThreadsClause(OMPThreadsClause *C) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 0921190e637d..c25ce4942316 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11666,6 +11666,9 @@ OMPClause *OMPClauseReader::readClause() { case OMPC_seq_cst: C = new (Context) OMPSeqCstClause(); break; + case OMPC_acq_rel: + C = new (Context) OMPAcqRelClause(); + break; case OMPC_threads: C = new (Context) OMPThreadsClause(); break; @@ -11928,6 +11931,8 @@ void OMPClauseReader::VisitOMPCaptureClause(OMPCaptureClause *) {} void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {} +void OMPClauseReader::VisitOMPAcqRelClause(OMPAcqRelClause *) {} + void OMPClauseReader::VisitOMPThreadsClause(OMPThreadsClause *) {} void OMPClauseReader::VisitOMPSIMDClause(OMPSIMDClause *) {} diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 123f83a36db3..2e19d735265c 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -6147,6 +6147,8 @@ void OMPClauseWriter::VisitOMPCaptureClause(OMPCaptureClause *) {} void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {} +void OMPClauseWriter::VisitOMPAcqRelClause(OMPAcqRelClause *) {} + void OMPClauseWriter::VisitOMPThreadsClause(OMPThreadsClause *) {} void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {} diff --git a/clang/test/OpenMP/atomic_ast_print.cpp b/clang/test/OpenMP/atomic_ast_print.cpp index c66249b708ed..06c1aea19691 100644 --- a/clang/test/OpenMP/atomic_ast_print.cpp +++ b/clang/test/OpenMP/atomic_ast_print.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// 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-simd -ast-print %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -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 // expected-no-diagnostics #ifndef HEADER @@ -44,6 +44,21 @@ T foo(T argc) { a = b; b++; } +#pragma omp atomic acq_rel + a++; +#pragma omp atomic read acq_rel + a = argc; +#pragma omp atomic acq_rel write + a = argc + argc; +#pragma omp atomic update acq_rel + a = a + argc; +#pragma omp atomic acq_rel capture + a = b++; +#pragma omp atomic capture acq_rel + { + a = b; + b++; + } return T(); } @@ -78,6 +93,21 @@ T foo(T argc) { // CHECK-NEXT: a = b; // CHECK-NEXT: b++; // CHECK-NEXT: } +// CHECK-NEXT: #pragma omp atomic acq_rel +// CHECK-NEXT: a++; +// CHECK-NEXT: #pragma omp atomic read acq_rel +// CHECK-NEXT: a = argc; +// CHECK-NEXT: #pragma omp atomic acq_rel write +// CHECK-NEXT: a = argc + argc; +// CHECK-NEXT: #pragma omp atomic update acq_rel +// CHECK-NEXT: a = a + argc; +// CHECK-NEXT: #pragma omp atomic acq_rel capture +// CHECK-NEXT: a = b++; +// CHECK-NEXT: #pragma omp atomic capture acq_rel +// CHECK-NEXT: { +// CHECK-NEXT: a = b; +// CHECK-NEXT: b++; +// CHECK-NEXT: } // CHECK: int a = int(); // CHECK-NEXT: #pragma omp atomic // CHECK-NEXT: a++; @@ -109,6 +139,21 @@ T foo(T argc) { // CHECK-NEXT: a = b; // CHECK-NEXT: b++; // CHECK-NEXT: } +// CHECK-NEXT: #pragma omp atomic acq_rel +// CHECK-NEXT: a++; +// CHECK-NEXT: #pragma omp atomic read acq_rel +// CHECK-NEXT: a = argc; +// CHECK-NEXT: #pragma omp atomic acq_rel write +// CHECK-NEXT: a = argc + argc; +// CHECK-NEXT: #pragma omp atomic update acq_rel +// CHECK-NEXT: a = a + argc; +// CHECK-NEXT: #pragma omp atomic acq_rel capture +// CHECK-NEXT: a = b++; +// CHECK-NEXT: #pragma omp atomic capture acq_rel +// CHECK-NEXT: { +// CHECK-NEXT: a = b; +// CHECK-NEXT: b++; +// CHECK-NEXT: } int main(int argc, char **argv) { int b = 0; @@ -144,6 +189,21 @@ int main(int argc, char **argv) { a = b; b++; } +#pragma omp atomic acq_rel + a++; +#pragma omp atomic read acq_rel + a = argc; +#pragma omp atomic acq_rel write + a = argc + argc; +#pragma omp atomic update acq_rel + a = a + argc; +#pragma omp atomic acq_rel capture + a = b++; +#pragma omp atomic capture acq_rel + { + a = b; + b++; + } // CHECK-NEXT: #pragma omp atomic // CHECK-NEXT: a++; // CHECK-NEXT: #pragma omp atomic read @@ -174,6 +234,21 @@ int main(int argc, char **argv) { // CHECK-NEXT: a = b; // CHECK-NEXT: b++; // CHECK-NEXT: } + // CHECK-NEXT: #pragma omp atomic acq_rel + // CHECK-NEXT: a++; + // CHECK-NEXT: #pragma omp atomic read acq_rel + // CHECK-NEXT: a = argc; + // CHECK-NEXT: #pragma omp atomic acq_rel write + // CHECK-NEXT: a = argc + argc; + // CHECK-NEXT: #pragma omp atomic update acq_rel + // CHECK-NEXT: a = a + argc; + // CHECK-NEXT: #pragma omp atomic acq_rel capture + // CHECK-NEXT: a = b++; + // CHECK-NEXT: #pragma omp atomic capture acq_rel + // CHECK-NEXT: { + // CHECK-NEXT: a = b; + // CHECK-NEXT: b++; + // CHECK-NEXT: } return foo(a); } diff --git a/clang/test/OpenMP/atomic_messages.cpp b/clang/test/OpenMP/atomic_messages.cpp index e4ca628075f0..804375a852e5 100644 --- a/clang/test/OpenMP/atomic_messages.cpp +++ b/clang/test/OpenMP/atomic_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 150 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -fopenmp-version=50 -ferror-limit 150 %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 150 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -ferror-limit 150 %s -Wuninitialized int foo() { L1: @@ -723,6 +725,48 @@ int seq_cst() { return seq_cst(); } +template +T acq_rel() { + T a = 0, b = 0; +// omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}} +#pragma omp atomic acq_rel + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} + ; +// omp50-error@+1 2 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' or 'acq_rel' clause}} omp50-note@+1 2 {{'acq_rel' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}} +#pragma omp atomic acq_rel seq_cst + a += b; + +// omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}} +#pragma omp atomic update acq_rel + // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} + ; + + return T(); +} + +int acq_rel() { + int a = 0, b = 0; +// Test for atomic acq_rel +// omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}} +#pragma omp atomic acq_rel + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} + ; +// omp50-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' or 'acq_rel' clause}} omp50-note@+1 {{'seq_cst' clause used here}} omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}} +#pragma omp atomic seq_cst acq_rel + a += b; + +// omp45-error@+1 {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp atomic'}} +#pragma omp atomic update acq_rel + // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}} + // expected-note@+1 {{expected an expression statement}} + ; + + return acq_rel(); // omp50-note {{in instantiation of function template specialization 'acq_rel' requested here}} +} + template T mixed() { T a, b = T(); diff --git a/clang/test/OpenMP/flush_ast_print.cpp b/clang/test/OpenMP/flush_ast_print.cpp index 8cde315a453c..ca275b8e1f59 100644 --- a/clang/test/OpenMP/flush_ast_print.cpp +++ b/clang/test/OpenMP/flush_ast_print.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// 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-simd -ast-print %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -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 // expected-no-diagnostics #ifndef HEADER @@ -16,25 +16,31 @@ template T tmain(T argc) { static T a; #pragma omp flush +#pragma omp flush acq_rel #pragma omp flush(a) return a + argc; } // CHECK: static T a; // CHECK-NEXT: #pragma omp flush{{$}} +// CHECK-NEXT: #pragma omp flush acq_rel{{$}} // CHECK-NEXT: #pragma omp flush (a) // CHECK: static int a; // CHECK-NEXT: #pragma omp flush +// CHECK-NEXT: #pragma omp flush acq_rel{{$}} // CHECK-NEXT: #pragma omp flush (a) // CHECK: static char a; // CHECK-NEXT: #pragma omp flush +// CHECK-NEXT: #pragma omp flush acq_rel{{$}} // CHECK-NEXT: #pragma omp flush (a) int main(int argc, char **argv) { static int a; // CHECK: static int a; #pragma omp flush +#pragma omp flush acq_rel #pragma omp flush(a) // CHECK-NEXT: #pragma omp flush +// CHECK-NEXT: #pragma omp flush acq_rel // CHECK-NEXT: #pragma omp flush (a) return tmain(argc) + tmain(argv[0][0]) + a; } diff --git a/clang/test/OpenMP/flush_messages.cpp b/clang/test/OpenMP/flush_messages.cpp index 5838e12ce8c4..234db25f26dc 100644 --- a/clang/test/OpenMP/flush_messages.cpp +++ b/clang/test/OpenMP/flush_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 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -fopenmp-version=50 -ferror-limit 100 %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 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 %s -Wuninitialized struct S1 { // expected-note 2 {{declared here}} int a; @@ -132,5 +134,9 @@ label1 : { #pragma omp flush(argc) flush(argc) // expected-warning {{extra tokens at the end of '#pragma omp flush' are ignored}} #pragma omp parallel flush(argc) // expected-warning {{extra tokens at the end of '#pragma omp parallel' are ignored}} ; +#pragma omp flush seq_cst // expected-error {{unexpected OpenMP clause 'seq_cst' in directive '#pragma omp flush'}} +#pragma omp flush acq_rel // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} +#pragma omp flush acq_rel (argc) // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} omp50-error {{'flush' directive with memory order clause 'acq_rel' cannot have the list}} omp50-note {{memory order clause 'acq_rel' is specified here}} +#pragma omp flush(argc) acq_rel // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} omp50-error {{'flush' directive with memory order clause 'acq_rel' cannot have the list}} omp50-note {{memory order clause 'acq_rel' is specified here}} return tmain(argc); } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 8d1fb8f0fb82..95cb517fa332 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2234,6 +2234,8 @@ void OMPClauseEnqueue::VisitOMPCaptureClause(const OMPCaptureClause *) {} void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {} +void OMPClauseEnqueue::VisitOMPAcqRelClause(const OMPAcqRelClause *) {} + void OMPClauseEnqueue::VisitOMPThreadsClause(const OMPThreadsClause *) {} void OMPClauseEnqueue::VisitOMPSIMDClause(const OMPSIMDClause *) {}