]> granicus.if.org Git - clang/commitdiff
[OPENMP] Additional checking for 'collapse' clause.
authorAlexey Bataev <a.bataev@hotmail.com>
Tue, 24 Jun 2014 12:55:56 +0000 (12:55 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Tue, 24 Jun 2014 12:55:56 +0000 (12:55 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@211589 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/StmtOpenMP.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaOpenMP.cpp
test/OpenMP/for_ast_print.cpp
test/OpenMP/for_collapse_messages.cpp
test/OpenMP/for_misc_messages.c
test/OpenMP/simd_collapse_messages.cpp
test/OpenMP/simd_misc_messages.c

index f8ba48ab0589c534d0eaf7f558c0711e464e9c1a..70a914f999c838656578da5626f4f4057fef4632 100644 (file)
@@ -67,8 +67,9 @@ protected:
   OMPExecutableDirective(const T *, StmtClass SC, OpenMPDirectiveKind K,
                          SourceLocation StartLoc, SourceLocation EndLoc,
                          unsigned NumClauses, unsigned NumChildren)
-      : Stmt(SC), Kind(K), StartLoc(StartLoc), EndLoc(EndLoc),
-        NumClauses(NumClauses), NumChildren(NumChildren),
+      : Stmt(SC), Kind(K), StartLoc(std::move(StartLoc)),
+        EndLoc(std::move(EndLoc)), NumClauses(NumClauses),
+        NumChildren(NumChildren),
         ClausesOffset(llvm::RoundUpToAlignment(sizeof(T),
                                                llvm::alignOf<OMPClause *>())) {}
 
@@ -85,6 +86,44 @@ protected:
   void setAssociatedStmt(Stmt *S) { *child_begin() = S; }
 
 public:
+  /// \brief Iterates over a filtered subrange of clauses applied to a
+  /// directive.
+  ///
+  /// This iterator visits only those declarations that meet some run-time
+  /// criteria.
+  template <class FilterPredicate> class filtered_clause_iterator {
+    ArrayRef<OMPClause *>::const_iterator Current;
+    ArrayRef<OMPClause *>::const_iterator End;
+    void SkipToNextClause() {
+      while (Current != End && !FilterPredicate()(*Current))
+        ++Current;
+    }
+
+  public:
+    typedef const OMPClause *value_type;
+    filtered_clause_iterator() : Current(), End() {}
+    explicit filtered_clause_iterator(ArrayRef<OMPClause *> Arr)
+        : Current(Arr.begin()), End(Arr.end()) {
+      SkipToNextClause();
+    }
+    value_type operator*() const { return *Current; }
+    value_type operator->() const { return *Current; }
+    filtered_clause_iterator &operator++() {
+      ++Current;
+      SkipToNextClause();
+      return *this;
+    }
+
+    filtered_clause_iterator operator++(int) {
+      filtered_clause_iterator tmp(*this);
+      ++(*this);
+      return tmp;
+    }
+
+    bool operator!() { return Current == End; }
+    operator bool() { return Current != End; }
+  };
+
   /// \brief Returns starting location of directive kind.
   SourceLocation getLocStart() const { return StartLoc; }
   /// \brief Returns ending location of directive.
index 98745ca9b8be5fca018e72f1095d0bb6a3714164..a189330d57769bd971ca53b10524299abdde6d33 100644 (file)
@@ -7020,7 +7020,10 @@ def note_omp_predetermined_dsa : Note<
 def err_omp_loop_var_dsa : Error<
   "loop iteration variable may not be %0">;
 def err_omp_not_for : Error<
-  "statement after '#pragma omp %0' must be a for loop">;
+  "%select{statement after '#pragma omp %1' must be a for loop|"
+  "expected %2 for loops after '#pragma omp %1'%select{|, but found only %4}3}0">;
+def note_omp_collapse_expr : Note<
+  "as specified in 'collapse' clause">;
 def err_omp_negative_expression_in_clause : Error<
   "argument to '%0' clause must be a positive integer value">;
 def err_omp_not_integral : Error<
index 561251c25655178fde6f622b4eb27379dc06b907..16def4ec90f2ba9cd915aee50b8fea3794f0ade3 100644 (file)
@@ -1391,13 +1391,22 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) {
 /// \brief Called on a for stmt to check and extract its iteration space
 /// for further processing (such as collapsing).
 static bool CheckOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S,
-                                      Sema &SemaRef, DSAStackTy &DSA) {
+                                      Sema &SemaRef, DSAStackTy &DSA,
+                                      unsigned CurrentNestedLoopCount,
+                                      unsigned NestedLoopCount,
+                                      Expr *NestedLoopCountExpr) {
   // OpenMP [2.6, Canonical Loop Form]
   //   for (init-expr; test-expr; incr-expr) structured-block
   auto For = dyn_cast_or_null<ForStmt>(S);
   if (!For) {
     SemaRef.Diag(S->getLocStart(), diag::err_omp_not_for)
-        << getOpenMPDirectiveName(DKind);
+        << (NestedLoopCountExpr != nullptr) << getOpenMPDirectiveName(DKind)
+        << NestedLoopCount << (CurrentNestedLoopCount > 0)
+        << CurrentNestedLoopCount;
+    if (NestedLoopCount > 1)
+      SemaRef.Diag(NestedLoopCountExpr->getExprLoc(),
+                   diag::note_omp_collapse_expr)
+          << NestedLoopCountExpr->getSourceRange();
     return true;
   }
   assert(For->getBody());
@@ -1491,14 +1500,21 @@ static Stmt *IgnoreContainerStmts(Stmt *S, bool IgnoreCaptured) {
 }
 
 /// \brief Called on a for stmt to check itself and nested loops (if any).
-static bool CheckOpenMPLoop(OpenMPDirectiveKind DKind, unsigned NestedLoopCount,
+static bool CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr,
                             Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA) {
+  unsigned NestedLoopCount = 1;
+  if (NestedLoopCountExpr) {
+    // Found 'collapse' clause - calculate collapse number.
+    llvm::APSInt Result;
+    if (NestedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext()))
+      NestedLoopCount = Result.getLimitedValue();
+  }
   // This is helper routine for loop directives (e.g., 'for', 'simd',
   // 'for simd', etc.).
-  assert(NestedLoopCount == 1);
   Stmt *CurStmt = IgnoreContainerStmts(AStmt, true);
   for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
-    if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA))
+    if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt,
+                                  NestedLoopCount, NestedLoopCountExpr))
       return true;
     // Move on to the next nested for loop, or to the loop body.
     CurStmt = IgnoreContainerStmts(cast<ForStmt>(CurStmt)->getBody(), false);
