forked from OSchip/llvm-project
[OPENMP] Initial support for 'in_reduction' clause.
Parsing/sema analysis for 'in_reduction' clause for task-based directives. llvm-svn: 308768
This commit is contained in:
parent
6ab9ea9614
commit
fa312f33f8
|
@ -2101,6 +2101,216 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// This represents clause 'in_reduction' in the '#pragma omp task' directives.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp task in_reduction(+:a,b)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp task' has clause 'in_reduction' with
|
||||
/// operator '+' and the variables 'a' and 'b'.
|
||||
///
|
||||
class OMPInReductionClause final
|
||||
: public OMPVarListClause<OMPInReductionClause>,
|
||||
public OMPClauseWithPostUpdate,
|
||||
private llvm::TrailingObjects<OMPInReductionClause, Expr *> {
|
||||
friend TrailingObjects;
|
||||
friend OMPVarListClause;
|
||||
friend class OMPClauseReader;
|
||||
/// Location of ':'.
|
||||
SourceLocation ColonLoc;
|
||||
/// Nested name specifier for C++.
|
||||
NestedNameSpecifierLoc QualifierLoc;
|
||||
/// Name of custom operator.
|
||||
DeclarationNameInfo NameInfo;
|
||||
|
||||
/// 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 ColonLoc Location of ':'.
|
||||
/// \param N Number of the variables in the clause.
|
||||
/// \param QualifierLoc The nested-name qualifier with location information
|
||||
/// \param NameInfo The full name info for reduction identifier.
|
||||
///
|
||||
OMPInReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation ColonLoc, SourceLocation EndLoc,
|
||||
unsigned N, NestedNameSpecifierLoc QualifierLoc,
|
||||
const DeclarationNameInfo &NameInfo)
|
||||
: OMPVarListClause<OMPInReductionClause>(OMPC_in_reduction, StartLoc,
|
||||
LParenLoc, EndLoc, N),
|
||||
OMPClauseWithPostUpdate(this), ColonLoc(ColonLoc),
|
||||
QualifierLoc(QualifierLoc), NameInfo(NameInfo) {}
|
||||
|
||||
/// Build an empty clause.
|
||||
///
|
||||
/// \param N Number of variables.
|
||||
///
|
||||
explicit OMPInReductionClause(unsigned N)
|
||||
: OMPVarListClause<OMPInReductionClause>(
|
||||
OMPC_in_reduction, SourceLocation(), SourceLocation(),
|
||||
SourceLocation(), N),
|
||||
OMPClauseWithPostUpdate(this), ColonLoc(), QualifierLoc(), NameInfo() {}
|
||||
|
||||
/// Sets location of ':' symbol in clause.
|
||||
void setColonLoc(SourceLocation CL) { ColonLoc = CL; }
|
||||
/// Sets the name info for specified reduction identifier.
|
||||
void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; }
|
||||
/// Sets the nested name specifier.
|
||||
void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; }
|
||||
|
||||
/// Set list of helper expressions, required for proper codegen of the clause.
|
||||
/// These expressions represent private copy of the reduction variable.
|
||||
void setPrivates(ArrayRef<Expr *> Privates);
|
||||
|
||||
/// Get the list of helper privates.
|
||||
MutableArrayRef<Expr *> getPrivates() {
|
||||
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
|
||||
}
|
||||
ArrayRef<const Expr *> getPrivates() const {
|
||||
return llvm::makeArrayRef(varlist_end(), varlist_size());
|
||||
}
|
||||
|
||||
/// Set list of helper expressions, required for proper codegen of the clause.
|
||||
/// These expressions represent LHS expression in the final reduction
|
||||
/// expression performed by the reduction clause.
|
||||
void setLHSExprs(ArrayRef<Expr *> LHSExprs);
|
||||
|
||||
/// Get the list of helper LHS expressions.
|
||||
MutableArrayRef<Expr *> getLHSExprs() {
|
||||
return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size());
|
||||
}
|
||||
ArrayRef<const Expr *> getLHSExprs() const {
|
||||
return llvm::makeArrayRef(getPrivates().end(), varlist_size());
|
||||
}
|
||||
|
||||
/// Set list of helper expressions, required for proper codegen of the clause.
|
||||
/// These expressions represent RHS expression in the final reduction
|
||||
/// expression performed by the reduction clause. Also, variables in these
|
||||
/// expressions are used for proper initialization of reduction copies.
|
||||
void setRHSExprs(ArrayRef<Expr *> RHSExprs);
|
||||
|
||||
/// Get the list of helper destination expressions.
|
||||
MutableArrayRef<Expr *> getRHSExprs() {
|
||||
return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size());
|
||||
}
|
||||
ArrayRef<const Expr *> getRHSExprs() const {
|
||||
return llvm::makeArrayRef(getLHSExprs().end(), varlist_size());
|
||||
}
|
||||
|
||||
/// Set list of helper reduction expressions, required for proper
|
||||
/// codegen of the clause. These expressions are binary expressions or
|
||||
/// operator/custom reduction call that calculates new value from source
|
||||
/// helper expressions to destination helper expressions.
|
||||
void setReductionOps(ArrayRef<Expr *> ReductionOps);
|
||||
|
||||
/// Get the list of helper reduction expressions.
|
||||
MutableArrayRef<Expr *> getReductionOps() {
|
||||
return MutableArrayRef<Expr *>(getRHSExprs().end(), varlist_size());
|
||||
}
|
||||
ArrayRef<const Expr *> getReductionOps() const {
|
||||
return llvm::makeArrayRef(getRHSExprs().end(), varlist_size());
|
||||
}
|
||||
|
||||
public:
|
||||
/// Creates clause with a list of variables \a VL.
|
||||
///
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param ColonLoc Location of ':'.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param VL The variables in the clause.
|
||||
/// \param QualifierLoc The nested-name qualifier with location information
|
||||
/// \param NameInfo The full name info for reduction identifier.
|
||||
/// \param Privates List of helper expressions for proper generation of
|
||||
/// private copies.
|
||||
/// \param LHSExprs List of helper expressions for proper generation of
|
||||
/// assignment operation required for copyprivate clause. This list represents
|
||||
/// LHSs of the reduction expressions.
|
||||
/// \param RHSExprs List of helper expressions for proper generation of
|
||||
/// assignment operation required for copyprivate clause. This list represents
|
||||
/// RHSs of the reduction expressions.
|
||||
/// Also, variables in these expressions are used for proper initialization of
|
||||
/// reduction copies.
|
||||
/// \param ReductionOps List of helper expressions that represents reduction
|
||||
/// expressions:
|
||||
/// \code
|
||||
/// LHSExprs binop RHSExprs;
|
||||
/// operator binop(LHSExpr, RHSExpr);
|
||||
/// <CutomReduction>(LHSExpr, RHSExpr);
|
||||
/// \endcode
|
||||
/// Required for proper codegen of final reduction operation performed by the
|
||||
/// reduction clause.
|
||||
/// \param PreInit Statement that must be executed before entering the OpenMP
|
||||
/// region with this clause.
|
||||
/// \param PostUpdate Expression that must be executed after exit from the
|
||||
/// OpenMP region with this clause.
|
||||
///
|
||||
static OMPInReductionClause *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
|
||||
NestedNameSpecifierLoc QualifierLoc,
|
||||
const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates,
|
||||
ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
|
||||
ArrayRef<Expr *> ReductionOps, Stmt *PreInit, Expr *PostUpdate);
|
||||
|
||||
/// Creates an empty clause with the place for \a N variables.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param N The number of variables.
|
||||
///
|
||||
static OMPInReductionClause *CreateEmpty(const ASTContext &C, unsigned N);
|
||||
|
||||
/// Gets location of ':' symbol in clause.
|
||||
SourceLocation getColonLoc() const { return ColonLoc; }
|
||||
/// Gets the name info for specified reduction identifier.
|
||||
const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
|
||||
/// Gets the nested name specifier.
|
||||
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
|
||||
|
||||
typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
|
||||
typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
|
||||
typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
|
||||
typedef llvm::iterator_range<helper_expr_const_iterator>
|
||||
helper_expr_const_range;
|
||||
|
||||
helper_expr_const_range privates() const {
|
||||
return helper_expr_const_range(getPrivates().begin(), getPrivates().end());
|
||||
}
|
||||
helper_expr_range privates() {
|
||||
return helper_expr_range(getPrivates().begin(), getPrivates().end());
|
||||
}
|
||||
helper_expr_const_range lhs_exprs() const {
|
||||
return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end());
|
||||
}
|
||||
helper_expr_range lhs_exprs() {
|
||||
return helper_expr_range(getLHSExprs().begin(), getLHSExprs().end());
|
||||
}
|
||||
helper_expr_const_range rhs_exprs() const {
|
||||
return helper_expr_const_range(getRHSExprs().begin(), getRHSExprs().end());
|
||||
}
|
||||
helper_expr_range rhs_exprs() {
|
||||
return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end());
|
||||
}
|
||||
helper_expr_const_range reduction_ops() const {
|
||||
return helper_expr_const_range(getReductionOps().begin(),
|
||||
getReductionOps().end());
|
||||
}
|
||||
helper_expr_range reduction_ops() {
|
||||
return helper_expr_range(getReductionOps().begin(),
|
||||
getReductionOps().end());
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
|
||||
reinterpret_cast<Stmt **>(varlist_end()));
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == OMPC_in_reduction;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief This represents clause 'linear' in the '#pragma omp ...'
|
||||
/// directives.
|
||||
///
|
||||
|
|
|
@ -3038,6 +3038,28 @@ bool RecursiveASTVisitor<Derived>::VisitOMPTaskReductionClause(
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPInReductionClause(
|
||||
OMPInReductionClause *C) {
|
||||
TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
|
||||
TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
|
||||
TRY_TO(VisitOMPClauseList(C));
|
||||
TRY_TO(VisitOMPClauseWithPostUpdate(C));
|
||||
for (auto *E : C->privates()) {
|
||||
TRY_TO(TraverseStmt(E));
|
||||
}
|
||||
for (auto *E : C->lhs_exprs()) {
|
||||
TRY_TO(TraverseStmt(E));
|
||||
}
|
||||
for (auto *E : C->rhs_exprs()) {
|
||||
TRY_TO(TraverseStmt(E));
|
||||
}
|
||||
for (auto *E : C->reduction_ops()) {
|
||||
TRY_TO(TraverseStmt(E));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) {
|
||||
TRY_TO(VisitOMPClauseList(C));
|
||||
|
|
|
@ -8671,6 +8671,12 @@ def err_omp_reduction_in_task : Error<
|
|||
"reduction variables may not be accessed in an explicit task">;
|
||||
def err_omp_reduction_id_not_compatible : Error<
|
||||
"list item of type %0 is not valid for specified reduction operation: unable to provide default initialization value">;
|
||||
def err_omp_in_reduction_not_task_reduction : Error<
|
||||
"in_reduction variable must appear in a task_reduction clause">;
|
||||
def err_omp_reduction_identifier_mismatch : Error<
|
||||
"in_reduction variable must have the same reduction operation as in a task_reduction clause">;
|
||||
def note_omp_previous_reduction_identifier : Note<
|
||||
"previously marked as task_reduction with different reduction operation">;
|
||||
def err_omp_prohibited_region : Error<
|
||||
"region cannot be%select{| closely}0 nested inside '%1' region"
|
||||
"%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?|"
|
||||
|
|
|
@ -274,6 +274,7 @@ OPENMP_CLAUSE(from, OMPFromClause)
|
|||
OPENMP_CLAUSE(use_device_ptr, OMPUseDevicePtrClause)
|
||||
OPENMP_CLAUSE(is_device_ptr, OMPIsDevicePtrClause)
|
||||
OPENMP_CLAUSE(task_reduction, OMPTaskReductionClause)
|
||||
OPENMP_CLAUSE(in_reduction, OMPInReductionClause)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel'.
|
||||
OPENMP_PARALLEL_CLAUSE(if)
|
||||
|
@ -434,6 +435,7 @@ OPENMP_TASK_CLAUSE(untied)
|
|||
OPENMP_TASK_CLAUSE(mergeable)
|
||||
OPENMP_TASK_CLAUSE(depend)
|
||||
OPENMP_TASK_CLAUSE(priority)
|
||||
OPENMP_TASK_CLAUSE(in_reduction)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'atomic'.
|
||||
OPENMP_ATOMIC_CLAUSE(read)
|
||||
|
@ -557,6 +559,7 @@ OPENMP_TASKLOOP_CLAUSE(grainsize)
|
|||
OPENMP_TASKLOOP_CLAUSE(nogroup)
|
||||
OPENMP_TASKLOOP_CLAUSE(num_tasks)
|
||||
OPENMP_TASKLOOP_CLAUSE(reduction)
|
||||
OPENMP_TASKLOOP_CLAUSE(in_reduction)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'taskloop simd'.
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(if)
|
||||
|
@ -578,6 +581,7 @@ OPENMP_TASKLOOP_SIMD_CLAUSE(grainsize)
|
|||
OPENMP_TASKLOOP_SIMD_CLAUSE(nogroup)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(num_tasks)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(reduction)
|
||||
OPENMP_TASKLOOP_SIMD_CLAUSE(in_reduction)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'critical'.
|
||||
OPENMP_CRITICAL_CLAUSE(hint)
|
||||
|
|
|
@ -9029,6 +9029,13 @@ public:
|
|||
CXXScopeSpec &ReductionIdScopeSpec,
|
||||
const DeclarationNameInfo &ReductionId,
|
||||
ArrayRef<Expr *> UnresolvedReductions = llvm::None);
|
||||
/// Called on well-formed 'in_reduction' clause.
|
||||
OMPClause *ActOnOpenMPInReductionClause(
|
||||
ArrayRef<Expr *> VarList, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
|
||||
CXXScopeSpec &ReductionIdScopeSpec,
|
||||
const DeclarationNameInfo &ReductionId,
|
||||
ArrayRef<Expr *> UnresolvedReductions = llvm::None);
|
||||
/// \brief Called on well-formed 'linear' clause.
|
||||
OMPClause *
|
||||
ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
|
||||
|
|
|
@ -48,6 +48,8 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
|
|||
return static_cast<const OMPReductionClause *>(C);
|
||||
case OMPC_task_reduction:
|
||||
return static_cast<const OMPTaskReductionClause *>(C);
|
||||
case OMPC_in_reduction:
|
||||
return static_cast<const OMPInReductionClause *>(C);
|
||||
case OMPC_linear:
|
||||
return static_cast<const OMPLinearClause *>(C);
|
||||
case OMPC_if:
|
||||
|
@ -116,6 +118,8 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
|
|||
return static_cast<const OMPReductionClause *>(C);
|
||||
case OMPC_task_reduction:
|
||||
return static_cast<const OMPTaskReductionClause *>(C);
|
||||
case OMPC_in_reduction:
|
||||
return static_cast<const OMPInReductionClause *>(C);
|
||||
case OMPC_linear:
|
||||
return static_cast<const OMPLinearClause *>(C);
|
||||
case OMPC_schedule:
|
||||
|
@ -562,6 +566,59 @@ OMPTaskReductionClause *OMPTaskReductionClause::CreateEmpty(const ASTContext &C,
|
|||
return new (Mem) OMPTaskReductionClause(N);
|
||||
}
|
||||
|
||||
void OMPInReductionClause::setPrivates(ArrayRef<Expr *> Privates) {
|
||||
assert(Privates.size() == varlist_size() &&
|
||||
"Number of private copies is not the same as the preallocated buffer");
|
||||
std::copy(Privates.begin(), Privates.end(), varlist_end());
|
||||
}
|
||||
|
||||
void OMPInReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
|
||||
assert(
|
||||
LHSExprs.size() == varlist_size() &&
|
||||
"Number of LHS expressions is not the same as the preallocated buffer");
|
||||
std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end());
|
||||
}
|
||||
|
||||
void OMPInReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
|
||||
assert(
|
||||
RHSExprs.size() == varlist_size() &&
|
||||
"Number of RHS expressions is not the same as the preallocated buffer");
|
||||
std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end());
|
||||
}
|
||||
|
||||
void OMPInReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
|
||||
assert(ReductionOps.size() == varlist_size() && "Number of in reduction "
|
||||
"expressions is not the same "
|
||||
"as the preallocated buffer");
|
||||
std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end());
|
||||
}
|
||||
|
||||
OMPInReductionClause *OMPInReductionClause::Create(
|
||||
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
|
||||
NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
|
||||
ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
|
||||
ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, Stmt *PreInit,
|
||||
Expr *PostUpdate) {
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size()));
|
||||
OMPInReductionClause *Clause = new (Mem) OMPInReductionClause(
|
||||
StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
|
||||
Clause->setVarRefs(VL);
|
||||
Clause->setPrivates(Privates);
|
||||
Clause->setLHSExprs(LHSExprs);
|
||||
Clause->setRHSExprs(RHSExprs);
|
||||
Clause->setReductionOps(ReductionOps);
|
||||
Clause->setPreInitStmt(PreInit);
|
||||
Clause->setPostUpdateExpr(PostUpdate);
|
||||
return Clause;
|
||||
}
|
||||
|
||||
OMPInReductionClause *OMPInReductionClause::CreateEmpty(const ASTContext &C,
|
||||
unsigned N) {
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * N));
|
||||
return new (Mem) OMPInReductionClause(N);
|
||||
}
|
||||
|
||||
OMPFlushClause *OMPFlushClause::Create(const ASTContext &C,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
|
|
|
@ -859,6 +859,28 @@ void OMPClausePrinter::VisitOMPTaskReductionClause(
|
|||
}
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) {
|
||||
if (!Node->varlist_empty()) {
|
||||
OS << "in_reduction(";
|
||||
NestedNameSpecifier *QualifierLoc =
|
||||
Node->getQualifierLoc().getNestedNameSpecifier();
|
||||
OverloadedOperatorKind OOK =
|
||||
Node->getNameInfo().getName().getCXXOverloadedOperator();
|
||||
if (QualifierLoc == nullptr && OOK != OO_None) {
|
||||
// Print reduction identifier in C format
|
||||
OS << getOperatorSpelling(OOK);
|
||||
} else {
|
||||
// Use C++ format
|
||||
if (QualifierLoc != nullptr)
|
||||
QualifierLoc->print(OS, Policy);
|
||||
OS << Node->getNameInfo();
|
||||
}
|
||||
OS << ":";
|
||||
VisitOMPClauseList(Node, ' ');
|
||||
OS << ")";
|
||||
}
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) {
|
||||
if (!Node->varlist_empty()) {
|
||||
OS << "linear";
|
||||
|
|
|
@ -573,6 +573,30 @@ void OMPClauseProfiler::VisitOMPTaskReductionClause(
|
|||
Profiler->VisitStmt(E);
|
||||
}
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPInReductionClause(
|
||||
const OMPInReductionClause *C) {
|
||||
Profiler->VisitNestedNameSpecifier(
|
||||
C->getQualifierLoc().getNestedNameSpecifier());
|
||||
Profiler->VisitName(C->getNameInfo().getName());
|
||||
VisitOMPClauseList(C);
|
||||
VistOMPClauseWithPostUpdate(C);
|
||||
for (auto *E : C->privates()) {
|
||||
if (E)
|
||||
Profiler->VisitStmt(E);
|
||||
}
|
||||
for (auto *E : C->lhs_exprs()) {
|
||||
if (E)
|
||||
Profiler->VisitStmt(E);
|
||||
}
|
||||
for (auto *E : C->rhs_exprs()) {
|
||||
if (E)
|
||||
Profiler->VisitStmt(E);
|
||||
}
|
||||
for (auto *E : C->reduction_ops()) {
|
||||
if (E)
|
||||
Profiler->VisitStmt(E);
|
||||
}
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
VistOMPClauseWithPostUpdate(C);
|
||||
|
|
|
@ -139,6 +139,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
|
|||
case OMPC_shared:
|
||||
case OMPC_reduction:
|
||||
case OMPC_task_reduction:
|
||||
case OMPC_in_reduction:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
case OMPC_copyprivate:
|
||||
|
@ -279,6 +280,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
|
|||
case OMPC_shared:
|
||||
case OMPC_reduction:
|
||||
case OMPC_task_reduction:
|
||||
case OMPC_in_reduction:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
case OMPC_copyprivate:
|
||||
|
@ -851,8 +853,8 @@ bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) {
|
|||
bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) {
|
||||
return Kind == OMPC_private || Kind == OMPC_firstprivate ||
|
||||
Kind == OMPC_lastprivate || Kind == OMPC_linear ||
|
||||
Kind == OMPC_reduction ||
|
||||
Kind == OMPC_task_reduction; // TODO add next clauses like 'reduction'.
|
||||
Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
|
||||
Kind == OMPC_in_reduction; // TODO add next clauses like 'reduction'.
|
||||
}
|
||||
|
||||
bool clang::isOpenMPThreadPrivate(OpenMPClauseKind Kind) {
|
||||
|
|
|
@ -3467,6 +3467,7 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
|
|||
case OMPC_lastprivate:
|
||||
case OMPC_reduction:
|
||||
case OMPC_task_reduction:
|
||||
case OMPC_in_reduction:
|
||||
case OMPC_safelen:
|
||||
case OMPC_simdlen:
|
||||
case OMPC_collapse:
|
||||
|
|
|
@ -1102,7 +1102,8 @@ bool Parser::ParseOpenMPSimpleVarList(
|
|||
/// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
|
||||
/// thread_limit-clause | priority-clause | grainsize-clause |
|
||||
/// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
|
||||
/// from-clause | is_device_ptr-clause | task_reduction-clause
|
||||
/// from-clause | is_device_ptr-clause | task_reduction-clause |
|
||||
/// in_reduction-clause
|
||||
///
|
||||
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||
OpenMPClauseKind CKind, bool FirstClause) {
|
||||
|
@ -1221,6 +1222,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
|||
case OMPC_shared:
|
||||
case OMPC_reduction:
|
||||
case OMPC_task_reduction:
|
||||
case OMPC_in_reduction:
|
||||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
|
@ -1586,7 +1588,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
|
|||
BalancedDelimiterTracker LinearT(*this, tok::l_paren,
|
||||
tok::annot_pragma_openmp_end);
|
||||
// Handle reduction-identifier for reduction clause.
|
||||
if (Kind == OMPC_reduction || Kind == OMPC_task_reduction) {
|
||||
if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
|
||||
Kind == OMPC_in_reduction) {
|
||||
ColonProtectionRAIIObject ColonRAII(*this);
|
||||
if (getLangOpts().CPlusPlus)
|
||||
ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec,
|
||||
|
@ -1734,13 +1737,14 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
|
|||
Diag(Tok, diag::warn_pragma_expected_colon) << "map type";
|
||||
}
|
||||
|
||||
bool IsComma = (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
|
||||
Kind != OMPC_depend && Kind != OMPC_map) ||
|
||||
(Kind == OMPC_reduction && !InvalidReductionId) ||
|
||||
(Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
|
||||
(!MapTypeModifierSpecified ||
|
||||
Data.MapTypeModifier == OMPC_MAP_always)) ||
|
||||
(Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
|
||||
bool IsComma =
|
||||
(Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
|
||||
Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
|
||||
(Kind == OMPC_reduction && !InvalidReductionId) ||
|
||||
(Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown &&
|
||||
(!MapTypeModifierSpecified ||
|
||||
Data.MapTypeModifier == OMPC_MAP_always)) ||
|
||||
(Kind == OMPC_depend && Data.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))) {
|
||||
|
@ -1796,7 +1800,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
|
|||
}
|
||||
|
||||
/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
|
||||
/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction' or 'task_reduction'.
|
||||
/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
|
||||
/// 'in_reduction'.
|
||||
///
|
||||
/// private-clause:
|
||||
/// 'private' '(' list ')'
|
||||
|
@ -1814,6 +1819,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
|
|||
/// 'reduction' '(' reduction-identifier ':' list ')'
|
||||
/// task_reduction-clause:
|
||||
/// 'task_reduction' '(' reduction-identifier ':' list ')'
|
||||
/// in_reduction-clause:
|
||||
/// 'in_reduction' '(' reduction-identifier ':' list ')'
|
||||
/// copyprivate-clause:
|
||||
/// 'copyprivate' '(' list ')'
|
||||
/// flush-clause:
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/Sema/SemaInternal.h"
|
||||
#include "llvm/ADT/PointerEmbeddedInt.h"
|
||||
using namespace clang;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -84,9 +85,26 @@ private:
|
|||
CriticalsWithHintsTy;
|
||||
typedef llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>
|
||||
DoacrossDependMapTy;
|
||||
struct ReductionData {
|
||||
SourceRange ReductionRange;
|
||||
llvm::PointerUnion<const Expr *,
|
||||
llvm::PointerEmbeddedInt<BinaryOperatorKind>>
|
||||
ReductionOp;
|
||||
ReductionData() = default;
|
||||
void set(BinaryOperatorKind BO, SourceRange RR) {
|
||||
ReductionRange = RR;
|
||||
ReductionOp = BO;
|
||||
}
|
||||
void set(const Expr *RefExpr, SourceRange RR) {
|
||||
ReductionRange = RR;
|
||||
ReductionOp = RefExpr;
|
||||
}
|
||||
};
|
||||
typedef llvm::DenseMap<ValueDecl *, ReductionData> DeclReductionMapTy;
|
||||
|
||||
struct SharingMapTy final {
|
||||
DeclSAMapTy SharingMap;
|
||||
DeclReductionMapTy ReductionMap;
|
||||
AlignedMapTy AlignedMap;
|
||||
MappedExprComponentsTy MappedExprComponents;
|
||||
LoopControlVariablesMapTy LCVMap;
|
||||
|
@ -221,6 +239,21 @@ public:
|
|||
void addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
|
||||
DeclRefExpr *PrivateCopy = nullptr);
|
||||
|
||||
/// Adds additional information for the reduction items with the reduction id
|
||||
/// represented as an operator.
|
||||
void addReductionData(ValueDecl *D, SourceRange SR, BinaryOperatorKind BOK);
|
||||
/// Adds additional information for the reduction items with the reduction id
|
||||
/// represented as reduction identifier.
|
||||
void addReductionData(ValueDecl *D, SourceRange SR, const Expr *ReductionRef);
|
||||
/// Returns the location and reduction operation from the innermost parent
|
||||
/// region for the given \p D.
|
||||
bool getTopMostReductionData(ValueDecl *D, SourceRange &SR,
|
||||
BinaryOperatorKind &BOK);
|
||||
/// Returns the location and reduction operation from the innermost parent
|
||||
/// region for the given \p D.
|
||||
bool getTopMostReductionData(ValueDecl *D, SourceRange &SR,
|
||||
const Expr *&ReductionRef);
|
||||
|
||||
/// \brief Returns data sharing attributes from top of the stack for the
|
||||
/// specified declaration.
|
||||
DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
|
||||
|
@ -709,6 +742,81 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
|
|||
}
|
||||
}
|
||||
|
||||
void DSAStackTy::addReductionData(ValueDecl *D, SourceRange SR,
|
||||
BinaryOperatorKind BOK) {
|
||||
D = getCanonicalDecl(D);
|
||||
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
|
||||
auto &Data = Stack.back().first.back().SharingMap[D];
|
||||
assert(
|
||||
Data.Attributes == OMPC_reduction &&
|
||||
"Additional reduction info may be specified only for reduction items.");
|
||||
auto &ReductionData = Stack.back().first.back().ReductionMap[D];
|
||||
assert(ReductionData.ReductionRange.isInvalid() &&
|
||||
"Additional reduction info may be specified only once for reduction "
|
||||
"items.");
|
||||
ReductionData.set(BOK, SR);
|
||||
}
|
||||
|
||||
void DSAStackTy::addReductionData(ValueDecl *D, SourceRange SR,
|
||||
const Expr *ReductionRef) {
|
||||
D = getCanonicalDecl(D);
|
||||
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
|
||||
auto &Data = Stack.back().first.back().SharingMap[D];
|
||||
assert(
|
||||
Data.Attributes == OMPC_reduction &&
|
||||
"Additional reduction info may be specified only for reduction items.");
|
||||
auto &ReductionData = Stack.back().first.back().ReductionMap[D];
|
||||
assert(ReductionData.ReductionRange.isInvalid() &&
|
||||
"Additional reduction info may be specified only once for reduction "
|
||||
"items.");
|
||||
ReductionData.set(ReductionRef, SR);
|
||||
}
|
||||
|
||||
bool DSAStackTy::getTopMostReductionData(ValueDecl *D, SourceRange &SR,
|
||||
BinaryOperatorKind &BOK) {
|
||||
D = getCanonicalDecl(D);
|
||||
assert(!isStackEmpty() && Stack.back().first.size() > 1 &&
|
||||
"Data-sharing attributes stack is empty or has only 1 region.");
|
||||
for (auto I = std::next(Stack.back().first.rbegin(), 0),
|
||||
E = Stack.back().first.rend();
|
||||
I != E; std::advance(I, 1)) {
|
||||
auto &Data = I->SharingMap[D];
|
||||
if (Data.Attributes != OMPC_reduction)
|
||||
continue;
|
||||
auto &ReductionData = I->ReductionMap[D];
|
||||
if (!ReductionData.ReductionOp ||
|
||||
ReductionData.ReductionOp.is<const Expr *>())
|
||||
return false;
|
||||
SR = ReductionData.ReductionRange;
|
||||
BOK = ReductionData.ReductionOp
|
||||
.get<llvm::PointerEmbeddedInt<BinaryOperatorKind>>();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DSAStackTy::getTopMostReductionData(ValueDecl *D, SourceRange &SR,
|
||||
const Expr *&ReductionRef) {
|
||||
D = getCanonicalDecl(D);
|
||||
assert(!isStackEmpty() && Stack.back().first.size() > 1 &&
|
||||
"Data-sharing attributes stack is empty or has only 1 region.");
|
||||
for (auto I = std::next(Stack.back().first.rbegin(), 0),
|
||||
E = Stack.back().first.rend();
|
||||
I != E; std::advance(I, 1)) {
|
||||
auto &Data = I->SharingMap[D];
|
||||
if (Data.Attributes != OMPC_reduction)
|
||||
continue;
|
||||
auto &ReductionData = I->ReductionMap[D];
|
||||
if (!ReductionData.ReductionOp ||
|
||||
!ReductionData.ReductionOp.is<const Expr *>())
|
||||
return false;
|
||||
SR = ReductionData.ReductionRange;
|
||||
ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
|
||||
D = D->getCanonicalDecl();
|
||||
if (!isStackEmpty() && Stack.back().first.size() > 1) {
|
||||
|
@ -6853,6 +6961,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
|
|||
case OMPC_shared:
|
||||
case OMPC_reduction:
|
||||
case OMPC_task_reduction:
|
||||
case OMPC_in_reduction:
|
||||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
|
@ -7157,6 +7266,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
|
|||
case OMPC_lastprivate:
|
||||
case OMPC_reduction:
|
||||
case OMPC_task_reduction:
|
||||
case OMPC_in_reduction:
|
||||
case OMPC_linear:
|
||||
case OMPC_default:
|
||||
case OMPC_proc_bind:
|
||||
|
@ -7473,6 +7583,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
|
|||
case OMPC_shared:
|
||||
case OMPC_reduction:
|
||||
case OMPC_task_reduction:
|
||||
case OMPC_in_reduction:
|
||||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
|
@ -7631,6 +7742,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
|
|||
case OMPC_shared:
|
||||
case OMPC_reduction:
|
||||
case OMPC_task_reduction:
|
||||
case OMPC_in_reduction:
|
||||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
|
@ -7829,6 +7941,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
|
|||
case OMPC_shared:
|
||||
case OMPC_reduction:
|
||||
case OMPC_task_reduction:
|
||||
case OMPC_in_reduction:
|
||||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
|
@ -7946,6 +8059,11 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
|
|||
EndLoc, ReductionIdScopeSpec,
|
||||
ReductionId);
|
||||
break;
|
||||
case OMPC_in_reduction:
|
||||
Res =
|
||||
ActOnOpenMPInReductionClause(VarList, StartLoc, LParenLoc, ColonLoc,
|
||||
EndLoc, ReductionIdScopeSpec, ReductionId);
|
||||
break;
|
||||
case OMPC_linear:
|
||||
Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc,
|
||||
LinKind, DepLinMapLoc, ColonLoc, EndLoc);
|
||||
|
@ -9428,6 +9546,51 @@ static bool ActOnOMPReductionKindClause(
|
|||
continue;
|
||||
}
|
||||
|
||||
// OpenMP [2.15.4.6, Restrictions, p.2]
|
||||
// A list item that appears in an in_reduction clause of a task construct
|
||||
// must appear in a task_reduction clause of a construct associated with a
|
||||
// taskgroup region that includes the participating task in its taskgroup
|
||||
// set. The construct associated with the innermost region that meets this
|
||||
// condition must specify the same reduction-identifier as the in_reduction
|
||||
// clause.
|
||||
if (ClauseKind == OMPC_in_reduction) {
|
||||
DVar = Stack->hasDSA(
|
||||
D, [](OpenMPClauseKind K) { return K != OMPC_unknown; },
|
||||
[](OpenMPDirectiveKind K) { return K == OMPD_taskgroup; },
|
||||
/*FromParent=*/true);
|
||||
if (DVar.CKind != OMPC_reduction || DVar.DKind != OMPD_taskgroup) {
|
||||
S.Diag(ELoc, diag::err_omp_in_reduction_not_task_reduction);
|
||||
continue;
|
||||
}
|
||||
SourceRange ParentSR;
|
||||
BinaryOperatorKind ParentBOK;
|
||||
const Expr *ParentReductionOp;
|
||||
bool IsParentBOK = Stack->getTopMostReductionData(D, ParentSR, ParentBOK);
|
||||
bool IsParentReductionOp =
|
||||
Stack->getTopMostReductionData(D, ParentSR, ParentReductionOp);
|
||||
if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
|
||||
(DeclareReductionRef.isUsable() && IsParentBOK) || BOK != ParentBOK ||
|
||||
IsParentReductionOp) {
|
||||
bool EmitError = true;
|
||||
if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
|
||||
llvm::FoldingSetNodeID RedId, ParentRedId;
|
||||
ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
|
||||
DeclareReductionRef.get()->Profile(RedId, Context,
|
||||
/*Canonical=*/true);
|
||||
EmitError = RedId != ParentRedId;
|
||||
}
|
||||
if (EmitError) {
|
||||
S.Diag(ReductionId.getLocStart(),
|
||||
diag::err_omp_reduction_identifier_mismatch)
|
||||
<< ReductionIdRange << RefExpr->getSourceRange();
|
||||
S.Diag(ParentSR.getBegin(),
|
||||
diag::note_omp_previous_reduction_identifier)
|
||||
<< ParentSR << DVar.RefExpr->getSourceRange();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeclRefExpr *Ref = nullptr;
|
||||
Expr *VarsExpr = RefExpr->IgnoreParens();
|
||||
if (!VD && !S.CurContext->isDependentContext()) {
|
||||
|
@ -9465,6 +9628,10 @@ static bool ActOnOMPReductionKindClause(
|
|||
// All reduction items are still marked as reduction (to do not increase
|
||||
// code base size).
|
||||
Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref);
|
||||
if (DeclareReductionRef.isUsable())
|
||||
Stack->addReductionData(D, ReductionIdRange, DeclareReductionRef.get());
|
||||
else
|
||||
Stack->addReductionData(D, ReductionIdRange, BOK);
|
||||
RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get());
|
||||
}
|
||||
return RD.Vars.empty();
|
||||
|
@ -9512,6 +9679,27 @@ OMPClause *Sema::ActOnOpenMPTaskReductionClause(
|
|||
buildPostUpdate(*this, RD.ExprPostUpdates));
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPInReductionClause(
|
||||
ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation ColonLoc, SourceLocation EndLoc,
|
||||
CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
|
||||
ArrayRef<Expr *> UnresolvedReductions) {
|
||||
ReductionData RD(VarList.size());
|
||||
|
||||
if (ActOnOMPReductionKindClause(*this, DSAStack, OMPC_in_reduction, VarList,
|
||||
StartLoc, LParenLoc, ColonLoc, EndLoc,
|
||||
ReductionIdScopeSpec, ReductionId,
|
||||
UnresolvedReductions, RD))
|
||||
return nullptr;
|
||||
|
||||
return OMPInReductionClause::Create(
|
||||
Context, StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
|
||||
ReductionIdScopeSpec.getWithLocInContext(Context), ReductionId,
|
||||
RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
|
||||
buildPreInits(Context, RD.ExprCaptures),
|
||||
buildPostUpdate(*this, RD.ExprPostUpdates));
|
||||
}
|
||||
|
||||
bool Sema::CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
|
||||
SourceLocation LinLoc) {
|
||||
if ((!LangOpts.CPlusPlus && LinKind != OMPC_LINEAR_val) ||
|
||||
|
|
|
@ -1666,6 +1666,22 @@ public:
|
|||
ReductionId, UnresolvedReductions);
|
||||
}
|
||||
|
||||
/// Build a new OpenMP 'in_reduction' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OMPClause *
|
||||
RebuildOMPInReductionClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation ColonLoc,
|
||||
SourceLocation EndLoc,
|
||||
CXXScopeSpec &ReductionIdScopeSpec,
|
||||
const DeclarationNameInfo &ReductionId,
|
||||
ArrayRef<Expr *> UnresolvedReductions) {
|
||||
return getSema().ActOnOpenMPInReductionClause(
|
||||
VarList, StartLoc, LParenLoc, ColonLoc, EndLoc, ReductionIdScopeSpec,
|
||||
ReductionId, UnresolvedReductions);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'linear' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new OpenMP clause.
|
||||
|
@ -8459,6 +8475,51 @@ OMPClause *TreeTransform<Derived>::TransformOMPTaskReductionClause(
|
|||
C->getLocEnd(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions);
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPInReductionClause(OMPInReductionClause *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());
|
||||
}
|
||||
CXXScopeSpec ReductionIdScopeSpec;
|
||||
ReductionIdScopeSpec.Adopt(C->getQualifierLoc());
|
||||
|
||||
DeclarationNameInfo NameInfo = C->getNameInfo();
|
||||
if (NameInfo.getName()) {
|
||||
NameInfo = getDerived().TransformDeclarationNameInfo(NameInfo);
|
||||
if (!NameInfo.getName())
|
||||
return nullptr;
|
||||
}
|
||||
// Build a list of all UDR decls with the same names ranged by the Scopes.
|
||||
// The Scope boundary is a duplication of the previous decl.
|
||||
llvm::SmallVector<Expr *, 16> UnresolvedReductions;
|
||||
for (auto *E : C->reduction_ops()) {
|
||||
// Transform all the decls.
|
||||
if (E) {
|
||||
auto *ULE = cast<UnresolvedLookupExpr>(E);
|
||||
UnresolvedSet<8> Decls;
|
||||
for (auto *D : ULE->decls()) {
|
||||
NamedDecl *InstD =
|
||||
cast<NamedDecl>(getDerived().TransformDecl(E->getExprLoc(), D));
|
||||
Decls.addDecl(InstD, InstD->getAccess());
|
||||
}
|
||||
UnresolvedReductions.push_back(UnresolvedLookupExpr::Create(
|
||||
SemaRef.Context, /*NamingClass=*/nullptr,
|
||||
ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo,
|
||||
/*ADL=*/true, ULE->isOverloaded(), Decls.begin(), Decls.end()));
|
||||
} else
|
||||
UnresolvedReductions.push_back(nullptr);
|
||||
}
|
||||
return getDerived().RebuildOMPInReductionClause(
|
||||
Vars, C->getLocStart(), C->getLParenLoc(), C->getColonLoc(),
|
||||
C->getLocEnd(), ReductionIdScopeSpec, NameInfo, UnresolvedReductions);
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *C) {
|
||||
|
|
|
@ -1837,6 +1837,9 @@ OMPClause *OMPClauseReader::readClause() {
|
|||
case OMPC_task_reduction:
|
||||
C = OMPTaskReductionClause::CreateEmpty(Context, Reader->Record.readInt());
|
||||
break;
|
||||
case OMPC_in_reduction:
|
||||
C = OMPInReductionClause::CreateEmpty(Context, Reader->Record.readInt());
|
||||
break;
|
||||
case OMPC_linear:
|
||||
C = OMPLinearClause::CreateEmpty(Context, Reader->Record.readInt());
|
||||
break;
|
||||
|
@ -2175,6 +2178,40 @@ void OMPClauseReader::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {
|
|||
C->setReductionOps(Vars);
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPInReductionClause(OMPInReductionClause *C) {
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
C->setLParenLoc(Reader->ReadSourceLocation());
|
||||
C->setColonLoc(Reader->ReadSourceLocation());
|
||||
NestedNameSpecifierLoc NNSL = Reader->Record.readNestedNameSpecifierLoc();
|
||||
DeclarationNameInfo DNI;
|
||||
Reader->ReadDeclarationNameInfo(DNI);
|
||||
C->setQualifierLoc(NNSL);
|
||||
C->setNameInfo(DNI);
|
||||
|
||||
unsigned NumVars = C->varlist_size();
|
||||
SmallVector<Expr *, 16> Vars;
|
||||
Vars.reserve(NumVars);
|
||||
for (unsigned I = 0; I != NumVars; ++I)
|
||||
Vars.push_back(Reader->Record.readSubExpr());
|
||||
C->setVarRefs(Vars);
|
||||
Vars.clear();
|
||||
for (unsigned I = 0; I != NumVars; ++I)
|
||||
Vars.push_back(Reader->Record.readSubExpr());
|
||||
C->setPrivates(Vars);
|
||||
Vars.clear();
|
||||
for (unsigned I = 0; I != NumVars; ++I)
|
||||
Vars.push_back(Reader->Record.readSubExpr());
|
||||
C->setLHSExprs(Vars);
|
||||
Vars.clear();
|
||||
for (unsigned I = 0; I != NumVars; ++I)
|
||||
Vars.push_back(Reader->Record.readSubExpr());
|
||||
C->setRHSExprs(Vars);
|
||||
Vars.clear();
|
||||
for (unsigned I = 0; I != NumVars; ++I)
|
||||
Vars.push_back(Reader->Record.readSubExpr());
|
||||
C->setReductionOps(Vars);
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
C->setLParenLoc(Reader->ReadSourceLocation());
|
||||
|
|
|
@ -1982,6 +1982,25 @@ void OMPClauseWriter::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {
|
|||
Record.AddStmt(E);
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPInReductionClause(OMPInReductionClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
Record.AddSourceLocation(C->getLParenLoc());
|
||||
Record.AddSourceLocation(C->getColonLoc());
|
||||
Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());
|
||||
Record.AddDeclarationNameInfo(C->getNameInfo());
|
||||
for (auto *VE : C->varlists())
|
||||
Record.AddStmt(VE);
|
||||
for (auto *VE : C->privates())
|
||||
Record.AddStmt(VE);
|
||||
for (auto *E : C->lhs_exprs())
|
||||
Record.AddStmt(E);
|
||||
for (auto *E : C->rhs_exprs())
|
||||
Record.AddStmt(E);
|
||||
for (auto *E : C->reduction_ops())
|
||||
Record.AddStmt(E);
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
|
|
|
@ -13,17 +13,19 @@ struct S1 {
|
|||
S1(int v) : a(v) {}
|
||||
int a;
|
||||
typedef int type;
|
||||
S1 operator +(const S1&);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class S7 : public T {
|
||||
protected:
|
||||
T a;
|
||||
T a, b;
|
||||
S7() : a(0) {}
|
||||
|
||||
public:
|
||||
S7(typename T::type v) : a(v) {
|
||||
#pragma omp task private(a) private(this->a) private(T::a)
|
||||
#pragma omp taskgroup task_reduction(+:b)
|
||||
#pragma omp task private(a) private(this->a) private(T::a) in_reduction(+:this->b)
|
||||
for (int k = 0; k < a.a; ++k)
|
||||
++this->a.a;
|
||||
}
|
||||
|
@ -35,7 +37,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// CHECK: #pragma omp task private(this->a) private(this->a) private(T::a)
|
||||
// CHECK: #pragma omp taskgroup task_reduction(+: this->b)
|
||||
// CHECK: #pragma omp task private(this->a) private(this->a) private(T::a) in_reduction(+: this->b)
|
||||
// CHECK: #pragma omp task private(this->a) private(this->a)
|
||||
// CHECK: #pragma omp task private(this->a) private(this->a) private(this->S1::a)
|
||||
|
||||
|
@ -89,7 +92,8 @@ T tmain(T argc, T *argv) {
|
|||
a = 2;
|
||||
#pragma omp task default(none), private(argc, b) firstprivate(argv) shared(d) if (argc > 0) final(S<T>::TS > 0) priority(argc)
|
||||
foo();
|
||||
#pragma omp task if (C) mergeable priority(C)
|
||||
#pragma omp taskgroup task_reduction(-: argc)
|
||||
#pragma omp task if (C) mergeable priority(C) in_reduction(-: argc)
|
||||
foo();
|
||||
return 0;
|
||||
}
|
||||
|
@ -103,7 +107,8 @@ T tmain(T argc, T *argv) {
|
|||
// 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) priority(argc)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK-NEXT: #pragma omp task if(C) mergeable priority(C)
|
||||
// CHECK-NEXT: #pragma omp taskgroup task_reduction(-: argc)
|
||||
// CHECK-NEXT: #pragma omp task if(C) mergeable priority(C) in_reduction(-: argc)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
|
||||
// CHECK-NEXT: int b = argc, c, d, e, f, g;
|
||||
|
@ -114,7 +119,8 @@ T tmain(T argc, T *argv) {
|
|||
// 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) priority(argc)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK-NEXT: #pragma omp task if(5) mergeable priority(5)
|
||||
// CHECK-NEXT: #pragma omp taskgroup task_reduction(-: argc)
|
||||
// CHECK-NEXT: #pragma omp task if(5) mergeable priority(5) in_reduction(-: argc)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK: template<> long tmain<long, 1>(long argc, long *argv) {
|
||||
// CHECK-NEXT: long b = argc, c, d, e, f, g;
|
||||
|
@ -125,7 +131,8 @@ T tmain(T argc, T *argv) {
|
|||
// 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) priority(argc)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK-NEXT: #pragma omp task if(1) mergeable priority(1)
|
||||
// CHECK-NEXT: #pragma omp taskgroup task_reduction(-: argc)
|
||||
// CHECK-NEXT: #pragma omp task if(1) mergeable priority(1) in_reduction(-: argc)
|
||||
// CHECK-NEXT: foo()
|
||||
|
||||
enum Enum {};
|
||||
|
@ -134,7 +141,7 @@ int main(int argc, char **argv) {
|
|||
long x;
|
||||
int b = argc, c, d, e, f, g;
|
||||
static int a;
|
||||
int arr[10];
|
||||
int arr[10], arr1[argc];
|
||||
#pragma omp threadprivate(a)
|
||||
Enum ee;
|
||||
// CHECK: Enum ee;
|
||||
|
@ -142,8 +149,10 @@ int main(int argc, char **argv) {
|
|||
// CHECK-NEXT: #pragma omp task untied mergeable depend(out : argv[:a][1],(arr)[0:]) if(task: argc > 0) priority(f)
|
||||
a = 2;
|
||||
// CHECK-NEXT: a = 2;
|
||||
#pragma omp task default(none), private(argc, b) firstprivate(argv) if (argc > 0) final(a > 0) depend(inout : a, argv[:argc],arr[:a]) priority(23)
|
||||
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) if(argc > 0) final(a > 0) depend(inout : a,argv[:argc],arr[:a]) priority(23)
|
||||
#pragma omp taskgroup task_reduction(min: arr1)
|
||||
#pragma omp task default(none), private(argc, b) firstprivate(argv) if (argc > 0) final(a > 0) depend(inout : a, argv[:argc],arr[:a]) priority(23) in_reduction(min: arr1)
|
||||
// CHECK-NEXT: #pragma omp taskgroup task_reduction(min: arr1)
|
||||
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) if(argc > 0) final(a > 0) depend(inout : a,argv[:argc],arr[:a]) priority(23) in_reduction(min: arr1)
|
||||
foo();
|
||||
// CHECK-NEXT: foo();
|
||||
return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
|
||||
|
|
|
@ -0,0 +1,308 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
||||
bool foobool(int argc) {
|
||||
return argc;
|
||||
}
|
||||
|
||||
void foobar(int &ref) {
|
||||
#pragma omp taskgroup task_reduction(+:ref)
|
||||
#pragma omp task in_reduction(+:ref)
|
||||
foo();
|
||||
}
|
||||
|
||||
void foobar1(int &ref) {
|
||||
#pragma omp taskgroup task_reduction(+:ref)
|
||||
#pragma omp task in_reduction(-:ref)
|
||||
foo();
|
||||
}
|
||||
|
||||
#pragma omp declare reduction (red:int:omp_out += omp_in)
|
||||
|
||||
void foobar2(int &ref) {
|
||||
#pragma omp taskgroup task_reduction(+:ref) // expected-note {{previously marked as task_reduction with different reduction operation}}
|
||||
#pragma omp task in_reduction(red:ref) // expected-error{{in_reduction variable must have the same reduction operation as in a task_reduction clause}}
|
||||
foo();
|
||||
}
|
||||
|
||||
void foobar3(int &ref) {
|
||||
#pragma omp taskgroup task_reduction(red:ref) // expected-note {{previously marked as task_reduction with different reduction operation}}
|
||||
#pragma omp task in_reduction(min:ref) // expected-error{{in_reduction variable must have the same reduction operation as in a task_reduction clause}}
|
||||
foo();
|
||||
}
|
||||
|
||||
void foobar4(int &ref) {
|
||||
#pragma omp task in_reduction(min:ref) // expected-error {{in_reduction variable must appear in a task_reduction clause}}
|
||||
foo();
|
||||
}
|
||||
|
||||
struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}}
|
||||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
S2(S2 &s2) : a(s2.a) {}
|
||||
static float S2s; // expected-note 2 {{static data member is predetermined as shared}}
|
||||
static const float S2sc; // expected-note 2 {{'S2sc' declared here}}
|
||||
};
|
||||
const float S2::S2sc = 0;
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
||||
public:
|
||||
int b;
|
||||
S3() : a(0) {}
|
||||
S3(const S3 &s3) : a(s3.a) {}
|
||||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
int a;
|
||||
S4(); // expected-note {{implicitly declared private here}}
|
||||
S4(const S4 &s4);
|
||||
S4 &operator+(const S4 &arg) { return (*this); }
|
||||
|
||||
public:
|
||||
S4(int v) : a(v) {}
|
||||
};
|
||||
S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; }
|
||||
class S5 {
|
||||
int a;
|
||||
S5() : a(0) {} // expected-note {{implicitly declared private here}}
|
||||
S5(const S5 &s5) : a(s5.a) {}
|
||||
S5 &operator+(const S5 &arg);
|
||||
|
||||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
public:
|
||||
S6() : a(6) {}
|
||||
operator int() { return 6; }
|
||||
} o;
|
||||
|
||||
S3 h, k;
|
||||
#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
|
||||
|
||||
template <class T> // expected-note {{declared here}}
|
||||
T tmain(T argc) {
|
||||
const T d = T(); // expected-note 4 {{'d' defined here}}
|
||||
const T da[5] = {T()}; // expected-note 2 {{'da' defined here}}
|
||||
T qa[5] = {T()};
|
||||
T i;
|
||||
T &j = i; // expected-note 2 {{'j' defined here}}
|
||||
S3 &p = k; // expected-note 2 {{'p' defined here}}
|
||||
const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}}
|
||||
T &q = qa[(int)i];
|
||||
T fl;
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp task in_reduction // expected-error {{expected '(' after 'in_reduction'}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp task in_reduction + // expected-error {{expected '(' after 'in_reduction'}} expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp task in_reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp task in_reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp task in_reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp task in_reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp task in_reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(&:argc) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
#pragma omp task in_reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(|:argc) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
#pragma omp task in_reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(&&:argc)
|
||||
#pragma omp task in_reduction(&& : argc)
|
||||
foo();
|
||||
#pragma omp task in_reduction(^ : T) // expected-error {{'T' does not refer to a value}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:c)
|
||||
#pragma omp task in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-error 2 {{in_reduction variable must appear in a task_reduction clause}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:k)
|
||||
#pragma omp task in_reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
foo();
|
||||
#pragma omp parallel private(k)
|
||||
#pragma omp task in_reduction(+ : p), in_reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'in_reduction' must reference the same object in all threads}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:p)
|
||||
#pragma omp task in_reduction(+ : p), in_reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'in_reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp parallel shared(i)
|
||||
#pragma omp parallel reduction(min : i)
|
||||
#pragma omp task in_reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'in_reduction' must reference the same object in all threads}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:fl)
|
||||
#pragma omp task in_reduction(+ : fl)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(- : fl)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
#pragma omp taskgroup task_reduction(+:fl)
|
||||
#pragma omp task in_reduction(+ : fl)
|
||||
foo();
|
||||
|
||||
return T();
|
||||
}
|
||||
|
||||
namespace A {
|
||||
double x;
|
||||
#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
|
||||
}
|
||||
namespace B {
|
||||
using A::x;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const int d = 5; // expected-note 2 {{'d' defined here}}
|
||||
const int da[5] = {0}; // expected-note {{'da' defined here}}
|
||||
int qa[5] = {0};
|
||||
S4 e(4);
|
||||
S5 g(5);
|
||||
int i;
|
||||
int &j = i; // expected-note {{'j' defined here}}
|
||||
S3 &p = k; // expected-note 2 {{'p' defined here}}
|
||||
const int &r = da[i]; // expected-note {{'r' defined here}}
|
||||
int &q = qa[i];
|
||||
float fl;
|
||||
#pragma omp task in_reduction // expected-error {{expected '(' after 'in_reduction'}}
|
||||
foo();
|
||||
#pragma omp task in_reduction + // expected-error {{expected '(' after 'in_reduction'}} expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
|
||||
foo();
|
||||
#pragma omp task in_reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
foo();
|
||||
#pragma omp task in_reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(foo : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(|:argc)
|
||||
{
|
||||
#pragma omp taskgroup task_reduction(+:argc) // expected-note {{previously marked as task_reduction with different reduction operation}}
|
||||
{
|
||||
#pragma omp task in_reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{in_reduction variable must have the same reduction operation as in a task_reduction clause}}
|
||||
foo();
|
||||
}
|
||||
#pragma omp task in_reduction(| : argc)
|
||||
foo();
|
||||
}
|
||||
#pragma omp task in_reduction(|| : argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name, array element or array section}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(~ : argc) // expected-error {{expected unqualified-id}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(&&:argc)
|
||||
#pragma omp task in_reduction(&& : argc)
|
||||
foo();
|
||||
#pragma omp task in_reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:c)
|
||||
#pragma omp task in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{nvalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:k)
|
||||
#pragma omp task in_reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
foo();
|
||||
#pragma omp parallel private(k)
|
||||
#pragma omp task in_reduction(+ : p), in_reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'in_reduction' must reference the same object in all threads}}
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:p)
|
||||
#pragma omp task in_reduction(+ : p), in_reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'in_reduction' clause}} expected-note {{previously referenced here}}
|
||||
foo();
|
||||
#pragma omp task in_reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
foo();
|
||||
#pragma omp parallel shared(i)
|
||||
#pragma omp parallel reduction(min : i)
|
||||
#pragma omp task in_reduction(max : j) // expected-error {{argument of OpenMP clause 'in_reduction' must reference the same object in all threads}}
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for private(fl)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
#pragma omp taskgroup task_reduction(+:fl)
|
||||
#pragma omp task in_reduction(+ : fl)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:fl)
|
||||
#pragma omp task in_reduction(+ : fl)
|
||||
foo();
|
||||
static int m;
|
||||
#pragma omp taskgroup task_reduction(+:m)
|
||||
#pragma omp task in_reduction(+ : m) // OK
|
||||
m++;
|
||||
|
||||
return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
|
||||
}
|
|
@ -0,0 +1,376 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
||||
bool foobool(int argc) {
|
||||
return argc;
|
||||
}
|
||||
|
||||
void foobar(int &ref) {
|
||||
#pragma omp taskgroup task_reduction(+:ref)
|
||||
#pragma omp taskloop in_reduction(+:ref)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
}
|
||||
|
||||
void foobar1(int &ref) {
|
||||
#pragma omp taskgroup task_reduction(+:ref)
|
||||
#pragma omp taskloop in_reduction(-:ref)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
}
|
||||
|
||||
#pragma omp declare reduction (red:int:omp_out += omp_in)
|
||||
|
||||
void foobar2(int &ref) {
|
||||
#pragma omp taskgroup task_reduction(+:ref) // expected-note {{previously marked as task_reduction with different reduction operation}}
|
||||
#pragma omp taskloop in_reduction(red:ref) // expected-error{{in_reduction variable must have the same reduction operation as in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
}
|
||||
|
||||
void foobar3(int &ref) {
|
||||
#pragma omp taskgroup task_reduction(red:ref) // expected-note {{previously marked as task_reduction with different reduction operation}}
|
||||
#pragma omp taskloop in_reduction(min:ref) // expected-error{{in_reduction variable must have the same reduction operation as in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
}
|
||||
|
||||
void foobar4(int &ref) {
|
||||
#pragma omp taskloop in_reduction(min:ref) // expected-error {{in_reduction variable must appear in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
}
|
||||
|
||||
struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}}
|
||||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
S2(S2 &s2) : a(s2.a) {}
|
||||
static float S2s; // expected-note 2 {{static data member is predetermined as shared}}
|
||||
static const float S2sc; // expected-note 2 {{'S2sc' declared here}}
|
||||
};
|
||||
const float S2::S2sc = 0;
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
||||
public:
|
||||
int b;
|
||||
S3() : a(0) {}
|
||||
S3(const S3 &s3) : a(s3.a) {}
|
||||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
int a;
|
||||
S4(); // expected-note {{implicitly declared private here}}
|
||||
S4(const S4 &s4);
|
||||
S4 &operator+(const S4 &arg) { return (*this); }
|
||||
|
||||
public:
|
||||
S4(int v) : a(v) {}
|
||||
};
|
||||
S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; }
|
||||
class S5 {
|
||||
int a;
|
||||
S5() : a(0) {} // expected-note {{implicitly declared private here}}
|
||||
S5(const S5 &s5) : a(s5.a) {}
|
||||
S5 &operator+(const S5 &arg);
|
||||
|
||||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
public:
|
||||
S6() : a(6) {}
|
||||
operator int() { return 6; }
|
||||
} o;
|
||||
|
||||
S3 h, k;
|
||||
#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
|
||||
|
||||
template <class T> // expected-note {{declared here}}
|
||||
T tmain(T argc) {
|
||||
const T d = T(); // expected-note 4 {{'d' defined here}}
|
||||
const T da[5] = {T()}; // expected-note 2 {{'da' defined here}}
|
||||
T qa[5] = {T()};
|
||||
T i;
|
||||
T &j = i; // expected-note 2 {{'j' defined here}}
|
||||
S3 &p = k; // expected-note 2 {{'p' defined here}}
|
||||
const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}}
|
||||
T &q = qa[(int)i];
|
||||
T fl;
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop in_reduction // expected-error {{expected '(' after 'in_reduction'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop in_reduction + // expected-error {{expected '(' after 'in_reduction'}} expected-warning {{extra tokens at the end of '#pragma omp taskloop' are ignored}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop in_reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop in_reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop in_reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop in_reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop in_reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(&:argc) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
#pragma omp taskloop in_reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(|:argc) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
#pragma omp taskloop in_reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(&&:argc)
|
||||
#pragma omp taskloop in_reduction(&& : argc)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(^ : T) // expected-error {{'T' does not refer to a value}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:c)
|
||||
#pragma omp taskloop in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-error 2 {{in_reduction variable must appear in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:k)
|
||||
#pragma omp taskloop in_reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel private(k)
|
||||
#pragma omp taskloop in_reduction(+ : p), in_reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'in_reduction' must reference the same object in all threads}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:p)
|
||||
#pragma omp taskloop in_reduction(+ : p), in_reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'in_reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel shared(i)
|
||||
#pragma omp parallel reduction(min : i)
|
||||
#pragma omp taskloop in_reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'in_reduction' must reference the same object in all threads}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:fl)
|
||||
{
|
||||
#pragma omp taskloop in_reduction(+ : fl)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(*:fl) // expected-note 2 {{previously marked as task_reduction with different reduction operation}}
|
||||
{
|
||||
#pragma omp taskloop in_reduction(+ : fl) // expected-error 2 {{in_reduction variable must have the same reduction operation as in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
}
|
||||
}
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(- : fl)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
#pragma omp taskgroup task_reduction(+:fl)
|
||||
#pragma omp taskloop in_reduction(+ : fl)
|
||||
for (int j = 0; j < 10; ++j)
|
||||
foo();
|
||||
|
||||
return T();
|
||||
}
|
||||
|
||||
namespace A {
|
||||
double x;
|
||||
#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
|
||||
}
|
||||
namespace B {
|
||||
using A::x;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const int d = 5; // expected-note 2 {{'d' defined here}}
|
||||
const int da[5] = {0}; // expected-note {{'da' defined here}}
|
||||
int qa[5] = {0};
|
||||
S4 e(4);
|
||||
S5 g(5);
|
||||
int i;
|
||||
int &j = i; // expected-note {{'j' defined here}}
|
||||
S3 &p = k; // expected-note 2 {{'p' defined here}}
|
||||
const int &r = da[i]; // expected-note {{'r' defined here}}
|
||||
int &q = qa[i];
|
||||
float fl;
|
||||
#pragma omp taskloop in_reduction // expected-error {{expected '(' after 'in_reduction'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction + // expected-error {{expected '(' after 'in_reduction'}} expected-warning {{extra tokens at the end of '#pragma omp taskloop' are ignored}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(foo : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(|:argc)
|
||||
#pragma omp taskloop in_reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(|| : argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name, array element or array section}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(~ : argc) // expected-error {{expected unqualified-id}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(&&:argc)
|
||||
#pragma omp taskloop in_reduction(&& : argc)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:c)
|
||||
#pragma omp taskloop in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{nvalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:k)
|
||||
#pragma omp taskloop in_reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel private(k)
|
||||
#pragma omp taskloop in_reduction(+ : p), in_reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'in_reduction' must reference the same object in all threads}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:p)
|
||||
#pragma omp taskloop in_reduction(+ : p), in_reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'in_reduction' clause}} expected-note {{previously referenced here}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop in_reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel shared(i)
|
||||
#pragma omp parallel reduction(min : i)
|
||||
#pragma omp taskloop in_reduction(max : j) // expected-error {{argument of OpenMP clause 'in_reduction' must reference the same object in all threads}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for private(fl)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
#pragma omp taskgroup task_reduction(+:fl)
|
||||
#pragma omp taskloop in_reduction(+ : fl)
|
||||
for (int j = 0; j < 10; ++j)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:fl)
|
||||
#pragma omp taskloop in_reduction(+ : fl)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
static int m;
|
||||
#pragma omp taskgroup task_reduction(+:m)
|
||||
#pragma omp taskloop in_reduction(+ : m) // OK
|
||||
for (int i = 0; i < 10; ++i)
|
||||
m++;
|
||||
|
||||
return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
|
||||
}
|
|
@ -0,0 +1,376 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s
|
||||
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
||||
bool foobool(int argc) {
|
||||
return argc;
|
||||
}
|
||||
|
||||
void foobar(int &ref) {
|
||||
#pragma omp taskgroup task_reduction(+:ref)
|
||||
#pragma omp taskloop simd in_reduction(+:ref)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
}
|
||||
|
||||
void foobar1(int &ref) {
|
||||
#pragma omp taskgroup task_reduction(+:ref)
|
||||
#pragma omp taskloop simd in_reduction(-:ref)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
}
|
||||
|
||||
#pragma omp declare reduction (red:int:omp_out += omp_in)
|
||||
|
||||
void foobar2(int &ref) {
|
||||
#pragma omp taskgroup task_reduction(+:ref) // expected-note {{previously marked as task_reduction with different reduction operation}}
|
||||
#pragma omp taskloop simd in_reduction(red:ref) // expected-error{{in_reduction variable must have the same reduction operation as in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
}
|
||||
|
||||
void foobar3(int &ref) {
|
||||
#pragma omp taskgroup task_reduction(red:ref) // expected-note {{previously marked as task_reduction with different reduction operation}}
|
||||
#pragma omp taskloop simd in_reduction(min:ref) // expected-error{{in_reduction variable must have the same reduction operation as in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
}
|
||||
|
||||
void foobar4(int &ref) {
|
||||
#pragma omp taskloop simd in_reduction(min:ref) // expected-error {{in_reduction variable must appear in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
}
|
||||
|
||||
struct S1; // expected-note {{declared here}} expected-note 4 {{forward declaration of 'S1'}}
|
||||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
S2 &operator+(const S2 &arg) { return (*this); } // expected-note 3 {{implicitly declared private here}}
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
S2(S2 &s2) : a(s2.a) {}
|
||||
static float S2s; // expected-note 2 {{static data member is predetermined as shared}}
|
||||
static const float S2sc; // expected-note 2 {{'S2sc' declared here}}
|
||||
};
|
||||
const float S2::S2sc = 0;
|
||||
S2 b; // expected-note 3 {{'b' defined here}}
|
||||
const S2 ba[5]; // expected-note 2 {{'ba' defined here}}
|
||||
class S3 {
|
||||
int a;
|
||||
|
||||
public:
|
||||
int b;
|
||||
S3() : a(0) {}
|
||||
S3(const S3 &s3) : a(s3.a) {}
|
||||
S3 operator+(const S3 &arg1) { return arg1; }
|
||||
};
|
||||
int operator+(const S3 &arg1, const S3 &arg2) { return 5; }
|
||||
S3 c; // expected-note 3 {{'c' defined here}}
|
||||
const S3 ca[5]; // expected-note 2 {{'ca' defined here}}
|
||||
extern const int f; // expected-note 4 {{'f' declared here}}
|
||||
class S4 {
|
||||
int a;
|
||||
S4(); // expected-note {{implicitly declared private here}}
|
||||
S4(const S4 &s4);
|
||||
S4 &operator+(const S4 &arg) { return (*this); }
|
||||
|
||||
public:
|
||||
S4(int v) : a(v) {}
|
||||
};
|
||||
S4 &operator&=(S4 &arg1, S4 &arg2) { return arg1; }
|
||||
class S5 {
|
||||
int a;
|
||||
S5() : a(0) {} // expected-note {{implicitly declared private here}}
|
||||
S5(const S5 &s5) : a(s5.a) {}
|
||||
S5 &operator+(const S5 &arg);
|
||||
|
||||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
class S6 { // expected-note 3 {{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const S6' for 1st argument}}
|
||||
#if __cplusplus >= 201103L // C++11 or later
|
||||
// expected-note@-2 3 {{candidate function (the implicit move assignment operator) not viable}}
|
||||
#endif
|
||||
int a;
|
||||
|
||||
public:
|
||||
S6() : a(6) {}
|
||||
operator int() { return 6; }
|
||||
} o;
|
||||
|
||||
S3 h, k;
|
||||
#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
|
||||
|
||||
template <class T> // expected-note {{declared here}}
|
||||
T tmain(T argc) {
|
||||
const T d = T(); // expected-note 4 {{'d' defined here}}
|
||||
const T da[5] = {T()}; // expected-note 2 {{'da' defined here}}
|
||||
T qa[5] = {T()};
|
||||
T i;
|
||||
T &j = i; // expected-note 2 {{'j' defined here}}
|
||||
S3 &p = k; // expected-note 2 {{'p' defined here}}
|
||||
const T &r = da[(int)i]; // expected-note 2 {{'r' defined here}}
|
||||
T &q = qa[(int)i];
|
||||
T fl;
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop simd in_reduction // expected-error {{expected '(' after 'in_reduction'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop simd in_reduction + // expected-error {{expected '(' after 'in_reduction'}} expected-warning {{extra tokens at the end of '#pragma omp taskloop simd' are ignored}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop simd in_reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop simd in_reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop simd in_reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop simd in_reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:argc)
|
||||
#pragma omp taskloop simd in_reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(&:argc) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
#pragma omp taskloop simd in_reduction(& : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(|:argc) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
#pragma omp taskloop simd in_reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(|| : argc ? i : argc) // expected-error 2 {{expected variable name, array element or array section}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(foo : argc) //expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'float'}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max' or declare reduction for type 'int'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(&&:argc)
|
||||
#pragma omp taskloop simd in_reduction(&& : argc)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(^ : T) // expected-error {{'T' does not refer to a value}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:c)
|
||||
#pragma omp taskloop simd in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 3 {{const-qualified list item cannot be reduction}} expected-error 2 {{'operator+' is a private member of 'S2'}} expected-error 2 {{in_reduction variable must appear in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 4 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 3 {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}} expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:k)
|
||||
#pragma omp taskloop simd in_reduction(+ : h, k) // expected-error {{threadprivate or thread local variable cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(+ : o) // expected-error 2 {{no viable overloaded '='}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel private(k)
|
||||
#pragma omp taskloop simd in_reduction(+ : p), in_reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'in_reduction' must reference the same object in all threads}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:p)
|
||||
#pragma omp taskloop simd in_reduction(+ : p), in_reduction(+ : p) // expected-error 2 {{variable can appear only once in OpenMP 'in_reduction' clause}} expected-note 2 {{previously referenced here}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(+ : r) // expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel shared(i)
|
||||
#pragma omp parallel reduction(min : i)
|
||||
#pragma omp taskloop simd in_reduction(max : j) // expected-error 2 {{argument of OpenMP clause 'in_reduction' must reference the same object in all threads}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:fl)
|
||||
{
|
||||
#pragma omp taskloop simd in_reduction(+ : fl)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(*:fl) // expected-note 2 {{previously marked as task_reduction with different reduction operation}}
|
||||
{
|
||||
#pragma omp taskloop simd in_reduction(+ : fl) // expected-error 2 {{in_reduction variable must have the same reduction operation as in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
}
|
||||
}
|
||||
#pragma omp parallel
|
||||
#pragma omp for reduction(- : fl)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
#pragma omp taskgroup task_reduction(+:fl)
|
||||
#pragma omp taskloop simd in_reduction(+ : fl)
|
||||
for (int j = 0; j < 10; ++j)
|
||||
foo();
|
||||
|
||||
return T();
|
||||
}
|
||||
|
||||
namespace A {
|
||||
double x;
|
||||
#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
|
||||
}
|
||||
namespace B {
|
||||
using A::x;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const int d = 5; // expected-note 2 {{'d' defined here}}
|
||||
const int da[5] = {0}; // expected-note {{'da' defined here}}
|
||||
int qa[5] = {0};
|
||||
S4 e(4);
|
||||
S5 g(5);
|
||||
int i;
|
||||
int &j = i; // expected-note {{'j' defined here}}
|
||||
S3 &p = k; // expected-note 2 {{'p' defined here}}
|
||||
const int &r = da[i]; // expected-note {{'r' defined here}}
|
||||
int &q = qa[i];
|
||||
float fl;
|
||||
#pragma omp taskloop simd in_reduction // expected-error {{expected '(' after 'in_reduction'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction + // expected-error {{expected '(' after 'in_reduction'}} expected-warning {{extra tokens at the end of '#pragma omp taskloop simd' are ignored}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction( // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(- // expected-warning {{missing ':' after reduction identifier - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction() // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(*) // expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(\) // expected-error {{expected unqualified-id}} expected-warning {{missing ':' after reduction identifier - ignoring}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(foo : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(|:argc)
|
||||
#pragma omp taskloop simd in_reduction(| : argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(|| : argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name, array element or array section}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(~ : argc) // expected-error {{expected unqualified-id}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(&&:argc)
|
||||
#pragma omp taskloop simd in_reduction(&& : argc)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(^ : S1) // expected-error {{'S1' does not refer to a value}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:c)
|
||||
#pragma omp taskloop simd in_reduction(+ : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{const-qualified list item cannot be reduction}} expected-error {{'operator+' is a private member of 'S2'}} expected-error {{in_reduction variable must appear in a task_reduction clause}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(min : a, b, c, d, f) // expected-error {{a reduction list item with incomplete type 'S1'}} expected-error 2 {{arguments of OpenMP clause 'in_reduction' for 'min' or 'max' must be of arithmetic type}} expected-error 2 {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(max : h.b) // expected-error {{expected variable name, array element or array section}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(+ : ba) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(* : ca) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(- : da) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(^ : fl) // expected-error {{invalid operands to binary expression ('float' and 'float')}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(&& : S2::S2s) // expected-error {{shared variable cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(&& : S2::S2sc) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(& : e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{nvalid operands to binary expression ('S4' and 'S4')}} expected-error {{calling a private constructor of class 'S5'}} expected-error {{invalid operands to binary expression ('S5' and 'S5')}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:k)
|
||||
#pragma omp taskloop simd in_reduction(+ : h, k, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(+ : o) // expected-error {{no viable overloaded '='}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel private(k)
|
||||
#pragma omp taskloop simd in_reduction(+ : p), in_reduction(+ : p) // expected-error 2 {{argument of OpenMP clause 'in_reduction' must reference the same object in all threads}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:p)
|
||||
#pragma omp taskloop simd in_reduction(+ : p), in_reduction(+ : p) // expected-error {{variable can appear only once in OpenMP 'in_reduction' clause}} expected-note {{previously referenced here}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp taskloop simd in_reduction(+ : r) // expected-error {{const-qualified list item cannot be reduction}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel shared(i)
|
||||
#pragma omp parallel reduction(min : i)
|
||||
#pragma omp taskloop simd in_reduction(max : j) // expected-error {{argument of OpenMP clause 'in_reduction' must reference the same object in all threads}}
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp for private(fl)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
#pragma omp taskgroup task_reduction(+:fl)
|
||||
#pragma omp taskloop simd in_reduction(+ : fl)
|
||||
for (int j = 0; j < 10; ++j)
|
||||
foo();
|
||||
#pragma omp taskgroup task_reduction(+:fl)
|
||||
#pragma omp taskloop simd in_reduction(+ : fl)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
foo();
|
||||
static int m;
|
||||
#pragma omp taskgroup task_reduction(+:m)
|
||||
#pragma omp taskloop simd in_reduction(+ : m) // OK
|
||||
for (int i = 0; i < 10; ++i)
|
||||
m++;
|
||||
|
||||
return tmain(argc) + tmain(fl); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<float>' requested here}}
|
||||
}
|
|
@ -2281,6 +2281,23 @@ void OMPClauseEnqueue::VisitOMPTaskReductionClause(
|
|||
Visitor->AddStmt(E);
|
||||
}
|
||||
}
|
||||
void OMPClauseEnqueue::VisitOMPInReductionClause(
|
||||
const OMPInReductionClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
for (auto *E : C->privates()) {
|
||||
Visitor->AddStmt(E);
|
||||
}
|
||||
for (auto *E : C->lhs_exprs()) {
|
||||
Visitor->AddStmt(E);
|
||||
}
|
||||
for (auto *E : C->rhs_exprs()) {
|
||||
Visitor->AddStmt(E);
|
||||
}
|
||||
for (auto *E : C->reduction_ops()) {
|
||||
Visitor->AddStmt(E);
|
||||
}
|
||||
}
|
||||
void OMPClauseEnqueue::VisitOMPLinearClause(const OMPLinearClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
VisitOMPClauseWithPostUpdate(C);
|
||||
|
|
Loading…
Reference in New Issue