return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
}
};
+/// \brief This represents implicit clause 'depend' for the '#pragma omp task'
+/// directive.
+///
+/// \code
+/// #pragma omp task depend(in:a,b)
+/// \endcode
+/// In this example directive '#pragma omp task' with clause 'depend' with the
+/// variables 'a' and 'b' with dependency 'in'.
+///
+class OMPDependClause : public OMPVarListClause<OMPDependClause> {
+ friend class OMPClauseReader;
+ /// \brief Dependency type (one of in, out, inout).
+ OpenMPDependClauseKind DepKind;
+ /// \brief Dependency type location.
+ SourceLocation DepLoc;
+ /// \brief Colon location.
+ SourceLocation ColonLoc;
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ OMPDependClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPDependClause>(OMPC_depend, StartLoc, LParenLoc,
+ EndLoc, N),
+ DepKind(OMPC_DEPEND_unknown) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPDependClause(unsigned N)
+ : OMPVarListClause<OMPDependClause>(OMPC_depend, SourceLocation(),
+ SourceLocation(), SourceLocation(),
+ N),
+ DepKind(OMPC_DEPEND_unknown) {}
+ /// \brief Set dependency kind.
+ void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; }
+
+ /// \brief Set dependency kind and its location.
+ void setDependencyLoc(SourceLocation Loc) { DepLoc = Loc; }
+
+ /// \brief Set colon location.
+ void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param DepKind Dependency type.
+ /// \param DepLoc Location of the dependency type.
+ /// \param ColonLoc Colon location.
+ /// \param VL List of references to the variables.
+ ///
+ static OMPDependClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL);
+ /// \brief Creates an empty clause with \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ /// \brief Get dependency type.
+ OpenMPDependClauseKind getDependencyKind() const { return DepKind; }
+ /// \brief Get dependency type location.
+ SourceLocation getDependencyLoc() const { return DepLoc; }
+ /// \brief Get colon location.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ StmtRange children() {
+ return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_depend;
+ }
+};
+
} // end namespace clang
#endif
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
"expected %0 in OpenMP clause '%1'">;
def err_omp_expected_var_name : Error<
"expected variable name">;
+def err_omp_expected_var_name_or_array_item : Error<
+ "expected variable name, array element or array section">;
def note_omp_task_predetermined_firstprivate_here : Note<
"predetermined as a firstprivate in a task construct here">;
def err_omp_clause_ref_type_arg : Error<
#ifndef OPENMP_SCHEDULE_KIND
#define OPENMP_SCHEDULE_KIND(Name)
#endif
+#ifndef OPENMP_DEPEND_KIND
+#define OPENMP_DEPEND_KIND(Name)
+#endif
// OpenMP directives.
OPENMP_DIRECTIVE(threadprivate)
OPENMP_CLAUSE(update, OMPUpdateClause)
OPENMP_CLAUSE(capture, OMPCaptureClause)
OPENMP_CLAUSE(seq_cst, OMPSeqCstClause)
+OPENMP_CLAUSE(depend, OMPDependClause)
// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
OPENMP_SCHEDULE_KIND(auto)
OPENMP_SCHEDULE_KIND(runtime)
+// Static attributes for 'depend' clause.
+OPENMP_DEPEND_KIND(in)
+OPENMP_DEPEND_KIND(out)
+OPENMP_DEPEND_KIND(inout)
+
// Clauses allowed for OpenMP directive 'parallel for'.
OPENMP_PARALLEL_FOR_CLAUSE(if)
OPENMP_PARALLEL_FOR_CLAUSE(num_threads)
OPENMP_TASK_CLAUSE(shared)
OPENMP_TASK_CLAUSE(untied)
OPENMP_TASK_CLAUSE(mergeable)
+OPENMP_TASK_CLAUSE(depend)
// Clauses allowed for OpenMP directive 'atomic'.
OPENMP_ATOMIC_CLAUSE(read)
OPENMP_TEAMS_CLAUSE(shared)
OPENMP_TEAMS_CLAUSE(reduction)
+#undef OPENMP_DEPEND_KIND
#undef OPENMP_SCHEDULE_KIND
#undef OPENMP_PROC_BIND_KIND
#undef OPENMP_DEFAULT_KIND
OMPC_SCHEDULE_unknown
};
+/// \brief OpenMP attributes for 'depend' clause.
+enum OpenMPDependClauseKind {
+#define OPENMP_DEPEND_KIND(Name) \
+ OMPC_DEPEND_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_DEPEND_unknown
+};
+
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);
OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
SourceLocation EndLoc);
- OMPClause *
- ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef<Expr *> Vars,
- Expr *TailExpr, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation ColonLoc,
- SourceLocation EndLoc,
- CXXScopeSpec &ReductionIdScopeSpec,
- const DeclarationNameInfo &ReductionId);
+ OMPClause *ActOnOpenMPVarListClause(
+ OpenMPClauseKind Kind, ArrayRef<Expr *> Vars, Expr *TailExpr,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc);
/// \brief Called on well-formed 'private' clause.
OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// \brief Called on well-formed 'depend' clause.
+ OMPClause *
+ ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// \brief The kind of conversion being performed.
enum CheckedConversionKind {
return new (Mem) OMPFlushClause(N);
}
+OMPDependClause *
+OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VL) {
+ void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPDependClause),
+ llvm::alignOf<Expr *>()) +
+ sizeof(Expr *) * VL.size());
+ OMPDependClause *Clause =
+ new (Mem) OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ Clause->setDependencyKind(DepKind);
+ Clause->setDependencyLoc(DepLoc);
+ Clause->setColonLoc(ColonLoc);
+ return Clause;
+}
+
+OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N) {
+ void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPDependClause),
+ llvm::alignOf<Expr *>()) +
+ sizeof(Expr *) * N);
+ return new (Mem) OMPDependClause(N);
+}
+
const OMPClause *
OMPExecutableDirective::getSingleClause(OpenMPClauseKind K) const {
auto &&I = getClausesOfKind(K);
OS << ")";
}
}
+
+void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "depend(";
+ OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
+ Node->getDependencyKind())
+ << " :";
+ VisitOMPClauseList(Node, ' ');
+ OS << ")";
+ }
+}
}
//===----------------------------------------------------------------------===//
void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseProfiler::VisitOMPDependClause(const OMPDependClause *C) {
+ VisitOMPClauseList(C);
+}
}
void
#define OPENMP_SCHEDULE_KIND(Name) .Case(#Name, OMPC_SCHEDULE_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_SCHEDULE_unknown);
+ case OMPC_depend:
+ return llvm::StringSwitch<OpenMPDependClauseKind>(Str)
+#define OPENMP_DEPEND_KIND(Name) .Case(#Name, OMPC_DEPEND_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_DEPEND_unknown);
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
#define OPENMP_SCHEDULE_KIND(Name) \
case OMPC_SCHEDULE_##Name: \
return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ case OMPC_depend:
+ switch (Type) {
+ case OMPC_DEPEND_unknown:
+ return "unknown";
+#define OPENMP_DEPEND_KIND(Name) \
+ case OMPC_DEPEND_##Name: \
+ return #Name;
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'schedule' clause type");
case OMPC_nowait:
case OMPC_untied:
case OMPC_threadprivate:
+ case OMPC_depend:
case OMPC_mergeable:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
case OMPC_copyin:
case OMPC_copyprivate:
case OMPC_flush:
+ case OMPC_depend:
Clause = ParseOpenMPVarListClause(CKind);
break;
case OMPC_unknown:
/// 'copyprivate' '(' list ')'
/// flush-clause:
/// 'flush' '(' list ')'
+/// depend-clause:
+/// 'depend' '(' in | out | inout : list ')'
///
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
SourceLocation Loc = Tok.getLocation();
CXXScopeSpec ReductionIdScopeSpec;
UnqualifiedId ReductionId;
bool InvalidReductionId = false;
+ OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown;
+ SourceLocation DepLoc;
+
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
} else {
Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
}
+ } else if (Kind == OMPC_depend) {
+ // Handle dependency type for depend clause.
+ ColonProtectionRAIIObject ColonRAII(*this);
+ DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
+ DepLoc = Tok.getLocation();
+
+ if (DepKind == OMPC_DEPEND_unknown) {
+ SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ } else {
+ ConsumeToken();
+ }
+ if (Tok.is(tok::colon)) {
+ ColonLoc = ConsumeToken();
+ } else {
+ Diag(Tok, diag::warn_pragma_expected_colon) << "dependency type";
+ }
}
SmallVector<Expr *, 5> Vars;
- bool IsComma = !InvalidReductionId;
+ bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) ||
+ ((Kind == OMPC_reduction) && !InvalidReductionId) ||
+ ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown);
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
Tok.isNot(tok::annot_pragma_openmp_end))) {
// Parse ')'.
T.consumeClose();
- if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
+ if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) ||
+ (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) ||
+ InvalidReductionId)
return nullptr;
return Actions.ActOnOpenMPVarListClause(
Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
ReductionIdScopeSpec,
ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
- : DeclarationNameInfo());
+ : DeclarationNameInfo(),
+ DepKind, DepLoc);
}
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_depend:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_depend:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
case OMPC_update:
case OMPC_capture:
case OMPC_seq_cst:
+ case OMPC_depend:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
case OMPC_proc_bind:
case OMPC_threadprivate:
case OMPC_flush:
+ case OMPC_depend:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
- const DeclarationNameInfo &ReductionId) {
+ const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
case OMPC_private:
case OMPC_flush:
Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_depend:
+ Res = ActOnOpenMPDependClause(DepKind, DepLoc, ColonLoc, VarList, StartLoc,
+ LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
}
+OMPClause *
+Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc) {
+ if (DepKind == OMPC_DEPEND_unknown) {
+ std::string Values;
+ std::string Sep(", ");
+ for (unsigned i = 0; i < OMPC_DEPEND_unknown; ++i) {
+ Values += "'";
+ Values += getOpenMPSimpleClauseTypeName(OMPC_depend, i);
+ Values += "'";
+ switch (i) {
+ case OMPC_DEPEND_unknown - 2:
+ Values += " or ";
+ break;
+ case OMPC_DEPEND_unknown - 1:
+ break;
+ default:
+ Values += Sep;
+ break;
+ }
+ }
+ Diag(DepLoc, diag::err_omp_unexpected_clause_value)
+ << Values << getOpenMPClauseName(OMPC_depend);
+ return nullptr;
+ }
+ SmallVector<Expr *, 8> Vars;
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ // OpenMP [2.11.1.1, Restrictions, p.3]
+ // A variable that is part of another variable (such as a field of a
+ // structure) but is not an array element or an array section cannot appear
+ // in a depend clause.
+ auto *SimpleExpr = RefExpr->IgnoreParenCasts();
+ DeclRefExpr *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
+ ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
+ if (!RefExpr->IgnoreParenImpCasts()->isLValue() || (!ASE && !DE) ||
+ (DE && !isa<VarDecl>(DE->getDecl())) ||
+ (ASE && !ASE->getBase()->getType()->isAnyPointerType() &&
+ !ASE->getBase()->getType()->isArrayType())) {
+ Diag(ELoc, diag::err_omp_expected_var_name_or_array_item)
+ << RefExpr->getSourceRange();
+ continue;
+ }
+
+ Vars.push_back(RefExpr->IgnoreParenImpCasts());
+ }
+
+ if (Vars.empty())
+ return nullptr;
+
+ return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind,
+ DepLoc, ColonLoc, Vars);
+}
+
EndLoc);
}
+ /// \brief Build a new OpenMP 'depend' pseudo clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *
+ RebuildOMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPDependClause(DepKind, DepLoc, ColonLoc, VarList,
+ StartLoc, LParenLoc, EndLoc);
+ }
+
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
C->getLParenLoc(), C->getLocEnd());
}
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPDependClause(OMPDependClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPDependClause(
+ C->getDependencyKind(), C->getDependencyLoc(), C->getColonLoc(), Vars,
+ C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//
case OMPC_flush:
C = OMPFlushClause::CreateEmpty(Context, Record[Idx++]);
break;
+ case OMPC_depend:
+ C = OMPDependClause::CreateEmpty(Context, Record[Idx++]);
+ break;
}
Visit(C);
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
C->setVarRefs(Vars);
}
+void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setDependencyKind(static_cast<OpenMPDependClauseKind>(Record[Idx++]));
+ C->setDependencyLoc(Reader->ReadSourceLocation(Record, Idx));
+ C->setColonLoc(Reader->ReadSourceLocation(Record, Idx));
+ unsigned NumVars = C->varlist_size();
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setVarRefs(Vars);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
Writer->Writer.AddStmt(VE);
}
+void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {
+ Record.push_back(C->varlist_size());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+ Record.push_back(C->getDependencyKind());
+ Writer->Writer.AddSourceLocation(C->getDependencyLoc(), Record);
+ Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
+ for (auto *VE : C->varlists())
+ Writer->Writer.AddStmt(VE);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
T b = argc, c, d, e, f, g;
static T a;
S<T> s;
-#pragma omp task untied
+#pragma omp task untied depend(in : argc)
a = 2;
#pragma omp task default(none), private(argc, b) firstprivate(argv) shared(d) if (argc > 0) final(S<T>::TS > 0)
foo();
// 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 untied
+// CHECK-NEXT: #pragma omp task untied depend(in : argc)
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<int>::TS > 0)
// CHECK-NEXT: foo()
// 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 untied
+// CHECK-NEXT: #pragma omp task untied depend(in : argc)
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<long>::TS > 0)
// CHECK-NEXT: foo()
// 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 untied
+// CHECK-NEXT: #pragma omp task untied depend(in : argc)
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<T>::TS > 0)
// CHECK-NEXT: foo()
#pragma omp threadprivate(a)
Enum ee;
// CHECK: Enum ee;
-#pragma omp task untied mergeable
- // CHECK-NEXT: #pragma omp task untied mergeable
+#pragma omp task untied mergeable depend(out:argv[1])
+ // CHECK-NEXT: #pragma omp task untied mergeable depend(out : argv[1])
a = 2;
// CHECK-NEXT: a = 2;
-#pragma omp task default(none), private(argc, b) firstprivate(argv) if (argc > 0) final(a > 0)
- // CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) if(argc > 0) final(a > 0)
+#pragma omp task default(none), private(argc, b) firstprivate(argv) if (argc > 0) final(a > 0) depend(inout : a)
+ // CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) if(argc > 0) final(a > 0) depend(inout : a)
foo();
// CHECK-NEXT: foo();
return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
--- /dev/null
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note {{declared here}}
+
+class vector {
+ public:
+ int operator[](int index) { return 0; }
+};
+
+int main(int argc, char **argv) {
+ vector vec;
+ typedef float V __attribute__((vector_size(16)));
+ V a;
+
+ #pragma omp task depend // expected-error {{expected '(' after 'depend'}}
+ #pragma omp task depend ( // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after dependency type - ignoring}}
+ #pragma omp task depend () // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}}
+ #pragma omp task depend (argc // expected-error {{expected 'in', 'out' or 'inout' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp task depend (in : argc)) // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
+ #pragma omp task depend (out: ) // expected-error {{expected expression}}
+ #pragma omp task depend (inout : foobool(argc)), depend (in, argc) // expected-error {{expected variable name, array element or array section}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected expression}}
+ #pragma omp task depend (out :S1) // expected-error {{'S1' does not refer to a value}}
+ #pragma omp task depend(in : argv[1][1] = '2') // expected-error {{expected variable name, array element or array section}}
+ #pragma omp task depend (in : vec[1]) // expected-error {{expected variable name, array element or array section}}
+ #pragma omp task depend (in : argv[0])
+ #pragma omp task depend (in : ) // expected-error {{expected expression}}
+ #pragma omp task depend (in : main) // expected-error {{expected variable name, array element or array section}}
+ #pragma omp task depend(in : a[0]) // expected-error{{expected variable name, array element or array section}}
+ foo();
+
+ return 0;
+}
void OMPClauseEnqueue::VisitOMPFlushClause(const OMPFlushClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseEnqueue::VisitOMPDependClause(const OMPDependClause *C) {
+ VisitOMPClauseList(C);
+}
}
void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {