зеркало из https://github.com/microsoft/clang-1.git
[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
This commit is contained in:
Родитель
76fc5c55ec
Коммит
e559847c3d
|
@ -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,
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -192,3 +192,4 @@ def OMPTaskDirective : DStmt<OMPExecutableDirective>;
|
|||
def OMPTaskyieldDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPBarrierDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTaskwaitDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPFlushDirective : DStmt<OMPExecutableDirective>;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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>();
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 } };
|
||||
|
|
Загрузка…
Ссылка в новой задаче