[OPENMP50]Add basic support for inscan reduction modifier.

Added basic support (parsing/sema checks) for the inscan modifier in the
reduction clauses.
This commit is contained in:
Alexey Bataev 2020-03-26 15:58:02 -04:00
parent 08776defa5
commit 36ed0ceec7
8 changed files with 220 additions and 57 deletions

View File

@ -10101,6 +10101,19 @@ def err_omp_depobj_single_clause_expected : Error<
"exactly one of 'depend', 'destroy', or 'update' clauses is expected">; "exactly one of 'depend', 'destroy', or 'update' clauses is expected">;
def err_omp_scan_single_clause_expected : Error< def err_omp_scan_single_clause_expected : Error<
"exactly one of 'inclusive' or 'exclusive' clauses is expected">; "exactly one of 'inclusive' or 'exclusive' clauses is expected">;
def err_omp_inclusive_exclusive_not_reduction : Error<
"the list item must appear in 'reduction' clause with the 'inscan' modifier "
"of the parent directive">;
def err_omp_reduction_not_inclusive_exclusive : Error<
"the inscan reduction list item must appear as a list item in an 'inclusive' or"
" 'exclusive' clause on an inner 'omp scan' directive">;
def err_omp_wrong_inscan_reduction : Error<
"'inscan' modifier can be used only in 'omp for', 'omp simd', 'omp for simd',"
" 'omp parallel for', or 'omp parallel for simd' directive">;
def err_omp_inscan_reduction_expected : Error<
"expected 'reduction' clause with the 'inscan' modifier">;
def note_omp_previous_inscan_reduction : Note<
"'reduction' clause with 'inscan' modifier is used here">;
def err_omp_expected_predefined_allocator : Error< def err_omp_expected_predefined_allocator : Error<
"expected one of the predefined allocators for the variables with the static " "expected one of the predefined allocators for the variables with the static "
"storage: 'omp_default_mem_alloc', 'omp_large_cap_mem_alloc', " "storage: 'omp_default_mem_alloc', 'omp_large_cap_mem_alloc', "

View File

@ -1112,6 +1112,7 @@ OPENMP_DEPOBJ_CLAUSE(update)
// Modifiers for 'reduction' clause. // Modifiers for 'reduction' clause.
OPENMP_REDUCTION_MODIFIER(default) OPENMP_REDUCTION_MODIFIER(default)
OPENMP_REDUCTION_MODIFIER(inscan)
#undef OPENMP_REDUCTION_MODIFIER #undef OPENMP_REDUCTION_MODIFIER
#undef OPENMP_SCAN_CLAUSE #undef OPENMP_SCAN_CLAUSE

View File