@@ -1509,12 +1525,29 @@ static bool CheckOpenMPLoop(OpenMPDirectiveKind DKind, unsigned NestedLoopCount,
   return false;
 }
 
+namespace {
+struct OMPCollapseClauseFilter {
+  OMPCollapseClauseFilter() {}
+  bool operator()(const OMPClause *C) {
+    return C->getClauseKind() == OMPC_collapse;
+  }
+};
+} // namespace
+
+static Expr *GetCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) {
+  OMPExecutableDirective::filtered_clause_iterator<OMPCollapseClauseFilter> I(
+      Clauses);
+  if (I)
+    return cast<OMPCollapseClause>(*I)->getNumForLoops();
+  return nullptr;
+}
+
 StmtResult Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses,
                                           Stmt *AStmt, SourceLocation StartLoc,
                                           SourceLocation EndLoc) {
   // In presence of clause 'collapse', it will define the nested loops number.
-  // For now, pass default value of 1.
-  if (CheckOpenMPLoop(OMPD_simd, 1, AStmt, *this, *DSAStack))
+  if (CheckOpenMPLoop(OMPD_simd, GetCollapseNumberExpr(Clauses),
+                      AStmt, *this, *DSAStack))
     return StmtError();
 
   getCurFunction()->setHasBranchProtectedScope();
@@ -1525,8 +1558,8 @@ StmtResult Sema::ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses,
                                          Stmt *AStmt, SourceLocation StartLoc,
                                          SourceLocation EndLoc) {
   // In presence of clause 'collapse', it will define the nested loops number.
-  // For now, pass default value of 1.
-  if (CheckOpenMPLoop(OMPD_for, 1, AStmt, *this, *DSAStack))
+  if (CheckOpenMPLoop(OMPD_for, GetCollapseNumberExpr(Clauses),
+                      AStmt, *this, *DSAStack))
     return StmtError();
 
   getCurFunction()->setHasBranchProtectedScope();
index 838eb4e923a4758ba7ced9de4b0931c471e8172a..8802237b2574fd749e46240bc161a29464c87a06 100644 (file)
@@ -23,11 +23,17 @@ T tmain(T argc) {
 #pragma omp for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered nowait
   for (int i = 0; i < 10; ++i)
     for (int j = 0; j < 10; ++j)
-      foo();
+      for (int j = 0; j < 10; ++j)
+        for (int j = 0; j < 10; ++j)
+          for (int j = 0; j < 10; ++j)
+            foo();
   // CHECK-NEXT: #pragma omp parallel
   // CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered nowait
   // CHECK-NEXT: for (int i = 0; i < 10; ++i)
   // CHECK-NEXT: for (int j = 0; j < 10; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 10; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 10; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 10; ++j)
   // CHECK-NEXT: foo();
   return T();
 }
index 975c4fa6e71cd0f5b9b0fc124cfe2c55f02a8141..9e14234e07239fec567a6ddc5cdbd93687d70efc 100644 (file)
@@ -27,8 +27,8 @@ T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp for collapse (1)) // expected-warning {{extra tokens at the end of '#pragma omp for' are ignored}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
-  #pragma omp for collapse ((ST > 0) ? 1 + ST : 2)
-  for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
+  #pragma omp for collapse ((ST > 0) ? 1 + ST : 2) // expected-note 2 {{as specified in 'collapse' clause}}
+  for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp for', but found only 1}}
   // expected-error@+3 2 {{directive '#pragma omp for' 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}}
