Added basic parsing/sema/serialization support for depobj directive.
*/
CXCursor_OMPParallelMasterDirective = 285,
- CXCursor_LastStmt = CXCursor_OMPParallelMasterDirective,
+ /** OpenMP depobj directive.
+ */
+ CXCursor_OMPDepobjDirective = 286,
+
+ CXCursor_LastStmt = CXCursor_OMPDepobjDirective,
/**
* Cursor that represents the translation unit itself.
}
};
+/// This represents implicit clause 'depobj' for the '#pragma omp depobj'
+/// directive.
+/// This clause does not exist by itself, it can be only as a part of 'omp
+/// depobj' directive. This clause is introduced to keep the original structure
+/// of \a OMPExecutableDirective class and its derivatives and to use the
+/// existing infrastructure of clauses with the list of variables.
+///
+/// \code
+/// #pragma omp depobj(a) destroy
+/// \endcode
+/// In this example directive '#pragma omp depobj' has implicit clause 'depobj'
+/// with the depobj 'a'.
+class OMPDepobjClause final : public OMPClause {
+ friend class OMPClauseReader;
+
+ /// Location of '('.
+ SourceLocation LParenLoc;
+
+ /// Chunk size.
+ Expr *Depobj = nullptr;
+
+ /// 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.
+ OMPDepobjClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_depobj, StartLoc, EndLoc), LParenLoc(LParenLoc) {}
+
+ /// Build an empty clause.
+ ///
+ explicit OMPDepobjClause()
+ : OMPClause(OMPC_depobj, SourceLocation(), SourceLocation()) {}
+
+ void setDepobj(Expr *E) { Depobj = E; }
+
+ /// Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+
+public:
+ /// Creates clause.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param Depobj depobj expression associated with the 'depobj' directive.
+ static OMPDepobjClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc, Expr *Depobj);
+
+ /// Creates an empty clause.
+ ///
+ /// \param C AST context.
+ static OMPDepobjClause *CreateEmpty(const ASTContext &C);
+
+ /// Returns depobj expression associated with the clause.
+ Expr *getDepobj() { return Depobj; }
+ const Expr *getDepobj() const { return Depobj; }
+
+ /// Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(&Depobj),
+ reinterpret_cast<Stmt **>(&Depobj) + 1);
+ }
+
+ const_child_range children() const {
+ auto Children = const_cast<OMPDepobjClause *>(this)->children();
+ return const_child_range(Children.begin(), Children.end());
+ }
+
+ child_range used_children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+ const_child_range used_children() const {
+ return const_child_range(const_child_iterator(), const_child_iterator());
+ }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_depobj;
+ }
+};
+
/// This represents implicit clause 'depend' for the '#pragma omp task'
/// directive.
///
DEF_TRAVERSE_STMT(OMPFlushDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPDepobjDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
DEF_TRAVERSE_STMT(OMPOrderedDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
}
template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPDepobjClause(OMPDepobjClause *C) {
+ TRY_TO(TraverseStmt(C->getDepobj()));
+ return true;
+}
+
+template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
TRY_TO(VisitOMPClauseList(C));
return true;
}
};
+/// This represents '#pragma omp depobj' directive.
+///
+/// \code
+/// #pragma omp depobj(a) depend(in:x,y)
+/// \endcode
+/// In this example directive '#pragma omp depobj' initializes a depobj object
+/// 'a' with dependence type 'in' and a list with 'x' and 'y' locators.
+class OMPDepobjDirective final : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+
+ /// 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.
+ ///
+ OMPDepobjDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPDepobjDirectiveClass,
+ llvm::omp::OMPD_depobj, StartLoc, EndLoc,
+ NumClauses, 0) {}
+
+ /// Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPDepobjDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPDepobjDirectiveClass,
+ llvm::omp::OMPD_depobj, SourceLocation(),
+ SourceLocation(), NumClauses, 0) {}
+
+public:
+ /// 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.
+ ///
+ static OMPDepobjDirective *Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses);
+
+ /// Creates an empty directive with the place for \a NumClauses
+ /// clauses.
+ ///
+ /// \param C AST context.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPDepobjDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPDepobjDirectiveClass;
+ }
+};
+
/// This represents '#pragma omp ordered' directive.
///
/// \code
"expected 'this' subscript expression on map clause to be 'this[0]'">;
def err_omp_invalid_map_this_expr : Error <
"invalid 'this' expression on 'map' clause">;
-def err_implied_omp_allocator_handle_t_not_found : Error<
- "omp_allocator_handle_t type not found; include <omp.h>">;
+def err_omp_implied_type_not_found : Error<
+ "'%0' type not found; include <omp.h>">;
+def err_omp_expected_omp_depend_t_lvalue : Error<
+ "expected lvalue expression%select{ of 'omp_depend_t' type, not %1|}0">;
+def err_omp_depobj_expected : Error<
+ "expected depobj expression">;
+def err_omp_depobj_single_clause_expected : Error<
+ "exactly one of 'depend', 'destroy', or 'update' clauses is expected">;
def err_omp_expected_predefined_allocator : Error<
"expected one of the predefined allocators for the variables with the static "
"storage: 'omp_default_mem_alloc', 'omp_large_cap_mem_alloc', "
#ifndef OPENMP_FLUSH_CLAUSE
#define OPENMP_FLUSH_CLAUSE(Name)
#endif
+#ifndef OPENMP_DEPOBJ_CLAUSE
+#define OPENMP_DEPOBJ_CLAUSE(Name)
+#endif
// OpenMP clauses.
OPENMP_CLAUSE(allocator, OMPAllocatorClause)
OPENMP_CLAUSE(allocate, OMPAllocateClause)
OPENMP_CLAUSE(nontemporal, OMPNontemporalClause)
OPENMP_CLAUSE(order, OMPOrderClause)
+OPENMP_CLAUSE(depobj, OMPDepobjClause)
// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
OPENMP_FLUSH_CLAUSE(acquire)
OPENMP_FLUSH_CLAUSE(release)
+// Clauses allowed for OpenMP directive 'depobj'.
+OPENMP_DEPOBJ_CLAUSE(depend)
+
+#undef OPENMP_DEPOBJ_CLAUSE
#undef OPENMP_FLUSH_CLAUSE
#undef OPENMP_ORDER_KIND
#undef OPENMP_LASTPRIVATE_KIND
def OMPTaskwaitDirective : StmtNode<OMPExecutableDirective>;
def OMPTaskgroupDirective : StmtNode<OMPExecutableDirective>;
def OMPFlushDirective : StmtNode<OMPExecutableDirective>;
+def OMPDepobjDirective : StmtNode<OMPExecutableDirective>;
def OMPOrderedDirective : StmtNode<OMPExecutableDirective>;
def OMPAtomicDirective : StmtNode<OMPExecutableDirective>;
def OMPTargetDirective : StmtNode<OMPExecutableDirective>;
StmtResult ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp depobj'.
+ StmtResult ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
/// Called on well-formed '\#pragma omp ordered' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// Called on well-formed 'depobj' pseudo clause.
+ OMPClause *ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// Called on well-formed 'depend' clause.
OMPClause *
ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
STMT_OMP_BARRIER_DIRECTIVE,
STMT_OMP_TASKWAIT_DIRECTIVE,
STMT_OMP_FLUSH_DIRECTIVE,
+ STMT_OMP_DEPOBJ_DIRECTIVE,
STMT_OMP_ORDERED_DIRECTIVE,
STMT_OMP_ATOMIC_DIRECTIVE,
STMT_OMP_TARGET_DIRECTIVE,
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_flush:
+ case OMPC_depobj:
case OMPC_read:
case OMPC_write:
case OMPC_update:
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_flush:
+ case OMPC_depobj:
case OMPC_read:
case OMPC_write:
case OMPC_update:
return new (Mem) OMPFlushClause(N);
}
+OMPDepobjClause *OMPDepobjClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ Expr *Depobj) {
+ auto *Clause = new (C) OMPDepobjClause(StartLoc, LParenLoc, RParenLoc);
+ Clause->setDepobj(Depobj);
+ return Clause;
+}
+
+OMPDepobjClause *OMPDepobjClause::CreateEmpty(const ASTContext &C) {
+ return new (C) OMPDepobjClause();
+}
+
OMPDependClause *
OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
}
}
+void OMPClausePrinter::VisitOMPDepobjClause(OMPDepobjClause *Node) {
+ OS << "(";
+ Node->getDepobj()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) {
OS << "depend(";
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/StmtOpenMP.h"
-
#include "clang/AST/ASTContext.h"
+#include "clang/AST/StmtOpenMP.h"
using namespace clang;
using namespace llvm::omp;
return new (Mem) OMPFlushDirective(NumClauses);
}
+OMPDepobjDirective *OMPDepobjDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses) {
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPDepobjDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size(),
+ alignof(OMPDepobjDirective));
+ auto *Dir = new (Mem) OMPDepobjDirective(StartLoc, EndLoc, Clauses.size());
+ Dir->setClauses(Clauses);
+ return Dir;
+}
+
+OMPDepobjDirective *OMPDepobjDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ unsigned Size =
+ llvm::alignTo(sizeof(OMPDepobjDirective), alignof(OMPClause *));
+ void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses,
+ alignof(OMPDepobjDirective));
+ return new (Mem) OMPDepobjDirective(NumClauses);
+}
+
OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPDepobjDirective(OMPDepobjDirective *Node) {
+ Indent() << "#pragma omp depobj";
+ PrintOMPExecutableDirective(Node);
+}
+
void StmtPrinter::VisitOMPOrderedDirective(OMPOrderedDirective *Node) {
Indent() << "#pragma omp ordered";
PrintOMPExecutableDirective(Node, Node->hasClausesOfKind<OMPDependClause>());
void OMPClauseProfiler::VisitOMPFlushClause(const OMPFlushClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseProfiler::VisitOMPDepobjClause(const OMPDepobjClause *C) {
+ if (const Expr *Depobj = C->getDepobj())
+ Profiler->VisitStmt(Depobj);
+}
void OMPClauseProfiler::VisitOMPDependClause(const OMPDependClause *C) {
VisitOMPClauseList(C);
}
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPDepobjDirective(const OMPDepobjDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitOMPOrderedDirective(const OMPOrderedDirective *S) {
VisitOMPExecutableDirective(S);
}
// clause for 'flush' directive. If the 'flush' clause is explicitly specified
// the Parser should generate a warning about extra tokens at the end of the
// directive.
- if (Str == "flush")
+ // 'depobj' clause cannot be specified explicitly, because this is an implicit
+ // clause for 'depobj' directive. If the 'depobj' clause is explicitly
+ // specified the Parser should generate a warning about extra tokens at the
+ // end of the directive.
+ if (llvm::StringSwitch<bool>(Str)
+ .Case("flush", true)
+ .Case("depobj", true)
+ .Default(false))
return OMPC_unknown;
return llvm::StringSwitch<OpenMPClauseKind>(Str)
#define OPENMP_CLAUSE(Name, Class) .Case(#Name, OMPC_##Name)
case OMPC_untied:
case OMPC_mergeable:
case OMPC_flush:
+ case OMPC_depobj:
case OMPC_read:
case OMPC_write:
case OMPC_update:
case OMPC_untied:
case OMPC_mergeable:
case OMPC_flush:
+ case OMPC_depobj:
case OMPC_read:
case OMPC_write:
case OMPC_update:
break;
}
break;
+ case OMPD_depobj:
+ if (OpenMPVersion < 50)
+ return false;
+ switch (CKind) {
+#define OPENMP_DEPOBJ_CLAUSE(Name) \
+ case OMPC_##Name: \
+ return true;
+#include "clang/Basic/OpenMPKinds.def"
+ case OMPC_depobj:
+ return true;
+ default:
+ break;
+ }
+ break;
case OMPD_atomic:
if (OpenMPVersion < 50 &&
(CKind == OMPC_acq_rel || CKind == OMPC_acquire ||
case OMPD_cancellation_point:
case OMPD_cancel:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_taskgroup:
case OMPD_atomic:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_teams:
case OMPD_target_data:
case OMPD_target_exit_data:
case OMPD_taskgroup:
case OMPD_atomic:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_teams:
case OMPD_target_data:
case OMPD_target_exit_data:
case OMPD_taskgroup:
case OMPD_atomic:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_teams:
case OMPD_target_data:
case OMPD_target_exit_data:
case OMPD_taskgroup:
case OMPD_atomic:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_teams:
case OMPD_target_data:
case OMPD_target_exit_data:
case OMPD_taskgroup:
case OMPD_atomic:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_teams:
case OMPD_target_data:
case OMPD_distribute:
case OMPD_taskgroup:
case OMPD_atomic:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_teams:
case OMPD_target_data:
case OMPD_target_exit_data:
case OMPD_taskgroup:
case OMPD_atomic:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_teams:
case OMPD_target_data:
case OMPD_target_exit_data:
case OMPD_taskgroup:
case OMPD_atomic:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_teams:
case OMPD_target_data:
case OMPD_target_exit_data:
case OMPD_taskgroup:
case OMPD_atomic:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_teams:
case OMPD_target_data:
case OMPD_target_exit_data:
case Stmt::OMPFlushDirectiveClass:
EmitOMPFlushDirective(cast<OMPFlushDirective>(*S));
break;
+ case Stmt::OMPDepobjDirectiveClass:
+ EmitOMPDepobjDirective(cast<OMPDepobjDirective>(*S));
+ break;
case Stmt::OMPOrderedDirectiveClass:
EmitOMPOrderedDirective(cast<OMPOrderedDirective>(*S));
break;
S.getBeginLoc(), AO);
}
+void CodeGenFunction::EmitOMPDepobjDirective(const OMPDepobjDirective &S) {}
+
void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
const CodeGenLoopTy &CodeGenLoop,
Expr *IncExpr) {
case OMPC_copyin:
case OMPC_copyprivate:
case OMPC_flush:
+ case OMPC_depobj:
case OMPC_proc_bind:
case OMPC_schedule:
case OMPC_ordered:
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S);
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S);
void EmitOMPFlushDirective(const OMPFlushDirective &S);
+ void EmitOMPDepobjDirective(const OMPDepobjDirective &S);
void EmitOMPOrderedDirective(const OMPOrderedDirective &S);
void EmitOMPAtomicDirective(const OMPAtomicDirective &S);
void EmitOMPTargetDirective(const OMPTargetDirective &S);
case OMPD_taskwait:
case OMPD_taskgroup:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_for:
case OMPD_for_simd:
case OMPD_sections:
break;
}
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
case OMPD_target_teams_distribute_parallel_for:
case OMPD_target_teams_distribute_parallel_for_simd:
case OMPD_target_teams_distribute_simd: {
- // Special processing for flush clause.
- Token FlushTok;
- if (DKind == OMPD_flush)
- FlushTok = Tok;
+ // Special processing for flush and depobj clauses.
+ Token ImplicitTok;
+ bool ImplicitClauseAllowed = false;
+ if (DKind == OMPD_flush || DKind == OMPD_depobj) {
+ ImplicitTok = Tok;
+ ImplicitClauseAllowed = true;
+ }
ConsumeToken();
// Parse directive name of the 'critical' directive if any.
if (DKind == OMPD_critical) {
Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
- bool FlushHasClause = false;
- if (DKind == OMPD_flush && Tok.is(tok::l_paren)) {
- FlushHasClause = true;
+ bool HasImplicitClause = false;
+ if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {
+ HasImplicitClause = true;
// Push copy of the current token back to stream to properly parse
- // pseudo-clause OMPFlushClause.
+ // pseudo-clause OMPFlushClause or OMPDepobjClause.
PP.EnterToken(Tok, /*IsReinject*/ true);
- PP.EnterToken(FlushTok, /*IsReinject*/ true);
+ PP.EnterToken(ImplicitTok, /*IsReinject*/ true);
ConsumeAnyToken();
}
- OpenMPClauseKind CKind =
- Tok.isAnnotation()
- ? OMPC_unknown
- : FlushHasClause ? OMPC_flush
- : getOpenMPClauseKind(PP.getSpelling(Tok));
+ OpenMPClauseKind CKind = Tok.isAnnotation()
+ ? OMPC_unknown
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ if (HasImplicitClause) {
+ assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");
+ if (DKind == OMPD_flush) {
+ CKind = OMPC_flush;
+ } else {
+ assert(DKind == OMPD_depobj &&
+ "Expected flush or depobj directives.");
+ CKind = OMPC_depobj;
+ }
+ }
+ // No more implicit clauses allowed.
+ ImplicitClauseAllowed = false;
Actions.StartOpenMPClause(CKind);
- FlushHasClause = false;
+ HasImplicitClause = false;
OMPClause *Clause =
ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
FirstClauses[CKind].setInt(true);
/// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
/// from-clause | is_device_ptr-clause | task_reduction-clause |
/// in_reduction-clause | allocator-clause | allocate-clause |
-/// acq_rel-clause | acquire-clause | release-clause | relaxed-clause
+/// acq_rel-clause | acquire-clause | release-clause | relaxed-clause |
+/// depobj-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
case OMPC_num_tasks:
case OMPC_hint:
case OMPC_allocator:
+ case OMPC_depobj:
// OpenMP [2.5, Restrictions]
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
case Stmt::OMPDistributeParallelForSimdDirectiveClass:
case Stmt::OMPDistributeSimdDirectiveClass:
case Stmt::OMPFlushDirectiveClass:
+ case Stmt::OMPDepobjDirectiveClass:
case Stmt::OMPForDirectiveClass:
case Stmt::OMPForSimdDirectiveClass:
case Stmt::OMPMasterDirectiveClass:
SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
/// omp_allocator_handle_t type.
QualType OMPAllocatorHandleT;
+ /// omp_depend_t type.
+ QualType OMPDependT;
/// Expression for the predefined allocators.
Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
nullptr};
Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
return OMPPredefinedAllocators[AllocatorKind];
}
+ /// Sets omp_depend_t type.
+ void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
+ /// Gets omp_depend_t type.
+ QualType getOMPDependT() const { return OMPDependT; }
bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
OpenMPClauseKind getClauseParsingMode() const {
case OMPD_cancellation_point:
case OMPD_cancel:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
"No associated statement allowed for 'omp flush' directive");
Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
break;
+ case OMPD_depobj:
+ assert(AStmt == nullptr &&
+ "No associated statement allowed for 'omp depobj' directive");
+ Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
+ break;
case OMPD_ordered:
Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
continue;
case OMPC_allocator:
case OMPC_flush:
+ case OMPC_depobj:
case OMPC_threadprivate:
case OMPC_uniform:
case OMPC_unknown:
return OMPFlushDirective::Create(Context, StartLoc, EndLoc, Clauses);
}
+StmtResult Sema::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ if (Clauses.empty()) {
+ Diag(StartLoc, diag::err_omp_depobj_expected);
+ return StmtError();
+ } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
+ Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
+ return StmtError();
+ }
+ // Only depobj expression and another single clause is allowed.
+ if (Clauses.size() > 2) {
+ Diag(Clauses[2]->getBeginLoc(),
+ diag::err_omp_depobj_single_clause_expected);
+ return StmtError();
+ } else if (Clauses.size() < 1) {
+ Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
+ return StmtError();
+ }
+ return OMPDepobjDirective::Create(Context, StartLoc, EndLoc, Clauses);
+}
+
StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt,
SourceLocation StartLoc,
case OMPC_hint:
Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_depobj:
+ Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_default:
case OMPC_proc_bind:
case OMPD_taskwait:
case OMPD_cancellation_point:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_taskwait:
case OMPD_cancellation_point:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_taskwait:
case OMPD_cancellation_point:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_taskwait:
case OMPD_cancellation_point:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_taskwait:
case OMPD_cancellation_point:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_taskwait:
case OMPD_cancellation_point:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_taskwait:
case OMPD_cancellation_point:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPD_taskwait:
case OMPD_cancellation_point:
case OMPD_flush:
+ case OMPD_depobj:
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_flush:
+ case OMPC_depobj:
case OMPC_read:
case OMPC_write:
case OMPC_update:
Stack->setAllocator(AllocatorKind, Res.get());
}
if (ErrorFound) {
- S.Diag(Loc, diag::err_implied_omp_allocator_handle_t_not_found);
+ S.Diag(Loc, diag::err_omp_implied_type_not_found)
+ << "omp_allocator_handle_t";
return false;
}
OMPAllocatorHandleT.addConst();
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_flush:
+ case OMPC_depobj:
case OMPC_read:
case OMPC_write:
case OMPC_update:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_flush:
+ case OMPC_depobj:
case OMPC_read:
case OMPC_write:
case OMPC_update:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_flush:
+ case OMPC_depobj:
case OMPC_depend:
case OMPC_device:
case OMPC_map:
Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_if:
+ case OMPC_depobj:
case OMPC_final:
case OMPC_num_threads:
case OMPC_safelen:
return OMPFlushClause::Create(Context, StartLoc, LParenLoc, EndLoc, VarList);
}
+/// Tries to find omp_depend_t. type.
+static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
+ QualType OMPDependT = Stack->getOMPDependT();
+ if (!OMPDependT.isNull())
+ return true;
+ IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
+ ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
+ if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
+ S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
+ return false;
+ }
+ Stack->setOMPDependT(PT.get());
+ return true;
+}
+
+OMPClause *Sema::ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ if (!Depobj)
+ return nullptr;
+
+ bool OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack);
+
+ // OpenMP 5.0, 2.17.10.1 depobj Construct
+ // depobj is an lvalue expression of type omp_depend_t.
+ if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
+ !Depobj->isInstantiationDependent() &&
+ !Depobj->containsUnexpandedParameterPack() &&
+ (OMPDependTFound &&
+ !Context.typesAreCompatible(DSAStack->getOMPDependT(), Depobj->getType(),
+ /*CompareUnqualified=*/true))) {
+ Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
+ << 0 << Depobj->getType() << Depobj->getSourceRange();
+ }
+
+ if (!Depobj->isLValue()) {
+ Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
+ << 1 << Depobj->getSourceRange();
+ }
+
+ return OMPDepobjClause::Create(Context, StartLoc, LParenLoc, EndLoc, Depobj);
+}
+
OMPClause *
Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
SourceLocation DepLoc, SourceLocation ColonLoc,
EndLoc);
}
+ /// Build a new OpenMP 'depobj' pseudo clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPDepobjClause(Depobj, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
/// Build a new OpenMP 'depend' pseudo clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
template <typename Derived>
StmtResult
+TreeTransform<Derived>::TransformOMPDepobjDirective(OMPDepobjDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_depobj, DirName, nullptr,
+ D->getBeginLoc());
+ StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+ getDerived().getSema().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
+template <typename Derived>
+StmtResult
TreeTransform<Derived>::TransformOMPOrderedDirective(OMPOrderedDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().StartOpenMPDSABlock(OMPD_ordered, DirName, nullptr,
template <typename Derived>
OMPClause *
+TreeTransform<Derived>::TransformOMPDepobjClause(OMPDepobjClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getDepobj());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPDepobjClause(E.get(), C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
+}
+
+template <typename Derived>
+OMPClause *
TreeTransform<Derived>::TransformOMPDependClause(OMPDependClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
case OMPC_flush:
C = OMPFlushClause::CreateEmpty(Context, Record.readInt());
break;
+ case OMPC_depobj:
+ C = OMPDepobjClause::CreateEmpty(Context);
+ break;
case OMPC_depend: {
unsigned NumVars = Record.readInt();
unsigned NumLoops = Record.readInt();
C->setVarRefs(Vars);
}
+void OMPClauseReader::VisitOMPDepobjClause(OMPDepobjClause *C) {
+ C->setDepobj(Record.readSubExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
C->setLParenLoc(Record.readSourceLocation());
C->setDependencyKind(
VisitOMPExecutableDirective(D);
}
+void ASTStmtReader::VisitOMPDepobjDirective(OMPDepobjDirective *D) {
+ VisitStmt(D);
+ // The NumClauses field was read in ReadStmtFromStream.
+ Record.skipInts(1);
+ VisitOMPExecutableDirective(D);
+}
+
void ASTStmtReader::VisitOMPOrderedDirective(OMPOrderedDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
+ case STMT_OMP_DEPOBJ_DIRECTIVE:
+ S = OMPDepobjDirective::CreateEmpty(
+ Context, Record[ASTStmtReader::NumStmtFields], Empty);
+ break;
+
case STMT_OMP_ORDERED_DIRECTIVE:
S = OMPOrderedDirective::CreateEmpty(
Context, Record[ASTStmtReader::NumStmtFields], Empty);
Record.AddStmt(VE);
}
+void OMPClauseWriter::VisitOMPDepobjClause(OMPDepobjClause *C) {
+ Record.AddStmt(C->getDepobj());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {
Record.push_back(C->varlist_size());
Record.push_back(C->getNumLoops());
Code = serialization::STMT_OMP_FLUSH_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPDepobjDirective(OMPDepobjDirective *D) {
+ VisitStmt(D);
+ Record.push_back(D->getNumClauses());
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_DEPOBJ_DIRECTIVE;
+}
+
void ASTStmtWriter::VisitOMPOrderedDirective(OMPOrderedDirective *D) {
VisitStmt(D);
Record.push_back(D->getNumClauses());
case Stmt::OMPTaskwaitDirectiveClass:
case Stmt::OMPTaskgroupDirectiveClass:
case Stmt::OMPFlushDirectiveClass:
+ case Stmt::OMPDepobjDirectiveClass:
case Stmt::OMPOrderedDirectiveClass:
case Stmt::OMPAtomicDirectiveClass:
case Stmt::OMPTargetDirectiveClass:
#pragma omp allocate(sss) allocat // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}}
#pragma omp allocate(sss) allocate(sss) // expected-error {{unexpected OpenMP clause 'allocate' in directive '#pragma omp allocate'}}
#pragma omp allocate(sss) allocator // expected-error {{expected '(' after 'allocator'}}
-#pragma omp allocate(sss) allocator(0, // expected-error {{expected ')'}} expected-error {{omp_allocator_handle_t type not found; include <omp.h>}} expected-note {{to match this '('}}
-#pragma omp allocate(sss) allocator(0,sss // expected-error {{expected ')'}} expected-error {{omp_allocator_handle_t type not found; include <omp.h>}} expected-note {{to match this '('}}
-#pragma omp allocate(sss) allocator(0,sss) // expected-error {{expected ')'}} expected-error {{omp_allocator_handle_t type not found; include <omp.h>}} expected-note {{to match this '('}}
-#pragma omp allocate(sss) allocator(sss) // expected-error {{omp_allocator_handle_t type not found; include <omp.h>}}
+#pragma omp allocate(sss) allocator(0, // expected-error {{expected ')'}} expected-error {{'omp_allocator_handle_t' type not found; include <omp.h>}} expected-note {{to match this '('}}
+#pragma omp allocate(sss) allocator(0,sss // expected-error {{expected ')'}} expected-error {{'omp_allocator_handle_t' type not found; include <omp.h>}} expected-note {{to match this '('}}
+#pragma omp allocate(sss) allocator(0,sss) // expected-error {{expected ')'}} expected-error {{'omp_allocator_handle_t' type not found; include <omp.h>}} expected-note {{to match this '('}}
+#pragma omp allocate(sss) allocator(sss) // expected-error {{'omp_allocator_handle_t' type not found; include <omp.h>}}
typedef void **omp_allocator_handle_t;
extern const omp_allocator_handle_t omp_default_mem_alloc;
--- /dev/null
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+typedef void *omp_depend_t;
+
+void foo() {}
+
+template <class T>
+T tmain(T argc) {
+ static T a;
+#pragma omp depobj(a) depend(in:argc)
+ return argc;
+}
+// CHECK: static T a;
+// CHECK-NEXT: #pragma omp depobj (a) depend(in : argc){{$}}
+// CHECK: static void *a;
+// CHECK-NEXT: #pragma omp depobj (a) depend(in : argc){{$}}
+
+int main(int argc, char **argv) {
+ static omp_depend_t a;
+ omp_depend_t b;
+// CHECK: static omp_depend_t a;
+// CHECK-NEXT: omp_depend_t b;
+#pragma omp depobj(a) depend(out:argc, argv)
+// CHECK-NEXT: #pragma omp depobj (a) depend(out : argc,argv)
+ (void)tmain(a), tmain(b);
+ return 0;
+}
+
+#endif
--- /dev/null
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ferror-limit 100 %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 %s -Wuninitialized
+
+struct S1 { // expected-note 2 {{declared here}}
+ int a;
+} s;
+
+#pragma omp depobj(0) depend(in:s) // expected-error {{unexpected OpenMP directive '#pragma omp depobj'}}
+void foo() {
+#pragma omp depobj(0) depend(in:s) // expected-error {{'omp_depend_t' type not found; include <omp.h>}} expected-error {{expected lvalue expression}}}
+}
+
+typedef void *omp_depend_t;
+
+template <class T>
+T tmain(T argc) {
+ omp_depend_t x;
+#pragma omp depobj() allocate(argc) // expected-error {{expected expression}} expected-error {{expected depobj expression}} expected-error {{unexpected OpenMP clause 'allocate' in directive '#pragma omp depobj'}}
+ ;
+#pragma omp depobj(x) untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp depobj'}}
+#pragma omp depobj(x) unknown // expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}}
+ if (argc)
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
+ if (argc) {
+#pragma omp depobj(x) depend(in:s)
+ }
+ while (argc)
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
+ while (argc) {
+#pragma omp depobj(x) depend(in:s)
+ }
+ do
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
+ while (argc)
+ ;
+ do {
+#pragma omp depobj(x) depend(in:s)
+ } while (argc);
+ switch (argc)
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
+ switch (argc)
+ case 1:
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
+ switch (argc)
+ case 1: {
+#pragma omp depobj(x) depend(in:s)
+ }
+ switch (argc) {
+#pragma omp depobj(x) depend(in:s)
+ case 1:
+#pragma omp depobj(x) depend(in:s)
+ break;
+ default: {
+#pragma omp depobj(x) depend(in:s)
+ } break;
+ }
+ for (;;)
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
+ for (;;) {
+#pragma omp depobj(x) depend(in:s)
+ }
+label:
+#pragma omp depobj(x) depend(in:s)
+label1 : {
+#pragma omp depobj(x) depend(in:s)
+}
+
+#pragma omp depobj // expected-error {{expected depobj expression}}
+#pragma omp depobj( // expected-error {{expected expression}} expected-error {{expected depobj expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp depobj() // expected-error {{expected expression}} expected-error {{expected depobj expression}}
+#pragma omp depobj(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}}
+#pragma omp depobj(argc, // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}
+#pragma omp depobj(argc) // expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}
+#pragma omp depobj(S1) // expected-error {{'S1' does not refer to a value}} expected-error {{expected depobj expression}}
+#pragma omp depobj(argc) depobj(argc) // expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}}
+#pragma omp parallel depobj(argc) // expected-warning {{extra tokens at the end of '#pragma omp parallel' are ignored}}
+ ;
+ return T();
+}
+
+int main(int argc, char **argv) {
+omp_depend_t x;
+#pragma omp depobj(x) depend(in:s)
+ ;
+#pragma omp depobj(x) untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp depobj'}}
+#pragma omp depobj(x) unknown // expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}}
+ if (argc)
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
+ if (argc) {
+#pragma omp depobj(x) depend(in:s)
+ }
+ while (argc)
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
+ while (argc) {
+#pragma omp depobj(x) depend(in:s)
+ }
+ do
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
+ while (argc)
+ ;
+ do {
+#pragma omp depobj(x) depend(in:s)
+ } while (argc);
+ switch (argc)
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
+ switch (argc)
+ case 1:
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
+ switch (argc)
+ case 1: {
+#pragma omp depobj(x) depend(in:s)
+ }
+ switch (argc) {
+#pragma omp depobj(x) depend(in:s)
+ case 1:
+#pragma omp depobj(x) depend(in:s)
+ break;
+ default: {
+#pragma omp depobj(x) depend(in:s)
+ } break;
+ }
+ for (;;)
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
+ for (;;) {
+#pragma omp depobj(x) depend(in:s)
+ }
+label:
+#pragma omp depobj(x) depend(in:s)
+label1 : {
+#pragma omp depobj(x) depend(in:s)
+}
+
+#pragma omp depobj // expected-error {{expected depobj expression}}
+#pragma omp depobj( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected depobj expression}}
+#pragma omp depobj() // expected-error {{expected expression}} expected-error {{expected depobj expression}}
+#pragma omp depobj(argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}
+#pragma omp depobj(argc, // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}
+#pragma omp depobj(argc) // expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}
+#pragma omp depobj(S1) // expected-error {{'S1' does not refer to a value}} expected-error {{expected depobj expression}}
+#pragma omp depobj(argc) depobj(argc) // expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} expected-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}
+#pragma omp parallel depobj(argc) // expected-warning {{extra tokens at the end of '#pragma omp parallel' are ignored}}
+ ;
+#pragma omp depobj(x) seq_cst // expected-error {{unexpected OpenMP clause 'seq_cst' in directive '#pragma omp depobj'}}
+#pragma omp depobj(x) depend(in: x)
+#pragma omp depobj(x) (x) depend(in: x) // expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}}
+#pragma omp depobj(x) depend(in: x) depend(out:x) // expected-error {{exactly one of 'depend', 'destroy', or 'update' clauses is expected}}
+#pragma omp depend(out:x) depobj(x) // expected-error {{expected an OpenMP directive}}
+#pragma omp depobj depend(in:x) (x) // expected-error {{expected depobj expression}} expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}}
+ return tmain(argc); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}}
+}
#pragma omp flush seq_cst // expected-error {{unexpected OpenMP clause 'seq_cst' in directive '#pragma omp flush'}}
#pragma omp flush acq_rel acquire // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} omp45-error {{unexpected OpenMP clause 'acquire' in directive '#pragma omp flush'}} omp50-error {{directive '#pragma omp flush' cannot contain more than one 'acq_rel', 'acquire' or 'release' clause}} omp50-note {{'acq_rel' clause used here}}
#pragma omp flush release acquire // omp45-error {{unexpected OpenMP clause 'release' in directive '#pragma omp flush'}} omp45-error {{unexpected OpenMP clause 'acquire' in directive '#pragma omp flush'}} omp50-error {{directive '#pragma omp flush' cannot contain more than one 'acq_rel', 'acquire' or 'release' clause}} omp50-note {{'release' clause used here}}
-#pragma omp flush acq_rel (argc) // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} omp50-error {{'flush' directive with memory order clause 'acq_rel' cannot have the list}} omp50-note {{memory order clause 'acq_rel' is specified here}}
+#pragma omp flush acq_rel (argc) // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} expected-warning {{extra tokens at the end of '#pragma omp flush' are ignored}}
#pragma omp flush(argc) acq_rel // omp45-error {{unexpected OpenMP clause 'acq_rel' in directive '#pragma omp flush'}} omp50-error {{'flush' directive with memory order clause 'acq_rel' cannot have the list}} omp50-note {{memory order clause 'acq_rel' is specified here}}
return tmain(argc);
}
VisitOMPCancellationPointDirective(const OMPCancellationPointDirective *D);
void VisitOMPCancelDirective(const OMPCancelDirective *D);
void VisitOMPFlushDirective(const OMPFlushDirective *D);
+ void VisitOMPDepobjDirective(const OMPDepobjDirective *D);
void VisitOMPOrderedDirective(const OMPOrderedDirective *D);
void VisitOMPAtomicDirective(const OMPAtomicDirective *D);
void VisitOMPTargetDirective(const OMPTargetDirective *D);
void OMPClauseEnqueue::VisitOMPFlushClause(const OMPFlushClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseEnqueue::VisitOMPDepobjClause(const OMPDepobjClause *C) {
+ Visitor->AddStmt(C->getDepobj());
+}
void OMPClauseEnqueue::VisitOMPDependClause(const OMPDependClause *C) {
VisitOMPClauseList(C);
}
VisitOMPExecutableDirective(D);
}
+void EnqueueVisitor::VisitOMPDepobjDirective(const OMPDepobjDirective *D) {
+ VisitOMPExecutableDirective(D);
+}
+
void EnqueueVisitor::VisitOMPOrderedDirective(const OMPOrderedDirective *D) {
VisitOMPExecutableDirective(D);
}
VisitOMPExecutableDirective(D);
}
-void EnqueueVisitor::VisitOMPTargetDataDirective(const
- OMPTargetDataDirective *D) {
+void EnqueueVisitor::VisitOMPTargetDataDirective(
+ const OMPTargetDataDirective *D) {
VisitOMPExecutableDirective(D);
}
return cxstring::createRef("OMPTaskgroupDirective");
case CXCursor_OMPFlushDirective:
return cxstring::createRef("OMPFlushDirective");
+ case CXCursor_OMPDepobjDirective:
+ return cxstring::createRef("OMPDepobjDirective");
case CXCursor_OMPOrderedDirective:
return cxstring::createRef("OMPOrderedDirective");
case CXCursor_OMPAtomicDirective:
case Stmt::OMPFlushDirectiveClass:
K = CXCursor_OMPFlushDirective;
break;
+ case Stmt::OMPDepobjDirectiveClass:
+ K = CXCursor_OMPDepobjDirective;
+ break;
case Stmt::OMPOrderedDirectiveClass:
K = CXCursor_OMPOrderedDirective;
break;
__OMP_DIRECTIVE_EXT(master_taskloop_simd, "master taskloop simd")
__OMP_DIRECTIVE_EXT(parallel_master_taskloop_simd,
"parallel master taskloop simd")
+__OMP_DIRECTIVE(depobj)
// Has to be the last because Clang implicitly expects it to be.
__OMP_DIRECTIVE(unknown)
#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize)
#endif
-#define __OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
+#define __OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize)
__OMP_ARRAY_TYPE(KmpCriticalName, Int32, 8)