@ -62,14 +62,15 @@ public:
struct DSAVarData { struct DSAVarData {
OpenMPDirectiveKind DKind = OMPD_unknown; OpenMPDirectiveKind DKind = OMPD_unknown;
OpenMPClauseKind CKind = OMPC_unknown; OpenMPClauseKind CKind = OMPC_unknown;
unsigned Modifier = 0;
const Expr *RefExpr = nullptr; const Expr *RefExpr = nullptr;
DeclRefExpr *PrivateCopy = nullptr; DeclRefExpr *PrivateCopy = nullptr;
SourceLocation ImplicitDSALoc; SourceLocation ImplicitDSALoc;
DSAVarData() = default; DSAVarData() = default;
DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
const Expr *RefExpr, DeclRefExpr *PrivateCopy, const Expr *RefExpr, DeclRefExpr *PrivateCopy,
SourceLocation ImplicitDSALoc) SourceLocation ImplicitDSALoc, unsigned Modifier)
: DKind(DKind), CKind(CKind), RefExpr(RefExpr), : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc) {} PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc) {}
}; };
using OperatorOffsetTy = using OperatorOffsetTy =
@ -80,6 +81,7 @@ public:
private: private:
struct DSAInfo { struct DSAInfo {
OpenMPClauseKind Attributes = OMPC_unknown; OpenMPClauseKind Attributes = OMPC_unknown;
unsigned Modifier = 0;
/// Pointer to a reference expression and a flag which shows that the /// Pointer to a reference expression and a flag which shows that the
/// variable is marked as lastprivate(true) or not (false). /// variable is marked as lastprivate(true) or not (false).
llvm::PointerIntPair<const Expr *, 1, bool> RefExpr; llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
@ -164,6 +166,8 @@ private:
/// List of globals marked as declare target link in this target region /// List of globals marked as declare target link in this target region
/// (isOpenMPTargetExecutionDirective(Directive) == true). /// (isOpenMPTargetExecutionDirective(Directive) == true).
llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls; llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
/// List of decls used in inclusive/exclusive clauses of the scan directive.
llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
Scope *CurScope, SourceLocation Loc) Scope *CurScope, SourceLocation Loc)
: Directive(DKind), DirectiveName(Name), CurScope(CurScope), : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
@ -469,9 +473,20 @@ public:
/// parent directive. /// parent directive.
const ValueDecl *getParentLoopControlVariable(unsigned I) const; const ValueDecl *getParentLoopControlVariable(unsigned I) const;
/// Marks the specified decl \p D as used in scan directive.
void markDeclAsUsedInScanDirective(ValueDecl *D) {
if (SharingMapTy *Stack = getSecondOnStackOrNull())
Stack->UsedInScanDirective.insert(D);
}
/// Checks if the specified declaration was used in the inner scan directive.
bool isUsedInScanDirective(ValueDecl *D) const {
return getTopOfStack().UsedInScanDirective.count(D) > 0;
}
/// Adds explicit data sharing attribute to the specified declaration. /// Adds explicit data sharing attribute to the specified declaration.
void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
DeclRefExpr *PrivateCopy = nullptr); DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0);
/// Adds additional information for the reduction items with the reduction id /// Adds additional information for the reduction items with the reduction id
/// represented as an operator. /// represented as an operator.
@ -1079,6 +1094,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
DVar.PrivateCopy = Data.PrivateCopy; DVar.PrivateCopy = Data.PrivateCopy;
DVar.CKind = Data.Attributes; DVar.CKind = Data.Attributes;
DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
DVar.Modifier = Data.Modifier;
return DVar; return DVar;
} }
@ -1226,19 +1242,21 @@ const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
} }
void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
DeclRefExpr *PrivateCopy) { DeclRefExpr *PrivateCopy, unsigned Modifier) {
D = getCanonicalDecl(D); D = getCanonicalDecl(D);
if (A == OMPC_threadprivate) { if (A == OMPC_threadprivate) {
DSAInfo &Data = Threadprivates[D]; DSAInfo &Data = Threadprivates[D];
Data.Attributes = A; Data.Attributes = A;
Data.RefExpr.setPointer(E); Data.RefExpr.setPointer(E);
Data.PrivateCopy = nullptr; Data.PrivateCopy = nullptr;
Data.Modifier = Modifier;
} else { } else {
DSAInfo &Data = getTopOfStack().SharingMap[D]; DSAInfo &Data = getTopOfStack().SharingMap[D];
assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) || assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
(A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) || (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
(A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) || (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
(isLoopControlVariable(D).first && A == OMPC_private)); (isLoopControlVariable(D).first && A == OMPC_private));
Data.Modifier = Modifier;
if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) { if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
Data.RefExpr.setInt(/*IntVal=*/true); Data.RefExpr.setInt(/*IntVal=*/true);
return; return;
@ -1250,6 +1268,7 @@ void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
Data.PrivateCopy = PrivateCopy; Data.PrivateCopy = PrivateCopy;
if (PrivateCopy) { if (PrivateCopy) {
DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()]; DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
Data.Modifier = Modifier;
Data.Attributes = A; Data.Attributes = A;
Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate); Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
Data.PrivateCopy = nullptr; Data.PrivateCopy = nullptr;
@ -1355,7 +1374,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
"set."); "set.");
TaskgroupDescriptor = I->TaskgroupReductionRef; TaskgroupDescriptor = I->TaskgroupReductionRef;
return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(), return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(),
Data.PrivateCopy, I->DefaultAttrLoc); Data.PrivateCopy, I->DefaultAttrLoc, /*Modifier=*/0);
} }
return DSAVarData(); return DSAVarData();
} }
@ -1380,7 +1399,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
"set."); "set.");
TaskgroupDescriptor = I->TaskgroupReductionRef; TaskgroupDescriptor = I->TaskgroupReductionRef;
return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(), return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(),
Data.PrivateCopy, I->DefaultAttrLoc); Data.PrivateCopy, I->DefaultAttrLoc, /*Modifier=*/0);
} }
return DSAVarData(); return DSAVarData();
} }
@ -1455,6 +1474,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
if (TI != Threadprivates.end()) { if (TI != Threadprivates.end()) {
DVar.RefExpr = TI->getSecond().RefExpr.getPointer(); DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
DVar.CKind = OMPC_threadprivate; DVar.CKind = OMPC_threadprivate;
DVar.Modifier = TI->getSecond().Modifier;
return DVar; return DVar;
} }
if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) { if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
@ -1546,6 +1566,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
DVar.CKind = Data.Attributes; DVar.CKind = Data.Attributes;
DVar.ImplicitDSALoc = I->DefaultAttrLoc; DVar.ImplicitDSALoc = I->DefaultAttrLoc;
DVar.DKind = I->Directive; DVar.DKind = I->Directive;
DVar.Modifier = Data.Modifier;
return DVar; return DVar;
} }
@ -1592,6 +1613,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
DVar.CKind = Data.Attributes; DVar.CKind = Data.Attributes;
DVar.ImplicitDSALoc = I->DefaultAttrLoc; DVar.ImplicitDSALoc = I->DefaultAttrLoc;
DVar.DKind = I->Directive; DVar.DKind = I->Directive;
DVar.Modifier = Data.Modifier;
} }
return DVar; return DVar;
@ -2315,11 +2337,64 @@ void Sema::EndOpenMPClause() {
DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown); DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
} }
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
ArrayRef<OMPClause *> Clauses);
static std::pair<ValueDecl *, bool> static std::pair<ValueDecl *, bool>
getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
SourceRange &ERange, bool AllowArraySection = false); SourceRange &ERange, bool AllowArraySection = false);
/// Check consistency of the reduction clauses.
static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
ArrayRef<OMPClause *> Clauses) {
bool InscanFound = false;
SourceLocation InscanLoc;
// OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
// A reduction clause without the inscan reduction-modifier may not appear on
// a construct on which a reduction clause with the inscan reduction-modifier
// appears.
for (OMPClause *C : Clauses) {
if (C->getClauseKind() != OMPC_reduction)
continue;
auto *RC = cast<OMPReductionClause>(C);
if (RC->getModifier() == OMPC_REDUCTION_inscan) {
InscanFound = true;
InscanLoc = RC->getModifierLoc();
break;
}
}
if (InscanFound) {
for (OMPClause *C : Clauses) {
if (C->getClauseKind() != OMPC_reduction)
continue;
auto *RC = cast<OMPReductionClause>(C);
if (RC->getModifier() != OMPC_REDUCTION_inscan) {
S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
? RC->getBeginLoc()
: RC->getModifierLoc(),
diag::err_omp_inscan_reduction_expected);
S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
continue;
}
for (Expr *Ref : RC->varlists()) {
assert(Ref && "NULL expr in OpenMP nontemporal clause.");
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = Ref;
auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
/*AllowArraySection=*/true);
ValueDecl *D = Res.first;
if (!D)
continue;
if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
S.Diag(Ref->getExprLoc(),
diag::err_omp_reduction_not_inclusive_exclusive)
<< Ref->getSourceRange();
}
}
}
}
}
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
ArrayRef<OMPClause *> Clauses);
static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
bool WithInit); bool WithInit);
@ -2396,6 +2471,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
// Check allocate clauses. // Check allocate clauses.
if (!CurContext->isDependentContext()) if (!CurContext->isDependentContext())
checkAllocateClauses(*this, DSAStack, D->clauses()); checkAllocateClauses(*this, DSAStack, D->clauses());
checkReductionClauses(*this, DSAStack, D->clauses());
} }
DSAStack->pop(); DSAStack->pop();
@ -14111,9 +14187,11 @@ struct ReductionData {
SmallVector<Decl *, 4> ExprCaptures; SmallVector<Decl *, 4> ExprCaptures;
/// List of postupdate expressions. /// List of postupdate expressions.
SmallVector<Expr *, 4> ExprPostUpdates; SmallVector<Expr *, 4> ExprPostUpdates;
/// Reduction modifier.
unsigned RedModifier = 0;
ReductionData() = delete; ReductionData() = delete;
/// Reserves required memory for the reduction data. /// Reserves required memory for the reduction data.
ReductionData(unsigned Size) { ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
Vars.reserve(Size); Vars.reserve(Size);
Privates.reserve(Size); Privates.reserve(Size);
LHSs.reserve(Size); LHSs.reserve(Size);
@ -14831,7 +14909,8 @@ static bool actOnOMPReductionKindClause(
} }
// All reduction items are still marked as reduction (to do not increase // All reduction items are still marked as reduction (to do not increase
// code base size). // code base size).
Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref); Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref,
RD.RedModifier);
if (CurrDir == OMPD_taskgroup) { if (CurrDir == OMPD_taskgroup) {
if (DeclareReductionRef.isUsable()) if (DeclareReductionRef.isUsable())
Stack->addTaskgroupReductionData(D, ReductionIdRange, Stack->addTaskgroupReductionData(D, ReductionIdRange,
@ -14858,8 +14937,22 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
<< getOpenMPClauseName(OMPC_reduction); << getOpenMPClauseName(OMPC_reduction);
return nullptr; return nullptr;
} }
// OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
// A reduction clause with the inscan reduction-modifier may only appear on a
// worksharing-loop construct, a worksharing-loop SIMD construct, a simd
// construct, a parallel worksharing-loop construct or a parallel
// worksharing-loop SIMD construct.
if (Modifier == OMPC_REDUCTION_inscan &&
(DSAStack->getCurrentDirective() != OMPD_for &&
DSAStack->getCurrentDirective() != OMPD_for_simd &&
DSAStack->getCurrentDirective() != OMPD_simd &&
DSAStack->getCurrentDirective() != OMPD_parallel_for &&
DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
return nullptr;
}
ReductionData RD(VarList.size()); ReductionData RD(VarList.size(), Modifier);
if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList, if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
StartLoc, LParenLoc, ColonLoc, EndLoc, StartLoc, LParenLoc, ColonLoc, EndLoc,
ReductionIdScopeSpec, ReductionId, ReductionIdScopeSpec, ReductionId,
@ -18161,6 +18254,19 @@ OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
if (!D) if (!D)
continue; continue;
const DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D, /*FromParent=*/true);
// OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
// A list item that appears in the inclusive or exclusive clause must appear
// in a reduction clause with the inscan modifier on the enclosing
// worksharing-loop, worksharing-loop SIMD, or simd construct.
if (DVar.CKind != OMPC_reduction ||
DVar.Modifier != OMPC_REDUCTION_inscan)
Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
<< RefExpr->getSourceRange();
if (DSAStack->getParentDirective() != OMPD_unknown)
DSAStack->markDeclAsUsedInScanDirective(D);
Vars.push_back(RefExpr); Vars.push_back(RefExpr);
} }
@ -18189,6 +18295,19 @@ OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
if (!D) if (!D)
continue; continue;
const DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(D, /*FromParent=*/true);
// OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
// A list item that appears in the inclusive or exclusive clause must appear
// in a reduction clause with the inscan modifier on the enclosing
// worksharing-loop, worksharing-loop SIMD, or simd construct.
if (DVar.CKind != OMPC_reduction ||
DVar.Modifier != OMPC_REDUCTION_inscan)
Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
<< RefExpr->getSourceRange();
if (DSAStack->getParentDirective() != OMPD_unknown)
DSAStack->markDeclAsUsedInScanDirective(D);
Vars.push_back(RefExpr); Vars.push_back(RefExpr);
} }