@@ -43,6 +43,8 @@ T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
   for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST];
   #pragma omp for 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];
+  #pragma omp for collapse (2) // expected-note {{as specified in 'collapse' clause}}
+  foo(); // expected-error {{expected 2 for loops after '#pragma omp for'}}
   return argc;
 }
 
@@ -53,10 +55,10 @@ int main(int argc, char **argv) {
   for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
   #pragma omp for collapse () // expected-error {{expected expression}}
   for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
-  #pragma omp for 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 for collapse (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp for' are ignored}}
-  for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4];
+  #pragma omp for collapse (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{as specified in 'collapse' clause}}
+  for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp for', but found only 1}}
+  #pragma omp for collapse (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp for' are ignored}}  expected-note {{as specified in 'collapse' clause}}
+  for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp for', but found only 1}}
   #pragma omp for 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}}
@@ -73,6 +75,8 @@ int main(int argc, char **argv) {
   // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
   #pragma omp for collapse(collapse(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
   foo();
+  #pragma omp for collapse (2) // expected-note {{as specified in 'collapse' clause}}
+  foo(); // expected-error {{expected 2 for loops after '#pragma omp for'}}
   // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, 1, 0>' requested here}}
   return tmain<int, char, 1, 0>(argc, argv);
 }
index 9b3f290d0e72f356123618763ff51c9103551c6c..854898c04432e491d4d1d20c98e1e178574a2c3b 100644 (file)
@@ -119,38 +119,39 @@ void test_collapse() {
     ;
 #pragma omp parallel
 // expected-error@+2 {{expected ')'}}
-// expected-note@+1 {{to match this '('}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
 #pragma omp for collapse(4
   for (i = 0; i < 16; ++i)
-    ;
+    ; // expected-error {{expected 4 for loops after '#pragma omp for', but found only 1}}
 #pragma omp parallel
 // expected-error@+2 {{expected ')'}}
-// expected-note@+1 {{to match this '('}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
 #pragma omp for collapse(4,
   for (i = 0; i < 16; ++i)
-    ;
+    ; // expected-error {{expected 4 for loops after '#pragma omp for', but found only 1}}
 #pragma omp parallel
 // expected-error@+2 {{expected ')'}}
-// expected-note@+1 {{to match this '('}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
 #pragma omp for collapse(4, )
   for (i = 0; i < 16; ++i)
-    ;
+    ; // expected-error {{expected 4 for loops after '#pragma omp for', but found only 1}}
 #pragma omp parallel
+// expected-note@+1 {{as specified in 'collapse' clause}}
 #pragma omp for collapse(4)
   for (i = 0; i < 16; ++i)
-    ;
+    ; // expected-error {{expected 4 for loops after '#pragma omp for', but found only 1}}
 #pragma omp parallel
 // expected-error@+2 {{expected ')'}}
-// expected-note@+1 {{to match this '('}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
 #pragma omp for collapse(4 4)
   for (i = 0; i < 16; ++i)
-    ;
+    ; // expected-error {{expected 4 for loops after '#pragma omp for', but found only 1}}
 #pragma omp parallel
 // expected-error@+2 {{expected ')'}}
-// expected-note@+1 {{to match this '('}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
 #pragma omp for collapse(4, , 4)
   for (i = 0; i < 16; ++i)
-    ;
+    ; // expected-error {{expected 4 for loops after '#pragma omp for', but found only 1}}
 #pragma omp parallel
 #pragma omp for collapse(4)
   for (int i1 = 0; i1 < 16; ++i1)
@@ -160,10 +161,10 @@ void test_collapse() {
           foo();
 #pragma omp parallel
 // expected-error@+2 {{expected ')'}}
-// expected-note@+1 {{to match this '('}}
+// expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
 #pragma omp for collapse(4, 8)
   for (i = 0; i < 16; ++i)
-    ;
+    ; // expected-error {{expected 4 for loops after '#pragma omp for', but found only 1}}
 #pragma omp parallel
 // expected-error@+1 {{expression is not an integer constant expression}}
 #pragma omp for collapse(2.5)
index eea9596ac3b62a56db875d84422bc80b5b0276a2..56523b33726cb10b55d771572632063eed1d9d01 100644 (file)
@@ -27,8 +27,8 @@ T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
   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];
+  #pragma omp simd collapse ((ST > 0) ? 1 + ST : 2) // expected-note 2 {{as specified in 'collapse' clause}}
+  for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; // expected-error 2 {{expected 2 for loops after '#pragma omp simd', but found only 1}}
   // 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}}
@@ -43,6 +43,8 @@ T tmain(T argc, S **argv) { //expected-note 2 {{declared here}}
   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];
+  #pragma omp simd collapse (2) // expected-note {{as specified in 'collapse' clause}}
+  foo(); // expected-error {{expected 2 for loops after '#pragma omp simd'}}
   return argc;
 }
 
