From: Alexey Bataev Date: Fri, 21 Mar 2014 04:51:18 +0000 (+0000) Subject: [OPENMP] parsing of clause 'safelen' (for directive 'omp simd') X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a465dc43f18a62a73536fb51fbc75172ef4fbbc3;p=clang [OPENMP] parsing of clause 'safelen' (for directive 'omp simd') git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@204428 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h index 5afa9cd679..01934ce26d 100644 --- a/include/clang/AST/DataRecursiveASTVisitor.h +++ b/include/clang/AST/DataRecursiveASTVisitor.h @@ -2367,6 +2367,13 @@ bool DataRecursiveASTVisitor::VisitOMPNumThreadsClause( return true; } +template +bool DataRecursiveASTVisitor::VisitOMPSafelenClause( + OMPSafelenClause *C) { + TraverseStmt(C->getSafelen()); + return true; +} + template bool DataRecursiveASTVisitor::VisitOMPDefaultClause(OMPDefaultClause *C) { return true; diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index 04ebb6a698..97c4869b98 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -250,6 +250,62 @@ public: StmtRange children() { return StmtRange(&NumThreads, &NumThreads + 1); } }; +/// \brief This represents 'safelen' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp simd safelen(4) +/// \endcode +/// In this example directive '#pragma omp simd' has clause 'safelen' +/// with single expression '4'. +/// If the safelen clause is used then no two iterations executed +/// concurrently with SIMD instructions can have a greater distance +/// in the logical iteration space than its value. The parameter of +/// the safelen clause must be a constant positive integer expression. +/// +class OMPSafelenClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Safe iteration space distance. + Stmt *Safelen; + + /// \brief Set safelen. + void setSafelen(Expr *Len) { Safelen = Len; } + +public: + /// \brief Build 'safelen' clause. + /// + /// \param Len Expression associated with this clause. + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPSafelenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_safelen, StartLoc, EndLoc), LParenLoc(LParenLoc), + Safelen(Len) {} + + /// \brief Build an empty clause. + /// + explicit OMPSafelenClause() + : OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), Safelen(0) {} + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Return safe iteration space distance. + Expr *getSafelen() const { return cast_or_null(Safelen); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_safelen; + } + + StmtRange children() { return StmtRange(&Safelen, &Safelen + 1); } +}; + /// \brief This represents 'default' clause in the '#pragma omp ...' directive. /// /// \code diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 3226c3c32d..9541b66487 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -2405,6 +2405,12 @@ bool RecursiveASTVisitor::VisitOMPNumThreadsClause( return true; } +template +bool RecursiveASTVisitor::VisitOMPSafelenClause(OMPSafelenClause *C) { + TraverseStmt(C->getSafelen()); + return true; +} + template bool RecursiveASTVisitor::VisitOMPDefaultClause(OMPDefaultClause *C) { return true; diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def index da43a58d17..c753f0c422 100644 --- a/include/clang/Basic/OpenMPKinds.def +++ b/include/clang/Basic/OpenMPKinds.def @@ -37,12 +37,13 @@ OPENMP_DIRECTIVE(simd) // OpenMP clauses. OPENMP_CLAUSE(if, OMPIfClause) OPENMP_CLAUSE(num_threads, OMPNumThreadsClause) +OPENMP_CLAUSE(safelen, OMPSafelenClause) OPENMP_CLAUSE(default, OMPDefaultClause) OPENMP_CLAUSE(private, OMPPrivateClause) OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause) OPENMP_CLAUSE(shared, OMPSharedClause) -// Clauses allowed for OpenMP directives. +// Clauses allowed for OpenMP directive 'parallel'. OPENMP_PARALLEL_CLAUSE(if) OPENMP_PARALLEL_CLAUSE(num_threads) OPENMP_PARALLEL_CLAUSE(default) @@ -52,6 +53,7 @@ OPENMP_PARALLEL_CLAUSE(shared) // FIXME: more clauses allowed for directive 'omp simd'. OPENMP_SIMD_CLAUSE(private) +OPENMP_SIMD_CLAUSE(safelen) // Static attributes for 'default' clause. OPENMP_DEFAULT_KIND(none) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index d1a62dcd10..5ce80a6a48 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -7114,6 +7114,8 @@ private: void InitDataSharingAttributesStack(); void DestroyDataSharingAttributesStack(); ExprResult PerformImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op); + ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, + OpenMPClauseKind CKind); public: /// \brief Called on start of new data sharing attribute block. void StartOpenMPDSABlock(OpenMPDirectiveKind K, @@ -7169,6 +7171,11 @@ public: SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// \brief Called on well-formed 'safelen' clause. + OMPClause *ActOnOpenMPSafelenClause(Expr *Length, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index a1dec268d5..2371b93fe4 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -613,6 +613,12 @@ void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) { OS << ")"; } +void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) { + OS << "safelen("; + Node->getSafelen()->printPretty(OS, 0, Policy, 0); + OS << ")"; +} + void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) { OS << "default(" << getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind()) diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index e663778e99..9fc4c77e2c 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -274,6 +274,11 @@ void OMPClauseProfiler::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) { Profiler->VisitStmt(C->getNumThreads()); } +void OMPClauseProfiler::VisitOMPSafelenClause(const OMPSafelenClause *C) { + if (C->getSafelen()) + Profiler->VisitStmt(C->getSafelen()); +} + void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { } template diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp index 0a25b240cb..a5147a2136 100644 --- a/lib/Basic/OpenMPKinds.cpp +++ b/lib/Basic/OpenMPKinds.cpp @@ -79,6 +79,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_threadprivate: case OMPC_if: case OMPC_num_threads: + case OMPC_safelen: case OMPC_private: case OMPC_firstprivate: case OMPC_shared: @@ -104,6 +105,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_threadprivate: case OMPC_if: case OMPC_num_threads: + case OMPC_safelen: case OMPC_private: case OMPC_firstprivate: case OMPC_shared: diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index 037dd36fc7..fa55b44da7 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -257,7 +257,8 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, /// \brief Parsing of OpenMP clauses. /// /// clause: -/// default-clause|private-clause|firstprivate-clause|shared-clause +/// if-clause | num_threads-clause | safelen-clause | default-clause | +/// private-clause | firstprivate-clause | shared-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -273,9 +274,12 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, switch (CKind) { case OMPC_if: case OMPC_num_threads: + case OMPC_safelen: // OpenMP [2.5, Restrictions] // At most one if clause can appear on the directive. // At most one num_threads clause can appear on the directive. + // OpenMP [2.8.1, simd construct, Restrictions] + // Only one safelen clause can appear on a simd directive. if (!FirstClause) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind); @@ -321,6 +325,12 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, /// if-clause: /// 'if' '(' expression ')' /// +/// num_threads-clause: +/// 'num_threads' '(' expression ')' +/// +/// safelen-clause: +/// 'safelen' '(' expression ')' +/// OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) { SourceLocation Loc = ConsumeToken(); diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 1e1dbfed0b..e43b4f453e 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -761,6 +761,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, case OMPC_num_threads: Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc); break; + case OMPC_safelen: + Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc); + break; case OMPC_default: case OMPC_private: case OMPC_firstprivate: @@ -868,6 +871,38 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads, EndLoc); } +ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E, + OpenMPClauseKind CKind) { + if (!E) + return ExprError(); + if (E->isValueDependent() || E->isTypeDependent() || + E->isInstantiationDependent() || E->containsUnexpandedParameterPack()) + return Owned(E); + llvm::APSInt Result; + ExprResult ICE = VerifyIntegerConstantExpression(E, &Result); + if (ICE.isInvalid()) + return ExprError(); + if (!Result.isStrictlyPositive()) { + Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause) + << getOpenMPClauseName(CKind) << E->getSourceRange(); + return ExprError(); + } + return ICE; +} + +OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + // OpenMP [2.8.1, simd construct, Description] + // The parameter of the safelen clause must be a constant + // positive integer expression. + ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen); + if (Safelen.isInvalid()) + return 0; + return new (Context) + OMPSafelenClause(Safelen.take(), StartLoc, LParenLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, @@ -883,6 +918,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, break; case OMPC_if: case OMPC_num_threads: + case OMPC_safelen: case OMPC_private: case OMPC_firstprivate: case OMPC_shared: @@ -956,6 +992,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, break; case OMPC_if: case OMPC_num_threads: + case OMPC_safelen: case OMPC_default: case OMPC_threadprivate: case OMPC_unknown: diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 5000d28098..a8ec18c740 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1323,6 +1323,16 @@ public: LParenLoc, EndLoc); } + /// \brief Build a new OpenMP 'safelen' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPSafelenClause(Expr *Len, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPSafelenClause(Len, StartLoc, LParenLoc, EndLoc); + } + /// \brief Build a new OpenMP 'default' clause. /// /// By default, performs semantic analysis to build the new statement. @@ -6340,6 +6350,16 @@ TreeTransform::TransformOMPNumThreadsClause(OMPNumThreadsClause *C) { C->getLocEnd()); } +template +OMPClause * +TreeTransform::TransformOMPSafelenClause(OMPSafelenClause *C) { + ExprResult E = getDerived().TransformExpr(C->getSafelen()); + if (E.isInvalid()) + return 0; + return getDerived().RebuildOMPSafelenClause( + E.take(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); +} + template OMPClause * TreeTransform::TransformOMPDefaultClause(OMPDefaultClause *C) { diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index f5110ea43a..594d029e0e 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1677,6 +1677,9 @@ OMPClause *OMPClauseReader::readClause() { case OMPC_num_threads: C = new (Context) OMPNumThreadsClause(); break; + case OMPC_safelen: + C = new (Context) OMPSafelenClause(); + break; case OMPC_default: C = new (Context) OMPDefaultClause(); break; @@ -1707,6 +1710,11 @@ void OMPClauseReader::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); } +void OMPClauseReader::VisitOMPSafelenClause(OMPSafelenClause *C) { + C->setSafelen(Reader->Reader.ReadSubExpr()); + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); +} + void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) { C->setDefaultKind( static_cast(Record[Idx++])); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index c55f0bca82..866b738d74 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1684,6 +1684,11 @@ void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); } +void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) { + Writer->Writer.AddStmt(C->getSafelen()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); +} + void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) { Record.push_back(C->getDefaultKind()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); diff --git a/test/OpenMP/simd_ast_print.cpp b/test/OpenMP/simd_ast_print.cpp index fd9668c436..4b1fccb92f 100644 --- a/test/OpenMP/simd_ast_print.cpp +++ b/test/OpenMP/simd_ast_print.cpp @@ -33,12 +33,22 @@ template struct S { T val; // CHECK: T res; // CHECK: T val; -#pragma omp simd private(val) -// CHECK-NEXT: #pragma omp simd private(val) + #pragma omp simd private(val) safelen(7) +// CHECK-NEXT: #pragma omp simd private(val) safelen(7) for (T i = 7; i < m_a; ++i) { val = v[i-7] + m_a; res = val; } + const T clen = 3; +// CHECK: T clen = 3; + #pragma omp simd safelen(clen-1) +// CHECK-NEXT: #pragma omp simd safelen(clen - 1) + for(T i = clen+2; i < 20; ++i) { +// CHECK-NEXT: for (T i = clen + 2; i < 20; ++i) { + v[i] = v[v-clen] + 1; +// CHECK-NEXT: v[i] = v[v - clen] + 1; + } +// CHECK-NEXT: } return res; } ~S() @@ -46,6 +56,24 @@ template struct S { T m_a; }; +template struct S2 { + static void func(int n, float *a, float *b, float *c) { +#pragma omp simd safelen(LEN) + for(int i = 0; i < n; i++) { + c[i] = a[i] + b[i]; + } + } +}; + +// S2<4>::func is called below in main. +// CHECK: template struct S2 { +// CHECK-NEXT: static void func(int n, float *a, float *b, float *c) { +// CHECK-NEXT: #pragma omp simd safelen(4) +// CHECK-NEXT: for (int i = 0; i < n; i++) { +// CHECK-NEXT: c[i] = a[i] + b[i]; +// CHECK-NEXT: } +// CHECK-NEXT: } + int main (int argc, char **argv) { int b = argc, c, d, e, f, g; int k1=0,k2=0; @@ -69,11 +97,16 @@ int main (int argc, char **argv) { for (int i = 0; i < 10; ++i)foo(); // CHECK-NEXT: for (int i = 0; i < 10; ++i) // CHECK-NEXT: foo(); -#pragma omp simd -// CHECK-NEXT: #pragma omp simd + const int CLEN = 4; +// CHECK-NEXT: const int CLEN = 4; + #pragma omp simd safelen(CLEN) +// CHECK-NEXT: #pragma omp simd safelen(CLEN) for (int i = 0; i < 10; ++i)foo(); // CHECK-NEXT: for (int i = 0; i < 10; ++i) // CHECK-NEXT: foo(); + + float arr[16]; + S2<4>::func(0,arr,arr,arr); return (0); } diff --git a/test/OpenMP/simd_misc_messages.c b/test/OpenMP/simd_misc_messages.c index 622c4389b5..0800d22988 100644 --- a/test/OpenMP/simd_misc_messages.c +++ b/test/OpenMP/simd_misc_messages.c @@ -77,6 +77,75 @@ void test_non_identifiers() for (i = 0; i < 16; ++i) ; } +extern int foo(); +void test_safelen() +{ + int i; + // expected-error@+1 {{expected '('}} + #pragma omp simd safelen + for (i = 0; i < 16; ++i) ; + // expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} + #pragma omp simd safelen( + for (i = 0; i < 16; ++i) ; + // expected-error@+1 {{expected expression}} + #pragma omp simd safelen() + for (i = 0; i < 16; ++i) ; + // expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} + #pragma omp simd safelen(, + for (i = 0; i < 16; ++i) ; + // expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} + #pragma omp simd safelen(,) + for (i = 0; i < 16; ++i) ; + // expected-warning@+2 {{extra tokens at the end of '#pragma omp simd' are ignored}} + // expected-error@+1 {{expected '('}} + #pragma omp simd safelen 4) + for (i = 0; i < 16; ++i) ; + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp simd safelen(4 + for (i = 0; i < 16; ++i) ; + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp simd safelen(4, + for (i = 0; i < 16; ++i) ; + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp simd safelen(4,) + for (i = 0; i < 16; ++i) ; + // xxpected-error@+1 {{expected expression}} + #pragma omp simd safelen(4) + for (i = 0; i < 16; ++i) ; + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp simd safelen(4 4) + for (i = 0; i < 16; ++i) ; + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp simd safelen(4,,4) + for (i = 0; i < 16; ++i) ; + #pragma omp simd safelen(4) + for (i = 0; i < 16; ++i) ; + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp simd safelen(4,8) + for (i = 0; i < 16; ++i) ; + // expected-error@+1 {{expression is not an integer constant expression}} + #pragma omp simd safelen(2.5) + for (i = 0; i < 16; ++i); + // expected-error@+1 {{expression is not an integer constant expression}} + #pragma omp simd safelen(foo()) + for (i = 0; i < 16; ++i); + // expected-error@+1 {{argument to 'safelen' clause must be a positive integer value}} + #pragma omp simd safelen(-5) + for (i = 0; i < 16; ++i); + // expected-error@+1 {{argument to 'safelen' clause must be a positive integer value}} + #pragma omp simd safelen(0) + for (i = 0; i < 16; ++i); + // expected-error@+1 {{argument to 'safelen' clause must be a positive integer value}} + #pragma omp simd safelen(5-5) + for (i = 0; i < 16; ++i); +} + void test_private() { int i; @@ -121,3 +190,4 @@ void test_firstprivate() #pragma omp simd firstprivate( for (i = 0; i < 16; ++i) ; } + diff --git a/test/OpenMP/simd_safelen_messages.cpp b/test/OpenMP/simd_safelen_messages.cpp new file mode 100644 index 0000000000..0e7e80dd97 --- /dev/null +++ b/test/OpenMP/simd_safelen_messages.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 %s + +void foo() { +} + +bool foobool(int argc) { + return argc; +} + +struct S1; // expected-note {{declared here}} + +template // expected-note {{declared here}} +T tmain(T argc, S **argv) { //expected-note 2 {{declared here}} + #pragma omp simd safelen // expected-error {{expected '(' after 'safelen'}} + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + #pragma omp simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + #pragma omp simd safelen () // expected-error {{expected expression}} + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + // expected-error@+3 {{expected ')'}} expected-note@+3 {{to match this '('}} + // expected-error@+2 2 {{expression is not an integral constant expression}} + // expected-note@+1 2 {{read of non-const variable 'argc' is not allowed in a constant expression}} + #pragma omp simd safelen (argc + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + // expected-error@+1 {{argument to 'safelen' clause must be a positive integer value}} + #pragma omp simd safelen (ST // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + #pragma omp simd safelen (1)) // expected-warning {{extra tokens at the end of '#pragma omp simd' are ignored}} + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + #pragma omp simd safelen ((ST > 0) ? 1 + ST : 2) + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + // expected-error@+3 2 {{directive '#pragma omp simd' cannot contain more than one 'safelen' clause}} + // expected-error@+2 2 {{argument to 'safelen' clause must be a positive integer value}} + // expected-error@+1 2 {{expression is not an integral constant expression}} + #pragma omp simd safelen (foobool(argc)), safelen (true), safelen (-5) + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + #pragma omp simd safelen (S) // expected-error {{'S' does not refer to a value}} + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + // expected-error@+1 2 {{expression is not an integral constant expression}} + #pragma omp simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + #pragma omp simd safelen (4) + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + #pragma omp simd safelen (N) // expected-error {{argument to 'safelen' clause must be a positive integer value}} + for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + return argc; +} + +int main(int argc, char **argv) { + #pragma omp simd safelen // expected-error {{expected '(' after 'safelen'}} + for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; + #pragma omp simd safelen ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; + #pragma omp simd safelen () // expected-error {{expected expression}} + for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; + #pragma omp simd safelen (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; + #pragma omp simd safelen (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp simd' are ignored}} + for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; + #pragma omp simd safelen (foobool(1) > 0 ? 1 : 2) // expected-error {{expression is not an integral constant expression}} + for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; + // expected-error@+3 {{expression is not an integral constant expression}} + // expected-error@+2 2 {{directive '#pragma omp simd' cannot contain more than one 'safelen' clause}} + // expected-error@+1 2 {{argument to 'safelen' clause must be a positive integer value}} + #pragma omp simd safelen (foobool(argc)), safelen (true), safelen (-5) + for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; + #pragma omp simd safelen (S1) // expected-error {{'S1' does not refer to a value}} + for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; + // expected-error@+1 {{expression is not an integral constant expression}} + #pragma omp simd safelen (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} + for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; + // expected-error@+3 {{statement after '#pragma omp simd' must be a for loop}} + // expected-note@+1 {{in instantiation of function template specialization 'tmain' requested here}} + #pragma omp simd safelen(safelen(tmain(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} + foo(); + // expected-note@+1 {{in instantiation of function template specialization 'tmain' requested here}} + return tmain(argc, argv); +} + diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 255e642b15..e3de44675f 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1932,6 +1932,10 @@ void OMPClauseEnqueue::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) { Visitor->AddStmt(C->getNumThreads()); } +void OMPClauseEnqueue::VisitOMPSafelenClause(const OMPSafelenClause *C) { + Visitor->AddStmt(C->getSafelen()); +} + void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) { } template