View File

@ -2892,7 +2892,7 @@ void foo() {
} }
#pragma omp parallel for simd #pragma omp parallel for simd
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} #pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
bar(); bar();
} }
#pragma omp parallel for simd #pragma omp parallel for simd

View File

@ -1,10 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 150 -o - %s -Wuninitialized // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ferror-limit 150 -o - %s -Wuninitialized
// RUN: %clang_cc1 -verify -fopenmp -std=c++98 -ferror-limit 150 -o - %s -Wuninitialized // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -std=c++98 -ferror-limit 150 -o - %s -Wuninitialized
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -ferror-limit 150 -o - %s -Wuninitialized // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -std=c++11 -ferror-limit 150 -o - %s -Wuninitialized
// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 150 -o - %s -Wuninitialized // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 150 -o - %s -Wuninitialized
// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++98 -ferror-limit 150 -o - %s -Wuninitialized // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -std=c++98 -ferror-limit 150 -o - %s -Wuninitialized
// RUN: %clang_cc1 -verify -fopenmp-simd -std=c++11 -ferror-limit 150 -o - %s -Wuninitialized // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -std=c++11 -ferror-limit 150 -o - %s -Wuninitialized
extern int omp_default_mem_alloc; extern int omp_default_mem_alloc;
void xxx(int argc) { void xxx(int argc) {
@ -78,6 +78,14 @@ public:
#pragma omp for reduction(+:a) // expected-error {{reduction variable must be shared}} #pragma omp for reduction(+:a) // expected-error {{reduction variable must be shared}}
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
::foo(); ::foo();
#pragma omp parallel for reduction(inscan, +:a)
for (int i = 0; i < 10; ++i) {
#pragma omp scan inclusive(a)
}
#pragma omp parallel for reduction(inscan, +:a)
for (int i = 0; i < 10; ++i) {
#pragma omp scan exclusive(a)
}
} }
}; };
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}} 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}}
@ -333,5 +341,21 @@ int main(int argc, char **argv) {
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
m++; m++;
#pragma omp parallel for reduction(inscan, + : m) reduction(*: fl) reduction(default, &&: j) // expected-error 2 {{expected 'reduction' clause with the 'inscan' modifier}} expected-note 2 {{'reduction' clause with 'inscan' modifier is used here}}
for (int i = 0; i < 10; ++i) {
#pragma omp scan exclusive(m)
m++;
}
#pragma omp parallel for reduction(inscan, + : m, fl, j) // expected-error 2 {{the inscan reduction list item must appear as a list item in an 'inclusive' or 'exclusive' clause on an inner 'omp scan' directive}}
for (int i = 0; i < 10; ++i) {
#pragma omp scan exclusive(m)
m++;
}
#pragma omp parallel for reduction(inscan, + : m, fl, j) // expected-error 2 {{the inscan reduction list item must appear as a list item in an 'inclusive' or 'exclusive' clause on an inner 'omp scan' directive}}
for (int i = 0; i < 10; ++i) {
#pragma omp scan inclusive(m)
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}} 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}}
} }

