diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 044d35f19e200..549ba4447a3f6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -10101,6 +10101,19 @@ def err_omp_depobj_single_clause_expected : Error< "exactly one of 'depend', 'destroy', or 'update' clauses is expected">; def err_omp_scan_single_clause_expected : Error< "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< "expected one of the predefined allocators for the variables with the static " "storage: 'omp_default_mem_alloc', 'omp_large_cap_mem_alloc', " diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index bfb41ab105ea5..3cf92ead9560e 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -1112,6 +1112,7 @@ OPENMP_DEPOBJ_CLAUSE(update) // Modifiers for 'reduction' clause. OPENMP_REDUCTION_MODIFIER(default) +OPENMP_REDUCTION_MODIFIER(inscan) #undef OPENMP_REDUCTION_MODIFIER #undef OPENMP_SCAN_CLAUSE diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 318b075db8bdb..b10cdb4f3e40d 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -62,14 +62,15 @@ class DSAStackTy { struct DSAVarData { OpenMPDirectiveKind DKind = OMPD_unknown; OpenMPClauseKind CKind = OMPC_unknown; + unsigned Modifier = 0; const Expr *RefExpr = nullptr; DeclRefExpr *PrivateCopy = nullptr; SourceLocation ImplicitDSALoc; DSAVarData() = default; DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, const Expr *RefExpr, DeclRefExpr *PrivateCopy, - SourceLocation ImplicitDSALoc) - : DKind(DKind), CKind(CKind), RefExpr(RefExpr), + SourceLocation ImplicitDSALoc, unsigned Modifier) + : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr), PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc) {} }; using OperatorOffsetTy = @@ -80,6 +81,7 @@ class DSAStackTy { private: struct DSAInfo { OpenMPClauseKind Attributes = OMPC_unknown; + unsigned Modifier = 0; /// Pointer to a reference expression and a flag which shows that the /// variable is marked as lastprivate(true) or not (false). llvm::PointerIntPair RefExpr; @@ -164,6 +166,8 @@ class DSAStackTy { /// List of globals marked as declare target link in this target region /// (isOpenMPTargetExecutionDirective(Directive) == true). llvm::SmallVector DeclareTargetLinkVarDecls; + /// List of decls used in inclusive/exclusive clauses of the scan directive. + llvm::DenseSet> UsedInScanDirective; SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name, Scope *CurScope, SourceLocation Loc) : Directive(DKind), DirectiveName(Name), CurScope(CurScope), @@ -469,9 +473,20 @@ class DSAStackTy { /// parent directive. 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. 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 /// represented as an operator. @@ -1079,6 +1094,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter, DVar.PrivateCopy = Data.PrivateCopy; DVar.CKind = Data.Attributes; DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; + DVar.Modifier = Data.Modifier; return DVar; } @@ -1226,19 +1242,21 @@ const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const { } void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, - DeclRefExpr *PrivateCopy) { + DeclRefExpr *PrivateCopy, unsigned Modifier) { D = getCanonicalDecl(D); if (A == OMPC_threadprivate) { DSAInfo &Data = Threadprivates[D]; Data.Attributes = A; Data.RefExpr.setPointer(E); Data.PrivateCopy = nullptr; + Data.Modifier = Modifier; } else { DSAInfo &Data = getTopOfStack().SharingMap[D]; assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) || (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) || (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) || (isLoopControlVariable(D).first && A == OMPC_private)); + Data.Modifier = Modifier; if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) { Data.RefExpr.setInt(/*IntVal=*/true); return; @@ -1250,6 +1268,7 @@ void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A, Data.PrivateCopy = PrivateCopy; if (PrivateCopy) { DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()]; + Data.Modifier = Modifier; Data.Attributes = A; Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate); Data.PrivateCopy = nullptr; @@ -1355,7 +1374,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData( "set."); TaskgroupDescriptor = I->TaskgroupReductionRef; return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(), - Data.PrivateCopy, I->DefaultAttrLoc); + Data.PrivateCopy, I->DefaultAttrLoc, /*Modifier=*/0); } return DSAVarData(); } @@ -1380,7 +1399,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData( "set."); TaskgroupDescriptor = I->TaskgroupReductionRef; return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(), - Data.PrivateCopy, I->DefaultAttrLoc); + Data.PrivateCopy, I->DefaultAttrLoc, /*Modifier=*/0); } return DSAVarData(); } @@ -1455,6 +1474,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, if (TI != Threadprivates.end()) { DVar.RefExpr = TI->getSecond().RefExpr.getPointer(); DVar.CKind = OMPC_threadprivate; + DVar.Modifier = TI->getSecond().Modifier; return DVar; } if (VD && VD->hasAttr()) { @@ -1546,6 +1566,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, DVar.CKind = Data.Attributes; DVar.ImplicitDSALoc = I->DefaultAttrLoc; DVar.DKind = I->Directive; + DVar.Modifier = Data.Modifier; return DVar; } @@ -1592,6 +1613,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, DVar.CKind = Data.Attributes; DVar.ImplicitDSALoc = I->DefaultAttrLoc; DVar.DKind = I->Directive; + DVar.Modifier = Data.Modifier; } return DVar; @@ -2315,11 +2337,64 @@ void Sema::EndOpenMPClause() { DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown); } -static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, - ArrayRef Clauses); static std::pair getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection = false); + +/// Check consistency of the reduction clauses. +static void checkReductionClauses(Sema &S, DSAStackTy *Stack, + ArrayRef 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(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(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 Clauses); static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit); @@ -2396,6 +2471,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { // Check allocate clauses. if (!CurContext->isDependentContext()) checkAllocateClauses(*this, DSAStack, D->clauses()); + checkReductionClauses(*this, DSAStack, D->clauses()); } DSAStack->pop(); @@ -14111,9 +14187,11 @@ struct ReductionData { SmallVector ExprCaptures; /// List of postupdate expressions. SmallVector ExprPostUpdates; + /// Reduction modifier. + unsigned RedModifier = 0; ReductionData() = delete; /// Reserves required memory for the reduction data. - ReductionData(unsigned Size) { + ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) { Vars.reserve(Size); Privates.reserve(Size); LHSs.reserve(Size); @@ -14831,7 +14909,8 @@ 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); + Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, + RD.RedModifier); if (CurrDir == OMPD_taskgroup) { if (DeclareReductionRef.isUsable()) Stack->addTaskgroupReductionData(D, ReductionIdRange, @@ -14858,8 +14937,22 @@ OMPClause *Sema::ActOnOpenMPReductionClause( << getOpenMPClauseName(OMPC_reduction); 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, StartLoc, LParenLoc, ColonLoc, EndLoc, ReductionIdScopeSpec, ReductionId, @@ -18161,6 +18254,19 @@ OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef VarList, if (!D) 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); } @@ -18189,6 +18295,19 @@ OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef VarList, if (!D) 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); } diff --git a/clang/test/OpenMP/nesting_of_regions.cpp b/clang/test/OpenMP/nesting_of_regions.cpp index 4bfaf3f7aeb6f..9824c1df5310e 100644 --- a/clang/test/OpenMP/nesting_of_regions.cpp +++ b/clang/test/OpenMP/nesting_of_regions.cpp @@ -2892,7 +2892,7 @@ void foo() { } #pragma omp parallel for simd 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(); } #pragma omp parallel for simd diff --git a/clang/test/OpenMP/parallel_for_reduction_messages.cpp b/clang/test/OpenMP/parallel_for_reduction_messages.cpp index b28fe6c379992..50a93129b1fa2 100644 --- a/clang/test/OpenMP/parallel_for_reduction_messages.cpp +++ b/clang/test/OpenMP/parallel_for_reduction_messages.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -verify -fopenmp -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 -std=c++11 -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 -fopenmp-version=50 -std=c++98 -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 -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 -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 -fopenmp-version=50 -std=c++11 -ferror-limit 150 -o - %s -Wuninitialized extern int omp_default_mem_alloc; void xxx(int argc) { @@ -78,6 +78,14 @@ class S5 { #pragma omp for reduction(+:a) // expected-error {{reduction variable must be shared}} for (int i = 0; i < 10; ++i) ::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}} @@ -333,5 +341,21 @@ int main(int argc, char **argv) { for (int i = 0; i < 10; ++i) 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' requested here}} expected-note {{in instantiation of function template specialization 'tmain' requested here}} } diff --git a/clang/test/OpenMP/parallel_reduction_messages.c b/clang/test/OpenMP/parallel_reduction_messages.c index 61a3e9300436c..b5e66672cde93 100644 --- a/clang/test/OpenMP/parallel_reduction_messages.c +++ b/clang/test/OpenMP/parallel_reduction_messages.c @@ -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(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(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 []'}} ; } diff --git a/clang/test/OpenMP/scan_ast_print.cpp b/clang/test/OpenMP/scan_ast_print.cpp index 4b9eca6f7ec9f..0bee5d9f744a8 100644 --- a/clang/test/OpenMP/scan_ast_print.cpp +++ b/clang/test/OpenMP/scan_ast_print.cpp @@ -15,33 +15,35 @@ void foo() {} template T tmain(T argc) { static T a; -#pragma omp for +#pragma omp for reduction(inscan, +: a) for (int i = 0; i < 10; ++i) { #pragma omp scan inclusive(a) } return a + argc; } // 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: #pragma omp scan inclusive(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: #pragma omp scan inclusive(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: #pragma omp scan inclusive(a) int main(int argc, char **argv) { 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) { #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: #pragma omp scan exclusive(a,argc){{$}} return tmain(argc) + tmain(argv[0][0]) + a; diff --git a/clang/test/OpenMP/scan_messages.cpp b/clang/test/OpenMP/scan_messages.cpp index c72897eb378c7..9ce8314511c1f 100644 --- a/clang/test/OpenMP/scan_messages.cpp +++ b/clang/test/OpenMP/scan_messages.cpp @@ -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 -T tmain(T argc) { +T tmain() { + static T argc; #pragma omp for for (int i = 0; i < 10; ++i) { #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 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) if (argc) #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} 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 simd +#pragma omp simd reduction(inscan, +: argc) for (int i = 0; i < 10; ++i) while (argc) #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} 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 simd +#pragma omp simd reduction(inscan, +: argc) for (int i = 0; i < 10; ++i) do #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} while (argc) ; -#pragma omp simd +#pragma omp simd reduction(inscan, +: argc) for (int i = 0; i < 10; ++i) do { #pragma omp scan inclusive(argc) } while (argc); -#pragma omp simd +#pragma omp simd reduction(inscan, +: argc) for (int i = 0; i < 10; ++i) switch (argc) #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: { #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) switch (argc) { #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}} } break; } -#pragma omp simd +#pragma omp simd reduction(inscan, +: argc) for (int i = 0; i < 10; ++i) for (;;) #pragma omp scan exclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} 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 simd +#pragma omp simd reduction(inscan, +: argc) for (int i = 0; i < 10; ++i) { label: #pragma omp scan exclusive(argc) } -#pragma omp simd +#pragma omp simd reduction(inscan, +: argc) for (int i = 0; i < 10; ++i) { label1 : { #pragma omp scan inclusive(argc) @@ -83,64 +84,65 @@ label1 : { return T(); } -int main(int argc, char **argv) { -#pragma omp simd +int main() { + static int argc; +#pragma omp simd reduction(inscan, +: argc) 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 simd +#pragma omp simd reduction(inscan, +: argc) 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 simd +#pragma omp simd reduction(inscan, +: argc) 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 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) { #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 simd +#pragma omp simd reduction(inscan, +: argc) for (int i = 0; i < 10; ++i) if (argc) #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} 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) while (argc) #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} 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) do #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} while (argc) ; -#pragma omp simd +#pragma omp simd reduction(inscan, +: argc) for (int i = 0; i < 10; ++i) do { #pragma omp scan exclusive(argc) } while (argc); -#pragma omp simd +#pragma omp simd reduction(inscan, +: argc) for (int i = 0; i < 10; ++i) switch (argc) #pragma omp scan exclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} switch (argc) 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) 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) switch (argc) { #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}} } break; } -#pragma omp simd +#pragma omp simd reduction(inscan, +: argc) for (int i = 0; i < 10; ++i) for (;;) #pragma omp scan inclusive(argc) // expected-error {{'#pragma omp scan' cannot be an immediate substatement}} 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) { label: #pragma omp scan inclusive(argc) } -#pragma omp simd +#pragma omp simd reduction(inscan, +: argc) for (int i = 0; i < 10; ++i) { label1 : { #pragma omp scan inclusive(argc) } } - return tmain(argc); + return tmain(); }