From 9c2e8ee72fe8c99a016a204a2f2b167cd17e188a Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Fri, 11 Jul 2014 11:25:16 +0000 Subject: [PATCH] [OPENMP] Parsing and sema analysis for 'omp task' directive. llvm-svn: 212804 --- clang/include/clang-c/Index.h | 6 +- clang/include/clang/AST/DataRecursiveASTVisitor.h | 3 + clang/include/clang/AST/RecursiveASTVisitor.h | 3 + clang/include/clang/AST/StmtOpenMP.h | 58 ++++ clang/include/clang/Basic/DiagnosticSemaKinds.td | 7 + clang/include/clang/Basic/OpenMPKinds.def | 11 + clang/include/clang/Basic/StmtNodes.td | 1 + clang/include/clang/Sema/Sema.h | 5 + clang/include/clang/Serialization/ASTBitCodes.h | 1 + clang/lib/AST/Stmt.cpp | 26 ++ clang/lib/AST/StmtPrinter.cpp | 5 + clang/lib/AST/StmtProfile.cpp | 4 + clang/lib/Basic/OpenMPKinds.cpp | 11 +- clang/lib/CodeGen/CGStmt.cpp | 3 + clang/lib/CodeGen/CGStmtOpenMP.cpp | 4 + clang/lib/CodeGen/CodeGenFunction.h | 1 + clang/lib/Parse/ParseOpenMP.cpp | 12 +- clang/lib/Sema/SemaOpenMP.cpp | 298 +++++++++++----- clang/lib/Sema/TreeTransform.h | 11 + clang/lib/Serialization/ASTReaderStmt.cpp | 12 + clang/lib/Serialization/ASTWriterStmt.cpp | 7 + clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 + clang/test/OpenMP/nesting_of_regions.cpp | 376 +++++++++++++++++++++ .../OpenMP/parallel_sections_private_messages.cpp | 4 +- clang/test/OpenMP/task_ast_print.cpp | 96 ++++++ clang/test/OpenMP/task_default_messages.cpp | 21 ++ clang/test/OpenMP/task_firstprivate_messages.cpp | 86 +++++ clang/test/OpenMP/task_if_messages.cpp | 46 +++ clang/test/OpenMP/task_messages.cpp | 263 ++++++++++++++ clang/test/OpenMP/task_private_messages.cpp | 85 +++++ clang/test/OpenMP/task_shared_messages.cpp | 102 ++++++ clang/tools/libclang/CIndex.cpp | 7 + clang/tools/libclang/CXCursor.cpp | 3 + 33 files changed, 1480 insertions(+), 99 deletions(-) create mode 100644 clang/test/OpenMP/task_ast_print.cpp create mode 100644 clang/test/OpenMP/task_default_messages.cpp create mode 100644 clang/test/OpenMP/task_firstprivate_messages.cpp create mode 100644 clang/test/OpenMP/task_if_messages.cpp create mode 100644 clang/test/OpenMP/task_messages.cpp create mode 100644 clang/test/OpenMP/task_private_messages.cpp create mode 100644 clang/test/OpenMP/task_shared_messages.cpp diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index f6709f1..7f3f248 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/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/clang/include/clang/AST/DataRecursiveASTVisitor.h b/clang/include/clang/AST/DataRecursiveASTVisitor.h index e2dcdbe..a84be8a 100644 --- a/clang/include/clang/AST/DataRecursiveASTVisitor.h +++ b/clang/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 bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index b4c4fd6..2cb8ea1 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/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 bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index f6fe473..e74febe 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/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 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/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e48da10..5a77459 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 691d13a..f64b137 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/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/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 1b0ead9..71b5629 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -186,3 +186,4 @@ def OMPSectionDirective : DStmt; def OMPSingleDirective : DStmt; def OMPParallelForDirective : DStmt; def OMPParallelSectionsDirective : DStmt; +def OMPTaskDirective : DStmt; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index c771ff9..88bcab8 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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 Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 8d9cb01..1b1cd0a 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/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/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 9cd3831..b415e92 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/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 Clauses, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective), + llvm::alignOf()); + 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()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPTaskDirective(NumClauses); +} + diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 1d01e65..0351571 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/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/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index db691a9..a364f68 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/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/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index b48c02c..188bd2d 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/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/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index b9d74b6..39adf9b 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -200,6 +200,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::OMPParallelSectionsDirectiveClass: EmitOMPParallelSectionsDirective(cast(*S)); break; + case Stmt::OMPTaskDirectiveClass: + EmitOMPTaskDirective(cast(*S)); + break; } } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index e253efc..3d36dbb 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/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/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index a2d92ff..f6dd39f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/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/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index b3a1063..caa8d8f 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/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/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index a7ad809..f065014 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/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 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 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 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 -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(cast(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 { public: void VisitDeclRefExpr(DeclRefExpr *E) { - if (VarDecl *VD = dyn_cast(E->getDecl())) { + if (auto *VD = dyn_cast(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(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(Child)) - Visit(Child); + for (auto *C : S->children()) { + if (C && !isa(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 Clauses, Clauses, AStmt); } +StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc) { + assert(AStmt && isa(AStmt) && "Captured statement expected"); + CapturedStmt *CS = cast(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 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 VarList, SourceLocation LParenLoc, SourceLocation EndLoc) { SmallVector 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(RefExpr)) { @@ -2525,7 +2611,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef 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 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 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 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 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 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 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 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 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 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 { public: bool VisitDeclRefExpr(DeclRefExpr *E) { if (VarDecl *VD = dyn_cast(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 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 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 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/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 269a3bd..dc0b5c2 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6512,6 +6512,17 @@ StmtResult TreeTransform::TransformOMPParallelSectionsDirective( return Res; } +template +StmtResult +TreeTransform::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/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index cee2aa2..8239f47 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/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/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 8f0c69e..30ee769 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/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/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 9b7e746..dec4d46 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/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/clang/test/OpenMP/nesting_of_regions.cpp b/clang/test/OpenMP/nesting_of_regions.cpp index 2c58e0b..f56cc0e 100644 --- a/clang/test/OpenMP/nesting_of_regions.cpp +++ b/clang/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(); } diff --git a/clang/test/OpenMP/parallel_sections_private_messages.cpp b/clang/test/OpenMP/parallel_sections_private_messages.cpp index 9bcae83..7d39c7e 100644 --- a/clang/test/OpenMP/parallel_sections_private_messages.cpp +++ b/clang/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/clang/test/OpenMP/task_ast_print.cpp b/clang/test/OpenMP/task_ast_print.cpp new file mode 100644 index 0000000..cf4198e --- /dev/null +++ b/clang/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 +struct S { + operator T() { return T(); } + static T TS; +#pragma omp threadprivate(TS) +}; + +// CHECK: template struct S { +// CHECK: static int TS; +// CHECK-NEXT: #pragma omp threadprivate(S::TS) +// CHECK-NEXT: } +// CHECK: template struct S { +// CHECK: static long TS; +// CHECK-NEXT: #pragma omp threadprivate(S::TS) +// CHECK-NEXT: } +// CHECK: template struct S { +// CHECK: static T TS; +// CHECK-NEXT: #pragma omp threadprivate(S::TS) +// CHECK: }; + +template +T tmain(T argc, T *argv) { + T b = argc, c, d, e, f, g; + static T a; + S 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 int tmain(int argc, int *argv) { +// CHECK-NEXT: int b = argc, c, d, e, f, g; +// CHECK-NEXT: static int a; +// CHECK-NEXT: S 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 long tmain(long argc, long *argv) { +// CHECK-NEXT: long b = argc, c, d, e, f, g; +// CHECK-NEXT: static long a; +// CHECK-NEXT: S 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 T tmain(T argc, T *argv) { +// CHECK-NEXT: T b = argc, c, d, e, f, g; +// CHECK-NEXT: static T a; +// CHECK-NEXT: S 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(b, &b) + tmain(x, &x); +} + +#endif diff --git a/clang/test/OpenMP/task_default_messages.cpp b/clang/test/OpenMP/task_default_messages.cpp new file mode 100644 index 0000000..8da6b1a --- /dev/null +++ b/clang/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/clang/test/OpenMP/task_firstprivate_messages.cpp b/clang/test/OpenMP/task_firstprivate_messages.cpp new file mode 100644 index 0000000..85d3f9f --- /dev/null +++ b/clang/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/clang/test/OpenMP/task_if_messages.cpp b/clang/test/OpenMP/task_if_messages.cpp new file mode 100644 index 0000000..51900c0 --- /dev/null +++ b/clang/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 // 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/clang/test/OpenMP/task_messages.cpp b/clang/test/OpenMP/task_messages.cpp new file mode 100644 index 0000000..3c89682 --- /dev/null +++ b/clang/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 +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' requested here}} + // expected-note@+1 {{in instantiation of function template specialization 'foo' requested here}} + return foo() + foo(); +} + diff --git a/clang/test/OpenMP/task_private_messages.cpp b/clang/test/OpenMP/task_private_messages.cpp new file mode 100644 index 0000000..0be238d --- /dev/null +++ b/clang/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/clang/test/OpenMP/task_shared_messages.cpp b/clang/test/OpenMP/task_shared_messages.cpp new file mode 100644 index 0000000..7479237 --- /dev/null +++ b/clang/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/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 5bfac51..56d761f 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/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/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 48f3480..6875f5a 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/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 } }; -- 2.7.4