View File

@ -10,10 +10,12 @@ void test() {
; ;
#pragma omp parallel reduction(default, // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-note {{to match this '('}} #pragma omp parallel reduction(default, // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-note {{to match this '('}}
; ;
#pragma omp parallel reduction(unknown, +: a) // expected-error {{expected 'default' in OpenMP clause 'reduction'}} #pragma omp parallel reduction(unknown, +: a) // expected-error {{expected 'default' or 'inscan' in OpenMP clause 'reduction'}}
; ;
#pragma omp parallel reduction(default, + : a) #pragma omp parallel reduction(default, + : a)
; ;
#pragma omp parallel reduction(inscan, + : a) // expected-error {{'inscan' modifier can be used only in 'omp for', 'omp simd', 'omp for simd', 'omp parallel for', or 'omp parallel for simd' directive}}
;
#pragma omp parallel reduction(+ : incomplete) // expected-error {{a reduction list item with incomplete type 'int []'}} #pragma omp parallel reduction(+ : incomplete) // expected-error {{a reduction list item with incomplete type 'int []'}}
; ;
} }

View File

@ -15,33 +15,35 @@ void foo() {}
template <class T> template <class T>
T tmain(T argc) { T tmain(T argc) {
static T a; static T a;
#pragma omp for #pragma omp for reduction(inscan, +: a)
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
#pragma omp scan inclusive(a) #pragma omp scan inclusive(a)
} }
return a + argc; return a + argc;
} }
// CHECK: static T a; // CHECK: static T a;
// CHECK-NEXT: #pragma omp for // CHECK-NEXT: #pragma omp for reduction(inscan, +: a)
// CHECK-NEXT: for (int i = 0; i < 10; ++i) { // CHECK-NEXT: for (int i = 0; i < 10; ++i) {
// CHECK-NEXT: #pragma omp scan inclusive(a){{$}} // CHECK-NEXT: #pragma omp scan inclusive(a){{$}}
// CHECK: static int a; // CHECK: static int a;
// CHECK-NEXT: #pragma omp for // CHECK-NEXT: #pragma omp for reduction(inscan, +: a)
// CHECK-NEXT: for (int i = 0; i < 10; ++i) { // CHECK-NEXT: for (int i = 0; i < 10; ++i) {
// CHECK-NEXT: #pragma omp scan inclusive(a) // CHECK-NEXT: #pragma omp scan inclusive(a)
// CHECK: static char a; // CHECK: static char a;
// CHECK-NEXT: #pragma omp for // CHECK-NEXT: #pragma omp for reduction(inscan, +: a)
// CHECK-NEXT: for (int i = 0; i < 10; ++i) { // CHECK-NEXT: for (int i = 0; i < 10; ++i) {
// CHECK-NEXT: #pragma omp scan inclusive(a) // CHECK-NEXT: #pragma omp scan inclusive(a)
int main(int argc, char **argv) { int main(int argc, char **argv) {
static int a; static int a;
// CHECK: static int a; // CHECK: static int a;
#pragma omp for simd #pragma omp parallel
#pragma omp for simd reduction(inscan, ^: a, argc)
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
#pragma omp scan exclusive(a, argc) #pragma omp scan exclusive(a, argc)
} }
// CHECK-NEXT: #pragma omp for simd // CHECK-NEXT: #pragma omp parallel
// CHECK-NEXT: #pragma omp for simd reduction(inscan, ^: a,argc)
// CHECK-NEXT: for (int i = 0; i < 10; ++i) { // CHECK-NEXT: for (int i = 0; i < 10; ++i) {
// CHECK-NEXT: #pragma omp scan exclusive(a,argc){{$}} // CHECK-NEXT: #pragma omp scan exclusive(a,argc){{$}}
return tmain(argc) + tmain(argv[0][0]) + a; return tmain(argc) + tmain(argv[0][0]) + a;

