summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2014-07-21 11:26:11 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2014-07-21 11:26:11 +0000
commite559847c3d4cf821fee268eafee4ac355ca834cd (patch)
treeb4e8b53ac1cede2b4f05f2f700202a1ffd92f45e
parent76fc5c55ecf19799784bf1f798293da347a7e56f (diff)
[OPENMP] Initial parsing and sema analysis for 'flush' directive.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@213512 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang-c/Index.h6
-rw-r--r--include/clang/AST/DataRecursiveASTVisitor.h9
-rw-r--r--include/clang/AST/OpenMPClause.h60
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h9
-rw-r--r--include/clang/AST/StmtOpenMP.h59
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td2
-rw-r--r--include/clang/Basic/OpenMPKinds.def2
-rw-r--r--include/clang/Basic/StmtNodes.td1
-rw-r--r--include/clang/Sema/Sema.h11
-rw-r--r--include/clang/Serialization/ASTBitCodes.h1
-rw-r--r--lib/AST/Stmt.cpp43
-rw-r--r--lib/AST/StmtPrinter.cpp11
-rw-r--r--lib/AST/StmtProfile.cpp7
-rw-r--r--lib/Basic/OpenMPKinds.cpp7
-rw-r--r--lib/CodeGen/CGStmt.cpp3
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp4
-rw-r--r--lib/CodeGen/CodeGenFunction.h1
-rw-r--r--lib/Parse/ParseOpenMP.cpp35
-rw-r--r--lib/Sema/SemaOpenMP.cpp49
-rw-r--r--lib/Sema/TreeTransform.h37
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp25
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp14
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp1
-rw-r--r--test/OpenMP/flush_ast_print.cpp38
-rw-r--r--test/OpenMP/flush_messages.cpp134
-rw-r--r--test/OpenMP/nesting_of_regions.cpp102
-rw-r--r--tools/libclang/CIndex.cpp10
-rw-r--r--tools/libclang/CXCursor.cpp3
28 files changed, 673 insertions, 11 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index e4d3ebd533..f69f567c26 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -2187,9 +2187,13 @@ enum CXCursorKind {
*/
CXCursor_OMPTaskwaitDirective = 245,
+ /** \brief OpenMP flush directive.
+ */
+ CXCursor_OMPFlushDirective = 246,
+
/** \brief Windows Structured Exception Handling's leave statement.
*/
- CXCursor_SEHLeaveStmt = 246,
+ CXCursor_SEHLeaveStmt = 247,
CXCursor_LastStmt = CXCursor_SEHLeaveStmt,
diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h
index 072bd7b0d9..9ef008717b 100644
--- a/include/clang/AST/DataRecursiveASTVisitor.h
+++ b/include/clang/AST/DataRecursiveASTVisitor.h
@@ -2323,6 +2323,9 @@ DEF_TRAVERSE_STMT(OMPBarrierDirective,
DEF_TRAVERSE_STMT(OMPTaskwaitDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPFlushDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
// OpenMP clauses.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
@@ -2482,6 +2485,12 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h
index 009d8839b5..3345959653 100644
--- a/include/clang/AST/OpenMPClause.h
+++ b/include/clang/AST/OpenMPClause.h
@@ -1390,6 +1390,66 @@ public:
}
};
+/// \brief This represents pseudo clause 'flush' for the '#pragma omp flush'
+/// directive.
+///
+/// \code
+/// #pragma omp flush(a,b)
+/// \endcode
+/// In this example directive '#pragma omp flush' has pseudo clause 'flush'
+/// with the variables 'a' and 'b'.
+///
+class OMPFlushClause : public OMPVarListClause<OMPFlushClause> {
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPFlushClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPFlushClause>(OMPC_flush, StartLoc, LParenLoc,
+ EndLoc, N) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPFlushClause(unsigned N)
+ : OMPVarListClause<OMPFlushClause>(OMPC_flush, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ N) {}
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ ///
+ static OMPFlushClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ ArrayRef<Expr *> VL);
+ /// \brief Creates an empty clause with \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPFlushClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ StmtRange children() {
+ return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_flush;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 2953e7ad76..ff46ffb94e 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -2345,6 +2345,9 @@ DEF_TRAVERSE_STMT(OMPBarrierDirective,
DEF_TRAVERSE_STMT(OMPTaskwaitDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPFlushDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
// OpenMP clauses.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
@@ -2504,6 +2507,12 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
index 2c38c167f6..db02afe056 100644
--- a/include/clang/AST/StmtOpenMP.h
+++ b/include/clang/AST/StmtOpenMP.h
@@ -969,6 +969,65 @@ public:
}
};
+/// \brief This represents '#pragma omp flush' directive.
+///
+/// \code
+/// #pragma omp flush(a,b)
+/// \endcode
+/// In this example directive '#pragma omp flush' has 2 arguments- variables 'a'
+/// and 'b'.
+/// 'omp flush' directive does not have clauses but have an optional list of
+/// variables to flush. This list of variables is stored within some fake clause
+/// FlushClause.
+class OMPFlushDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPFlushDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPFlushDirectiveClass, OMPD_flush,
+ StartLoc, EndLoc, NumClauses, 0) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPFlushDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPFlushDirectiveClass, OMPD_flush,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 0) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses (only single OMPFlushClause clause is
+ /// allowed).
+ ///
+ static OMPFlushDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPFlushDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPFlushDirectiveClass;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 34ac6a4525..aed53bdc9b 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -903,7 +903,7 @@ def err_omp_unknown_directive : Error<
def err_omp_unexpected_directive : Error<
"unexpected OpenMP directive '#pragma omp %0'">;
def err_omp_expected_punc : Error<
- "expected ',' or ')' in '%0' clause">;
+ "expected ',' or ')' in '%0' %select{clause|directive}1">;
def err_omp_unexpected_clause : Error<
"unexpected OpenMP clause '%0' in directive '#pragma omp %1'">;
def err_omp_more_one_clause : Error<
diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def
index a871ff24a1..6cfa5ea549 100644
--- a/include/clang/Basic/OpenMPKinds.def
+++ b/include/clang/Basic/OpenMPKinds.def
@@ -69,6 +69,7 @@ OPENMP_DIRECTIVE(critical)
OPENMP_DIRECTIVE(taskyield)
OPENMP_DIRECTIVE(barrier)
OPENMP_DIRECTIVE(taskwait)
+OPENMP_DIRECTIVE(flush)
OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for")
OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections")
@@ -94,6 +95,7 @@ OPENMP_CLAUSE(ordered, OMPOrderedClause)
OPENMP_CLAUSE(nowait, OMPNowaitClause)
OPENMP_CLAUSE(untied, OMPUntiedClause)
OPENMP_CLAUSE(mergeable, OMPMergeableClause)
+OPENMP_CLAUSE(flush, OMPFlushClause)
// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index 28e0f4cf7b..d980648649 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -192,3 +192,4 @@ def OMPTaskDirective : DStmt<OMPExecutableDirective>;
def OMPTaskyieldDirective : DStmt<OMPExecutableDirective>;
def OMPBarrierDirective : DStmt<OMPExecutableDirective>;
def OMPTaskwaitDirective : DStmt<OMPExecutableDirective>;
+def OMPFlushDirective : DStmt<OMPExecutableDirective>;
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 6d8b62dbf0..43fa508ad4 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -7382,7 +7382,11 @@ public:
SourceLocation EndLoc);
/// \brief Called on well-formed '\#pragma omp taskwait'.
StmtResult ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
- SourceLocation EndLoc);
+ SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp flush'.
+ StmtResult ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Expr *Expr,
@@ -7520,6 +7524,11 @@ public:
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// \brief Called on well-formed 'flush' pseudo clause.
+ OMPClause *ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// \brief The kind of conversion being performed.
enum CheckedConversionKind {
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 8c1b91af16..7ae1977d3e 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1354,6 +1354,7 @@ namespace clang {
STMT_OMP_TASKYIELD_DIRECTIVE,
STMT_OMP_BARRIER_DIRECTIVE,
STMT_OMP_TASKWAIT_DIRECTIVE,
+ STMT_OMP_FLUSH_DIRECTIVE,
// ARC
EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index b011f9f24c..a8483dc5bb 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -1327,6 +1327,27 @@ OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPReductionClause(N);
}
+OMPFlushClause *OMPFlushClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ ArrayRef<Expr *> VL) {
+ void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFlushClause),
+ llvm::alignOf<Expr *>()) +
+ sizeof(Expr *) * VL.size());
+ OMPFlushClause *Clause =
+ new (Mem) OMPFlushClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ return Clause;
+}
+
+OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) {
+ void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPFlushClause),
+ llvm::alignOf<Expr *>()) +
+ sizeof(Expr *) * N);
+ return new (Mem) OMPFlushClause(N);
+}
+
OMPParallelDirective *OMPParallelDirective::Create(
const ASTContext &C,
SourceLocation StartLoc,
@@ -1635,3 +1656,25 @@ OMPTaskwaitDirective *OMPTaskwaitDirective::CreateEmpty(const ASTContext &C,
return new (Mem) OMPTaskwaitDirective();
}
+OMPFlushDirective *OMPFlushDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPFlushDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size());
+ OMPFlushDirective *Dir =
+ new (Mem) OMPFlushDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ return Dir;
+}
+
+OMPFlushDirective *OMPFlushDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPFlushDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses);
+ return new (Mem) OMPFlushDirective(NumClauses);
+}
+
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 9c00eeaa0f..1fdad9f427 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -775,6 +775,12 @@ void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause *Node) {
}
}
+void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) {
+ if (!Node->varlist_empty()) {
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
}
//===----------------------------------------------------------------------===//
@@ -875,6 +881,11 @@ void StmtPrinter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *Node) {
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPFlushDirective(OMPFlushDirective *Node) {
+ Indent() << "#pragma omp flush ";
+ PrintOMPExecutableDirective(Node);
+}
+
//===----------------------------------------------------------------------===//
// Expr printing methods.
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 56827ed383..f44f25c96a 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -352,6 +352,9 @@ void
OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) {
+ VisitOMPClauseList(C);
+}
}
void
@@ -424,6 +427,10 @@ void StmtProfiler::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *S) {
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPFlushDirective(const OMPFlushDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitExpr(const Expr *S) {
VisitStmt(S);
}
diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index 869b00c02a..06f010f7ce 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/lib/Basic/OpenMPKinds.cpp
@@ -46,6 +46,8 @@ const char *clang::getOpenMPDirectiveName(OpenMPDirectiveKind Kind) {
}
OpenMPClauseKind clang::getOpenMPClauseKind(StringRef Str) {
+ if (Str == "flush")
+ return OMPC_unknown;
return llvm::StringSwitch<OpenMPClauseKind>(Str)
#define OPENMP_CLAUSE(Name, Class) .Case(#Name, OMPC_##Name)
#include "clang/Basic/OpenMPKinds.def"
@@ -105,6 +107,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_nowait:
case OMPC_untied:
case OMPC_mergeable:
+ case OMPC_flush:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -163,6 +166,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_nowait:
case OMPC_untied:
case OMPC_mergeable:
+ case OMPC_flush:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -253,6 +257,9 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
}
break;
+ case OMPD_flush:
+ return CKind == OMPC_flush;
+ break;
case OMPD_unknown:
case OMPD_threadprivate:
case OMPD_section:
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index 82566382db..f36111607d 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -218,6 +218,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::OMPTaskwaitDirectiveClass:
EmitOMPTaskwaitDirective(cast<OMPTaskwaitDirective>(*S));
break;
+ case Stmt::OMPFlushDirectiveClass:
+ EmitOMPFlushDirective(cast<OMPFlushDirective>(*S));
+ break;
}
}
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index e4ef5a6911..867f41592d 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -124,3 +124,7 @@ void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &) {
llvm_unreachable("CodeGen for 'omp taskwait' is not supported yet.");
}
+void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &) {
+ llvm_unreachable("CodeGen for 'omp flush' is not supported yet.");
+}
+
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 66bf78f002..59cc30da42 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1935,6 +1935,7 @@ public:
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S);
void EmitOMPBarrierDirective(const OMPBarrierDirective &S);
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S);
+ void EmitOMPFlushDirective(const OMPFlushDirective &S);
//===--------------------------------------------------------------------===//
// LValue Expression Emission
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index 79cf6af6fd..d1544e6baa 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -86,6 +86,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
+ case OMPD_flush:
case OMPD_for:
case OMPD_sections:
case OMPD_section:
@@ -112,7 +113,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
/// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
-/// 'barrier' | 'taskwait' {clause} annot_pragma_openmp_end
+/// 'barrier' | 'taskwait' | 'flush' {clause} annot_pragma_openmp_end
///
StmtResult
Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
@@ -130,6 +131,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
DeclarationNameInfo DirName;
StmtResult Directive = StmtError();
bool HasAssociatedStatement = true;
+ bool FlushHasClause = false;
switch (DKind) {
case OMPD_threadprivate:
@@ -148,6 +150,13 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
}
SkipUntil(tok::annot_pragma_openmp_end);
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);
+ }
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
@@ -156,6 +165,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
<< getOpenMPDirectiveName(DKind);
}
HasAssociatedStatement = false;
+ // Fall through for further analysis.
case OMPD_parallel:
case OMPD_simd:
case OMPD_for:
@@ -192,9 +202,12 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
- OpenMPClauseKind CKind = Tok.isAnnotation()
- ? OMPC_unknown
- : getOpenMPClauseKind(PP.getSpelling(Tok));
+ OpenMPClauseKind CKind =
+ Tok.isAnnotation()
+ ? OMPC_unknown
+ : FlushHasClause ? OMPC_flush
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ FlushHasClause = false;
OMPClause *Clause =
ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
FirstClauses[CKind].setInt(true);
@@ -324,7 +337,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
/// | linear-clause | aligned-clause | collapse-clause |
/// lastprivate-clause | reduction-clause | proc_bind-clause |
/// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
-/// mergeable-clause
+/// mergeable-clause | flush-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@@ -407,6 +420,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_aligned:
case OMPC_copyin:
case OMPC_copyprivate:
+ case OMPC_flush:
Clause = ParseOpenMPVarListClause(CKind);
break;
case OMPC_unknown:
@@ -605,7 +619,7 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
}
/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
-/// 'shared', 'copyin', or 'reduction'.
+/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
///
/// private-clause:
/// 'private' '(' list ')'
@@ -621,6 +635,10 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
/// 'aligned' '(' list [ ':' alignment ] ')'
/// reduction-clause:
/// 'reduction' '(' reduction-identifier ':' list ')'
+/// copyprivate-clause:
+/// 'copyprivate' '(' list ')'
+/// flush-clause:
+/// 'flush' '(' list ')'
///
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
SourceLocation Loc = Tok.getLocation();
@@ -676,7 +694,10 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
else if (Tok.isNot(tok::r_paren) &&
Tok.isNot(tok::annot_pragma_openmp_end) &&
(!MayHaveTail || Tok.isNot(tok::colon)))
- Diag(Tok, diag::err_omp_expected_punc) << getOpenMPClauseName(Kind);
+ Diag(Tok, diag::err_omp_expected_punc)
+ << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
+ : getOpenMPClauseName(Kind))
+ << (Kind == OMPC_flush);
}
// Parse ':' linear-step (or ':' alignment).
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index c0a6d60a16..7f2af68e55 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -1085,6 +1085,14 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
+ case OMPD_flush: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
case OMPD_threadprivate:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
@@ -1114,6 +1122,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel | taskyield | * |
// | parallel | barrier | * |
// | parallel | taskwait | * |
+ // | parallel | flush | * |
// +------------------+-----------------+------------------------------------+
// | for | parallel | * |
// | for | for | + |
@@ -1129,6 +1138,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | for | taskyield | * |
// | for | barrier | + |
// | for | taskwait | * |
+ // | for | flush | * |
// +------------------+-----------------+------------------------------------+
// | master | parallel | * |
// | master | for | + |
@@ -1144,6 +1154,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | master | taskyield | * |
// | master | barrier | + |
// | master | taskwait | * |
+ // | master | flush | * |
// +------------------+-----------------+------------------------------------+
// | critical | parallel | * |
// | critical | for | + |
@@ -1174,6 +1185,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | simd | taskyield | |
// | simd | barrier | |
// | simd | taskwait | |
+ // | simd | flush | |
// +------------------+-----------------+------------------------------------+
// | sections | parallel | * |
// | sections | for | + |
@@ -1189,6 +1201,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | sections | taskyield | * |
// | sections | barrier | + |
// | sections | taskwait | * |
+ // | sections | flush | * |
// +------------------+-----------------+------------------------------------+
// | section | parallel | * |
// | section | for | + |
@@ -1204,6 +1217,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | section | taskyield | * |
// | section | barrier | + |
// | section | taskwait | * |
+ // | section | flush | * |
// +------------------+-----------------+------------------------------------+
// | single | parallel | * |
// | single | for | + |
@@ -1219,6 +1233,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | single | taskyield | * |
// | single | barrier | + |
// | single | taskwait | * |
+ // | single | flush | * |
// +------------------+-----------------+------------------------------------+
// | parallel for | parallel | * |
// | parallel for | for | + |
@@ -1234,6 +1249,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel for | taskyield | * |
// | parallel for | barrier | + |
// | parallel for | taskwait | * |
+ // | parallel for | flush | * |
// +------------------+-----------------+------------------------------------+
// | parallel sections| parallel | * |
// | parallel sections| for | + |
@@ -1249,6 +1265,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel sections| taskyield | * |
// | parallel sections| barrier | + |
// | parallel sections| taskwait | * |
+ // | parallel sections| flush | * |
// +------------------+-----------------+------------------------------------+
// | task | parallel | * |
// | task | for | + |
@@ -1264,6 +1281,7 @@ static bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | task | taskyield | * |
// | task | barrier | + |
// | task | taskwait | * |
+ // | task | flush | * |
// +------------------+-----------------+------------------------------------+
if (Stack->getCurScope()) {
auto ParentRegion = Stack->getParentDirective();
@@ -1371,6 +1389,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
llvm::DenseMap<VarDecl *, Expr *> VarsWithInheritedDSA;
bool ErrorFound = false;
+ ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
if (AStmt) {
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
@@ -1381,7 +1400,6 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
return StmtError();
// Generate list of implicitly defined firstprivate variables.
VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
- ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
if (!DSAChecker.getImplicitFirstprivate().empty()) {
if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
@@ -1464,6 +1482,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
"No associated statement allowed for 'omp taskwait' directive");
Res = ActOnOpenMPTaskwaitDirective(StartLoc, EndLoc);
break;
+ case OMPD_flush:
+ assert(AStmt == nullptr &&
+ "No associated statement allowed for 'omp flush' directive");
+ Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
+ break;
case OMPD_threadprivate:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
@@ -2234,6 +2257,13 @@ StmtResult Sema::ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc);
}
+StmtResult Sema::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(Clauses.size() <= 1 && "Extra clauses in flush directive");
+ return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
+}
+
OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -2272,6 +2302,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
+ case OMPC_flush:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -2474,6 +2505,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
+ case OMPC_flush:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -2588,6 +2620,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
+ case OMPC_flush:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -2685,6 +2718,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_default:
case OMPC_proc_bind:
case OMPC_threadprivate:
+ case OMPC_flush:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@@ -2748,6 +2782,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_copyprivate:
Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_flush:
+ Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
@@ -4052,4 +4089,14 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
}
+OMPClause *Sema::ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ if (VarList.empty())
+ return nullptr;
+
+ return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
+}
+
#undef DSAStack
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index ba67df7417..34d13c9085 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1517,6 +1517,18 @@ public:
EndLoc);
}
+ /// \brief Build a new OpenMP 'flush' pseudo clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPFlushClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -6610,6 +6622,17 @@ TreeTransform<Derived>::TransformOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
return Res;
}
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPFlushDirective(OMPFlushDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_flush, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clause transformation
//===----------------------------------------------------------------------===//
@@ -6869,6 +6892,20 @@ TreeTransform<Derived>::TransformOMPCopyprivateClause(OMPCopyprivateClause *C) {
Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
}
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPFlushClause(OMPFlushClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPFlushClause(Vars, C->getLocStart(),
+ C->getLParenLoc(), C->getLocEnd());
+}
+
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index e8a84282e7..8bf17d51b3 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -1742,6 +1742,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_copyprivate:
C = OMPCopyprivateClause::CreateEmpty(Context, Record[Idx++]);
break;
+ case OMPC_flush:
+ C = OMPFlushClause::CreateEmpty(Context, Record[Idx++]);
+ break;
}
Visit(C);
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
@@ -1908,6 +1911,16 @@ void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
C->setVarRefs(Vars);
}
+void OMPClauseReader::VisitOMPFlushClause(OMPFlushClause *C) {
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setVarRefs(Vars);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
@@ -2011,6 +2024,13 @@ void ASTStmtReader::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
VisitOMPExecutableDirective(D);
}
+void ASTStmtReader::VisitOMPFlushDirective(OMPFlushDirective *D) {
+ VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ ++Idx;
+ VisitOMPExecutableDirective(D);
+}
+
//===----------------------------------------------------------------------===//
// ASTReader Implementation
//===----------------------------------------------------------------------===//
@@ -2561,6 +2581,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = OMPTaskwaitDirective::CreateEmpty(Context, Empty);
break;
+ case STMT_OMP_FLUSH_DIRECTIVE:
+ S = OMPFlushDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
case EXPR_CXX_OPERATOR_CALL:
S = new (Context) CXXOperatorCallExpr(Context, Empty);
break;
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index dd78c2446b..a43b3527a7 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -1805,6 +1805,13 @@ void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
Writer->Writer.AddStmt(VE);
}
+void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) {
+ Record.push_back(C->varlist_size());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+ for (auto *VE : C->varlists())
+ Writer->Writer.AddStmt(VE);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
@@ -1916,6 +1923,13 @@ void ASTStmtWriter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
Code = serialization::STMT_OMP_TASKWAIT_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPFlushDirective(OMPFlushDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_FLUSH_DIRECTIVE;
+}
+
//===----------------------------------------------------------------------===//
// ASTWriter Implementation
//===----------------------------------------------------------------------===//
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index af2ef5e07a..4e4095c5e0 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -745,6 +745,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::OMPTaskyieldDirectiveClass:
case Stmt::OMPBarrierDirectiveClass:
case Stmt::OMPTaskwaitDirectiveClass:
+ case Stmt::OMPFlushDirectiveClass:
llvm_unreachable("Stmt should not be in analyzer evaluation loop");
case Stmt::ObjCSubscriptRefExprClass:
diff --git a/test/OpenMP/flush_ast_print.cpp b/test/OpenMP/flush_ast_print.cpp
new file mode 100644
index 0000000000..7eb18f0c17
--- /dev/null
+++ b/test/OpenMP/flush_ast_print.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp=libiomp5 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void foo() {}
+
+template <class T>
+T tmain(T argc) {
+ static T a;
+#pragma omp flush
+#pragma omp flush(a)
+ return a + argc;
+}
+// CHECK: static int a;
+// CHECK-NEXT: #pragma omp flush
+// CHECK-NEXT: #pragma omp flush (a)
+// CHECK: static char a;
+// CHECK-NEXT: #pragma omp flush
+// CHECK-NEXT: #pragma omp flush (a)
+// CHECK: static T a;
+// CHECK-NEXT: #pragma omp flush
+// 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(a)
+// CHECK-NEXT: #pragma omp flush
+// CHECK-NEXT: #pragma omp flush (a)
+ return tmain(argc) + tmain(argv[0][0]) + a;
+}
+
+#endif
diff --git a/test/OpenMP/flush_messages.cpp b/test/OpenMP/flush_messages.cpp
new file mode 100644
index 0000000000..8c61680929
--- /dev/null
+++ b/test/OpenMP/flush_messages.cpp
@@ -0,0 +1,134 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s
+
+struct S1 { // expected-note 2 {{declared here}}
+ int a;
+};
+
+template <class T>
+T tmain(T argc) {
+#pragma omp flush
+ ;
+#pragma omp flush untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp flush'}}
+#pragma omp flush unknown // expected-warning {{extra tokens at the end of '#pragma omp flush' are ignored}}
+ if (argc)
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ if (argc) {
+#pragma omp flush
+ }
+ while (argc)
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ while (argc) {
+#pragma omp flush
+ }
+ do
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ while (argc)
+ ;
+ do {
+#pragma omp flush
+ } while (argc);
+ switch (argc)
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ switch (argc)
+ case 1:
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ switch (argc)
+ case 1: {
+#pragma omp flush
+ }
+ switch (argc) {
+#pragma omp flush
+ case 1:
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ break;
+ default: {
+#pragma omp flush
+ } break;
+ }
+ for (;;)
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ for (;;) {
+#pragma omp flush
+ }
+label:
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+label1 : {
+#pragma omp flush
+}
+
+#pragma omp flush
+#pragma omp flush( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp flush() // expected-error {{expected expression}}
+#pragma omp flush(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp flush(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp flush(argc)
+#pragma omp flush(S1) // expected-error {{'S1' does not refer to a value}}
+#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}}
+ ;
+ return T();
+}
+
+int main(int argc, char **argv) {
+#pragma omp flush
+ ;
+#pragma omp flush untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp flush'}}
+#pragma omp flush unknown // expected-warning {{extra tokens at the end of '#pragma omp flush' are ignored}}
+ if (argc)
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ if (argc) {
+#pragma omp flush
+ }
+ while (argc)
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ while (argc) {
+#pragma omp flush
+ }
+ do
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ while (argc)
+ ;
+ do {
+#pragma omp flush
+ } while (argc);
+ switch (argc)
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ switch (argc)
+ case 1:
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ switch (argc)
+ case 1: {
+#pragma omp flush
+ }
+ switch (argc) {
+#pragma omp flush
+ case 1:
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ break;
+ default: {
+#pragma omp flush
+ } break;
+ }
+ for (;;)
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+ for (;;) {
+#pragma omp flush
+ }
+label:
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
+label1 : {
+#pragma omp flush
+}
+
+#pragma omp flush
+#pragma omp flush( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp flush() // expected-error {{expected expression}}
+#pragma omp flush(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp flush(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp flush(argc)
+#pragma omp flush(S1) // expected-error {{'S1' does not refer to a value}}
+#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}}
+ ;
+ return tmain(argc);
+}
diff --git a/test/OpenMP/nesting_of_regions.cpp b/test/OpenMP/nesting_of_regions.cpp
index 7224ceb00c..d8dcec5edf 100644
--- a/test/OpenMP/nesting_of_regions.cpp
+++ b/test/OpenMP/nesting_of_regions.cpp
@@ -66,6 +66,11 @@ void foo() {
#pragma omp taskwait
bar();
}
+#pragma omp parallel
+ {
+#pragma omp flush
+ bar();
+ }
// SIMD DIRECTIVE
#pragma omp simd
@@ -156,6 +161,11 @@ void foo() {
#pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
bar();
}
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
// FOR DIRECTIVE
#pragma omp for
@@ -264,6 +274,11 @@ void foo() {
#pragma omp taskwait
bar();
}
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush
+ bar();
+ }
// SECTIONS DIRECTIVE
#pragma omp sections
@@ -385,6 +400,10 @@ void foo() {
{
#pragma omp taskwait
}
+#pragma omp sections
+ {
+#pragma omp flush
+ }
// SECTION DIRECTIVE
#pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}}
@@ -523,6 +542,14 @@ void foo() {
bar();
}
}
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp flush
+ bar();
+ }
+ }
// SINGLE DIRECTIVE
#pragma omp single
@@ -623,6 +650,11 @@ void foo() {
#pragma omp taskwait
bar();
}
+#pragma omp single
+ {
+#pragma omp flush
+ bar();
+ }
// MASTER DIRECTIVE
#pragma omp master
@@ -723,6 +755,11 @@ void foo() {
#pragma omp taskwait
bar();
}
+#pragma omp master
+ {
+#pragma omp flush
+ bar();
+ }
// CRITICAL DIRECTIVE
#pragma omp critical
@@ -952,6 +989,11 @@ void foo() {
#pragma omp taskwait
bar();
}
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush
+ bar();
+ }
// PARALLEL SECTIONS DIRECTIVE
#pragma omp parallel sections
@@ -1059,6 +1101,10 @@ void foo() {
{
#pragma omp taskwait
}
+#pragma omp parallel sections
+ {
+#pragma omp flush
+ }
// TASK DIRECTIVE
#pragma omp task
@@ -1118,6 +1164,11 @@ void foo() {
#pragma omp taskwait
bar();
}
+#pragma omp task
+ {
+#pragma omp flush
+ bar();
+ }
}
void foo() {
@@ -1183,6 +1234,11 @@ void foo() {
#pragma omp taskwait
bar();
}
+#pragma omp parallel
+ {
+#pragma omp flush
+ bar();
+ }
// SIMD DIRECTIVE
#pragma omp simd
@@ -1266,6 +1322,11 @@ void foo() {
#pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
bar();
}
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ bar();
+ }
// FOR DIRECTIVE
#pragma omp for
@@ -1361,6 +1422,11 @@ void foo() {
#pragma omp taskwait
bar();
}
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush
+ bar();
+ }
// SECTIONS DIRECTIVE
#pragma omp sections
@@ -1454,6 +1520,10 @@ void foo() {
{
#pragma omp taskwait
}
+#pragma omp sections
+ {
+#pragma omp flush
+ }
// SECTION DIRECTIVE
#pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}}
@@ -1592,6 +1662,14 @@ void foo() {
bar();
}
}
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp flush
+ bar();
+ }
+ }
// SINGLE DIRECTIVE
#pragma omp single
@@ -1682,6 +1760,11 @@ void foo() {
#pragma omp taskwait
bar();
}
+#pragma omp single
+ {
+#pragma omp flush
+ bar();
+ }
// MASTER DIRECTIVE
#pragma omp master
@@ -1782,6 +1865,11 @@ void foo() {
#pragma omp taskwait
bar();
}
+#pragma omp master
+ {
+#pragma omp flush
+ bar();
+ }
// CRITICAL DIRECTIVE
#pragma omp critical
@@ -2010,6 +2098,11 @@ void foo() {
#pragma omp taskwait
bar();
}
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp flush
+ bar();
+ }
// PARALLEL SECTIONS DIRECTIVE
#pragma omp parallel sections
@@ -2113,6 +2206,10 @@ void foo() {
{
#pragma omp taskwait
}
+#pragma omp parallel sections
+ {
+#pragma omp flush
+ }
// TASK DIRECTIVE
#pragma omp task
@@ -2171,6 +2268,11 @@ void foo() {
#pragma omp taskwait
bar();
}
+#pragma omp task
+ {
+#pragma omp flush
+ bar();
+ }
return foo<int>();
}
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index eb1765efbc..fc8703afac 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -1870,6 +1870,7 @@ public:
void VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D);
void VisitOMPBarrierDirective(const OMPBarrierDirective *D);
void VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D);
+ void VisitOMPFlushDirective(const OMPFlushDirective *D);
private:
void AddDeclarationNameInfo(const Stmt *S);
@@ -2016,6 +2017,9 @@ void
OMPClauseEnqueue::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseEnqueue::VisitOMPFlushClause(const OMPFlushClause *C) {
+ VisitOMPClauseList(C);
+}
}
void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {
@@ -2365,6 +2369,10 @@ void EnqueueVisitor::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D) {
VisitOMPExecutableDirective(D);
}
+void EnqueueVisitor::VisitOMPFlushDirective(const OMPFlushDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) {
EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S);
}
@@ -4065,6 +4073,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OMPBarrierDirective");
case CXCursor_OMPTaskwaitDirective:
return cxstring::createRef("OMPTaskwaitDirective");
+ case CXCursor_OMPFlushDirective:
+ return cxstring::createRef("OMPFlushDirective");
}
llvm_unreachable("Unhandled CXCursorKind");
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index 94d209e7a7..432190390b 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -559,6 +559,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::OMPTaskwaitDirectiveClass:
K = CXCursor_OMPTaskwaitDirective;
break;
+ case Stmt::OMPFlushDirectiveClass:
+ K = CXCursor_OMPFlushDirective;
+ break;
}
CXCursor C = { K, 0, { Parent, S, TU } };