summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2014-07-11 11:25:16 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2014-07-11 11:25:16 +0000
commit3e0fef67a6def9631840ff038b64c6a332806bdc (patch)
tree4b1cef72cafc4f157efda95f777fd6b50cb3edbd
parent35bd5e0e85960a80a90b36fc13b6bf8ce5d45c88 (diff)
[OPENMP] Parsing and sema analysis for 'omp task' directive.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@212804 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang-c/Index.h6
-rw-r--r--include/clang/AST/DataRecursiveASTVisitor.h3
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h3
-rw-r--r--include/clang/AST/StmtOpenMP.h58
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td7
-rw-r--r--include/clang/Basic/OpenMPKinds.def11
-rw-r--r--include/clang/Basic/StmtNodes.td1
-rw-r--r--include/clang/Sema/Sema.h5
-rw-r--r--include/clang/Serialization/ASTBitCodes.h1
-rw-r--r--lib/AST/Stmt.cpp26
-rw-r--r--lib/AST/StmtPrinter.cpp5
-rw-r--r--lib/AST/StmtProfile.cpp4
-rw-r--r--lib/Basic/OpenMPKinds.cpp11
-rw-r--r--lib/CodeGen/CGStmt.cpp3
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp4
-rw-r--r--lib/CodeGen/CodeGenFunction.h1
-rw-r--r--lib/Parse/ParseOpenMP.cpp12
-rw-r--r--lib/Sema/SemaOpenMP.cpp298
-rw-r--r--lib/Sema/TreeTransform.h11
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp12
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp7
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp1
-rw-r--r--test/OpenMP/nesting_of_regions.cpp376
-rw-r--r--test/OpenMP/parallel_sections_private_messages.cpp4
-rw-r--r--test/OpenMP/task_ast_print.cpp96
-rw-r--r--test/OpenMP/task_default_messages.cpp21
-rw-r--r--test/OpenMP/task_firstprivate_messages.cpp86
-rw-r--r--test/OpenMP/task_if_messages.cpp46
-rw-r--r--test/OpenMP/task_messages.cpp263
-rw-r--r--test/OpenMP/task_private_messages.cpp85
-rw-r--r--test/OpenMP/task_shared_messages.cpp102
-rw-r--r--tools/libclang/CIndex.cpp7
-rw-r--r--tools/libclang/CXCursor.cpp3
33 files changed, 1480 insertions, 99 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index f6709f1af7..7f3f248266 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -2163,9 +2163,13 @@ enum CXCursorKind {
*/
CXCursor_OMPParallelSectionsDirective = 239,
+ /** \brief OpenMP task directive.
+ */
+ CXCursor_OMPTaskDirective = 240,
+
/** \brief Windows Structured Exception Handling's leave statement.
*/
- CXCursor_SEHLeaveStmt = 240,
+ CXCursor_SEHLeaveStmt = 241,
CXCursor_LastStmt = CXCursor_SEHLeaveStmt,
diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h
index e2dcdbe392..a84be8ad2b 100644
--- a/include/clang/AST/DataRecursiveASTVisitor.h
+++ b/include/clang/AST/DataRecursiveASTVisitor.h
@@ -2303,6 +2303,9 @@ DEF_TRAVERSE_STMT(OMPParallelForDirective,
DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPTaskDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
// OpenMP clauses.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index b4c4fd6ddb..2cb8ea1786 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -2325,6 +2325,9 @@ DEF_TRAVERSE_STMT(OMPParallelForDirective,
DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPTaskDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
// OpenMP clauses.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
index f6fe473f7b..e74febea9c 100644
--- a/include/clang/AST/StmtOpenMP.h
+++ b/include/clang/AST/StmtOpenMP.h
@@ -658,6 +658,64 @@ public:
}
};
+/// \brief This represents '#pragma omp task' directive.
+///
+/// \code
+/// #pragma omp task private(a,b) final(d)
+/// \endcode
+/// In this example directive '#pragma omp task' has clauses 'private' with the
+/// variables 'a' and 'b' and 'final' with condition 'd'.
+///
+class OMPTaskDirective : 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.
+ ///
+ OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, StartLoc,
+ EndLoc, NumClauses, 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTaskDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task,
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
+
+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.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPTaskDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTaskDirectiveClass;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index e48da10350..5a77459d79 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7017,8 +7017,12 @@ def err_omp_expected_var_name : Error<
"expected variable name">;
def err_omp_required_method : Error<
"%0 variable must have an accessible, unambiguous %select{default constructor|copy constructor|copy assignment operator|'%2'|destructor}1">;
+def err_omp_task_predetermined_firstprivate_required_method : Error<
+ "predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous %select{copy constructor|destructor}0">;
def err_omp_clause_ref_type_arg : Error<
"arguments of OpenMP clause '%0' cannot be of reference type %1">;
+def err_omp_task_predetermined_firstprivate_ref_type_arg : Error<
+ "predetermined as a firstprivate in a task construct variable cannot be of reference type %0">;
def err_omp_threadprivate_incomplete_type : Error<
"threadprivate variable with incomplete type %0">;
def err_omp_no_dsa_for_variable : Error<
@@ -7035,6 +7039,7 @@ def note_omp_predetermined_dsa : Note<
"loop iteration variable is predetermined as lastprivate|"
"constant variable is predetermined as shared|"
"global variable is predetermined as shared|"
+ "non-shared variable in a task construct is predetermined as firstprivate|"
"variable with automatic storage duration is predetermined as private}0"
"%select{|; perhaps you forget to enclose 'omp %2' directive into a parallel or another task region?}1">;
def note_omp_implicit_dsa : Note<
@@ -7137,6 +7142,8 @@ def err_omp_sections_substmt_not_section : Error<
"statement in 'omp sections' directive must be enclosed into a section region">;
def err_omp_parallel_sections_substmt_not_section : Error<
"statement in 'omp parallel sections' directive must be enclosed into a section region">;
+def err_omp_parallel_reduction_in_task_firstprivate : Error<
+ "argument of a reduction clause of a %0 construct must not appear in a firstprivate clause on a task construct">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def
index 691d13a312..f64b13765d 100644
--- a/include/clang/Basic/OpenMPKinds.def
+++ b/include/clang/Basic/OpenMPKinds.def
@@ -42,6 +42,9 @@
#ifndef OPENMP_PARALLEL_SECTIONS_CLAUSE
# define OPENMP_PARALLEL_SECTIONS_CLAUSE(Name)
#endif
+#ifndef OPENMP_TASK_CLAUSE
+# define OPENMP_TASK_CLAUSE(Name)
+#endif
#ifndef OPENMP_DEFAULT_KIND
# define OPENMP_DEFAULT_KIND(Name)
#endif
@@ -170,6 +173,13 @@ OPENMP_PARALLEL_SECTIONS_CLAUSE(reduction)
OPENMP_PARALLEL_SECTIONS_CLAUSE(copyin)
OPENMP_PARALLEL_SECTIONS_CLAUSE(lastprivate)
+// TODO more clauses allowed for OpenMP directive 'task'.
+OPENMP_TASK_CLAUSE(if)
+OPENMP_TASK_CLAUSE(default)
+OPENMP_TASK_CLAUSE(private)
+OPENMP_TASK_CLAUSE(firstprivate)
+OPENMP_TASK_CLAUSE(shared)
+
#undef OPENMP_SCHEDULE_KIND
#undef OPENMP_PROC_BIND_KIND
#undef OPENMP_DEFAULT_KIND
@@ -181,6 +191,7 @@ OPENMP_PARALLEL_SECTIONS_CLAUSE(lastprivate)
#undef OPENMP_PARALLEL_CLAUSE
#undef OPENMP_PARALLEL_FOR_CLAUSE
#undef OPENMP_PARALLEL_SECTIONS_CLAUSE
+#undef OPENMP_TASK_CLAUSE
#undef OPENMP_SIMD_CLAUSE
#undef OPENMP_FOR_CLAUSE
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index 1b0ead9676..71b5629811 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -186,3 +186,4 @@ def OMPSectionDirective : DStmt<OMPExecutableDirective>;
def OMPSingleDirective : DStmt<OMPExecutableDirective>;
def OMPParallelForDirective : DStmt<OMPExecutableDirective>;
def OMPParallelSectionsDirective : DStmt<OMPExecutableDirective>;
+def OMPTaskDirective : DStmt<OMPExecutableDirective>;
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index c771ff9388..88bcab8801 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -7356,6 +7356,11 @@ public:
Stmt *AStmt,
SourceLocation StartLoc,
SourceLocation EndLoc);
+ /// \brief Called on well-formed '\#pragma omp task' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Expr *Expr,
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 8d9cb01835..1b1cd0a66b 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1348,6 +1348,7 @@ namespace clang {
STMT_OMP_SINGLE_DIRECTIVE,
STMT_OMP_PARALLEL_FOR_DIRECTIVE,
STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE,
+ STMT_OMP_TASK_DIRECTIVE,
// ARC
EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 9cd3831bf2..b415e9201e 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -1528,3 +1528,29 @@ OMPParallelSectionsDirective::CreateEmpty(const ASTContext &C,
return new (Mem) OMPParallelSectionsDirective(NumClauses);
}
+OMPTaskDirective *OMPTaskDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
+ OMPTaskDirective *Dir =
+ new (Mem) OMPTaskDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ Dir->setAssociatedStmt(AssociatedStmt);
+ return Dir;
+}
+
+OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective),
+ llvm::alignOf<OMPClause *>());
+ void *Mem =
+ C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
+ return new (Mem) OMPTaskDirective(NumClauses);
+}
+
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 1d01e65565..0351571832 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -826,6 +826,11 @@ void StmtPrinter::VisitOMPParallelSectionsDirective(
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPTaskDirective(OMPTaskDirective *Node) {
+ Indent() << "#pragma omp task ";
+ PrintOMPExecutableDirective(Node);
+}
+
//===----------------------------------------------------------------------===//
// Expr printing methods.
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index db691a93ed..a364f68e30 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -390,6 +390,10 @@ void StmtProfiler::VisitOMPParallelSectionsDirective(
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPTaskDirective(const OMPTaskDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitExpr(const Expr *S) {
VisitStmt(S);
}
diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index b48c02ca26..188bd2dbfd 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/lib/Basic/OpenMPKinds.cpp
@@ -237,9 +237,18 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
}
break;
+ case OMPD_task:
+ switch (CKind) {
+#define OPENMP_TASK_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ default:
+ break;
+ }
+ break;
case OMPD_unknown:
case OMPD_threadprivate:
- case OMPD_task:
case OMPD_section:
break;
}
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index b9d74b675a..39adf9b713 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -200,6 +200,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
case Stmt::OMPParallelSectionsDirectiveClass:
EmitOMPParallelSectionsDirective(cast<OMPParallelSectionsDirective>(*S));
break;
+ case Stmt::OMPTaskDirectiveClass:
+ EmitOMPTaskDirective(cast<OMPTaskDirective>(*S));
+ break;
}
}
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index e253efc2cb..3d36dbb1b1 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -100,3 +100,7 @@ void CodeGenFunction::EmitOMPParallelSectionsDirective(
llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
}
+void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) {
+ llvm_unreachable("CodeGen for 'omp task' is not supported yet.");
+}
+
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index a2d92ff18c..f6dd39f8fb 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1918,6 +1918,7 @@ public:
void EmitOMPSingleDirective(const OMPSingleDirective &S);
void EmitOMPParallelForDirective(const OMPParallelForDirective &S);
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S);
+ void EmitOMPTaskDirective(const OMPTaskDirective &S);
//===--------------------------------------------------------------------===//
// LValue Expression Emission
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index b3a1063ed2..caa8d8f782 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -105,8 +105,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
///
/// executable-directive:
/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
-/// 'section' | 'single' | 'parallel for' | 'parallel sections' {clause}
-/// annot_pragma_openmp_end
+/// 'section' | 'single' | 'parallel for' | 'parallel sections' | 'task'
+/// {clause} annot_pragma_openmp_end
///
StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
@@ -147,7 +147,8 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
case OMPD_single:
case OMPD_section:
case OMPD_parallel_for:
- case OMPD_parallel_sections: {
+ case OMPD_parallel_sections:
+ case OMPD_task: {
ConsumeToken();
if (isOpenMPLoopDirective(DKind))
@@ -209,11 +210,6 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
Diag(Tok, diag::err_omp_unknown_directive);
SkipUntil(tok::annot_pragma_openmp_end);
break;
- case OMPD_task:
- Diag(Tok, diag::err_omp_unexpected_directive)
- << getOpenMPDirectiveName(DKind);
- SkipUntil(tok::annot_pragma_openmp_end);
- break;
}
return Directive;
}
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index a7ad809778..f065014887 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -139,21 +139,22 @@ public:
/// \brief Returns data sharing attributes from top of the stack for the
/// specified declaration.
- DSAVarData getTopDSA(VarDecl *D);
+ DSAVarData getTopDSA(VarDecl *D, bool FromParent);
/// \brief Returns data-sharing attributes for the specified declaration.
- DSAVarData getImplicitDSA(VarDecl *D);
+ DSAVarData getImplicitDSA(VarDecl *D, bool FromParent);
/// \brief Checks if the specified variables has data-sharing attributes which
/// match specified \a CPred predicate in any directive which matches \a DPred
/// predicate.
template <class ClausesPredicate, class DirectivesPredicate>
DSAVarData hasDSA(VarDecl *D, ClausesPredicate CPred,
- DirectivesPredicate DPred);
+ DirectivesPredicate DPred, bool FromParent);
/// \brief Checks if the specified variables has data-sharing attributes which
/// match specified \a CPred predicate in any innermost directive which
/// matches \a DPred predicate.
template <class ClausesPredicate, class DirectivesPredicate>
DSAVarData hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
- DirectivesPredicate DPred);
+ DirectivesPredicate DPred,
+ bool FromParent);
/// \brief Returns currently analyzed directive.
OpenMPDirectiveKind getCurrentDirective() const {
@@ -186,7 +187,7 @@ public:
/// \brief Checks if the specified variable is a threadprivate.
bool isThreadPrivate(VarDecl *D) {
- DSAVarData DVar = getTopDSA(D);
+ DSAVarData DVar = getTopDSA(D, false);
return isOpenMPThreadPrivate(DVar.CKind);
}
@@ -194,6 +195,10 @@ public:
Scope *getCurScope() { return Stack.back().CurScope; }
SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
};
+bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
+ return isOpenMPParallelDirective(DKind) || DKind == OMPD_task ||
+ DKind == OMPD_unknown;
+}
} // namespace
DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
@@ -234,6 +239,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
if (Iter->SharingMap.count(D)) {
DVar.RefExpr = Iter->SharingMap[D].RefExpr;
DVar.CKind = Iter->SharingMap[D].Attributes;
+ DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
return DVar;
}
@@ -282,7 +288,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
DVar.CKind = OMPC_firstprivate;
return DVar;
}
- if (isOpenMPParallelDirective(I->Directive))
+ if (isParallelOrTaskRegion(I->Directive))
break;
}
DVar.DKind = OMPD_task;
@@ -328,7 +334,7 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
if (Stack.size() > 2) {
reverse_iterator I = Iter, E = std::prev(Stack.rend());
Scope *TopScope = nullptr;
- while (I != E && !isOpenMPParallelDirective(I->Directive)) {
+ while (I != E && !isParallelOrTaskRegion(I->Directive)) {
++I;
}
if (I == E)
@@ -343,7 +349,7 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
return false;
}
-DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
+DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) {
DSAVarData DVar;
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
@@ -363,9 +369,15 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
// in a Construct, C/C++, predetermined, p.1]
// Variables with automatic storage duration that are declared in a scope
// inside the construct are private.
- OpenMPDirectiveKind Kind = getCurrentDirective();
- if (!isOpenMPParallelDirective(Kind)) {
- if (isOpenMPLocal(D, std::next(Stack.rbegin())) && D->isLocalVarDecl() &&
+ OpenMPDirectiveKind Kind =
+ FromParent ? getParentDirective() : getCurrentDirective();
+ auto StartI = std::next(Stack.rbegin());
+ auto EndI = std::prev(Stack.rend());
+ if (FromParent && StartI != EndI) {
+ StartI = std::next(StartI);
+ }
+ if (!isParallelOrTaskRegion(Kind)) {
+ if (isOpenMPLocal(D, StartI) && D->isLocalVarDecl() &&
(D->getStorageClass() == SC_Auto || D->getStorageClass() == SC_None)) {
DVar.CKind = OMPC_private;
return DVar;
@@ -378,8 +390,8 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
if (D->isStaticDataMember()) {
// Variables with const-qualified type having no mutable member may be
// listed in a firstprivate clause, even if they are static data members.
- DSAVarData DVarTemp =
- hasDSA(D, MatchesAnyClause(OMPC_firstprivate), MatchesAlways());
+ DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate),
+ MatchesAlways(), FromParent);
if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
return DVar;
@@ -403,8 +415,8 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
!(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) {
// Variables with const-qualified type having no mutable member may be
// listed in a firstprivate clause, even if they are static data members.
- DSAVarData DVarTemp =
- hasDSA(D, MatchesAnyClause(OMPC_firstprivate), MatchesAlways());
+ DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate),
+ MatchesAlways(), FromParent);
if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
return DVar;
@@ -423,25 +435,36 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
// Explicitly specified attributes and local variables with predetermined
// attributes.
- if (Stack.back().SharingMap.count(D)) {
- DVar.RefExpr = Stack.back().SharingMap[D].RefExpr;
- DVar.CKind = Stack.back().SharingMap[D].Attributes;
+ auto I = std::prev(StartI);
+ if (I->SharingMap.count(D)) {
+ DVar.RefExpr = I->SharingMap[D].RefExpr;
+ DVar.CKind = I->SharingMap[D].Attributes;
+ DVar.ImplicitDSALoc = I->DefaultAttrLoc;
}
return DVar;
}
-DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D) {
- return getDSA(std::next(Stack.rbegin()), D);
+DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D, bool FromParent) {
+ auto StartI = Stack.rbegin();
+ auto EndI = std::prev(Stack.rend());
+ if (FromParent && StartI != EndI) {
+ StartI = std::next(StartI);
+ }
+ return getDSA(StartI, D);
}
template <class ClausesPredicate, class DirectivesPredicate>
DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, ClausesPredicate CPred,
- DirectivesPredicate DPred) {
- for (StackTy::reverse_iterator I = std::next(Stack.rbegin()),
- E = std::prev(Stack.rend());
- I != E; ++I) {
- if (!DPred(I->Directive))
+ DirectivesPredicate DPred,
+ bool FromParent) {
+ auto StartI = std::next(Stack.rbegin());
+ auto EndI = std::prev(Stack.rend());
+ if (FromParent && StartI != EndI) {
+ StartI = std::next(StartI);
+ }
+ for (auto I = StartI, EE = EndI; I != EE; ++I) {
+ if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive))
continue;
DSAVarData DVar = getDSA(I, D);
if (CPred(DVar.CKind))
@@ -451,12 +474,17 @@ DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, ClausesPredicate CPred,
}
template <class ClausesPredicate, class DirectivesPredicate>
-DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(VarDecl *D,
- ClausesPredicate CPred,
- DirectivesPredicate DPred) {
- for (auto I = Stack.rbegin(), EE = std::prev(Stack.rend()); I != EE; ++I) {
+DSAStackTy::DSAVarData
+DSAStackTy::hasInnermostDSA(VarDecl *D, ClausesPredicate CPred,
+ DirectivesPredicate DPred, bool FromParent) {
+ auto StartI = std::next(Stack.rbegin());
+ auto EndI = std::prev(Stack.rend());
+ if (FromParent && StartI != EndI) {
+ StartI = std::next(StartI);
+ }
+ for (auto I = StartI, EE = EndI; I != EE; ++I) {
if (!DPred(I->Directive))
- continue;
+ break;
DSAVarData DVar = getDSA(I, D);
if (CPred(DVar.CKind))
return DVar;
@@ -493,7 +521,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
if (VarRef->isValueDependent() || VarRef->isTypeDependent())
continue;
auto VD = cast<VarDecl>(cast<DeclRefExpr>(VarRef)->getDecl());
- auto DVar = DSAStack->getTopDSA(VD);
+ auto DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind == OMPC_lastprivate) {
SourceLocation ELoc = VarRef->getExprLoc();
auto Type = VarRef->getType();
@@ -795,10 +823,12 @@ static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
PDSA_LoopIterVarLastprivate,
PDSA_ConstVarShared,
PDSA_GlobalVarShared,
+ PDSA_TaskVarFirstprivate,
PDSA_LocalVarPrivate,
PDSA_Implicit
} Reason = PDSA_Implicit;
bool ReportHint = false;
+ auto ReportLoc = VD->getLocation();
if (IsLoopIterVar) {
if (DVar.CKind == OMPC_private)
Reason = PDSA_LoopIterVarPrivate;
@@ -806,6 +836,9 @@ static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
Reason = PDSA_LoopIterVarLastprivate;
else
Reason = PDSA_LoopIterVarLinear;
+ } else if (DVar.DKind == OMPD_task && DVar.CKind == OMPC_firstprivate) {
+ Reason = PDSA_TaskVarFirstprivate;
+ ReportLoc = DVar.ImplicitDSALoc;
} else if (VD->isStaticLocal())
Reason = PDSA_StaticLocalVarShared;
else if (VD->isStaticDataMember())
@@ -819,7 +852,7 @@ static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
Reason = PDSA_LocalVarPrivate;
}
if (Reason != PDSA_Implicit) {
- SemaRef.Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
+ SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
<< Reason << ReportHint
<< getOpenMPDirectiveName(Stack->getCurrentDirective());
} else if (DVar.ImplicitDSALoc.isValid()) {
@@ -839,27 +872,23 @@ class DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> {
public:
void VisitDeclRefExpr(DeclRefExpr *E) {
- if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
+ if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
// Skip internally declared variables.
if (VD->isLocalVarDecl() && !CS->capturesVariable(VD))
return;
- SourceLocation ELoc = E->getExprLoc();
+ auto DVar = Stack->getTopDSA(VD, false);
+ // Check if the variable has explicit DSA set and stop analysis if it so.
+ if (DVar.RefExpr) return;
- OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
- DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD);
- if (DVar.CKind != OMPC_unknown) {
- if (DKind == OMPD_task && DVar.CKind != OMPC_shared &&
- !Stack->isThreadPrivate(VD) && !DVar.RefExpr)
- ImplicitFirstprivate.push_back(DVar.RefExpr);
- return;
- }
+ auto ELoc = E->getExprLoc();
+ auto DKind = Stack->getCurrentDirective();
// The default(none) clause requires that each variable that is referenced
// in the construct, and does not have a predetermined data-sharing
// attribute, must have its data-sharing attribute explicitly determined
// by being listed in a data-sharing attribute clause.
if (DVar.CKind == OMPC_unknown && Stack->getDefaultDSA() == DSA_none &&
- (isOpenMPParallelDirective(DKind) || DKind == OMPD_task) &&
+ isParallelOrTaskRegion(DKind) &&
VarsWithInheritedDSA.count(VD) == 0) {
VarsWithInheritedDSA[VD] = E;
return;
@@ -870,7 +899,11 @@ public:
// enclosing worksharing or parallel construct may not be accessed in an
// explicit task.
DVar = Stack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction),
- MatchesAlways());
+ [](OpenMPDirectiveKind K) -> bool {
+ return isOpenMPParallelDirective(K) ||
+ isOpenMPWorksharingDirective(K);
+ },
+ false);
if (DKind == OMPD_task && DVar.CKind == OMPC_reduction) {
ErrorFound = true;
SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
@@ -879,24 +912,27 @@ public:
}
// Define implicit data-sharing attributes for task.
- DVar = Stack->getImplicitDSA(VD);
+ DVar = Stack->getImplicitDSA(VD, false);
if (DKind == OMPD_task && DVar.CKind != OMPC_shared)
- ImplicitFirstprivate.push_back(DVar.RefExpr);
+ ImplicitFirstprivate.push_back(E);
}
}
void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
- for (auto C : S->clauses())
- if (C)
- for (StmtRange R = C->children(); R; ++R)
- if (Stmt *Child = *R)
- Visit(Child);
+ for (auto *C : S->clauses()) {
+ // Skip analysis of arguments of implicitly defined firstprivate clause
+ // for task directives.
+ if (C && (!isa<OMPFirstprivateClause>(C) || C->getLocStart().isValid()))
+ for (auto *CC : C->children()) {
+ if (CC)
+ Visit(CC);
+ }
+ }
}
void VisitStmt(Stmt *S) {
- for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E;
- ++I)
- if (Stmt *Child = *I)
- if (!isa<OMPExecutableDirective>(Child))
- Visit(Child);
+ for (auto *C : S->children()) {
+ if (C && !isa<OMPExecutableDirective>(C))
+ Visit(C);
+ }
}
bool isErrorFound() { return ErrorFound; }
@@ -984,8 +1020,15 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
Params);
break;
}
+ case OMPD_task: {
+ Sema::CapturedParamNameType Params[] = {
+ std::make_pair(StringRef(), QualType()) // __context with shared vars
+ };
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
+ break;
+ }
case OMPD_threadprivate:
- case OMPD_task:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -1007,6 +1050,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel | single | * |
// | parallel | parallel for | * |
// | parallel |parallel sections| * |
+ // | parallel | task | * |
// +------------------+-----------------+------------------------------------+
// | for | parallel | * |
// | for | for | + |
@@ -1016,6 +1060,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | for | single | + |
// | for | parallel for | * |
// | for |parallel sections| * |
+ // | for | task | * |
// +------------------+-----------------+------------------------------------+
// | simd | parallel | |
// | simd | for | |
@@ -1025,6 +1070,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | simd | single | |
// | simd | parallel for | |
// | simd |parallel sections| |
+ // | simd | task | |
// +------------------+-----------------+------------------------------------+
// | sections | parallel | * |
// | sections | for | + |
@@ -1034,6 +1080,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | sections | single | + |
// | sections | parallel for | * |
// | sections |parallel sections| * |
+ // | sections | task | * |
// +------------------+-----------------+------------------------------------+
// | section | parallel | * |
// | section | for | + |
@@ -1043,6 +1090,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | section | single | + |
// | section | parallel for | * |
// | section |parallel sections| * |
+ // | section | task | * |
// +------------------+-----------------+------------------------------------+
// | single | parallel | * |
// | single | for | + |
@@ -1052,6 +1100,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | single | single | + |
// | single | parallel for | * |
// | single |parallel sections| * |
+ // | single | task | * |
// +------------------+-----------------+------------------------------------+
// | parallel for | parallel | * |
// | parallel for | for | + |
@@ -1061,6 +1110,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel for | single | + |
// | parallel for | parallel for | * |
// | parallel for |parallel sections| * |
+ // | parallel for | task | * |
// +------------------+-----------------+------------------------------------+
// | parallel sections| parallel | * |
// | parallel sections| for | + |
@@ -1070,6 +1120,17 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// | parallel sections| single | + |
// | parallel sections| parallel for | * |
// | parallel sections|parallel sections| * |
+ // | parallel sections| task | * |
+ // +------------------+-----------------+------------------------------------+
+ // | task | parallel | * |
+ // | task | for | + |
+ // | task | simd | * |
+ // | task | sections | + |
+ // | task | section | + |
+ // | task | single | + |
+ // | task | parallel for | * |
+ // | task |parallel sections| * |
+ // | task | task | * |
// +------------------+-----------------+------------------------------------+
if (Stack->getCurScope()) {
auto ParentRegion = Stack->getParentDirective();
@@ -1103,8 +1164,9 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack,
// A worksharing region may not be closely nested inside a worksharing,
// explicit task, critical, ordered, atomic, or master region.
// TODO
- NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) &&
- !isOpenMPSimdDirective(ParentRegion);
+ NestingProhibited = (isOpenMPWorksharingDirective(ParentRegion) &&
+ !isOpenMPSimdDirective(ParentRegion)) ||
+ ParentRegion == OMPD_task;
ShouldBeInParallelRegion = true;
}
if (NestingProhibited) {
@@ -1184,8 +1246,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
StartLoc, EndLoc);
break;
- case OMPD_threadprivate:
case OMPD_task:
+ Res =
+ ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
+ break;
+ case OMPD_threadprivate:
llvm_unreachable("OpenMP Directive is not allowed");
case OMPD_unknown:
llvm_unreachable("Unknown OpenMP directive");
@@ -1651,7 +1716,7 @@ static bool CheckOpenMPIterationSpace(
// constant-linear-step that is the increment of the associated for-loop.
// The loop iteration variable(s) in the associated for-loop(s) of a for or
// parallel for construct may be listed in a private or lastprivate clause.
- DSAStackTy::DSAVarData DVar = DSA.getTopDSA(Var);
+ DSAStackTy::DSAVarData DVar = DSA.getTopDSA(Var, false);
auto PredeterminedCKind =
isOpenMPSimdDirective(DKind)
? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate)
@@ -1898,6 +1963,23 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
Clauses, AStmt);
}
+StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
+ CapturedStmt *CS = cast<CapturedStmt>(AStmt);
+ // 1.2.2 OpenMP Language Terminology
+ // Structured block - An executable statement with a single entry at the
+ // top and a single exit at the bottom.
+ // The point of exit cannot be a branch out of the structured block.
+ // longjmp() and throw() must not violate the entry/exit criteria.
+ CS->getCapturedDecl()->setNothrow();
+
+ getCurFunction()->setHasBranchProtectedScope();
+
+ return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt);
+}
+
OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -2494,7 +2576,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
// listed below. For these exceptions only, listing a predetermined
// variable in a data-sharing attribute clause is allowed and overrides
// the variable's predetermined data-sharing attributes.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_private);
@@ -2517,6 +2599,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
+ bool IsImplicitClause =
+ StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
+ auto ImplicitClauseLoc = DSAStack->getConstructLoc();
+
for (auto &RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
@@ -2525,7 +2611,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
continue;
}
- SourceLocation ELoc = RefExpr->getExprLoc();
+ SourceLocation ELoc = IsImplicitClause ? ImplicitClauseLoc
+ : RefExpr->getExprLoc();
// OpenMP [2.1, C/C++]
// A list item is a variable name.
// OpenMP [2.9.3.3, Restrictions, p.1]
@@ -2554,8 +2641,15 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
continue;
}
if (Type->isReferenceType()) {
- Diag(ELoc, diag::err_omp_clause_ref_type_arg)
- << getOpenMPClauseName(OMPC_firstprivate) << Type;
+ if (IsImplicitClause) {
+ Diag(ImplicitClauseLoc,
+ diag::err_omp_task_predetermined_firstprivate_ref_type_arg)
+ << Type;
+ Diag(RefExpr->getExprLoc(), diag::note_used_here);
+ } else {
+ Diag(ELoc, diag::err_omp_clause_ref_type_arg)
+ << getOpenMPClauseName(OMPC_firstprivate) << Type;
+ }
bool IsDecl =
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
Diag(VD->getLocation(),
@@ -2583,8 +2677,15 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
InitializedEntity::InitializeTemporary(Type),
CD->getAccess(), PD) == AR_inaccessible ||
CD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_firstprivate) << 1;
+ if (IsImplicitClause) {
+ Diag(ImplicitClauseLoc,
+ diag::err_omp_task_predetermined_firstprivate_required_method)
+ << 0;
+ Diag(RefExpr->getExprLoc(), diag::note_used_here);
+ } else {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_firstprivate) << 1;
+ }
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
VarDecl::DeclarationOnly;
Diag(VD->getLocation(),
@@ -2600,8 +2701,15 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
if (DD) {
if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
DD->isDeleted()) {
- Diag(ELoc, diag::err_omp_required_method)
- << getOpenMPClauseName(OMPC_firstprivate) << 4;
+ if (IsImplicitClause) {
+ Diag(ImplicitClauseLoc,
+ diag::err_omp_task_predetermined_firstprivate_required_method)
+ << 1;
+ Diag(RefExpr->getExprLoc(), diag::note_used_here);
+ } else {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_firstprivate) << 4;
+ }
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
VarDecl::DeclarationOnly;
Diag(VD->getLocation(),
@@ -2615,10 +2723,9 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
}
}
- // If StartLoc and EndLoc are invalid - this is an implicit firstprivate
- // variable and it was checked already.
- if (StartLoc.isValid() && EndLoc.isValid()) {
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+ // If an implicit firstprivate variable found it was checked already.
+ if (!IsImplicitClause) {
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
Type = Type.getNonReferenceType().getCanonicalType();
bool IsConstant = Type.isConstant(Context);
Type = Context.getBaseElementType(Type);
@@ -2663,8 +2770,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// to any of the parallel regions arising from the parallel construct.
if (isOpenMPWorksharingDirective(CurrDir) &&
!isOpenMPParallelDirective(CurrDir)) {
- DVar = DSAStack->getImplicitDSA(VD);
- if (DVar.CKind != OMPC_shared) {
+ DVar = DSAStack->getImplicitDSA(VD, true);
+ if (DVar.CKind != OMPC_shared &&
+ (isOpenMPParallelDirective(DVar.DKind) ||
+ DVar.DKind == OMPD_unknown)) {
Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_firstprivate)
<< getOpenMPClauseName(OMPC_shared);
@@ -2678,13 +2787,28 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
// construct if any of the worksharing or task regions arising from the
// worksharing or task construct ever bind to any of the parallel regions
// arising from the parallel construct.
- // TODO
// OpenMP [2.9.3.4, Restrictions, p.4]
// A list item that appears in a reduction clause in worksharing
// construct must not appear in a firstprivate clause in a task construct
// encountered during execution of any of the worksharing regions arising
// from the worksharing construct.
- // TODO
+ if (CurrDir == OMPD_task) {
+ DVar =
+ DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction),
+ [](OpenMPDirectiveKind K) -> bool {
+ return isOpenMPParallelDirective(K) ||
+ isOpenMPWorksharingDirective(K);
+ },
+ false);
+ if (DVar.CKind == OMPC_reduction &&
+ (isOpenMPParallelDirective(DVar.DKind) ||
+ isOpenMPWorksharingDirective(DVar.DKind))) {
+ Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
+ << getOpenMPDirectiveName(DVar.DKind);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ }
}
DSAStack->addDSA(VD, DE, OMPC_firstprivate);
@@ -2755,7 +2879,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
// Variables with the predetermined data-sharing attributes may not be
// listed in data-sharing attributes clauses, except for the cases
// listed below.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
DVar.CKind != OMPC_firstprivate &&
(DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
@@ -2775,7 +2899,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
// regions.
if (isOpenMPWorksharingDirective(CurrDir) &&
!isOpenMPParallelDirective(CurrDir)) {
- DVar = DSAStack->getImplicitDSA(VD);
+ DVar = DSAStack->getImplicitDSA(VD, true);
if (DVar.CKind != OMPC_shared) {
Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_lastprivate)
@@ -2895,7 +3019,7 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
// listed below. For these exceptions only, listing a predetermined
// variable in a data-sharing attribute clause is allowed and overrides
// the variable's predetermined data-sharing attributes.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
@@ -2921,13 +3045,13 @@ class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
public:
bool VisitDeclRefExpr(DeclRefExpr *E) {
if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
- DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD);
+ DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, false);
if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
return false;
if (DVar.CKind != OMPC_unknown)
return true;
DSAStackTy::DSAVarData DVarPrivate =
- Stack->hasDSA(VD, isOpenMPPrivate, MatchesAlways());
+ Stack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(), false);
if (DVarPrivate.CKind != OMPC_unknown)
return true;
return false;
@@ -3145,7 +3269,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
// Any number of reduction clauses can be specified on the directive,
// but a list item can appear only once in the reduction clauses for that
// directive.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind == OMPC_reduction) {
Diag(ELoc, diag::err_omp_once_referenced)
<< getOpenMPClauseName(OMPC_reduction);
@@ -3167,7 +3291,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
if (isOpenMPWorksharingDirective(CurrDir) &&
!isOpenMPParallelDirective(CurrDir)) {
- DVar = DSAStack->getImplicitDSA(VD);
+ DVar = DSAStack->getImplicitDSA(VD, true);
if (DVar.CKind != OMPC_shared) {
Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_reduction)
@@ -3275,7 +3399,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
// A list-item cannot appear in more than one linear clause.
// A list-item that appears in a linear clause cannot appear in any
// other data-sharing attribute clause.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
if (DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_linear);
@@ -3558,7 +3682,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
// A list item that appears in a copyprivate clause may not appear in a
// private or firstprivate clause on the single construct.
if (!DSAStack->isThreadPrivate(VD)) {
- auto DVar = DSAStack->getTopDSA(VD);
+ auto DVar = DSAStack->getTopDSA(VD, false);
if (DVar.CKind != OMPC_copyprivate && DVar.CKind != OMPC_unknown &&
!(DVar.CKind == OMPC_private && !DVar.RefExpr)) {
Diag(ELoc, diag::err_omp_wrong_dsa)
@@ -3572,7 +3696,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
// All list items that appear in a copyprivate clause must be either
// threadprivate or private in the enclosing context.
if (DVar.CKind == OMPC_unknown) {
- DVar = DSAStack->getImplicitDSA(VD);
+ DVar = DSAStack->getImplicitDSA(VD, false);
if (DVar.CKind == OMPC_shared) {
Diag(ELoc, diag::err_omp_required_access)
<< getOpenMPClauseName(OMPC_copyprivate)
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 269a3bd8a8..dc0b5c288c 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -6512,6 +6512,17 @@ StmtResult TreeTransform<Derived>::TransformOMPParallelSectionsDirective(
return Res;
}
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPTaskDirective(OMPTaskDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_task, DirName, nullptr,
+ D->getLocStart());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clause transformation
//===----------------------------------------------------------------------===//
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index cee2aa23b9..8239f4761c 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -1958,6 +1958,13 @@ void ASTStmtReader::VisitOMPParallelSectionsDirective(
VisitOMPExecutableDirective(D);
}
+void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) {
+ VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ ++Idx;
+ VisitOMPExecutableDirective(D);
+}
+
//===----------------------------------------------------------------------===//
// ASTReader Implementation
//===----------------------------------------------------------------------===//
@@ -2483,6 +2490,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
+ case STMT_OMP_TASK_DIRECTIVE:
+ S = OMPTaskDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
case EXPR_CXX_OPERATOR_CALL:
S = new (Context) CXXOperatorCallExpr(Context, Empty);
break;
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 8f0c69e431..30ee76934e 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -1867,6 +1867,13 @@ void ASTStmtWriter::VisitOMPParallelSectionsDirective(
Code = serialization::STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPTaskDirective(OMPTaskDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_TASK_DIRECTIVE;
+}
+
//===----------------------------------------------------------------------===//
// ASTWriter Implementation
//===----------------------------------------------------------------------===//
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 9b7e746b1c..dec4d46b15 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -739,6 +739,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::OMPSingleDirectiveClass:
case Stmt::OMPParallelForDirectiveClass:
case Stmt::OMPParallelSectionsDirectiveClass:
+ case Stmt::OMPTaskDirectiveClass:
llvm_unreachable("Stmt should not be in analyzer evaluation loop");
case Stmt::ObjCSubscriptRefExprClass:
diff --git a/test/OpenMP/nesting_of_regions.cpp b/test/OpenMP/nesting_of_regions.cpp
index 2c58e0b4f9..f56cc0ec8b 100644
--- a/test/OpenMP/nesting_of_regions.cpp
+++ b/test/OpenMP/nesting_of_regions.cpp
@@ -35,6 +35,11 @@ void foo() {
{
bar();
}
+#pragma omp parallel
+#pragma omp task
+ {
+ bar();
+ }
// SIMD DIRECTIVE
#pragma omp simd
@@ -89,6 +94,13 @@ void foo() {
bar();
}
}
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
// FOR DIRECTIVE
#pragma omp for
@@ -160,6 +172,13 @@ void foo() {
bar();
}
}
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task
+ {
+ bar();
+ }
+ }
// SECTIONS DIRECTIVE
#pragma omp sections
@@ -232,12 +251,123 @@ 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}}
{
bar();
}
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp for // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp simd
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp parallel
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a section region}}
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp single // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+ bar();
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp parallel
+ {
+#pragma omp single // OK
+ {
+ bar();
+ }
+#pragma omp for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp sections // OK
+ {
+ bar();
+ }
+ }
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp parallel sections
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp task
+ {
+ bar();
+ }
+ }
+ }
// SINGLE DIRECTIVE
#pragma omp single
@@ -302,6 +432,13 @@ void foo() {
bar();
}
}
+#pragma omp single
+ {
+#pragma omp task
+ {
+ bar();
+ }
+ }
// PARALLEL FOR DIRECTIVE
#pragma omp parallel for
@@ -373,6 +510,13 @@ void foo() {
bar();
}
}
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task
+ {
+ bar();
+ }
+ }
// PARALLEL SECTIONS DIRECTIVE
#pragma omp parallel sections
@@ -445,6 +589,50 @@ void foo() {
bar();
}
}
+#pragma omp parallel sections
+ {
+#pragma omp task
+ {
+ bar();
+ }
+ }
+
+// TASK DIRECTIVE
+#pragma omp task
+#pragma omp for // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp task
+#pragma omp simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp task
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+ {
+ bar();
+ }
+#pragma omp task
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a task region}}
+ {
+ bar();
+ }
+#pragma omp task
+#pragma omp single // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+ bar();
+#pragma omp task
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp task
+#pragma omp parallel sections
+ {
+ bar();
+ }
+#pragma omp task
+#pragma omp task
+ {
+ bar();
+ }
}
void foo() {
@@ -484,6 +672,11 @@ void foo() {
{
bar();
}
+#pragma omp parallel
+#pragma omp task
+ {
+ bar();
+ }
// SIMD DIRECTIVE
#pragma omp simd
@@ -536,6 +729,13 @@ void foo() {
bar();
}
}
+#pragma omp simd
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+ {
+ bar();
+ }
+ }
// FOR DIRECTIVE
#pragma omp for
@@ -605,6 +805,13 @@ void foo() {
bar();
}
}
+#pragma omp for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task
+ {
+ bar();
+ }
+ }
// SECTIONS DIRECTIVE
#pragma omp sections
@@ -674,12 +881,123 @@ 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}}
{
bar();
}
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp for // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp simd
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp parallel
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a section region}}
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp single // expected-error {{region cannot be closely nested inside 'section' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+ bar();
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp parallel
+ {
+#pragma omp single // OK
+ {
+ bar();
+ }
+#pragma omp for // OK
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp sections // OK
+ {
+ bar();
+ }
+ }
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp parallel sections
+ {
+ bar();
+ }
+ }
+ }
+#pragma omp sections
+ {
+#pragma omp section
+ {
+#pragma omp task
+ {
+ bar();
+ }
+ }
+ }
// SINGLE DIRECTIVE
#pragma omp single
@@ -744,6 +1062,13 @@ void foo() {
bar();
}
}
+#pragma omp single
+ {
+#pragma omp task
+ {
+ bar();
+ }
+ }
// PARALLEL FOR DIRECTIVE
#pragma omp parallel for
@@ -815,6 +1140,13 @@ void foo() {
bar();
}
}
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i) {
+#pragma omp task
+ {
+ bar();
+ }
+ }
// PARALLEL SECTIONS DIRECTIVE
#pragma omp parallel sections
@@ -887,6 +1219,50 @@ void foo() {
bar();
}
}
+#pragma omp parallel sections
+ {
+#pragma omp task
+ {
+ bar();
+ }
+ }
+
+// TASK DIRECTIVE
+#pragma omp task
+#pragma omp for // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp task
+#pragma omp simd
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp task
+#pragma omp sections // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp sections' directive into a parallel region?}}
+ {
+ bar();
+ }
+#pragma omp task
+#pragma omp section // expected-error {{'omp section' directive must be closely nested to a sections region, not a task region}}
+ {
+ bar();
+ }
+#pragma omp task
+#pragma omp single // expected-error {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp single' directive into a parallel region?}}
+ bar();
+#pragma omp task
+#pragma omp parallel for
+ for (int i = 0; i < 10; ++i)
+ ;
+#pragma omp task
+#pragma omp parallel sections
+ {
+ bar();
+ }
+#pragma omp task
+#pragma omp task
+ {
+ bar();
+ }
return foo<int>();
}
diff --git a/test/OpenMP/parallel_sections_private_messages.cpp b/test/OpenMP/parallel_sections_private_messages.cpp
index 9bcae8314f..7d39c7e2c5 100644
--- a/test/OpenMP/parallel_sections_private_messages.cpp
+++ b/test/OpenMP/parallel_sections_private_messages.cpp
@@ -96,7 +96,7 @@ int foomain(I argc, C **argv) {
{
foo();
}
-#pragma omp parallel sections copyprivate(i) // expected-error {{unexpected OpenMP clause 'copyprivate' in directive '#pragma omp parallel sections'}}
+#pragma omp parallel sections copyprivate(h) // expected-error {{unexpected OpenMP clause 'copyprivate' in directive '#pragma omp parallel sections'}}
{
foo();
}
@@ -176,7 +176,7 @@ int main(int argc, char **argv) {
{
foo();
}
-#pragma omp parallel sections copyprivate(i) // expected-error {{unexpected OpenMP clause 'copyprivate' in directive '#pragma omp parallel sections'}}
+#pragma omp parallel sections copyprivate(h) // expected-error {{unexpected OpenMP clause 'copyprivate' in directive '#pragma omp parallel sections'}}
{
foo();
}
diff --git a/test/OpenMP/task_ast_print.cpp b/test/OpenMP/task_ast_print.cpp
new file mode 100644
index 0000000000..cf4198ebfa
--- /dev/null
+++ b/test/OpenMP/task_ast_print.cpp
@@ -0,0 +1,96 @@
+// 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>
+struct S {
+ operator T() { return T(); }
+ static T TS;
+#pragma omp threadprivate(TS)
+};
+
+// CHECK: template <class T = int> struct S {
+// CHECK: static int TS;
+// CHECK-NEXT: #pragma omp threadprivate(S<int>::TS)
+// CHECK-NEXT: }
+// CHECK: template <class T = long> struct S {
+// CHECK: static long TS;
+// CHECK-NEXT: #pragma omp threadprivate(S<long>::TS)
+// CHECK-NEXT: }
+// CHECK: template <class T> struct S {
+// CHECK: static T TS;
+// CHECK-NEXT: #pragma omp threadprivate(S::TS)
+// CHECK: };
+
+template <typename T, int C>
+T tmain(T argc, T *argv) {
+ T b = argc, c, d, e, f, g;
+ static T a;
+ S<T> s;
+#pragma omp task
+ a = 2;
+#pragma omp task default(none), private(argc, b) firstprivate(argv) shared(d) if (argc > 0)
+ foo();
+#pragma omp task if (C)
+ foo();
+ return 0;
+}
+
+// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
+// CHECK-NEXT: int b = argc, c, d, e, f, g;
+// CHECK-NEXT: static int a;
+// CHECK-NEXT: S<int> s;
+// CHECK-NEXT: #pragma omp task
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp task if(5)
+// CHECK-NEXT: foo()
+// CHECK: template <typename T = long, int C = 1> long tmain(long argc, long *argv) {
+// CHECK-NEXT: long b = argc, c, d, e, f, g;
+// CHECK-NEXT: static long a;
+// CHECK-NEXT: S<long> s;
+// CHECK-NEXT: #pragma omp task
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp task if(1)
+// CHECK-NEXT: foo()
+// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
+// CHECK-NEXT: T b = argc, c, d, e, f, g;
+// CHECK-NEXT: static T a;
+// CHECK-NEXT: S<T> s;
+// CHECK-NEXT: #pragma omp task
+// CHECK-NEXT: a = 2;
+// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0)
+// CHECK-NEXT: foo()
+// CHECK-NEXT: #pragma omp task if(C)
+// CHECK-NEXT: foo()
+
+enum Enum {};
+
+int main(int argc, char **argv) {
+ long x;
+ int b = argc, c, d, e, f, g;
+ static int a;
+#pragma omp threadprivate(a)
+ Enum ee;
+// CHECK: Enum ee;
+#pragma omp task
+ // CHECK-NEXT: #pragma omp task
+ a = 2;
+// CHECK-NEXT: a = 2;
+#pragma omp task default(none), private(argc, b) firstprivate(argv) if (argc > 0)
+ // CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) if(argc > 0)
+ foo();
+ // CHECK-NEXT: foo();
+ return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
+}
+
+#endif
diff --git a/test/OpenMP/task_default_messages.cpp b/test/OpenMP/task_default_messages.cpp
new file mode 100644
index 0000000000..8da6b1aeea
--- /dev/null
+++ b/test/OpenMP/task_default_messages.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 -o - %s
+
+void foo();
+
+int main(int argc, char **argv) {
+#pragma omp task default // expected-error {{expected '(' after 'default'}}
+#pragma omp task default( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task default() // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp task default(none // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task default(shared), default(shared) // expected-error {{directive '#pragma omp task' cannot contain more than one 'default' clause}}
+#pragma omp task default(x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+ foo();
+
+#pragma omp task default(none)
+ ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+#pragma omp task default(none)
+#pragma omp task default(shared)
+ ++argc;
+ return 0;
+}
diff --git a/test/OpenMP/task_firstprivate_messages.cpp b/test/OpenMP/task_firstprivate_messages.cpp
new file mode 100644
index 0000000000..85d3f9f461
--- /dev/null
+++ b/test/OpenMP/task_firstprivate_messages.cpp
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+ static float S2s;
+ static const float S2sc;
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+
+public:
+ S3() : a(0) {}
+ S3(S3 &s3) : a(s3.a) {}
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 { // expected-note {{'S4' declared here}}
+ int a;
+ S4();
+ S4(const S4 &s4);
+
+public:
+ S4(int v) : a(v) {}
+};
+class S5 { // expected-note {{'S5' declared here}}
+ int a;
+ S5() : a(0) {}
+ S5(const S5 &s5) : a(s5.a) {}
+
+public:
+ S5(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = {0};
+ S4 e(4); // expected-note {{'e' defined here}}
+ S5 g(5); // expected-note {{'g' defined here}}
+ int i;
+ int &j = i; // expected-note {{'j' defined here}}
+#pragma omp task firstprivate // expected-error {{expected '(' after 'firstprivate'}}
+#pragma omp task firstprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task firstprivate() // expected-error {{expected expression}}
+#pragma omp task firstprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task firstprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task firstprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+#pragma omp task firstprivate(argc)
+#pragma omp task firstprivate(S1) // expected-error {{'S1' does not refer to a value}}
+#pragma omp task firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
+#pragma omp task firstprivate(argv[1]) // expected-error {{expected variable name}}
+#pragma omp task firstprivate(ba)
+#pragma omp task firstprivate(ca)
+#pragma omp task firstprivate(da)
+#pragma omp task firstprivate(S2::S2s)
+#pragma omp task firstprivate(S2::S2sc)
+#pragma omp task firstprivate(e, g) // expected-error 2 {{firstprivate variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
+#pragma omp task private(i), firstprivate(i) // expected-error {{private variable cannot be firstprivate}} expected-note{{defined as private}}
+ foo();
+#pragma omp task shared(i)
+#pragma omp task firstprivate(i)
+#pragma omp task firstprivate(j) // expected-error {{arguments of OpenMP clause 'firstprivate' cannot be of reference type}}
+ foo();
+
+ return 0;
+}
diff --git a/test/OpenMP/task_if_messages.cpp b/test/OpenMP/task_if_messages.cpp
new file mode 100644
index 0000000000..51900c0be2
--- /dev/null
+++ b/test/OpenMP/task_if_messages.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+template <class T, class S> // expected-note {{declared here}}
+int tmain(T argc, S **argv) {
+ #pragma omp task if // expected-error {{expected '(' after 'if'}}
+ #pragma omp task if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp task if () // expected-error {{expected expression}}
+ #pragma omp task if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp task if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+ #pragma omp task if (argc > 0 ? argv[1] : argv[2])
+ #pragma omp task if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp task' cannot contain more than one 'if' clause}}
+ #pragma omp task if (S) // expected-error {{'S' does not refer to a value}}
+ #pragma omp task if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp task if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp task if(argc)
+ foo();
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ #pragma omp task if // expected-error {{expected '(' after 'if'}}
+ #pragma omp task if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp task if () // expected-error {{expected expression}}
+ #pragma omp task if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp task if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+ #pragma omp task if (argc > 0 ? argv[1] : argv[2])
+ #pragma omp task if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp task' cannot contain more than one 'if' clause}}
+ #pragma omp task if (S1) // expected-error {{'S1' does not refer to a value}}
+ #pragma omp task if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp task if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp task if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp task if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+
+ return tmain(argc, argv);
+}
diff --git a/test/OpenMP/task_messages.cpp b/test/OpenMP/task_messages.cpp
new file mode 100644
index 0000000000..3c8968299c
--- /dev/null
+++ b/test/OpenMP/task_messages.cpp
@@ -0,0 +1,263 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 -std=c++11 -o - %s
+
+void foo() {
+}
+
+#pragma omp task // expected-error {{unexpected OpenMP directive '#pragma omp task'}}
+
+class S { // expected-note 6 {{'S' declared here}}
+ S(const S &s) { a = s.a + 12; }
+ int a;
+
+public:
+ S() : a(0) {}
+ S(int a) : a(a) {}
+ operator int() { return a; }
+ S &operator++() { return *this; }
+ S operator+(const S &) { return *this; }
+};
+
+template <class T>
+int foo() {
+ T a; // expected-note 3 {{'a' defined here}}
+ T &b = a; // expected-note 4 {{'b' defined here}}
+ int r;
+#pragma omp task default(none)
+#pragma omp task default(shared)
+ ++a;
+// expected-error@+2 {{predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task default(none)
+#pragma omp task
+// expected-note@+1 {{used here}}
+ ++a;
+#pragma omp task
+// expected-error@+1 {{predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task
+ // expected-note@+1 {{used here}}
+ ++a;
+#pragma omp task default(shared)
+#pragma omp task
+ ++a;
+#pragma omp task
+#pragma omp parallel
+ ++a;
+// expected-error@+2 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'int &'}}
+// expected-error@+1 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'S &'}}
+#pragma omp task
+ // expected-note@+1 2 {{used here}}
+ ++b;
+// expected-error@+3 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'int &'}}
+// expected-error@+2 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'S &'}}
+// expected-error@+1 {{predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task
+// expected-note@+1 3 {{used here}}
+#pragma omp parallel shared(a, b)
+ ++a, ++b;
+// expected-note@+1 3 {{defined as reduction}}
+#pragma omp parallel reduction(+ : r)
+// expected-error@+1 {{argument of a reduction clause of a parallel construct must not appear in a firstprivate clause on a task construct}}
+#pragma omp task firstprivate(r)
+ // expected-error@+1 2 {{reduction variables may not be accessed in an explicit task}}
+ ++r;
+// expected-note@+1 2 {{defined as reduction}}
+#pragma omp parallel reduction(+ : r)
+#pragma omp task default(shared)
+ // expected-error@+1 2 {{reduction variables may not be accessed in an explicit task}}
+ ++r;
+// expected-note@+1 2 {{defined as reduction}}
+#pragma omp parallel reduction(+ : r)
+#pragma omp task
+ // expected-error@+1 2 {{reduction variables may not be accessed in an explicit task}}
+ ++r;
+#pragma omp parallel
+// expected-note@+1 3 {{defined as reduction}}
+#pragma omp for reduction(+ : r)
+ for (int i = 0; i < 10; ++i)
+// expected-error@+1 {{argument of a reduction clause of a for construct must not appear in a firstprivate clause on a task construct}}
+#pragma omp task firstprivate(r)
+ // expected-error@+1 2 {{reduction variables may not be accessed in an explicit task}}
+ ++r;
+#pragma omp parallel
+// expected-note@+1 2 {{defined as reduction}}
+#pragma omp for reduction(+ : r)
+ for (int i = 0; i < 10; ++i)
+#pragma omp task default(shared)
+ // expected-error@+1 2 {{reduction variables may not be accessed in an explicit task}}
+ ++r;
+#pragma omp parallel
+// expected-note@+1 2 {{defined as reduction}}
+#pragma omp for reduction(+ : r)
+ for (int i = 0; i < 10; ++i)
+#pragma omp task
+ // expected-error@+1 2 {{reduction variables may not be accessed in an explicit task}}
+ ++r;
+// expected-note@+1 {{non-shared variable in a task construct is predetermined as firstprivate}}
+#pragma omp task
+// expected-error@+2 {{reduction variable must be shared}}
+// expected-error@+1 {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+#pragma omp for reduction(+ : r)
+ ++r;
+ return a + b;
+}
+
+int main(int argc, char **argv) {
+ int a;
+ int &b = a; // expected-note 2 {{'b' defined here}}
+ S sa; // expected-note 3 {{'sa' defined here}}
+ S &sb = sa; // expected-note 2 {{'sb' defined here}}
+ int r;
+#pragma omp task { // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+ foo();
+#pragma omp task( // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+ foo();
+#pragma omp task[ // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+ foo();
+#pragma omp task] // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+ foo();
+#pragma omp task) // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+ foo();
+#pragma omp task } // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+ foo();
+#pragma omp task
+// expected-warning@+1 {{extra tokens at the end of '#pragma omp task' are ignored}}
+#pragma omp task unknown()
+ foo();
+L1:
+ foo();
+#pragma omp task
+ ;
+#pragma omp task
+ {
+ goto L1; // expected-error {{use of undeclared label 'L1'}}
+ argc++;
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ switch (argc) {
+ case (0):
+#pragma omp task
+ {
+ foo();
+ break; // expected-error {{'break' statement not in loop or switch statement}}
+ continue; // expected-error {{'continue' statement not in loop statement}}
+ }
+ default:
+ break;
+ }
+ }
+#pragma omp task default(none)
+ ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+ goto L2; // expected-error {{use of undeclared label 'L2'}}
+#pragma omp task
+L2:
+ foo();
+#pragma omp task
+ {
+ return 1; // expected-error {{cannot return from OpenMP region}}
+ }
+
+ [[]] // expected-error {{an attribute list cannot appear here}}
+#pragma omp task
+ for (int n = 0; n < 100; ++n) {
+ }
+
+#pragma omp task default(none)
+#pragma omp task default(shared)
+ ++a;
+#pragma omp task default(none)
+#pragma omp task
+ ++a;
+#pragma omp task default(shared)
+#pragma omp task
+ ++a;
+#pragma omp task
+#pragma omp parallel
+ ++a;
+// expected-error@+1 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'int &'}}
+#pragma omp task
+ // expected-note@+1 {{used here}}
+ ++b;
+// expected-error@+1 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'int &'}}
+#pragma omp task
+// expected-note@+1 {{used here}}
+#pragma omp parallel shared(a, b)
+ ++a, ++b;
+#pragma omp task default(none)
+#pragma omp task default(shared)
+ ++sa;
+#pragma omp task default(none)
+// expected-error@+1 {{predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task
+// expected-note@+1 {{used here}}
+ ++sa;
+#pragma omp task
+// expected-error@+1 {{predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task
+// expected-note@+1 {{used here}}
+ ++sa;
+#pragma omp task default(shared)
+#pragma omp task
+ ++sa;
+#pragma omp task
+#pragma omp parallel
+ ++sa;
+// expected-error@+1 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'S &'}}
+#pragma omp task
+ // expected-note@+1 {{used here}}
+ ++sb;
+// expected-error@+2 {{predetermined as a firstprivate in a task construct variable cannot be of reference type 'S &'}}
+// expected-error@+1 {{predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous copy constructor}}
+#pragma omp task
+// expected-note@+1 2 {{used here}}
+#pragma omp parallel shared(sa, sb)
+ ++sa, ++sb;
+// expected-note@+1 2 {{defined as reduction}}
+#pragma omp parallel reduction(+ : r)
+// expected-error@+1 {{argument of a reduction clause of a parallel construct must not appear in a firstprivate clause on a task construct}}
+#pragma omp task firstprivate(r)
+ // expected-error@+1 {{reduction variables may not be accessed in an explicit task}}
+ ++r;
+// expected-note@+1 {{defined as reduction}}
+#pragma omp parallel reduction(+ : r)
+#pragma omp task default(shared)
+ // expected-error@+1 {{reduction variables may not be accessed in an explicit task}}
+ ++r;
+// expected-note@+1 {{defined as reduction}}
+#pragma omp parallel reduction(+ : r)
+#pragma omp task
+ // expected-error@+1 {{reduction variables may not be accessed in an explicit task}}
+ ++r;
+#pragma omp parallel
+// expected-note@+1 2 {{defined as reduction}}
+#pragma omp for reduction(+ : r)
+ for (int i = 0; i < 10; ++i)
+// expected-error@+1 {{argument of a reduction clause of a for construct must not appear in a firstprivate clause on a task construct}}
+#pragma omp task firstprivate(r)
+ // expected-error@+1 {{reduction variables may not be accessed in an explicit task}}
+ ++r;
+#pragma omp parallel
+// expected-note@+1 {{defined as reduction}}
+#pragma omp for reduction(+ : r)
+ for (int i = 0; i < 10; ++i)
+#pragma omp task default(shared)
+ // expected-error@+1 {{reduction variables may not be accessed in an explicit task}}
+ ++r;
+#pragma omp parallel
+// expected-note@+1 {{defined as reduction}}
+#pragma omp for reduction(+ : r)
+ for (int i = 0; i < 10; ++i)
+#pragma omp task
+ // expected-error@+1 {{reduction variables may not be accessed in an explicit task}}
+ ++r;
+// expected-note@+1 {{non-shared variable in a task construct is predetermined as firstprivate}}
+#pragma omp task
+// expected-error@+2 {{reduction variable must be shared}}
+// expected-error@+1 {{region cannot be closely nested inside 'task' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}}
+#pragma omp for reduction(+ : r)
+ ++r;
+ // expected-note@+2 {{in instantiation of function template specialization 'foo<int>' requested here}}
+ // expected-note@+1 {{in instantiation of function template specialization 'foo<S>' requested here}}
+ return foo<int>() + foo<S>();
+}
+
diff --git a/test/OpenMP/task_private_messages.cpp b/test/OpenMP/task_private_messages.cpp
new file mode 100644
index 0000000000..0be238dd90
--- /dev/null
+++ b/test/OpenMP/task_private_messages.cpp
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ static float S2s; // expected-note {{static data member is predetermined as shared}}
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+
+public:
+ S3() : a(0) {}
+};
+const S3 c; // expected-note {{global variable is predetermined as shared}}
+const S3 ca[5]; // expected-note {{global variable is predetermined as shared}}
+extern const int f; // expected-note {{global variable is predetermined as shared}}
+class S4 { // expected-note {{'S4' declared here}}
+ int a;
+ S4();
+
+public:
+ S4(int v) : a(v) {}
+};
+class S5 { // expected-note {{'S5' declared here}}
+ int a;
+ S5() : a(0) {}
+
+public:
+ S5(int v) : a(v) {}
+};
+
+int threadvar;
+#pragma omp threadprivate(threadvar) // expected-note {{defined as threadprivate or thread local}}
+
+int main(int argc, char **argv) {
+ const int d = 5; // expected-note {{constant variable is predetermined as shared}}
+ const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}}
+ S4 e(4); // expected-note {{'e' defined here}}
+ S5 g(5); // expected-note {{'g' defined here}}
+ int i;
+ int &j = i; // expected-note {{'j' defined here}}
+#pragma omp task private // expected-error {{expected '(' after 'private'}}
+#pragma omp task private( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task private() // expected-error {{expected expression}}
+#pragma omp task private(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task private(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task private(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+#pragma omp task private(argc argv) // expected-error {{expected ',' or ')' in 'private' clause}}
+#pragma omp task private(S1) // expected-error {{'S1' does not refer to a value}}
+#pragma omp task private(a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}} expected-error 3 {{shared variable cannot be private}}
+#pragma omp task private(argv[1]) // expected-error {{expected variable name}}
+#pragma omp task private(ba)
+#pragma omp task private(ca) // expected-error {{shared variable cannot be private}}
+#pragma omp task private(da) // expected-error {{shared variable cannot be private}}
+#pragma omp task private(S2::S2s) // expected-error {{shared variable cannot be private}}
+#pragma omp task private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}}
+#pragma omp task private(threadvar) // expected-error {{threadprivate or thread local variable cannot be private}}
+#pragma omp task shared(i), private(i) // expected-error {{shared variable cannot be private}} expected-note {{defined as shared}}
+ foo();
+#pragma omp task firstprivate(i) private(i) // expected-error {{firstprivate variable cannot be private}} expected-note {{defined as firstprivate}}
+ foo();
+#pragma omp task private(i)
+#pragma omp task private(j) // expected-error {{arguments of OpenMP clause 'private' cannot be of reference type 'int &'}}
+ foo();
+#pragma omp task firstprivate(i)
+ for (int k = 0; k < 10; ++k) {
+#pragma omp task private(i)
+ foo();
+ }
+
+ return 0;
+}
diff --git a/test/OpenMP/task_shared_messages.cpp b/test/OpenMP/task_shared_messages.cpp
new file mode 100644
index 0000000000..747923721b
--- /dev/null
+++ b/test/OpenMP/task_shared_messages.cpp
@@ -0,0 +1,102 @@
+// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+
+public:
+ S2() : a(0) {}
+ S2(S2 &s2) : a(s2.a) {}
+};
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+
+public:
+ S3() : a(0) {}
+ S3(S3 &s3) : a(s3.a) {}
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+
+public:
+ S4(int v) : a(v) {}
+};
+class S5 {
+ int a;
+ S5() : a(0) {}
+ S5(const S5 &s5) : a(s5.a) {}
+
+public:
+ S5(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = {0};
+ S4 e(4);
+ S5 g(5);
+ int i;
+ int &j = i;
+#pragma omp task shared // expected-error {{expected '(' after 'shared'}}
+ foo();
+#pragma omp task shared( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp task shared() // expected-error {{expected expression}}
+ foo();
+#pragma omp task shared(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp task shared(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ foo();
+#pragma omp task shared(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+ foo();
+#pragma omp task shared(argc)
+ foo();
+#pragma omp task shared(S1) // expected-error {{'S1' does not refer to a value}}
+ foo();
+#pragma omp task shared(a, b, c, d, f)
+ foo();
+#pragma omp task shared(argv[1]) // expected-error {{expected variable name}}
+ foo();
+#pragma omp task shared(ba)
+ foo();
+#pragma omp task shared(ca)
+ foo();
+#pragma omp task shared(da)
+ foo();
+#pragma omp task shared(e, g)
+ foo();
+#pragma omp task shared(h) // expected-error {{threadprivate or thread local variable cannot be shared}}
+ foo();
+#pragma omp task private(i), shared(i) // expected-error {{private variable cannot be shared}} expected-note {{defined as private}}
+ foo();
+#pragma omp task firstprivate(i), shared(i) // expected-error {{firstprivate variable cannot be shared}} expected-note {{defined as firstprivate}}
+ foo();
+#pragma omp parallel private(i)
+#pragma omp task shared(i)
+#pragma omp task shared(j)
+ foo();
+#pragma omp parallel firstprivate(i)
+#pragma omp task shared(i)
+#pragma omp task shared(j)
+ foo();
+
+ return 0;
+}
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 5bfac51802..56d761f3a0 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -1862,6 +1862,7 @@ public:
void VisitOMPSingleDirective(const OMPSingleDirective *D);
void VisitOMPParallelForDirective(const OMPParallelForDirective *D);
void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D);
+ void VisitOMPTaskDirective(const OMPTaskDirective *D);
private:
void AddDeclarationNameInfo(const Stmt *S);
@@ -2323,6 +2324,10 @@ void EnqueueVisitor::VisitOMPParallelSectionsDirective(
VisitOMPExecutableDirective(D);
}
+void EnqueueVisitor::VisitOMPTaskDirective(const OMPTaskDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) {
EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S);
}
@@ -4011,6 +4016,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OMPParallelForDirective");
case CXCursor_OMPParallelSectionsDirective:
return cxstring::createRef("OMPParallelSectionsDirective");
+ case CXCursor_OMPTaskDirective:
+ return cxstring::createRef("OMPTaskDirective");
}
llvm_unreachable("Unhandled CXCursorKind");
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index 48f3480bc2..6875f5abdc 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -541,6 +541,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::OMPParallelSectionsDirectiveClass:
K = CXCursor_OMPParallelSectionsDirective;
break;
+ case Stmt::OMPTaskDirectiveClass:
+ K = CXCursor_OMPTaskDirective;
+ break;
}
CXCursor C = { K, 0, { Parent, S, TU } };