[OPENMP] Initial parsing and sema analysis of 'taskyield' directive.

llvm-svn: 213355
This commit is contained in:
Alexey Bataev 2014-07-18 07:47:19 +00:00
parent 05c30880b6
commit 68446b7253
29 changed files with 481 additions and 37 deletions

View File

@ -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,

View File

@ -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) {

View File

@ -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) {

View File

@ -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

View File

@ -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<

View File

@ -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")

View File

@ -188,3 +188,4 @@ def OMPMasterDirective : DStmt<OMPExecutableDirective>;
def OMPParallelForDirective : DStmt<OMPExecutableDirective>;
def OMPParallelSectionsDirective : DStmt<OMPExecutableDirective>;
def OMPTaskDirective : DStmt<OMPExecutableDirective>;
def OMPTaskyieldDirective : DStmt<OMPExecutableDirective>;

View File

@ -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.

View File

@ -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,

View File

@ -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

View File

@ -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();
}

View File

@ -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.
//===----------------------------------------------------------------------===//

View File

@ -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);
}

View File

@ -257,6 +257,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
case OMPD_threadprivate:
case OMPD_section:
case OMPD_master:
case OMPD_taskyield:
break;
}
return false;

View File

@ -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;
}
}

View File

@ -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.");
}

View File

@ -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

View File

@ -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());

View File

@ -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);

View File

@ -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,32 +1237,35 @@ 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();
// 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;
ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
llvm::DenseMap<VarDecl *, Expr *> VarsWithInheritedDSA;
bool ErrorFound = false;
if (!DSAChecker.getImplicitFirstprivate().empty()) {
if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
DSAChecker.getImplicitFirstprivate(), SourceLocation(),
SourceLocation(), SourceLocation())) {
ClausesWithImplicit.push_back(Implicit);
ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
DSAChecker.getImplicitFirstprivate().size();
} else
ErrorFound = true;
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.
VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
if (!DSAChecker.getImplicitFirstprivate().empty()) {
if (OMPClause *Implicit = ActOnOpenMPFirstprivateClause(
DSAChecker.getImplicitFirstprivate(), SourceLocation(),
SourceLocation(), SourceLocation())) {
ClausesWithImplicit.push_back(Implicit);
ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
DSAChecker.getImplicitFirstprivate().size();
} else
ErrorFound = true;
}
}
switch (Kind) {
@ -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,

View File

@ -6428,12 +6428,17 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
TClauses.push_back(nullptr);
}
}
if (!D->getAssociatedStmt()) {
return StmtError();
StmtResult AssociatedStmt;
if (D->hasAssociatedStmt()) {
if (!D->getAssociatedStmt()) {
return StmtError();
}
AssociatedStmt = getDerived().TransformStmt(D->getAssociatedStmt());
if (AssociatedStmt.isInvalid()) {
return StmtError();
}
}
StmtResult AssociatedStmt =
getDerived().TransformStmt(D->getAssociatedStmt());
if (AssociatedStmt.isInvalid() || TClauses.size() != Clauses.size()) {
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
//===----------------------------------------------------------------------===//

View File

@ -1919,7 +1919,8 @@ void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
for (unsigned i = 0; i < E->getNumClauses(); ++i)
Clauses.push_back(ClauseReader.readClause());
E->setClauses(Clauses);
E->setAssociatedStmt(Reader.ReadSubStmt());
if (E->hasAssociatedStmt())
E->setAssociatedStmt(Reader.ReadSubStmt());
}
void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) {
@ -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;

View File

@ -1815,7 +1815,8 @@ void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
for (unsigned i = 0; i < E->getNumClauses(); ++i) {
ClauseWriter.writeClause(E->getClause(i));
}
Writer.AddStmt(E->getAssociatedStmt());
if (E->hasAssociatedStmt())
Writer.AddStmt(E->getAssociatedStmt());
}
void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) {
@ -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
//===----------------------------------------------------------------------===//

View File

@ -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:

View File

@ -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>();
}

View File

@ -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

View File

@ -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);
}

View File

@ -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");

View File

@ -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 } };