From: Alexander Musman Date: Tue, 27 May 2014 15:12:19 +0000 (+0000) Subject: Parsing/Sema for OMPCollapseClause. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=16bac88180640f1aa149823c8b9f2c1a664136d4;p=clang Parsing/Sema for OMPCollapseClause. Actual usage in Sema for collapsing loops will in some future patch. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209660 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h index 43fa147eea..109d623c79 100644 --- a/include/clang/AST/DataRecursiveASTVisitor.h +++ b/include/clang/AST/DataRecursiveASTVisitor.h @@ -2315,6 +2315,13 @@ bool RecursiveASTVisitor::VisitOMPSafelenClause(OMPSafelenClause *C) { return true; } +template +bool +RecursiveASTVisitor::VisitOMPCollapseClause(OMPCollapseClause *C) { + TraverseStmt(C->getNumForLoops()); + return true; +} + template bool RecursiveASTVisitor::VisitOMPDefaultClause(OMPDefaultClause *C) { return true; diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index 108238c092..2be6882f1d 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -306,6 +306,62 @@ public: StmtRange children() { return StmtRange(&Safelen, &Safelen + 1); } }; +/// \brief This represents 'collapse' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp simd collapse(3) +/// \endcode +/// In this example directive '#pragma omp simd' has clause 'collapse' +/// with single expression '3'. +/// The parameter must be a constant positive integer expression, it specifies +/// the number of nested loops that should be collapsed into a single iteration +/// space. +/// +class OMPCollapseClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Number of for-loops. + Stmt *NumForLoops; + + /// \brief Set the number of associated for-loops. + void setNumForLoops(Expr *Num) { NumForLoops = Num; } + +public: + /// \brief Build 'collapse' clause. + /// + /// \param Num Expression associated with this clause. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// + OMPCollapseClause(Expr *Num, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc) + : OMPClause(OMPC_collapse, StartLoc, EndLoc), LParenLoc(LParenLoc), + NumForLoops(Num) {} + + /// \brief Build an empty clause. + /// + explicit OMPCollapseClause() + : OMPClause(OMPC_collapse, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), NumForLoops(nullptr) {} + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Return the number of associated for-loops. + Expr *getNumForLoops() const { return cast_or_null(NumForLoops); } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_collapse; + } + + StmtRange children() { return StmtRange(&NumForLoops, &NumForLoops + 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 e1fa54829a..d000ae70e3 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -2331,13 +2331,19 @@ RecursiveASTVisitor::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) { return true; } -template +template bool RecursiveASTVisitor::VisitOMPSafelenClause(OMPSafelenClause *C) { TraverseStmt(C->getSafelen()); return true; } template +bool RecursiveASTVisitor::VisitOMPCollapseClause(OMPCollapseClause *C) { + TraverseStmt(C->getNumForLoops()); + 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 8977f99917..0adc9841e3 100644 --- a/include/clang/Basic/OpenMPKinds.def +++ b/include/clang/Basic/OpenMPKinds.def @@ -41,6 +41,7 @@ OPENMP_DIRECTIVE(simd) OPENMP_CLAUSE(if, OMPIfClause) OPENMP_CLAUSE(num_threads, OMPNumThreadsClause) OPENMP_CLAUSE(safelen, OMPSafelenClause) +OPENMP_CLAUSE(collapse, OMPCollapseClause) OPENMP_CLAUSE(default, OMPDefaultClause) OPENMP_CLAUSE(private, OMPPrivateClause) OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause) @@ -63,6 +64,7 @@ OPENMP_PARALLEL_CLAUSE(copyin) OPENMP_SIMD_CLAUSE(private) OPENMP_SIMD_CLAUSE(linear) OPENMP_SIMD_CLAUSE(safelen) +OPENMP_SIMD_CLAUSE(collapse) // Static attributes for 'default' clause. OPENMP_DEFAULT_KIND(none) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 4235c3d776..ecb405cb61 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -7334,6 +7334,10 @@ public: SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// \brief Called on well-formed 'collapse' clause. + OMPClause *ActOnOpenMPCollapseClause(Expr *Num, 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 e5f24dc5d5..0804d4089b 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -608,6 +608,12 @@ void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) { OS << ")"; } +void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) { + OS << "collapse("; + Node->getNumForLoops()->printPretty(OS, nullptr, 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 5dbaa0e832..9cff6d6743 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -279,6 +279,11 @@ void OMPClauseProfiler::VisitOMPSafelenClause(const OMPSafelenClause *C) { Profiler->VisitStmt(C->getSafelen()); } +void OMPClauseProfiler::VisitOMPCollapseClause(const OMPCollapseClause *C) { + if (C->getNumForLoops()) + Profiler->VisitStmt(C->getNumForLoops()); +} + void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { } void OMPClauseProfiler::VisitOMPProcBindClause(const OMPProcBindClause *C) { } diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp index f67cac8d40..c0142410b4 100644 --- a/lib/Basic/OpenMPKinds.cpp +++ b/lib/Basic/OpenMPKinds.cpp @@ -83,6 +83,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, case OMPC_if: case OMPC_num_threads: case OMPC_safelen: + case OMPC_collapse: case OMPC_private: case OMPC_firstprivate: case OMPC_shared: @@ -119,6 +120,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, case OMPC_if: case OMPC_num_threads: case OMPC_safelen: + case OMPC_collapse: case OMPC_private: case OMPC_firstprivate: case OMPC_shared: diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index dfd8ca7c2c..5916098ab1 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -257,7 +257,8 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, /// /// clause: /// if-clause | num_threads-clause | safelen-clause | default-clause | -/// private-clause | firstprivate-clause | shared-clause | linear-clause +/// private-clause | firstprivate-clause | shared-clause | linear-clause | +/// collapse-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -274,11 +275,13 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_if: case OMPC_num_threads: case OMPC_safelen: + case OMPC_collapse: // 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. + // Only one safelen clause can appear on a simd directive. + // Only one collapse clause can appear on a simd directive. if (!FirstClause) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind); @@ -334,6 +337,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, /// safelen-clause: /// 'safelen' '(' expression ')' /// +/// collapse-clause: +/// 'collapse' '(' expression ')' +/// OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) { SourceLocation Loc = ConsumeToken(); diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 18cfd43c80..39ec632735 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -809,6 +809,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, case OMPC_safelen: Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc); break; + case OMPC_collapse: + Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc); + break; case OMPC_default: case OMPC_proc_bind: case OMPC_private: @@ -950,6 +953,20 @@ OMPClause *Sema::ActOnOpenMPSafelenClause(Expr *Len, SourceLocation StartLoc, OMPSafelenClause(Safelen.take(), StartLoc, LParenLoc, EndLoc); } +OMPClause *Sema::ActOnOpenMPCollapseClause(Expr *Num, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + // OpenMP [2.8.1, simd construct, Description] + // The parameter of the collapse clause must be a constant + // positive integer expression. + ExprResult NumForLoops = + VerifyPositiveIntegerConstantInClause(Num, OMPC_collapse); + if (NumForLoops.isInvalid()) + return nullptr; + return new (Context) + OMPCollapseClause(NumForLoops.take(), StartLoc, LParenLoc, EndLoc); +} + OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, @@ -971,6 +988,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, case OMPC_if: case OMPC_num_threads: case OMPC_safelen: + case OMPC_collapse: case OMPC_private: case OMPC_firstprivate: case OMPC_shared: @@ -1086,6 +1104,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, case OMPC_if: case OMPC_num_threads: case OMPC_safelen: + case OMPC_collapse: case OMPC_default: case OMPC_proc_bind: case OMPC_threadprivate: diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index ef82b82146..3386b5bcee 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1333,6 +1333,17 @@ public: return getSema().ActOnOpenMPSafelenClause(Len, StartLoc, LParenLoc, EndLoc); } + /// \brief Build a new OpenMP 'collapse' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPCollapseClause(Expr *Num, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPCollapseClause(Num, StartLoc, LParenLoc, + EndLoc); + } + /// \brief Build a new OpenMP 'default' clause. /// /// By default, performs semantic analysis to build the new statement. @@ -6399,6 +6410,16 @@ TreeTransform::TransformOMPSafelenClause(OMPSafelenClause *C) { E.take(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd()); } +template +OMPClause * +TreeTransform::TransformOMPCollapseClause(OMPCollapseClause *C) { + ExprResult E = getDerived().TransformExpr(C->getNumForLoops()); + if (E.isInvalid()) + return 0; + return getDerived().RebuildOMPCollapseClause( + 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 b51f097638..89bc7fefa2 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1682,6 +1682,9 @@ OMPClause *OMPClauseReader::readClause() { case OMPC_safelen: C = new (Context) OMPSafelenClause(); break; + case OMPC_collapse: + C = new (Context) OMPCollapseClause(); + break; case OMPC_default: C = new (Context) OMPDefaultClause(); break; @@ -1726,6 +1729,11 @@ void OMPClauseReader::VisitOMPSafelenClause(OMPSafelenClause *C) { C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); } +void OMPClauseReader::VisitOMPCollapseClause(OMPCollapseClause *C) { + C->setNumForLoops(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 c827060d9d..a79772a533 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1690,6 +1690,11 @@ void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) { Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); } +void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) { + Writer->Writer.AddStmt(C->getNumForLoops()); + 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 5e8cbecfbc..efc65c9428 100644 --- a/test/OpenMP/simd_ast_print.cpp +++ b/test/OpenMP/simd_ast_print.cpp @@ -97,10 +97,10 @@ int main (int argc, char **argv) { for (int i=0; i < 2; ++i)*a=2; // CHECK-NEXT: for (int i = 0; i < 2; ++i) // CHECK-NEXT: *a = 2; -#pragma omp simd private(argc, b) +#pragma omp simd private(argc, b) collapse(2) for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) {foo(); k1 += 8; k2 += 8;} -// CHECK-NEXT: #pragma omp simd private(argc,b) +// CHECK-NEXT: #pragma omp simd private(argc,b) collapse(2) // CHECK-NEXT: for (int i = 0; i < 10; ++i) // CHECK-NEXT: for (int j = 0; j < 10; ++j) { // CHECK-NEXT: foo(); @@ -112,8 +112,8 @@ int main (int argc, char **argv) { // CHECK-NEXT: foo(); const int CLEN = 4; // CHECK-NEXT: const int CLEN = 4; - #pragma omp simd linear(a:CLEN) safelen(CLEN) -// CHECK-NEXT: #pragma omp simd linear(a: CLEN) safelen(CLEN) + #pragma omp simd linear(a:CLEN) safelen(CLEN) collapse( 1 ) +// CHECK-NEXT: #pragma omp simd linear(a: CLEN) safelen(CLEN) collapse(1) for (int i = 0; i < 10; ++i)foo(); // CHECK-NEXT: for (int i = 0; i < 10; ++i) // CHECK-NEXT: foo(); diff --git a/test/OpenMP/simd_collapse_messages.cpp b/test/OpenMP/simd_collapse_messages.cpp new file mode 100644 index 0000000000..eea9596ac3 --- /dev/null +++ b/test/OpenMP/simd_collapse_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 collapse // expected-error {{expected '(' after 'collapse'}} + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + #pragma omp simd collapse ( // 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 collapse () // 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 collapse (argc + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + // expected-error@+1 2 {{argument to 'collapse' clause must be a positive integer value}} + #pragma omp simd collapse (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 collapse (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 collapse ((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 'collapse' clause}} + // expected-error@+2 2 {{argument to 'collapse' clause must be a positive integer value}} + // expected-error@+1 2 {{expression is not an integral constant expression}} + #pragma omp simd collapse (foobool(argc)), collapse (true), collapse (-5) + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + #pragma omp simd collapse (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 collapse (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 collapse (1) + for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; + #pragma omp simd collapse (N) // expected-error {{argument to 'collapse' 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 collapse // expected-error {{expected '(' after 'collapse'}} + for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; + #pragma omp simd collapse ( // 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 collapse () // expected-error {{expected expression}} + for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; + #pragma omp simd collapse (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 collapse (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 collapse (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 'collapse' clause}} + // expected-error@+1 2 {{argument to 'collapse' clause must be a positive integer value}} + #pragma omp simd collapse (foobool(argc)), collapse (true), collapse (-5) + for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; + #pragma omp simd collapse (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 collapse (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 collapse(collapse(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/test/OpenMP/simd_misc_messages.c b/test/OpenMP/simd_misc_messages.c index 6e2f81cee1..58f10ac5da 100644 --- a/test/OpenMP/simd_misc_messages.c +++ b/test/OpenMP/simd_misc_messages.c @@ -146,6 +146,78 @@ void test_safelen() for (i = 0; i < 16; ++i); } +void test_collapse() +{ + int i; + // expected-error@+1 {{expected '('}} + #pragma omp simd collapse + for (i = 0; i < 16; ++i) ; + // expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} + #pragma omp simd collapse( + for (i = 0; i < 16; ++i) ; + // expected-error@+1 {{expected expression}} + #pragma omp simd collapse() + for (i = 0; i < 16; ++i) ; + // expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} + #pragma omp simd collapse(, + for (i = 0; i < 16; ++i) ; + // expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} + #pragma omp simd collapse(,) + 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 collapse 4) + for (i = 0; i < 16; ++i) ; + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp simd collapse(4 + for (i = 0; i < 16; ++i) ; + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp simd collapse(4, + for (i = 0; i < 16; ++i) ; + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp simd collapse(4,) + for (i = 0; i < 16; ++i) ; + // xxpected-error@+1 {{expected expression}} + #pragma omp simd collapse(4) + for (i = 0; i < 16; ++i) ; + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp simd collapse(4 4) + for (i = 0; i < 16; ++i) ; + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp simd collapse(4,,4) + for (i = 0; i < 16; ++i) ; + #pragma omp simd collapse(4) + for (int i1 = 0; i1 < 16; ++i1) + for (int i2 = 0; i2 < 16; ++i2) + for (int i3 = 0; i3 < 16; ++i3) + for (int i4 = 0; i4 < 16; ++i4) + foo(); + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp simd collapse(4,8) + for (i = 0; i < 16; ++i) ; + // expected-error@+1 {{expression is not an integer constant expression}} + #pragma omp simd collapse(2.5) + for (i = 0; i < 16; ++i); + // expected-error@+1 {{expression is not an integer constant expression}} + #pragma omp simd collapse(foo()) + for (i = 0; i < 16; ++i); + // expected-error@+1 {{argument to 'collapse' clause must be a positive integer value}} + #pragma omp simd collapse(-5) + for (i = 0; i < 16; ++i); + // expected-error@+1 {{argument to 'collapse' clause must be a positive integer value}} + #pragma omp simd collapse(0) + for (i = 0; i < 16; ++i); + // expected-error@+1 {{argument to 'collapse' clause must be a positive integer value}} + #pragma omp simd collapse(5-5) + for (i = 0; i < 16; ++i); +} + void test_linear() { int i; diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 5710d66890..bc1174ae3c 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1935,6 +1935,10 @@ void OMPClauseEnqueue::VisitOMPSafelenClause(const OMPSafelenClause *C) { Visitor->AddStmt(C->getSafelen()); } +void OMPClauseEnqueue::VisitOMPCollapseClause(const OMPCollapseClause *C) { + Visitor->AddStmt(C->getNumForLoops()); +} + void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) { } void OMPClauseEnqueue::VisitOMPProcBindClause(const OMPProcBindClause *C) { }