@@ -53,10 +55,10 @@ int main(int argc, char **argv) {
   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 (4 // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{as specified in 'collapse' clause}}
+  for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp simd', but found only 1}}
+  #pragma omp simd collapse (2+2)) // expected-warning {{extra tokens at the end of '#pragma omp simd' are ignored}} expected-note {{as specified in 'collapse' clause}}
+  for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i-4]; // expected-error {{expected 4 for loops after '#pragma omp simd', but found only 1}}
   #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}}
@@ -69,6 +71,8 @@ int main(int argc, char **argv) {
   // 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];
+  #pragma omp simd collapse (2) // expected-note {{as specified in 'collapse' clause}}
+  foo(); // expected-error {{expected 2 for loops after '#pragma omp simd'}}
   // expected-error@+3 {{statement after '#pragma omp simd' must be a for loop}}
   // expected-note@+1 {{in instantiation of function template specialization 'tmain<int, char, -1, -2>' requested here}}
   #pragma omp simd collapse(collapse(tmain<int, char, -1, -2>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}}
index 20c14f6fc2b6caf2f780c29df4b393054b470064..4a41bffbda913b77f804450815e7396873933562 100644 (file)
@@ -169,28 +169,28 @@ void test_collapse()
   #pragma omp simd collapse 4)
   for (i = 0; i < 16; ++i) ;
   // expected-error@+2 {{expected ')'}}
-  // expected-note@+1 {{to match this '('}}
+  // expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
   #pragma omp simd collapse(4
-  for (i = 0; i < 16; ++i) ;
+  for (i = 0; i < 16; ++i) ; // expected-error {{expected 4 for loops after '#pragma omp simd', but found only 1}}
   // expected-error@+2 {{expected ')'}}
-  // expected-note@+1 {{to match this '('}}
+  // expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
   #pragma omp simd collapse(4,
-  for (i = 0; i < 16; ++i) ;
+  for (i = 0; i < 16; ++i) ; // expected-error {{expected 4 for loops after '#pragma omp simd', but found only 1}}
   // expected-error@+2 {{expected ')'}}
-  // expected-note@+1 {{to match this '('}}
+  // expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
   #pragma omp simd collapse(4,)
-  for (i = 0; i < 16; ++i) ;
-  // xxpected-error@+1 {{expected expression}}
+  for (i = 0; i < 16; ++i) ; // expected-error {{expected 4 for loops after '#pragma omp simd', but found only 1}}
+  // xxpected-error@+1 {{expected expression}} expected-note@+1 {{as specified in 'collapse' clause}}
   #pragma omp simd collapse(4)
-  for (i = 0; i < 16; ++i) ;
+  for (i = 0; i < 16; ++i) ; // expected-error {{expected 4 for loops after '#pragma omp simd', but found only 1}}
   // expected-error@+2 {{expected ')'}}
-  // expected-note@+1 {{to match this '('}}
+  // expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
   #pragma omp simd collapse(4 4)
-  for (i = 0; i < 16; ++i) ;
+  for (i = 0; i < 16; ++i) ; // expected-error {{expected 4 for loops after '#pragma omp simd', but found only 1}}
   // expected-error@+2 {{expected ')'}}
-  // expected-note@+1 {{to match this '('}}
+  // expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
   #pragma omp simd collapse(4,,4)
-  for (i = 0; i < 16; ++i) ;
+  for (i = 0; i < 16; ++i) ; // expected-error {{expected 4 for loops after '#pragma omp simd', but found only 1}}
   #pragma omp simd collapse(4)
   for (int i1 = 0; i1 < 16; ++i1)
     for (int i2 = 0; i2 < 16; ++i2)
@@ -198,9 +198,9 @@ void test_collapse()
         for (int i4 = 0; i4 < 16; ++i4)
           foo();
   // expected-error@+2 {{expected ')'}}
-  // expected-note@+1 {{to match this '('}}
+  // expected-note@+1 {{to match this '('}} expected-note@+1 {{as specified in 'collapse' clause}}
   #pragma omp simd collapse(4,8)
-  for (i = 0; i < 16; ++i) ;
+  for (i = 0; i < 16; ++i) ; // expected-error {{expected 4 for loops after '#pragma omp simd', but found only 1}}
   // expected-error@+1 {{expression is not an integer constant expression}}
   #pragma omp simd collapse(2.5)
   for (i = 0; i < 16; ++i);