View File

@ -1,9 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ferror-limit 100 %s // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ferror-limit 150 %s
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 %s // RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 150 %s
template <class T> template <class T>
T tmain(T argc) { T tmain() {
static T argc;
#pragma omp for #pragma omp for
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
#pragma omp scan // expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} #pragma omp scan // expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
@ -15,32 +16,32 @@ T tmain(T argc) {
#pragma omp scan untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp scan'}} expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} #pragma omp scan untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp scan'}} expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
#pragma omp scan unknown // expected-warning {{extra tokens at the end of '#pragma omp scan' are ignored}} expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} #pragma omp scan unknown // expected-warning {{extra tokens at the end of '#pragma omp scan' are ignored}} expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
} }
#pragma omp for simd #pragma omp for simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
if (argc) if (argc)
#pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
if (argc) { if (argc) {
#pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} #pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}}
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
while (argc) while (argc)
#pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
while (argc) { while (argc) {
#pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} #pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}}
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
do do
#pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
while (argc) while (argc)
; ;
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
do { do {
#pragma omp scan inclusive(argc) #pragma omp scan inclusive(argc)
} while (argc); } while (argc);
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
switch (argc) switch (argc)
#pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
@ -51,7 +52,7 @@ T tmain(T argc) {
case 1: { case 1: {
#pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} #pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}}
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
switch (argc) { switch (argc) {
#pragma omp scan exclusive(argc) // expected-note 2 {{previous 'scan' directive used here}} #pragma omp scan exclusive(argc) // expected-note 2 {{previous 'scan' directive used here}}
@ -62,19 +63,19 @@ T tmain(T argc) {
#pragma omp scan exclusive(argc) // expected-error {{exactly one 'scan' directive must appear in the loop body of an enclosing directive}} #pragma omp scan exclusive(argc) // expected-error {{exactly one 'scan' directive must appear in the loop body of an enclosing directive}}
} break; } break;
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
for (;;) for (;;)
#pragma omp scan exclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} #pragma omp scan exclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
for (;;) { for (;;) {
#pragma omp scan exclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} #pragma omp scan exclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}}
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
label: label:
#pragma omp scan exclusive(argc) #pragma omp scan exclusive(argc)
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
label1 : { label1 : {
#pragma omp scan inclusive(argc) #pragma omp scan inclusive(argc)
@ -83,64 +84,65 @@ label1 : {
return T(); return T();
} }
int main(int argc, char **argv) { int main() {
#pragma omp simd static int argc;
#pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
#pragma omp scan inclusive(argc) inclusive(argc) // expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} #pragma omp scan inclusive(argc) inclusive(argc) // expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
; ;
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
#pragma omp scan exclusive(argc) inclusive(argc) // expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} #pragma omp scan exclusive(argc) inclusive(argc) // expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
; ;
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
#pragma omp scan exclusive(argc) exclusive(argc) // expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} #pragma omp scan exclusive(argc) exclusive(argc) // expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
; ;
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc) // expected-error {{the inscan reduction list item must appear as a list item in an 'inclusive' or 'exclusive' clause on an inner 'omp scan' directive}}
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
#pragma omp scan untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp scan'}} expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} #pragma omp scan untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp scan'}} expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
#pragma omp scan unknown // expected-warning {{extra tokens at the end of '#pragma omp scan' are ignored}} expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}} #pragma omp scan unknown // expected-warning {{extra tokens at the end of '#pragma omp scan' are ignored}} expected-error {{exactly one of 'inclusive' or 'exclusive' clauses is expected}}
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
if (argc) if (argc)
#pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
if (argc) { if (argc) {
#pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} #pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} expected-error {{the list item must appear in 'reduction' clause with the 'inscan' modifier of the parent directive}}
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
while (argc) while (argc)
#pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
while (argc) { while (argc) {
#pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} #pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} expected-error {{the list item must appear in 'reduction' clause with the 'inscan' modifier of the parent directive}}
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
do do
#pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
while (argc) while (argc)
; ;
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
do { do {
#pragma omp scan exclusive(argc) #pragma omp scan exclusive(argc)
} while (argc); } while (argc);
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
switch (argc) switch (argc)
#pragma omp scan exclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} #pragma omp scan exclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
switch (argc) switch (argc)
case 1: case 1:
#pragma omp scan exclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} #pragma omp scan exclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} expected-error {{the list item must appear in 'reduction' clause with the 'inscan' modifier of the parent directive}}
switch (argc) switch (argc)
case 1: { case 1: {
#pragma omp scan exclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} #pragma omp scan exclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} expected-error {{the list item must appear in 'reduction' clause with the 'inscan' modifier of the parent directive}}
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
switch (argc) { switch (argc) {
#pragma omp scan inclusive(argc) // expected-note 2 {{previous 'scan' directive used here}} #pragma omp scan inclusive(argc) // expected-note 2 {{previous 'scan' directive used here}}
@ -151,24 +153,24 @@ int main(int argc, char **argv) {
#pragma omp scan inclusive(argc) // expected-error {{exactly one 'scan' directive must appear in the loop body of an enclosing directive}} #pragma omp scan inclusive(argc) // expected-error {{exactly one 'scan' directive must appear in the loop body of an enclosing directive}}
} break; } break;
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
for (;;) for (;;)
#pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
for (;;) { for (;;) {
#pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} #pragma omp scan inclusive(argc) // expected-error {{orphaned 'omp scan' directives are prohibited; perhaps you forget to enclose the directive into a for, simd, for simd, parallel for, or parallel for simd region?}} expected-error {{the list item must appear in 'reduction' clause with the 'inscan' modifier of the parent directive}}
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
label: label:
#pragma omp scan inclusive(argc) #pragma omp scan inclusive(argc)
} }
#pragma omp simd #pragma omp simd reduction(inscan, +: argc)
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
label1 : { label1 : {
#pragma omp scan inclusive(argc) #pragma omp scan inclusive(argc)
} }
} }
return tmain(argc); return tmain<int>();
} }