зеркало из https://github.com/microsoft/clang-1.git
[OPENMP] Initial parsing and sema analysis of 'taskyield' directive.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@213355 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
08942b48da
Коммит
27b4c37d4a
|
@ -2171,9 +2171,13 @@ enum CXCursorKind {
|
|||
*/
|
||||
CXCursor_OMPMasterDirective = 241,
|
||||
|
||||
/** \brief OpenMP taskyield directive.
|
||||
*/
|
||||
CXCursor_OMPTaskyieldDirective = 242,
|
||||
|
||||
/** \brief Windows Structured Exception Handling's leave statement.
|
||||
*/
|
||||
CXCursor_SEHLeaveStmt = 242,
|
||||
CXCursor_SEHLeaveStmt = 243,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_SEHLeaveStmt,
|
||||
|
||||
|
|
|
@ -2309,6 +2309,9 @@ DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
|
|||
DEF_TRAVERSE_STMT(OMPTaskDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPTaskyieldDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
// OpenMP clauses.
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
|
||||
|
|
|
@ -2331,6 +2331,9 @@ DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
|
|||
DEF_TRAVERSE_STMT(OMPTaskDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPTaskyieldDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
// OpenMP clauses.
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
|
||||
|
|
|
@ -83,7 +83,10 @@ protected:
|
|||
///
|
||||
/// /param S Associated statement.
|
||||
///
|
||||
void setAssociatedStmt(Stmt *S) { *child_begin() = S; }
|
||||
void setAssociatedStmt(Stmt *S) {
|
||||
assert(hasAssociatedStmt() && "no associated statement.");
|
||||
*child_begin() = S;
|
||||
}
|
||||
|
||||
public:
|
||||
/// \brief Iterates over a filtered subrange of clauses applied to a
|
||||
|
@ -150,8 +153,14 @@ public:
|
|||
///
|
||||
OMPClause *getClause(unsigned i) const { return clauses()[i]; }
|
||||
|
||||
/// \brief Returns true if directive has associated statement.
|
||||
bool hasAssociatedStmt() const { return NumChildren > 0; }
|
||||
|
||||
/// \brief Returns statement associated with the directive.
|
||||
Stmt *getAssociatedStmt() const { return const_cast<Stmt *>(*child_begin()); }
|
||||
Stmt *getAssociatedStmt() const {
|
||||
assert(hasAssociatedStmt() && "no associated statement.");
|
||||
return const_cast<Stmt *>(*child_begin());
|
||||
}
|
||||
|
||||
OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
|
||||
|
||||
|
@ -161,6 +170,8 @@ public:
|
|||
}
|
||||
|
||||
child_range children() {
|
||||
if (!hasAssociatedStmt())
|
||||
return child_range();
|
||||
Stmt **ChildStorage = reinterpret_cast<Stmt **>(getClauses().end());
|
||||
return child_range(ChildStorage, ChildStorage + NumChildren);
|
||||
}
|
||||
|
@ -763,6 +774,50 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief This represents '#pragma omp taskyield' directive.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp taskyield
|
||||
/// \endcode
|
||||
///
|
||||
class OMPTaskyieldDirective : 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.
|
||||
///
|
||||
OMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
|
||||
: OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield,
|
||||
StartLoc, EndLoc, 0, 0) {}
|
||||
|
||||
/// \brief Build an empty directive.
|
||||
///
|
||||
explicit OMPTaskyieldDirective()
|
||||
: OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield,
|
||||
SourceLocation(), SourceLocation(), 0, 0) {}
|
||||
|
||||
public:
|
||||
/// \brief Creates directive.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param StartLoc Starting location of the directive kind.
|
||||
/// \param EndLoc Ending Location of the directive.
|
||||
///
|
||||
static OMPTaskyieldDirective *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
|
||||
|
||||
/// \brief Creates an empty directive.
|
||||
///
|
||||
/// \param C AST context.
|
||||
///
|
||||
static OMPTaskyieldDirective *CreateEmpty(const ASTContext &C, EmptyShell);
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPTaskyieldDirectiveClass;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
@ -908,6 +908,8 @@ def err_omp_unexpected_clause : Error<
|
|||
"unexpected OpenMP clause '%0' in directive '#pragma omp %1'">;
|
||||
def err_omp_more_one_clause : Error<
|
||||
"directive '#pragma omp %0' cannot contain more than one '%1' clause">;
|
||||
def err_omp_immediate_directive : Error<
|
||||
"'#pragma omp %0' cannot be an immediate substatement">;
|
||||
|
||||
// Pragma loop support.
|
||||
def err_pragma_loop_invalid_option : Error<
|
||||
|
|
|
@ -65,6 +65,7 @@ OPENMP_DIRECTIVE(sections)
|
|||
OPENMP_DIRECTIVE(section)
|
||||
OPENMP_DIRECTIVE(single)
|
||||
OPENMP_DIRECTIVE(master)
|
||||
OPENMP_DIRECTIVE(taskyield)
|
||||
OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for")
|
||||
OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections")
|
||||
|
||||
|
|
|
@ -188,3 +188,4 @@ def OMPMasterDirective : DStmt<OMPExecutableDirective>;
|
|||
def OMPParallelForDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPParallelSectionsDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTaskDirective : DStmt<OMPExecutableDirective>;
|
||||
def OMPTaskyieldDirective : DStmt<OMPExecutableDirective>;
|
||||
|
|
|
@ -2339,7 +2339,12 @@ private:
|
|||
SmallVectorImpl<Expr *> &VarList,
|
||||
bool AllowScopeSpecifier);
|
||||
/// \brief Parses declarative or executable directive.
|
||||
StmtResult ParseOpenMPDeclarativeOrExecutableDirective();
|
||||
///
|
||||
/// \param StandAloneAllowed true if allowed stand-alone directives,
|
||||
/// false - otherwise
|
||||
///
|
||||
StmtResult
|
||||
ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed);
|
||||
/// \brief Parses clause of kind \a CKind for directive of a kind \a Kind.
|
||||
///
|
||||
/// \param DKind Kind of current directive.
|
||||
|
|
|
@ -7368,6 +7368,10 @@ public:
|
|||
StmtResult ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AStmt, SourceLocation StartLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed '\#pragma omp taskyield' after parsing of the
|
||||
/// associated statement.
|
||||
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
|
||||
Expr *Expr,
|
||||
|
|
|
@ -1350,6 +1350,7 @@ namespace clang {
|
|||
STMT_OMP_PARALLEL_FOR_DIRECTIVE,
|
||||
STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE,
|
||||
STMT_OMP_TASK_DIRECTIVE,
|
||||
STMT_OMP_TASKYIELD_DIRECTIVE,
|
||||
|
||||
// ARC
|
||||
EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
|
||||
|
|
|
@ -1574,3 +1574,18 @@ OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C,
|
|||
return new (Mem) OMPTaskDirective(NumClauses);
|
||||
}
|
||||
|
||||
OMPTaskyieldDirective *OMPTaskyieldDirective::Create(const ASTContext &C,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc) {
|
||||
void *Mem = C.Allocate(sizeof(OMPTaskyieldDirective));
|
||||
OMPTaskyieldDirective *Dir =
|
||||
new (Mem) OMPTaskyieldDirective(StartLoc, EndLoc);
|
||||
return Dir;
|
||||
}
|
||||
|
||||
OMPTaskyieldDirective *OMPTaskyieldDirective::CreateEmpty(const ASTContext &C,
|
||||
EmptyShell) {
|
||||
void *Mem = C.Allocate(sizeof(OMPTaskyieldDirective));
|
||||
return new (Mem) OMPTaskyieldDirective();
|
||||
}
|
||||
|
||||
|
|
|
@ -791,7 +791,7 @@ void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S) {
|
|||
OS << ' ';
|
||||
}
|
||||
OS << "\n";
|
||||
if (S->getAssociatedStmt()) {
|
||||
if (S->hasAssociatedStmt() && S->getAssociatedStmt()) {
|
||||
assert(isa<CapturedStmt>(S->getAssociatedStmt()) &&
|
||||
"Expected captured statement!");
|
||||
Stmt *CS = cast<CapturedStmt>(S->getAssociatedStmt())->getCapturedStmt();
|
||||
|
@ -850,6 +850,11 @@ void StmtPrinter::VisitOMPTaskDirective(OMPTaskDirective *Node) {
|
|||
PrintOMPExecutableDirective(Node);
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *Node) {
|
||||
Indent() << "#pragma omp taskyield";
|
||||
PrintOMPExecutableDirective(Node);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Expr printing methods.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -407,6 +407,10 @@ void StmtProfiler::VisitOMPTaskDirective(const OMPTaskDirective *S) {
|
|||
VisitOMPExecutableDirective(S);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *S) {
|
||||
VisitOMPExecutableDirective(S);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitExpr(const Expr *S) {
|
||||
VisitStmt(S);
|
||||
}
|
||||
|
|
|
@ -257,6 +257,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
|
|||
case OMPD_threadprivate:
|
||||
case OMPD_section:
|
||||
case OMPD_master:
|
||||
case OMPD_taskyield:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -206,6 +206,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
|
|||
case Stmt::OMPTaskDirectiveClass:
|
||||
EmitOMPTaskDirective(cast<OMPTaskDirective>(*S));
|
||||
break;
|
||||
case Stmt::OMPTaskyieldDirectiveClass:
|
||||
EmitOMPTaskyieldDirective(cast<OMPTaskyieldDirective>(*S));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,3 +108,7 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) {
|
|||
llvm_unreachable("CodeGen for 'omp task' is not supported yet.");
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &) {
|
||||
llvm_unreachable("CodeGen for 'omp taskyield' is not supported yet.");
|
||||
}
|
||||
|
||||
|
|
|
@ -1931,6 +1931,7 @@ public:
|
|||
void EmitOMPParallelForDirective(const OMPParallelForDirective &S);
|
||||
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S);
|
||||
void EmitOMPTaskDirective(const OMPTaskDirective &S);
|
||||
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// LValue Expression Emission
|
||||
|
|
|
@ -83,6 +83,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
|
|||
case OMPD_parallel:
|
||||
case OMPD_simd:
|
||||
case OMPD_task:
|
||||
case OMPD_taskyield:
|
||||
case OMPD_for:
|
||||
case OMPD_sections:
|
||||
case OMPD_section:
|
||||
|
@ -107,9 +108,11 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
|
|||
/// executable-directive:
|
||||
/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
|
||||
/// 'section' | 'single' | 'master' | 'parallel for' |
|
||||
/// 'parallel sections' | 'task' {clause} annot_pragma_openmp_end
|
||||
/// 'parallel sections' | 'task' | 'taskyield' {clause}
|
||||
/// annot_pragma_openmp_end
|
||||
///
|
||||
StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
|
||||
StmtResult
|
||||
Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
|
||||
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
|
||||
ParenBraceBracketBalancer BalancerRAIIObj(*this);
|
||||
SmallVector<Expr *, 5> Identifiers;
|
||||
|
@ -123,6 +126,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
|
|||
// Name of critical directive.
|
||||
DeclarationNameInfo DirName;
|
||||
StmtResult Directive = StmtError();
|
||||
bool HasAssociatedStatement = true;
|
||||
|
||||
switch (DKind) {
|
||||
case OMPD_threadprivate:
|
||||
|
@ -141,6 +145,12 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
|
|||
}
|
||||
SkipUntil(tok::annot_pragma_openmp_end);
|
||||
break;
|
||||
case OMPD_taskyield:
|
||||
if (!StandAloneAllowed) {
|
||||
Diag(Tok, diag::err_omp_immediate_directive)
|
||||
<< getOpenMPDirectiveName(DKind);
|
||||
}
|
||||
HasAssociatedStatement = false;
|
||||
case OMPD_parallel:
|
||||
case OMPD_simd:
|
||||
case OMPD_for:
|
||||
|
@ -183,7 +193,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
|
|||
|
||||
StmtResult AssociatedStmt;
|
||||
bool CreateDirective = true;
|
||||
{
|
||||
if (HasAssociatedStatement) {
|
||||
// The body is a block scope like in Lambdas and Blocks.
|
||||
Sema::CompoundScopeRAII CompoundScope(Actions);
|
||||
Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
|
||||
|
|
|
@ -345,7 +345,7 @@ Retry:
|
|||
|
||||
case tok::annot_pragma_openmp:
|
||||
ProhibitAttributes(Attrs);
|
||||
return ParseOpenMPDeclarativeOrExecutableDirective();
|
||||
return ParseOpenMPDeclarativeOrExecutableDirective(!OnlyStatement);
|
||||
|
||||
case tok::annot_pragma_ms_pointers_to_members:
|
||||
ProhibitAttributes(Attrs);
|
||||
|
|
|
@ -1036,6 +1036,14 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
|
|||
Params);
|
||||
break;
|
||||
}
|
||||
case OMPD_taskyield: {
|
||||
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:
|
||||
|
@ -1060,6 +1068,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
|
|||
// | parallel | parallel for | * |
|
||||
// | parallel |parallel sections| * |
|
||||
// | parallel | task | * |
|
||||
// | parallel | taskyield | * |
|
||||
// +------------------+-----------------+------------------------------------+
|
||||
// | for | parallel | * |
|
||||
// | for | for | + |
|
||||
|
@ -1071,6 +1080,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
|
|||
// | for | parallel for | * |
|
||||
// | for |parallel sections| * |
|
||||
// | for | task | * |
|
||||
// | for | taskyield | * |
|
||||
// +------------------+-----------------+------------------------------------+
|
||||
// | master | parallel | * |
|
||||
// | master | for | + |
|
||||
|
@ -1082,6 +1092,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
|
|||
// | master | parallel for | * |
|
||||
// | master |parallel sections| * |
|
||||
// | master | task | * |
|
||||
// | master | taskyield | * |
|
||||
// +------------------+-----------------+------------------------------------+
|
||||
// | simd | parallel | |
|
||||
// | simd | for | |
|
||||
|
@ -1093,6 +1104,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
|
|||
// | simd | parallel for | |
|
||||
// | simd |parallel sections| |
|
||||
// | simd | task | |
|
||||
// | simd | taskyield | |
|
||||
// +------------------+-----------------+------------------------------------+
|
||||
// | sections | parallel | * |
|
||||
// | sections | for | + |
|
||||
|
@ -1104,6 +1116,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
|
|||
// | sections | parallel for | * |
|
||||
// | sections |parallel sections| * |
|
||||
// | sections | task | * |
|
||||
// | sections | taskyield | * |
|
||||
// +------------------+-----------------+------------------------------------+
|
||||
// | section | parallel | * |
|
||||
// | section | for | + |
|
||||
|
@ -1115,6 +1128,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
|
|||
// | section | parallel for | * |
|
||||
// | section |parallel sections| * |
|
||||
// | section | task | * |
|
||||
// | section | taskyield | * |
|
||||
// +------------------+-----------------+------------------------------------+
|
||||
// | single | parallel | * |
|
||||
// | single | for | + |
|
||||
|
@ -1126,6 +1140,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
|
|||
// | single | parallel for | * |
|
||||
// | single |parallel sections| * |
|
||||
// | single | task | * |
|
||||
// | single | taskyield | * |
|
||||
// +------------------+-----------------+------------------------------------+
|
||||
// | parallel for | parallel | * |
|
||||
// | parallel for | for | + |
|
||||
|
@ -1137,6 +1152,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
|
|||
// | parallel for | parallel for | * |
|
||||
// | parallel for |parallel sections| * |
|
||||
// | parallel for | task | * |
|
||||
// | parallel for | taskyield | * |
|
||||
// +------------------+-----------------+------------------------------------+
|
||||
// | parallel sections| parallel | * |
|
||||
// | parallel sections| for | + |
|
||||
|
@ -1148,6 +1164,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
|
|||
// | parallel sections| parallel for | * |
|
||||
// | parallel sections|parallel sections| * |
|
||||
// | parallel sections| task | * |
|
||||
// | parallel sections| taskyield | * |
|
||||
// +------------------+-----------------+------------------------------------+
|
||||
// | task | parallel | * |
|
||||
// | task | for | + |
|
||||
|
@ -1159,6 +1176,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
|
|||
// | task | parallel for | * |
|
||||
// | task |parallel sections| * |
|
||||
// | task | task | * |
|
||||
// | task | taskyield | * |
|
||||
// +------------------+-----------------+------------------------------------+
|
||||
if (Stack->getCurScope()) {
|
||||
auto ParentRegion = Stack->getParentDirective();
|
||||
|
@ -1219,23 +1237,25 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
|
|||
Stmt *AStmt,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc) {
|
||||
assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
|
||||
|
||||
StmtResult Res = StmtError();
|
||||
if (CheckNestingOfRegions(*this, DSAStack, Kind, StartLoc))
|
||||
return StmtError();
|
||||
|
||||
llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
|
||||
llvm::DenseMap<VarDecl *, Expr *> VarsWithInheritedDSA;
|
||||
bool ErrorFound = false;
|
||||
if (AStmt) {
|
||||
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
|
||||
|
||||
// Check default data sharing attributes for referenced variables.
|
||||
DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt));
|
||||
DSAChecker.Visit(cast<CapturedStmt>(AStmt)->getCapturedStmt());
|
||||
if (DSAChecker.isErrorFound())
|
||||
return StmtError();
|
||||
// Generate list of implicitly defined firstprivate variables.
|
||||
auto &VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
|
||||
llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
|
||||
VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
|
||||
ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
|
||||
|
||||
bool ErrorFound = false;
|
||||
if (!DSAChecker.getImplicitFirstprivate().empty()) {
|
||||
if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
|
||||
DSAChecker.getImplicitFirstprivate(), SourceLocation(),
|
||||
|
@ -1246,6 +1266,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
|
|||
} else
|
||||
ErrorFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Kind) {
|
||||
case OMPD_parallel:
|
||||
|
@ -1290,6 +1311,13 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
|
|||
Res =
|
||||
ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
|
||||
break;
|
||||
case OMPD_taskyield:
|
||||
assert(ClausesWithImplicit.empty() &&
|
||||
"No clauses are allowed for 'omp taskyield' directive");
|
||||
assert(AStmt == nullptr &&
|
||||
"No associated statement allowed for 'omp taskyield' directive");
|
||||
Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
|
||||
break;
|
||||
case OMPD_threadprivate:
|
||||
llvm_unreachable("OpenMP Directive is not allowed");
|
||||
case OMPD_unknown:
|
||||
|
@ -2033,6 +2061,11 @@ StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
|
|||
return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
|
||||
}
|
||||
|
||||
StmtResult Sema::ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
|
||||
SourceLocation EndLoc) {
|
||||
return OMPTaskyieldDirective::Create(Context, StartLoc, EndLoc);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
|
|
|
@ -6428,12 +6428,17 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
|
|||
TClauses.push_back(nullptr);
|
||||
}
|
||||
}
|
||||
StmtResult AssociatedStmt;
|
||||
if (D->hasAssociatedStmt()) {
|
||||
if (!D->getAssociatedStmt()) {
|
||||
return StmtError();
|
||||
}
|
||||
StmtResult AssociatedStmt =
|
||||
getDerived().TransformStmt(D->getAssociatedStmt());
|
||||
if (AssociatedStmt.isInvalid() || TClauses.size() != Clauses.size()) {
|
||||
AssociatedStmt = getDerived().TransformStmt(D->getAssociatedStmt());
|
||||
if (AssociatedStmt.isInvalid()) {
|
||||
return StmtError();
|
||||
}
|
||||
}
|
||||
if (TClauses.size() != Clauses.size()) {
|
||||
return StmtError();
|
||||
}
|
||||
|
||||
|
@ -6552,6 +6557,17 @@ TreeTransform<Derived>::TransformOMPTaskDirective(OMPTaskDirective *D) {
|
|||
return Res;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
StmtResult TreeTransform<Derived>::TransformOMPTaskyieldDirective(
|
||||
OMPTaskyieldDirective *D) {
|
||||
DeclarationNameInfo DirName;
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_taskyield, DirName, nullptr,
|
||||
D->getLocStart());
|
||||
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
|
||||
getDerived().getSema().EndOpenMPDSABlock(Res.get());
|
||||
return Res;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpenMP clause transformation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -1919,6 +1919,7 @@ void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
|
|||
for (unsigned i = 0; i < E->getNumClauses(); ++i)
|
||||
Clauses.push_back(ClauseReader.readClause());
|
||||
E->setClauses(Clauses);
|
||||
if (E->hasAssociatedStmt())
|
||||
E->setAssociatedStmt(Reader.ReadSubStmt());
|
||||
}
|
||||
|
||||
|
@ -1989,6 +1990,11 @@ void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) {
|
|||
VisitOMPExecutableDirective(D);
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) {
|
||||
VisitStmt(D);
|
||||
VisitOMPExecutableDirective(D);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ASTReader Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -2523,6 +2529,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
|||
Context, Record[ASTStmtReader::NumStmtFields], Empty);
|
||||
break;
|
||||
|
||||
case STMT_OMP_TASKYIELD_DIRECTIVE:
|
||||
S = OMPTaskyieldDirective::CreateEmpty(Context, Empty);
|
||||
break;
|
||||
|
||||
case EXPR_CXX_OPERATOR_CALL:
|
||||
S = new (Context) CXXOperatorCallExpr(Context, Empty);
|
||||
break;
|
||||
|
|
|
@ -1815,6 +1815,7 @@ void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
|
|||
for (unsigned i = 0; i < E->getNumClauses(); ++i) {
|
||||
ClauseWriter.writeClause(E->getClause(i));
|
||||
}
|
||||
if (E->hasAssociatedStmt())
|
||||
Writer.AddStmt(E->getAssociatedStmt());
|
||||
}
|
||||
|
||||
|
@ -1890,6 +1891,12 @@ void ASTStmtWriter::VisitOMPTaskDirective(OMPTaskDirective *D) {
|
|||
Code = serialization::STMT_OMP_TASK_DIRECTIVE;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitOMPTaskyieldDirective(OMPTaskyieldDirective *D) {
|
||||
VisitStmt(D);
|
||||
VisitOMPExecutableDirective(D);
|
||||
Code = serialization::STMT_OMP_TASKYIELD_DIRECTIVE;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ASTWriter Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -741,6 +741,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
|||
case Stmt::OMPParallelForDirectiveClass:
|
||||
case Stmt::OMPParallelSectionsDirectiveClass:
|
||||
case Stmt::OMPTaskDirectiveClass:
|
||||
case Stmt::OMPTaskyieldDirectiveClass:
|
||||
llvm_unreachable("Stmt should not be in analyzer evaluation loop");
|
||||
|
||||
case Stmt::ObjCSubscriptRefExprClass:
|
||||
|
|
|
@ -46,6 +46,11 @@ void foo() {
|
|||
{
|
||||
bar();
|
||||
}
|
||||
#pragma omp parallel
|
||||
{
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
|
||||
// SIMD DIRECTIVE
|
||||
#pragma omp simd
|
||||
|
@ -114,6 +119,11 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp simd
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
#pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside a simd region}}
|
||||
bar();
|
||||
}
|
||||
|
||||
// FOR DIRECTIVE
|
||||
#pragma omp for
|
||||
|
@ -201,6 +211,11 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp for
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
|
||||
// SECTIONS DIRECTIVE
|
||||
#pragma omp sections
|
||||
|
@ -291,6 +306,10 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp sections
|
||||
{
|
||||
#pragma omp taskyield
|
||||
}
|
||||
|
||||
// SECTION DIRECTIVE
|
||||
#pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}}
|
||||
|
@ -403,6 +422,14 @@ void foo() {
|
|||
}
|
||||
}
|
||||
}
|
||||
#pragma omp sections
|
||||
{
|
||||
#pragma omp section
|
||||
{
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
// SINGLE DIRECTIVE
|
||||
#pragma omp single
|
||||
|
@ -481,6 +508,11 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp single
|
||||
{
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
|
||||
// MASTER DIRECTIVE
|
||||
#pragma omp master
|
||||
|
@ -559,6 +591,11 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp master
|
||||
{
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
|
||||
// PARALLEL FOR DIRECTIVE
|
||||
#pragma omp parallel for
|
||||
|
@ -646,6 +683,11 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
|
||||
// PARALLEL SECTIONS DIRECTIVE
|
||||
#pragma omp parallel sections
|
||||
|
@ -733,6 +775,10 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp parallel sections
|
||||
{
|
||||
#pragma omp taskyield
|
||||
}
|
||||
|
||||
// TASK DIRECTIVE
|
||||
#pragma omp task
|
||||
|
@ -773,7 +819,11 @@ void foo() {
|
|||
{
|
||||
bar();
|
||||
}
|
||||
|
||||
#pragma omp task
|
||||
{
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
void foo() {
|
||||
|
@ -821,6 +871,11 @@ void foo() {
|
|||
{
|
||||
bar();
|
||||
}
|
||||
#pragma omp parallel
|
||||
{
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
|
||||
// SIMD DIRECTIVE
|
||||
#pragma omp simd
|
||||
|
@ -882,6 +937,11 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp simd
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
#pragma omp taskyield // expected-error {{OpenMP constructs may not be nested inside a simd region}}
|
||||
bar();
|
||||
}
|
||||
|
||||
// FOR DIRECTIVE
|
||||
#pragma omp for
|
||||
|
@ -960,6 +1020,11 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp for
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
|
||||
// SECTIONS DIRECTIVE
|
||||
#pragma omp sections
|
||||
|
@ -1038,6 +1103,11 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp sections
|
||||
{
|
||||
#pragma omp task
|
||||
bar();
|
||||
}
|
||||
|
||||
// SECTION DIRECTIVE
|
||||
#pragma omp section // expected-error {{orphaned 'omp section' directives are prohibited, it must be closely nested to a sections region}}
|
||||
|
@ -1150,6 +1220,14 @@ void foo() {
|
|||
}
|
||||
}
|
||||
}
|
||||
#pragma omp sections
|
||||
{
|
||||
#pragma omp section
|
||||
{
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
// SINGLE DIRECTIVE
|
||||
#pragma omp single
|
||||
|
@ -1223,6 +1301,11 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp single
|
||||
{
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
|
||||
// MASTER DIRECTIVE
|
||||
#pragma omp master
|
||||
|
@ -1301,6 +1384,11 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp master
|
||||
{
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
|
||||
// PARALLEL FOR DIRECTIVE
|
||||
#pragma omp parallel for
|
||||
|
@ -1387,6 +1475,11 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
|
||||
// PARALLEL SECTIONS DIRECTIVE
|
||||
#pragma omp parallel sections
|
||||
|
@ -1472,6 +1565,10 @@ void foo() {
|
|||
bar();
|
||||
}
|
||||
}
|
||||
#pragma omp parallel sections
|
||||
{
|
||||
#pragma omp taskyield
|
||||
}
|
||||
|
||||
// TASK DIRECTIVE
|
||||
#pragma omp task
|
||||
|
@ -1512,6 +1609,11 @@ void foo() {
|
|||
{
|
||||
bar();
|
||||
}
|
||||
#pragma omp task
|
||||
{
|
||||
#pragma omp taskyield
|
||||
bar();
|
||||
}
|
||||
return foo<int>();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// 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 taskyield
|
||||
return a + argc;
|
||||
}
|
||||
// CHECK: static int a;
|
||||
// CHECK-NEXT: #pragma omp taskyield
|
||||
// CHECK: static char a;
|
||||
// CHECK-NEXT: #pragma omp taskyield
|
||||
// CHECK: static T a;
|
||||
// CHECK-NEXT: #pragma omp taskyield
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
static int a;
|
||||
// CHECK: static int a;
|
||||
#pragma omp taskyield
|
||||
// CHECK-NEXT: #pragma omp taskyield
|
||||
return tmain(argc) + tmain(argv[0][0]) + a;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,110 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s
|
||||
|
||||
template <class T>
|
||||
T tmain(T argc) {
|
||||
#pragma omp taskyield
|
||||
;
|
||||
#pragma omp taskyield untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp taskyield'}}
|
||||
#pragma omp taskyield unknown // expected-warning {{extra tokens at the end of '#pragma omp taskyield' are ignored}}
|
||||
if (argc)
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
if (argc) {
|
||||
#pragma omp taskyield
|
||||
}
|
||||
while (argc)
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
while (argc) {
|
||||
#pragma omp taskyield
|
||||
}
|
||||
do
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
while (argc)
|
||||
;
|
||||
do {
|
||||
#pragma omp taskyield
|
||||
} while (argc);
|
||||
switch (argc)
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
switch (argc)
|
||||
case 1:
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
switch (argc)
|
||||
case 1: {
|
||||
#pragma omp taskyield
|
||||
}
|
||||
switch (argc) {
|
||||
#pragma omp taskyield
|
||||
case 1:
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
break;
|
||||
default: {
|
||||
#pragma omp taskyield
|
||||
} break;
|
||||
}
|
||||
for (;;)
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
for (;;) {
|
||||
#pragma omp taskyield
|
||||
}
|
||||
label:
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
label1 : {
|
||||
#pragma omp taskyield
|
||||
}
|
||||
|
||||
return T();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#pragma omp taskyield
|
||||
;
|
||||
#pragma omp taskyield untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp taskyield'}}
|
||||
#pragma omp taskyield unknown // expected-warning {{extra tokens at the end of '#pragma omp taskyield' are ignored}}
|
||||
if (argc)
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
if (argc) {
|
||||
#pragma omp taskyield
|
||||
}
|
||||
while (argc)
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
while (argc) {
|
||||
#pragma omp taskyield
|
||||
}
|
||||
do
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
while (argc)
|
||||
;
|
||||
do {
|
||||
#pragma omp taskyield
|
||||
} while (argc);
|
||||
switch (argc)
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
switch (argc)
|
||||
case 1:
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
switch (argc)
|
||||
case 1: {
|
||||
#pragma omp taskyield
|
||||
}
|
||||
switch (argc) {
|
||||
#pragma omp taskyield
|
||||
case 1:
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
break;
|
||||
default: {
|
||||
#pragma omp taskyield
|
||||
} break;
|
||||
}
|
||||
for (;;)
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
for (;;) {
|
||||
#pragma omp taskyield
|
||||
}
|
||||
label:
|
||||
#pragma omp taskyield // expected-error {{'#pragma omp taskyield' cannot be an immediate substatement}}
|
||||
label1 : {
|
||||
#pragma omp taskyield
|
||||
}
|
||||
|
||||
return tmain(argc);
|
||||
}
|
|
@ -1864,6 +1864,7 @@ public:
|
|||
void VisitOMPParallelForDirective(const OMPParallelForDirective *D);
|
||||
void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D);
|
||||
void VisitOMPTaskDirective(const OMPTaskDirective *D);
|
||||
void VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D);
|
||||
|
||||
private:
|
||||
void AddDeclarationNameInfo(const Stmt *S);
|
||||
|
@ -2341,6 +2342,11 @@ void EnqueueVisitor::VisitOMPTaskDirective(const OMPTaskDirective *D) {
|
|||
VisitOMPExecutableDirective(D);
|
||||
}
|
||||
|
||||
void
|
||||
EnqueueVisitor::VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D) {
|
||||
VisitOMPExecutableDirective(D);
|
||||
}
|
||||
|
||||
void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) {
|
||||
EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S);
|
||||
}
|
||||
|
@ -4033,6 +4039,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
|
|||
return cxstring::createRef("OMPParallelSectionsDirective");
|
||||
case CXCursor_OMPTaskDirective:
|
||||
return cxstring::createRef("OMPTaskDirective");
|
||||
case CXCursor_OMPTaskyieldDirective:
|
||||
return cxstring::createRef("OMPTaskyieldDirective");
|
||||
}
|
||||
|
||||
llvm_unreachable("Unhandled CXCursorKind");
|
||||
|
|
|
@ -547,6 +547,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
|
|||
case Stmt::OMPTaskDirectiveClass:
|
||||
K = CXCursor_OMPTaskDirective;
|
||||
break;
|
||||
case Stmt::OMPTaskyieldDirectiveClass:
|
||||
K = CXCursor_OMPTaskyieldDirective;
|
||||
break;
|
||||
}
|
||||
|
||||
CXCursor C = { K, 0, { Parent, S, TU } };
|
||||
|
|
Загрузка…
Ссылка в новой задаче