r243969 - [OPENMP 4.1] Support for 'linear' clause in loop directives.

Alexey Bataev a.bataev at hotmail.com
Tue Aug 4 04:18:20 PDT 2015


Author: abataev
Date: Tue Aug  4 06:18:19 2015
New Revision: 243969

URL: http://llvm.org/viewvc/llvm-project?rev=243969&view=rev
Log:
[OPENMP 4.1] Support for  'linear' clause in loop directives.

OpenMP 4.1 allows 'linear' clause in loop directives. Patch adds support for it.

Added:
    cfe/trunk/test/OpenMP/for_linear_codegen.cpp   (with props)
    cfe/trunk/test/OpenMP/for_linear_messages.cpp   (with props)
    cfe/trunk/test/OpenMP/parallel_for_linear_codegen.cpp   (with props)
    cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp   (with props)
Modified:
    cfe/trunk/include/clang/Basic/OpenMPKinds.def
    cfe/trunk/lib/Sema/SemaOpenMP.cpp
    cfe/trunk/test/OpenMP/for_ast_print.cpp
    cfe/trunk/test/OpenMP/for_firstprivate_messages.cpp
    cfe/trunk/test/OpenMP/for_lastprivate_messages.cpp
    cfe/trunk/test/OpenMP/for_loop_messages.cpp
    cfe/trunk/test/OpenMP/for_misc_messages.c
    cfe/trunk/test/OpenMP/parallel_for_ast_print.cpp
    cfe/trunk/test/OpenMP/parallel_for_firstprivate_messages.cpp
    cfe/trunk/test/OpenMP/parallel_for_lastprivate_messages.cpp
    cfe/trunk/test/OpenMP/parallel_for_loop_messages.cpp
    cfe/trunk/test/OpenMP/parallel_for_misc_messages.c

Modified: cfe/trunk/include/clang/Basic/OpenMPKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenMPKinds.def?rev=243969&r1=243968&r2=243969&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/OpenMPKinds.def (original)
+++ cfe/trunk/include/clang/Basic/OpenMPKinds.def Tue Aug  4 06:18:19 2015
@@ -163,6 +163,7 @@ OPENMP_FOR_CLAUSE(collapse)
 OPENMP_FOR_CLAUSE(schedule)
 OPENMP_FOR_CLAUSE(ordered)
 OPENMP_FOR_CLAUSE(nowait)
+OPENMP_FOR_CLAUSE(linear)
 
 // Clauses allowed for directive 'omp for simd'.
 OPENMP_FOR_SIMD_CLAUSE(private)
@@ -224,6 +225,7 @@ OPENMP_PARALLEL_FOR_CLAUSE(lastprivate)
 OPENMP_PARALLEL_FOR_CLAUSE(collapse)
 OPENMP_PARALLEL_FOR_CLAUSE(schedule)
 OPENMP_PARALLEL_FOR_CLAUSE(ordered)
+OPENMP_PARALLEL_FOR_CLAUSE(linear)
 
 // Clauses allowed for OpenMP directive 'parallel for simd'.
 OPENMP_PARALLEL_FOR_SIMD_CLAUSE(if)

Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=243969&r1=243968&r2=243969&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Tue Aug  4 06:18:19 2015
@@ -3384,6 +3384,16 @@ StmtResult Sema::ActOnOpenMPForDirective
   assert((CurContext->isDependentContext() || B.builtAll()) &&
          "omp for loop exprs were not built");
 
+  if (!CurContext->isDependentContext()) {
+    // Finalize the clauses that need pre-built expressions for CodeGen.
+    for (auto C : Clauses) {
+      if (auto LC = dyn_cast<OMPLinearClause>(C))
+        if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+                                     B.NumIterations, *this, CurScope))
+          return StmtError();
+    }
+  }
+
   getCurFunction()->setHasBranchProtectedScope();
   return OMPForDirective::Create(Context, StartLoc, EndLoc, NestedLoopCount,
                                  Clauses, AStmt, B);
@@ -3540,6 +3550,16 @@ StmtResult Sema::ActOnOpenMPParallelForD
   assert((CurContext->isDependentContext() || B.builtAll()) &&
          "omp parallel for loop exprs were not built");
 
+  if (!CurContext->isDependentContext()) {
+    // Finalize the clauses that need pre-built expressions for CodeGen.
+    for (auto C : Clauses) {
+      if (auto LC = dyn_cast<OMPLinearClause>(C))
+        if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
+                                     B.NumIterations, *this, CurScope))
+          return StmtError();
+    }
+  }
+
   getCurFunction()->setHasBranchProtectedScope();
   return OMPParallelForDirective::Create(Context, StartLoc, EndLoc,
                                          NestedLoopCount, Clauses, AStmt, B);

Modified: cfe/trunk/test/OpenMP/for_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_ast_print.cpp?rev=243969&r1=243968&r2=243969&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/for_ast_print.cpp Tue Aug  4 06:18:19 2015
@@ -13,37 +13,37 @@ T tmain(T argc) {
   T b = argc, c, d, e, f, g;
   static T a;
 // CHECK: static T a;
-#pragma omp for schedule(dynamic)
-  // CHECK-NEXT: #pragma omp for schedule(dynamic)
+#pragma omp for schedule(dynamic) linear(a)
+  // CHECK-NEXT: #pragma omp for schedule(dynamic) linear(a)
   for (int i = 0; i < 2; ++i)
     a = 2;
 // CHECK-NEXT: for (int i = 0; i < 2; ++i)
 // CHECK-NEXT: a = 2;
 #pragma omp parallel
-#pragma omp for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered(N) nowait
-  for (int i = 0; i < 10; ++i)
-    for (int j = 0; j < 10; ++j)
-      for (int j = 0; j < 10; ++j)
-        for (int j = 0; j < 10; ++j)
-          for (int j = 0; j < 10; ++j)
-  for (int i = 0; i < 10; ++i)
-    for (int j = 0; j < 10; ++j)
-      for (int j = 0; j < 10; ++j)
-        for (int j = 0; j < 10; ++j)
-          for (int j = 0; j < 10; ++j)
+#pragma omp for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered(N) nowait linear(a : N)
+  for (int i = 0; i < 2; ++i)
+    for (int j = 0; j < 2; ++j)
+      for (int j = 0; j < 2; ++j)
+        for (int j = 0; j < 2; ++j)
+          for (int j = 0; j < 2; ++j)
+  for (int i = 0; i < 2; ++i)
+    for (int j = 0; j < 2; ++j)
+      for (int j = 0; j < 2; ++j)
+        for (int j = 0; j < 2; ++j)
+          for (int j = 0; j < 2; ++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(N) 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: 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: #pragma omp for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered(N) nowait linear(a: N)
+  // CHECK-NEXT: for (int i = 0; i < 2; ++i)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int i = 0; i < 2; ++i)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
   // CHECK-NEXT: foo();
   return T();
 }
@@ -59,12 +59,12 @@ int main(int argc, char **argv) {
 // CHECK-NEXT: for (int i = 0; i < 2; ++i)
 // CHECK-NEXT: a = 2;
 #pragma omp parallel
-#pragma omp for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) schedule(auto) ordered nowait
+#pragma omp for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) schedule(auto) ordered nowait linear(g:-1)
   for (int i = 0; i < 10; ++i)
     for (int j = 0; j < 10; ++j)
       foo();
   // CHECK-NEXT: #pragma omp parallel
-  // CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) schedule(auto) ordered nowait
+  // CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) schedule(auto) ordered nowait linear(g: -1)
   // CHECK-NEXT: for (int i = 0; i < 10; ++i)
   // CHECK-NEXT: for (int j = 0; j < 10; ++j)
   // CHECK-NEXT: foo();

Modified: cfe/trunk/test/OpenMP/for_firstprivate_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_firstprivate_messages.cpp?rev=243969&r1=243968&r2=243969&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_firstprivate_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_firstprivate_messages.cpp Tue Aug  4 06:18:19 2015
@@ -115,10 +115,6 @@ int foomain(int argc, char **argv) {
   for (int k = 0; k < argc; ++k)
     ++k;
 #pragma omp parallel
-#pragma omp for linear(i) // expected-error {{unexpected OpenMP clause 'linear' in directive '#pragma omp for'}}
-  for (int k = 0; k < argc; ++k)
-    ++k;
-#pragma omp parallel
   {
     int v = 0;
     int i;                      // expected-note {{variable with automatic storage duration is predetermined as private; perhaps you forget to enclose 'omp for' directive into a parallel or another task region?}}

Modified: cfe/trunk/test/OpenMP/for_lastprivate_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_lastprivate_messages.cpp?rev=243969&r1=243968&r2=243969&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_lastprivate_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_lastprivate_messages.cpp Tue Aug  4 06:18:19 2015
@@ -117,10 +117,6 @@ int foomain(int argc, char **argv) {
   for (int k = 0; k < argc; ++k)
     ++k;
 #pragma omp parallel
-#pragma omp for linear(i) // expected-error {{unexpected OpenMP clause 'linear' in directive '#pragma omp for'}}
-  for (int k = 0; k < argc; ++k)
-    ++k;
-#pragma omp parallel
   {
     int v = 0;
     int i;                     // expected-note {{variable with automatic storage duration is predetermined as private; perhaps you forget to enclose 'omp for' directive into a parallel or another task region?}}

Added: cfe/trunk/test/OpenMP/for_linear_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_linear_codegen.cpp?rev=243969&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/for_linear_codegen.cpp (added)
+++ cfe/trunk/test/OpenMP/for_linear_codegen.cpp Tue Aug  4 06:18:19 2015
@@ -0,0 +1,263 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+// expected-no-diagnostics
+// REQUIRES: x86-registered-target
+#ifndef HEADER
+#define HEADER
+
+template <class T>
+struct S {
+  T f;
+  S(T a) : f(a) {}
+  S() : f() {}
+  S<T> &operator=(const S<T> &);
+  operator T() { return T(); }
+  ~S() {}
+};
+
+volatile int g = 1212;
+float f;
+char cnt;
+
+// CHECK: [[S_FLOAT_TY:%.+]] = type { float }
+// CHECK: [[CAP_MAIN_TY:%.+]] = type { float**, i64* }
+// CHECK: [[S_INT_TY:%.+]] = type { i32 }
+// CHECK: [[CAP_TMAIN_TY:%.+]] = type { i32**, i32* }
+// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
+// CHECK-DAG: [[F:@.+]] = global float 0.0
+// CHECK-DAG: [[CNT:@.+]] = global i8 0
+template <typename T>
+T tmain() {
+  S<T> test;
+  T *pvar = &test.f;
+  T lvar = T();
+#pragma omp parallel
+#pragma omp for linear(pvar, lvar)
+  for (int i = 0; i < 2; ++i) {
+    ++pvar, ++lvar;
+  }
+  return T();
+}
+
+int main() {
+#ifdef LAMBDA
+  // LAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212,
+  // LAMBDA-LABEL: @main
+  // LAMBDA: call void [[OUTER_LAMBDA:@.+]](
+  [&]() {
+  // LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
+  // LAMBDA: call void {{.+}} @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i8* %{{.+}})
+#pragma omp parallel
+#pragma omp for linear(g:5)
+  for (int i = 0; i < 2; ++i) {
+    // LAMBDA: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]])
+    // LAMBDA: alloca i{{[0-9]+}},
+    // LAMBDA: [[G_START_ADDR:%.+]] = alloca i{{[0-9]+}},
+    // LAMBDA: alloca i{{[0-9]+}},
+    // LAMBDA: alloca i{{[0-9]+}},
+    // LAMBDA: alloca i{{[0-9]+}},
+    // LAMBDA: alloca i{{[0-9]+}},
+    // LAMBDA: alloca i{{[0-9]+}},
+    // LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
+    // LAMBDA: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]],
+    // LAMBDA: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %{{.+}}
+    // LAMBDA: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
+    // LAMBDA: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1)
+    // LAMBDA: [[VAL:%.+]] = load i32, i32* [[G_START_ADDR]]
+    // LAMBDA: [[CNT:%.+]] = load i32, i32*
+    // LAMBDA: [[MUL:%.+]] = mul nsw i32 [[CNT]], 5
+    // LAMBDA: [[ADD:%.+]] = add nsw i32 [[VAL]], [[MUL]]
+    // LAMBDA: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]],
+    // LAMBDA: [[VAL:%.+]] = load i32, i32* [[G_PRIVATE_ADDR]],
+    // LAMBDA: [[ADD:%.+]] = add nsw i32 [[VAL]], 5
+    // LAMBDA: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]],
+    // LAMBDA: [[G_PRIVATE_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+    // LAMBDA: store i{{[0-9]+}}* [[G_PRIVATE_ADDR]], i{{[0-9]+}}** [[G_PRIVATE_ADDR_REF]]
+    // LAMBDA: call void [[INNER_LAMBDA:@.+]](%{{.+}}* [[ARG]])
+    // LAMBDA: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 [[GTID]])
+    g += 5;
+    // LAMBDA: call i32 @__kmpc_cancel_barrier(%{{.+}}* @{{.+}}, i{{[0-9]+}} [[GTID]])
+    [&]() {
+      // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]])
+      // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]],
+      g = 2;
+      // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]]
+      // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+      // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_PTR_REF]]
+      // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[G_REF]]
+    }();
+  }
+  }();
+  return 0;
+#elif defined(BLOCKS)
+  // BLOCKS: [[G:@.+]] = global i{{[0-9]+}} 1212,
+  // BLOCKS-LABEL: @main
+  // BLOCKS: call void {{%.+}}(i8
+  ^{
+  // BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8*
+  // BLOCKS: call void {{.+}} @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i8* %{{.+}})
+#pragma omp parallel
+#pragma omp for linear(g:5)
+  for (int i = 0; i < 2; ++i) {
+    // BLOCKS: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]])
+    // BLOCKS: alloca i{{[0-9]+}},
+    // BLOCKS: [[G_START_ADDR:%.+]] = alloca i{{[0-9]+}},
+    // BLOCKS: alloca i{{[0-9]+}},
+    // BLOCKS: alloca i{{[0-9]+}},
+    // BLOCKS: alloca i{{[0-9]+}},
+    // BLOCKS: alloca i{{[0-9]+}},
+    // BLOCKS: alloca i{{[0-9]+}},
+    // BLOCKS: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
+    // BLOCKS: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]],
+    // BLOCKS: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %{{.+}}
+    // BLOCKS: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
+    // BLOCKS: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1)
+    // BLOCKS: [[VAL:%.+]] = load i32, i32* [[G_START_ADDR]]
+    // BLOCKS: [[CNT:%.+]] = load i32, i32*
+    // BLOCKS: [[MUL:%.+]] = mul nsw i32 [[CNT]], 5
+    // BLOCKS: [[ADD:%.+]] = add nsw i32 [[VAL]], [[MUL]]
+    // BLOCKS: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]],
+    // BLOCKS: [[VAL:%.+]] = load i32, i32* [[G_PRIVATE_ADDR]],
+    // BLOCKS: [[ADD:%.+]] = add nsw i32 [[VAL]], 5
+    // BLOCKS: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]],
+    // BLOCKS-NOT: [[G]]{{[[^:word:]]}}
+    // BLOCKS: i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
+    // BLOCKS-NOT: [[G]]{{[[^:word:]]}}
+    // BLOCKS: call void {{%.+}}(i8
+    // BLOCKS: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 [[GTID]])
+    g += 5;
+    // BLOCKS: call i32 @__kmpc_cancel_barrier(%{{.+}}* @{{.+}}, i{{[0-9]+}} [[GTID]])
+    g = 1;
+    ^{
+      // BLOCKS: define {{.+}} void {{@.+}}(i8*
+      g = 2;
+      // BLOCKS-NOT: [[G]]{{[[^:word:]]}}
+      // BLOCKS: store i{{[0-9]+}} 2, i{{[0-9]+}}*
+      // BLOCKS-NOT: [[G]]{{[[^:word:]]}}
+      // BLOCKS: ret
+    }();
+  }
+  }();
+  return 0;
+#else
+  S<float> test;
+  float *pvar = &test.f;
+  long long lvar = 0;
+#pragma omp parallel
+#pragma omp for linear(pvar, lvar : 3)
+  for (int i = 0; i < 2; ++i) {
+    pvar += 3, lvar += 3;
+  }
+  return tmain<int>();
+#endif
+}
+
+// CHECK: define i{{[0-9]+}} @main()
+// CHECK: [[TEST:%.+]] = alloca [[S_FLOAT_TY]],
+// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
+// CHECK: %{{.+}} = bitcast [[CAP_MAIN_TY]]*
+// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[CAP_MAIN_TY]]*)* [[MAIN_MICROTASK:@.+]] to void
+// CHECK: = call {{.+}} [[TMAIN_INT:@.+]]()
+// CHECK: call void [[S_FLOAT_TY_DESTR:@.+]]([[S_FLOAT_TY]]*
+// CHECK: ret
+
+// CHECK: define internal void [[MAIN_MICROTASK]](i{{[0-9]+}}* [[GTID_ADDR:%.+]], i{{[0-9]+}}* %{{.+}}, [[CAP_MAIN_TY]]* %{{.+}})
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[PVAR_START:%.+]] = alloca float*,
+// CHECK: [[LVAR_START:%.+]] = alloca i64,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[PVAR_PRIV:%.+]] = alloca float*,
+// CHECK: [[LVAR_PRIV:%.+]] = alloca i64,
+// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]]
+
+// Check for default initialization.
+// CHECK: [[PVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: [[PVAR_REF:%.+]] = load float**, float*** [[PVAR_PTR_REF]],
+// CHECK: [[PVAR_VAL:%.+]] = load float*, float** [[PVAR_REF]],
+// CHECK: store float* [[PVAR_VAL]], float** [[PVAR_START]],
+// CHECK: [[LVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1
+// CHECK: [[LVAR_REF:%.+]] = load i64*, i64** [[LVAR_PTR_REF]],
+// CHECK: [[LVAR_VAL:%.+]] = load i64, i64* [[LVAR_REF]],
+// CHECK: store i64 [[LVAR_VAL]], i64* [[LVAR_START]],
+// CHECK: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID:%.+]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1)
+// CHECK: [[PVAR_VAL:%.+]] = load float*, float** [[PVAR_START]],
+// CHECK: [[CNT:%.+]] = load i32, i32*
+// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 3
+// CHECK: [[IDX:%.+]] = sext i32 [[MUL]] to i64
+// CHECK: [[PTR:%.+]] = getelementptr inbounds float, float* [[PVAR_VAL]], i64 [[IDX]]
+// CHECK: store float* [[PTR]], float** [[PVAR_PRIV]],
+// CHECK: [[LVAR_VAL:%.+]] = load i64, i64* [[LVAR_START]],
+// CHECK: [[CNT:%.+]] = load i32, i32*
+// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 3
+// CHECK: [[CONV:%.+]] = sext i32 [[MUL]] to i64
+// CHECK: [[VAL:%.+]] = add nsw i64 [[LVAR_VAL]], [[CONV]]
+// CHECK: store i64 [[VAL]], i64* [[LVAR_PRIV]],
+// CHECK: [[PVAR_VAL:%.+]] = load float*, float** [[PVAR_PRIV]]
+// CHECK: [[PTR:%.+]] = getelementptr inbounds float, float* [[PVAR_VAL]], i64 3
+// CHECK: store float* [[PTR]], float** [[PVAR_PRIV]],
+// CHECK: [[LVAR_VAL:%.+]] = load i64, i64* [[LVAR_PRIV]],
+// CHECK: [[ADD:%.+]] = add nsw i64 [[LVAR_VAL]], 3
+// CHECK: store i64 [[ADD]], i64* [[LVAR_PRIV]],
+// CHECK: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 %{{.+}})
+// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
+// CHECK: ret void
+
+// CHECK: define {{.*}} i{{[0-9]+}} [[TMAIN_INT]]()
+// CHECK: [[TEST:%.+]] = alloca [[S_INT_TY]],
+// CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]])
+// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[CAP_TMAIN_TY]]*)* [[TMAIN_MICROTASK:@.+]] to void
+// CHECK: call void [[S_INT_TY_DESTR:@.+]]([[S_INT_TY]]*
+// CHECK: ret
+//
+// CHECK: define internal void [[TMAIN_MICROTASK]](i{{[0-9]+}}* [[GTID_ADDR:%.+]], i{{[0-9]+}}* %{{.+}}, [[CAP_TMAIN_TY]]* %{{.+}})
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[PVAR_START:%.+]] = alloca i32*,
+// CHECK: [[LVAR_START:%.+]] = alloca i32,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[PVAR_PRIV:%.+]] = alloca i32*,
+// CHECK: [[LVAR_PRIV:%.+]] = alloca i32,
+// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]]
+
+// Check for default initialization.
+// CHECK: [[PVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_TMAIN_TY]], [[CAP_TMAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: [[PVAR_REF:%.+]] = load i32**, i32*** [[PVAR_PTR_REF]],
+// CHECK: [[PVAR_VAL:%.+]] = load i32*, i32** [[PVAR_REF]],
+// CHECK: store i32* [[PVAR_VAL]], i32** [[PVAR_START]],
+// CHECK: [[LVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_TMAIN_TY]], [[CAP_TMAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1
+// CHECK: [[LVAR_REF:%.+]] = load i32*, i32** [[LVAR_PTR_REF]],
+// CHECK: [[LVAR_VAL:%.+]] = load i32, i32* [[LVAR_REF]],
+// CHECK: store i32 [[LVAR_VAL]], i32* [[LVAR_START]],
+// CHECK: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID:%.+]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1)
+// CHECK: [[PVAR_VAL:%.+]] = load i32*, i32** [[PVAR_START]],
+// CHECK: [[CNT:%.+]] = load i32, i32*
+// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 1
+// CHECK: [[IDX:%.+]] = sext i32 [[MUL]] to i64
+// CHECK: [[PTR:%.+]] = getelementptr inbounds i32, i32* [[PVAR_VAL]], i64 [[IDX]]
+// CHECK: store i32* [[PTR]], i32** [[PVAR_PRIV]],
+// CHECK: [[LVAR_VAL:%.+]] = load i32, i32* [[LVAR_START]],
+// CHECK: [[CNT:%.+]] = load i32, i32*
+// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 1
+// CHECK: [[VAL:%.+]] = add nsw i32 [[LVAR_VAL]], [[MUL]]
+// CHECK: store i32 [[VAL]], i32* [[LVAR_PRIV]],
+// CHECK: [[PVAR_VAL:%.+]] = load i32*, i32** [[PVAR_PRIV]]
+// CHECK: [[PTR:%.+]] = getelementptr inbounds i32, i32* [[PVAR_VAL]], i32 1
+// CHECK: store i32* [[PTR]], i32** [[PVAR_PRIV]],
+// CHECK: [[LVAR_VAL:%.+]] = load i32, i32* [[LVAR_PRIV]],
+// CHECK: [[ADD:%.+]] = add nsw i32 [[LVAR_VAL]], 1
+// CHECK: store i32 [[ADD]], i32* [[LVAR_PRIV]],
+// CHECK: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 %{{.+}})
+// CHECK: call i32 @__kmpc_cancel_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
+// CHECK: ret void
+#endif
+

Propchange: cfe/trunk/test/OpenMP/for_linear_codegen.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/for_linear_codegen.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/for_linear_codegen.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/OpenMP/for_linear_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_linear_messages.cpp?rev=243969&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/for_linear_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/for_linear_messages.cpp Tue Aug  4 06:18:19 2015
@@ -0,0 +1,214 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+namespace X {
+  int x;
+};
+
+struct B {
+  static int ib; // expected-note {{'B::ib' declared here}}
+  static int bfoo() { return 8; }
+};
+
+int bfoo() { return 4; }
+
+int z;
+const int C1 = 1;
+const int C2 = 2;
+void test_linear_colons()
+{
+  int B = 0;
+  #pragma omp for linear(B:bfoo())
+  for (int i = 0; i < 10; ++i) ;
+  // expected-error at +1 {{unexpected ':' in nested name specifier; did you mean '::'}}
+  #pragma omp for linear(B::ib:B:bfoo())
+  for (int i = 0; i < 10; ++i) ;
+  // expected-error at +1 {{use of undeclared identifier 'ib'; did you mean 'B::ib'}}
+  #pragma omp for linear(B:ib)
+  for (int i = 0; i < 10; ++i) ;
+  // expected-error at +1 {{unexpected ':' in nested name specifier; did you mean '::'?}}
+  #pragma omp for linear(z:B:ib)
+  for (int i = 0; i < 10; ++i) ;
+  #pragma omp for linear(B:B::bfoo())
+  for (int i = 0; i < 10; ++i) ;
+  #pragma omp for linear(X::x : ::z)
+  for (int i = 0; i < 10; ++i) ;
+  #pragma omp for linear(B,::z, X::x)
+  for (int i = 0; i < 10; ++i) ;
+  #pragma omp for linear(::z)
+  for (int i = 0; i < 10; ++i) ;
+  // expected-error at +1 {{expected variable name}}
+  #pragma omp for linear(B::bfoo())
+  for (int i = 0; i < 10; ++i) ;
+  #pragma omp for linear(B::ib,B:C1+C2)
+  for (int i = 0; i < 10; ++i) ;
+}
+
+template<int L, class T, class N> T test_template(T* arr, N num) {
+  N i;
+  T sum = (T)0;
+  T ind2 = - num * L; // expected-note {{'ind2' defined here}}
+  // expected-error at +1 {{argument of a linear clause should be of integral or pointer type}}
+#pragma omp for linear(ind2:L)
+  for (i = 0; i < num; ++i) {
+    T cur = arr[(int)ind2];
+    ind2 += L;
+    sum += cur;
+  }
+  return T();
+}
+
+template<int LEN> int test_warn() {
+  int ind2 = 0;
+  // expected-warning at +1 {{zero linear step (ind2 should probably be const)}}
+  #pragma omp for linear(ind2:LEN)
+  for (int i = 0; i < 100; i++) {
+    ind2 += LEN;
+  }
+  return ind2;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+  mutable int a;
+public:
+  S2():a(0) { }
+};
+const S2 b; // expected-note 2 {{'b' defined here}}
+const S2 ba[5];
+class S3 {
+  int a;
+public:
+  S3():a(0) { }
+};
+const S3 ca[5];
+class S4 {
+  int a;
+  S4();
+public:
+  S4(int v):a(v) { }
+};
+class S5 {
+  int a;
+  S5():a(0) {}
+public:
+  S5(int v):a(v) { }
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template<class I, class C> int foomain(I argc, C **argv) {
+  I e(4);
+  I g(5);
+  int i;
+  int &j = i; // expected-note {{'j' defined here}}
+  #pragma omp for linear // expected-error {{expected '(' after 'linear'}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear () // expected-error {{expected expression}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear (argc : 5)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear (S1) // expected-error {{'S1' does not refer to a value}}
+  for (int k = 0; k < argc; ++k) ++k;
+  // expected-error at +2 {{linear variable with incomplete type 'S1'}}
+  // expected-error at +1 {{const-qualified variable cannot be linear}}
+  #pragma omp for linear (a, b:B::ib)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear (argv[1]) // expected-error {{expected variable name}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear(e, g)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear(i)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp parallel
+  {
+    int v = 0;
+    int i;
+    #pragma omp for linear(v:i)
+    for (int k = 0; k < argc; ++k) { i = k; v += i; }
+  }
+  #pragma omp for linear(j) // expected-error {{arguments of OpenMP clause 'linear' cannot be of reference type}}
+  for (int k = 0; k < argc; ++k) ++k;
+  int v = 0;
+  #pragma omp for linear(v:j)
+  for (int k = 0; k < argc; ++k) { ++k; v += j; }
+  #pragma omp for linear(i)
+  for (int k = 0; k < argc; ++k) ++k;
+  return 0;
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace C {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+  double darr[100];
+  // expected-note at +1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
+  test_template<-4>(darr, 4);
+  // expected-note at +1 {{in instantiation of function template specialization 'test_warn<0>' requested here}}
+  test_warn<0>();
+
+  S4 e(4); // expected-note {{'e' defined here}}
+  S5 g(5); // expected-note {{'g' defined here}}
+  int i;
+  int &j = i; // expected-note {{'j' defined here}}
+  #pragma omp for linear // expected-error {{expected '(' after 'linear'}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear () // expected-error {{expected expression}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear (argc)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear (S1) // expected-error {{'S1' does not refer to a value}}
+  for (int k = 0; k < argc; ++k) ++k;
+  // expected-error at +2 {{linear variable with incomplete type 'S1'}}
+  // expected-error at +1 {{const-qualified variable cannot be linear}}
+  #pragma omp for linear(a, b)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear (argv[1]) // expected-error {{expected variable name}}
+  for (int k = 0; k < argc; ++k) ++k;
+  // expected-error at +2 {{argument of a linear clause should be of integral or pointer type, not 'S4'}}
+  // expected-error at +1 {{argument of a linear clause should be of integral or pointer type, not 'S5'}}
+  #pragma omp for linear(e, g)
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear(h, C::x) // expected-error 2 {{threadprivate or thread local variable cannot be linear}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp parallel
+  {
+    int i;
+    #pragma omp for linear(i)
+    for (int k = 0; k < argc; ++k) ++k;
+    #pragma omp for linear(i : 4)
+    for (int k = 0; k < argc; ++k) { ++k; i += 4; }
+  }
+  #pragma omp for linear(j) // expected-error {{arguments of OpenMP clause 'linear' cannot be of reference type 'int &'}}
+  for (int k = 0; k < argc; ++k) ++k;
+  #pragma omp for linear(i)
+  for (int k = 0; k < argc; ++k) ++k;
+
+  foomain<int,char>(argc,argv);
+  return 0;
+}
+

Propchange: cfe/trunk/test/OpenMP/for_linear_messages.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/for_linear_messages.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/for_linear_messages.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/test/OpenMP/for_loop_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_loop_messages.cpp?rev=243969&r1=243968&r2=243969&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_loop_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_loop_messages.cpp Tue Aug  4 06:18:19 2015
@@ -289,7 +289,6 @@ int test_iteration_spaces() {
     c[ii] = a[ii];
 
 #pragma omp parallel
-// expected-error at +3 {{unexpected OpenMP clause 'linear' in directive '#pragma omp for'}}
 // expected-note at +2  {{defined as linear}}
 // expected-error at +2 {{loop iteration variable in the associated loop of 'omp for' directive may not be linear, predetermined as private}}
 #pragma omp for linear(ii)

Modified: cfe/trunk/test/OpenMP/for_misc_messages.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_misc_messages.c?rev=243969&r1=243968&r2=243969&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_misc_messages.c (original)
+++ cfe/trunk/test/OpenMP/for_misc_messages.c Tue Aug  4 06:18:19 2015
@@ -62,9 +62,8 @@ void test_non_identifiers() {
 #pragma omp for;
   for (i = 0; i < 16; ++i)
     ;
+// expected-warning at +2 {{extra tokens at the end of '#pragma omp for' are ignored}}
 #pragma omp parallel
-// expected-error at +2 {{unexpected OpenMP clause 'linear' in directive '#pragma omp for'}}
-// expected-warning at +1 {{extra tokens at the end of '#pragma omp for' are ignored}}
 #pragma omp for linear(x);
   for (i = 0; i < 16; ++i)
     ;

Modified: cfe/trunk/test/OpenMP/parallel_for_ast_print.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_ast_print.cpp?rev=243969&r1=243968&r2=243969&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_ast_print.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_ast_print.cpp Tue Aug  4 06:18:19 2015
@@ -15,35 +15,35 @@ T tmain(T argc) {
 // CHECK: static T a;
   static T g;
 #pragma omp threadprivate(g)
-#pragma omp parallel for schedule(dynamic) default(none) copyin(g)
-  // CHECK: #pragma omp parallel for schedule(dynamic) default(none) copyin(g)
+#pragma omp parallel for schedule(dynamic) default(none) copyin(g) linear(a)
+  // CHECK: #pragma omp parallel for schedule(dynamic) default(none) copyin(g) linear(a)
   for (int i = 0; i < 2; ++i)
     a = 2;
 // CHECK-NEXT: for (int i = 0; i < 2; ++i)
 // CHECK-NEXT: a = 2;
-#pragma omp parallel for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered(N) if (argc) num_threads(N) default(shared) shared(e) reduction(+ : h)
-  for (int i = 0; i < 10; ++i)
-    for (int j = 0; j < 10; ++j)
-      for (int j = 0; j < 10; ++j)
-        for (int j = 0; j < 10; ++j)
-          for (int j = 0; j < 10; ++j)
-  for (int i = 0; i < 10; ++i)
-    for (int j = 0; j < 10; ++j)
-      for (int j = 0; j < 10; ++j)
-        for (int j = 0; j < 10; ++j)
-          for (int j = 0; j < 10; ++j)
+#pragma omp parallel for private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered(N) if (argc) num_threads(N) default(shared) shared(e) reduction(+ : h) linear(a:N)
+  for (int i = 0; i < 2; ++i)
+    for (int j = 0; j < 2; ++j)
+      for (int j = 0; j < 2; ++j)
+        for (int j = 0; j < 2; ++j)
+          for (int j = 0; j < 2; ++j)
+  for (int i = 0; i < 2; ++i)
+    for (int j = 0; j < 2; ++j)
+      for (int j = 0; j < 2; ++j)
+        for (int j = 0; j < 2; ++j)
+          for (int j = 0; j < 2; ++j)
             foo();
-  // CHECK-NEXT: #pragma omp parallel for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered(N) if(argc) num_threads(N) default(shared) shared(e) reduction(+: h)
-  // 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: 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: #pragma omp parallel for private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered(N) if(argc) num_threads(N) default(shared) shared(e) reduction(+: h) linear(a: N)
+  // CHECK-NEXT: for (int i = 0; i < 2; ++i)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int i = 0; i < 2; ++i)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
+  // CHECK-NEXT: for (int j = 0; j < 2; ++j)
   // CHECK-NEXT: foo();
   return T();
 }
@@ -54,18 +54,18 @@ int main(int argc, char **argv) {
 // CHECK: static int a;
   static float g;
 #pragma omp threadprivate(g)
-#pragma omp parallel for schedule(guided, argc) default(none) copyin(g)
-  // CHECK: #pragma omp parallel for schedule(guided, argc) default(none) copyin(g)
+#pragma omp parallel for schedule(guided, argc) default(none) copyin(g) linear(a)
+  // CHECK: #pragma omp parallel for schedule(guided, argc) default(none) copyin(g) linear(a)
   for (int i = 0; i < 2; ++i)
     a = 2;
 // CHECK-NEXT: for (int i = 0; i < 2; ++i)
 // CHECK-NEXT: a = 2;
-#pragma omp parallel for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) schedule(auto) ordered if (argc) num_threads(a) default(shared) shared(e) reduction(+ : h)
+#pragma omp parallel for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) schedule(auto) ordered if (argc) num_threads(a) default(shared) shared(e) reduction(+ : h) linear(a:-5)
   for (int i = 0; i < 10; ++i)
     for (int j = 0; j < 10; ++j)
       foo();
-  // CHECK-NEXT: #pragma omp parallel for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) schedule(auto) ordered if(argc) num_threads(a) default(shared) shared(e) reduction(+: h)
-  // CHECK-NEXT: for (int i = 0; i < 10; ++i)
+  // CHECK-NEXT: #pragma omp parallel for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) schedule(auto) ordered if(argc) num_threads(a) default(shared) shared(e) reduction(+: h) linear(a: -5)
+ // CHECK-NEXT: for (int i = 0; i < 10; ++i)
   // CHECK-NEXT: for (int j = 0; j < 10; ++j)
   // CHECK-NEXT: foo();
   return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0]));

Modified: cfe/trunk/test/OpenMP/parallel_for_firstprivate_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_firstprivate_messages.cpp?rev=243969&r1=243968&r2=243969&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_firstprivate_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_firstprivate_messages.cpp Tue Aug  4 06:18:19 2015
@@ -102,9 +102,6 @@ int foomain(int argc, char **argv) {
 #pragma omp parallel for firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
   for (int k = 0; k < argc; ++k)
     ++k;
-#pragma omp parallel for linear(i) // expected-error {{unexpected OpenMP clause 'linear' in directive '#pragma omp parallel for'}}
-  for (int k = 0; k < argc; ++k)
-    ++k;
 #pragma omp parallel
   {
     int v = 0;

Modified: cfe/trunk/test/OpenMP/parallel_for_lastprivate_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_lastprivate_messages.cpp?rev=243969&r1=243968&r2=243969&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_lastprivate_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_lastprivate_messages.cpp Tue Aug  4 06:18:19 2015
@@ -104,9 +104,6 @@ int foomain(int argc, char **argv) {
 #pragma omp parallel for lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
   for (int k = 0; k < argc; ++k)
     ++k;
-#pragma omp parallel for linear(i) // expected-error {{unexpected OpenMP clause 'linear' in directive '#pragma omp parallel for'}}
-  for (int k = 0; k < argc; ++k)
-    ++k;
 #pragma omp parallel
   {
     int v = 0;

Added: cfe/trunk/test/OpenMP/parallel_for_linear_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_linear_codegen.cpp?rev=243969&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_linear_codegen.cpp (added)
+++ cfe/trunk/test/OpenMP/parallel_for_linear_codegen.cpp Tue Aug  4 06:18:19 2015
@@ -0,0 +1,261 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=LAMBDA %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-apple-darwin10 -emit-llvm %s -o - | FileCheck -check-prefix=BLOCKS %s
+// expected-no-diagnostics
+// REQUIRES: x86-registered-target
+#ifndef HEADER
+#define HEADER
+
+template <class T>
+struct S {
+  T f;
+  S(T a) : f(a) {}
+  S() : f() {}
+  S<T> &operator=(const S<T> &);
+  operator T() { return T(); }
+  ~S() {}
+};
+
+volatile int g = 1212;
+float f;
+char cnt;
+
+// CHECK: [[S_FLOAT_TY:%.+]] = type { float }
+// CHECK: [[CAP_MAIN_TY:%.+]] = type { float**, i64* }
+// CHECK: [[S_INT_TY:%.+]] = type { i32 }
+// CHECK: [[CAP_TMAIN_TY:%.+]] = type { i32**, i32* }
+// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
+// CHECK-DAG: [[F:@.+]] = global float 0.0
+// CHECK-DAG: [[CNT:@.+]] = global i8 0
+template <typename T>
+T tmain() {
+  S<T> test;
+  T *pvar = &test.f;
+  T lvar = T();
+#pragma omp parallel for linear(pvar, lvar)
+  for (int i = 0; i < 2; ++i) {
+    ++pvar, ++lvar;
+  }
+  return T();
+}
+
+int main() {
+#ifdef LAMBDA
+  // LAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212,
+  // LAMBDA-LABEL: @main
+  // LAMBDA: call void [[OUTER_LAMBDA:@.+]](
+  [&]() {
+  // LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
+  // LAMBDA: call void {{.+}} @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i8* %{{.+}})
+#pragma omp parallel for linear(g:5)
+  for (int i = 0; i < 2; ++i) {
+    // LAMBDA: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]])
+    // LAMBDA: alloca i{{[0-9]+}},
+    // LAMBDA: [[G_START_ADDR:%.+]] = alloca i{{[0-9]+}},
+    // LAMBDA: alloca i{{[0-9]+}},
+    // LAMBDA: alloca i{{[0-9]+}},
+    // LAMBDA: alloca i{{[0-9]+}},
+    // LAMBDA: alloca i{{[0-9]+}},
+    // LAMBDA: alloca i{{[0-9]+}},
+    // LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
+    // LAMBDA: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]],
+    // LAMBDA: store i32 0,
+    // LAMBDA: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %{{.+}}
+    // LAMBDA: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
+    // LAMBDA: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1)
+    // LAMBDA: [[VAL:%.+]] = load i32, i32* [[G_START_ADDR]]
+    // LAMBDA: [[CNT:%.+]] = load i32, i32*
+    // LAMBDA: [[MUL:%.+]] = mul nsw i32 [[CNT]], 5
+    // LAMBDA: [[ADD:%.+]] = add nsw i32 [[VAL]], [[MUL]]
+    // LAMBDA: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]],
+    // LAMBDA: [[VAL:%.+]] = load i32, i32* [[G_PRIVATE_ADDR]],
+    // LAMBDA: [[ADD:%.+]] = add nsw i32 [[VAL]], 5
+    // LAMBDA: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]],
+    // LAMBDA: [[G_PRIVATE_ADDR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG:%.+]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+    // LAMBDA: store i{{[0-9]+}}* [[G_PRIVATE_ADDR]], i{{[0-9]+}}** [[G_PRIVATE_ADDR_REF]]
+    // LAMBDA: call void [[INNER_LAMBDA:@.+]](%{{.+}}* [[ARG]])
+    // LAMBDA: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 [[GTID]])
+    g += 5;
+    // LAMBDA: call void @__kmpc_barrier(%{{.+}}* @{{.+}}, i{{[0-9]+}} [[GTID]])
+    [&]() {
+      // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]])
+      // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]],
+      g = 2;
+      // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]]
+      // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+      // LAMBDA: [[G_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[G_PTR_REF]]
+      // LAMBDA: store i{{[0-9]+}} 2, i{{[0-9]+}}* [[G_REF]]
+    }();
+  }
+  }();
+  return 0;
+#elif defined(BLOCKS)
+  // BLOCKS: [[G:@.+]] = global i{{[0-9]+}} 1212,
+  // BLOCKS-LABEL: @main
+  // BLOCKS: call void {{%.+}}(i8
+  ^{
+  // BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8*
+  // BLOCKS: call void {{.+}} @__kmpc_fork_call({{.+}}, i32 1, {{.+}}* [[OMP_REGION:@.+]] to {{.+}}, i8* %{{.+}})
+#pragma omp parallel for linear(g:5)
+  for (int i = 0; i < 2; ++i) {
+    // BLOCKS: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32* %{{.+}}, i32* %{{.+}}, %{{.+}}* [[ARG:%.+]])
+    // BLOCKS: alloca i{{[0-9]+}},
+    // BLOCKS: [[G_START_ADDR:%.+]] = alloca i{{[0-9]+}},
+    // BLOCKS: alloca i{{[0-9]+}},
+    // BLOCKS: alloca i{{[0-9]+}},
+    // BLOCKS: alloca i{{[0-9]+}},
+    // BLOCKS: alloca i{{[0-9]+}},
+    // BLOCKS: alloca i{{[0-9]+}},
+    // BLOCKS: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
+    // BLOCKS: store %{{.+}}* [[ARG]], %{{.+}}** [[ARG_REF:%.+]],
+    // BLOCKS: store i32 0,
+    // BLOCKS: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** %{{.+}}
+    // BLOCKS: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
+    // BLOCKS: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1)
+    // BLOCKS: [[VAL:%.+]] = load i32, i32* [[G_START_ADDR]]
+    // BLOCKS: [[CNT:%.+]] = load i32, i32*
+    // BLOCKS: [[MUL:%.+]] = mul nsw i32 [[CNT]], 5
+    // BLOCKS: [[ADD:%.+]] = add nsw i32 [[VAL]], [[MUL]]
+    // BLOCKS: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]],
+    // BLOCKS: [[VAL:%.+]] = load i32, i32* [[G_PRIVATE_ADDR]],
+    // BLOCKS: [[ADD:%.+]] = add nsw i32 [[VAL]], 5
+    // BLOCKS: store i32 [[ADD]], i32* [[G_PRIVATE_ADDR]],
+    // BLOCKS-NOT: [[G]]{{[[^:word:]]}}
+    // BLOCKS: i{{[0-9]+}}* [[G_PRIVATE_ADDR]]
+    // BLOCKS-NOT: [[G]]{{[[^:word:]]}}
+    // BLOCKS: call void {{%.+}}(i8
+    // BLOCKS: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 [[GTID]])
+    g += 5;
+    // BLOCKS: call void @__kmpc_barrier(%{{.+}}* @{{.+}}, i{{[0-9]+}} [[GTID]])
+    g = 1;
+    ^{
+      // BLOCKS: define {{.+}} void {{@.+}}(i8*
+      g = 2;
+      // BLOCKS-NOT: [[G]]{{[[^:word:]]}}
+      // BLOCKS: store i{{[0-9]+}} 2, i{{[0-9]+}}*
+      // BLOCKS-NOT: [[G]]{{[[^:word:]]}}
+      // BLOCKS: ret
+    }();
+  }
+  }();
+  return 0;
+#else
+  S<float> test;
+  float *pvar = &test.f;
+  long long lvar = 0;
+#pragma omp parallel for linear(pvar, lvar : 3)
+  for (int i = 0; i < 2; ++i) {
+    pvar += 3, lvar += 3;
+  }
+  return tmain<int>();
+#endif
+}
+
+// CHECK: define i{{[0-9]+}} @main()
+// CHECK: [[TEST:%.+]] = alloca [[S_FLOAT_TY]],
+// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
+// CHECK: %{{.+}} = bitcast [[CAP_MAIN_TY]]*
+// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[CAP_MAIN_TY]]*)* [[MAIN_MICROTASK:@.+]] to void
+// CHECK: = call {{.+}} [[TMAIN_INT:@.+]]()
+// CHECK: call void [[S_FLOAT_TY_DESTR:@.+]]([[S_FLOAT_TY]]*
+// CHECK: ret
+
+// CHECK: define internal void [[MAIN_MICROTASK]](i{{[0-9]+}}* [[GTID_ADDR:%.+]], i{{[0-9]+}}* %{{.+}}, [[CAP_MAIN_TY]]* %{{.+}})
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[PVAR_START:%.+]] = alloca float*,
+// CHECK: [[LVAR_START:%.+]] = alloca i64,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[PVAR_PRIV:%.+]] = alloca float*,
+// CHECK: [[LVAR_PRIV:%.+]] = alloca i64,
+// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]]
+
+// Check for default initialization.
+// CHECK: [[PVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: [[PVAR_REF:%.+]] = load float**, float*** [[PVAR_PTR_REF]],
+// CHECK: [[PVAR_VAL:%.+]] = load float*, float** [[PVAR_REF]],
+// CHECK: store float* [[PVAR_VAL]], float** [[PVAR_START]],
+// CHECK: [[LVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_MAIN_TY]], [[CAP_MAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1
+// CHECK: [[LVAR_REF:%.+]] = load i64*, i64** [[LVAR_PTR_REF]],
+// CHECK: [[LVAR_VAL:%.+]] = load i64, i64* [[LVAR_REF]],
+// CHECK: store i64 [[LVAR_VAL]], i64* [[LVAR_START]],
+// CHECK: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID:%.+]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1)
+// CHECK: [[PVAR_VAL:%.+]] = load float*, float** [[PVAR_START]],
+// CHECK: [[CNT:%.+]] = load i32, i32*
+// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 3
+// CHECK: [[IDX:%.+]] = sext i32 [[MUL]] to i64
+// CHECK: [[PTR:%.+]] = getelementptr inbounds float, float* [[PVAR_VAL]], i64 [[IDX]]
+// CHECK: store float* [[PTR]], float** [[PVAR_PRIV]],
+// CHECK: [[LVAR_VAL:%.+]] = load i64, i64* [[LVAR_START]],
+// CHECK: [[CNT:%.+]] = load i32, i32*
+// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 3
+// CHECK: [[CONV:%.+]] = sext i32 [[MUL]] to i64
+// CHECK: [[VAL:%.+]] = add nsw i64 [[LVAR_VAL]], [[CONV]]
+// CHECK: store i64 [[VAL]], i64* [[LVAR_PRIV]],
+// CHECK: [[PVAR_VAL:%.+]] = load float*, float** [[PVAR_PRIV]]
+// CHECK: [[PTR:%.+]] = getelementptr inbounds float, float* [[PVAR_VAL]], i64 3
+// CHECK: store float* [[PTR]], float** [[PVAR_PRIV]],
+// CHECK: [[LVAR_VAL:%.+]] = load i64, i64* [[LVAR_PRIV]],
+// CHECK: [[ADD:%.+]] = add nsw i64 [[LVAR_VAL]], 3
+// CHECK: store i64 [[ADD]], i64* [[LVAR_PRIV]],
+// CHECK: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
+// CHECK: ret void
+
+// CHECK: define {{.*}} i{{[0-9]+}} [[TMAIN_INT]]()
+// CHECK: [[TEST:%.+]] = alloca [[S_INT_TY]],
+// CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]])
+// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[CAP_TMAIN_TY]]*)* [[TMAIN_MICROTASK:@.+]] to void
+// CHECK: call void [[S_INT_TY_DESTR:@.+]]([[S_INT_TY]]*
+// CHECK: ret
+//
+// CHECK: define internal void [[TMAIN_MICROTASK]](i{{[0-9]+}}* [[GTID_ADDR:%.+]], i{{[0-9]+}}* %{{.+}}, [[CAP_TMAIN_TY]]* %{{.+}})
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[PVAR_START:%.+]] = alloca i32*,
+// CHECK: [[LVAR_START:%.+]] = alloca i32,
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: alloca i{{[0-9]+}},
+// CHECK: [[PVAR_PRIV:%.+]] = alloca i32*,
+// CHECK: [[LVAR_PRIV:%.+]] = alloca i32,
+// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]]
+
+// Check for default initialization.
+// CHECK: [[PVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_TMAIN_TY]], [[CAP_TMAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// CHECK: [[PVAR_REF:%.+]] = load i32**, i32*** [[PVAR_PTR_REF]],
+// CHECK: [[PVAR_VAL:%.+]] = load i32*, i32** [[PVAR_REF]],
+// CHECK: store i32* [[PVAR_VAL]], i32** [[PVAR_START]],
+// CHECK: [[LVAR_PTR_REF:%.+]] = getelementptr inbounds [[CAP_TMAIN_TY]], [[CAP_TMAIN_TY]]* %{{.+}}, i{{[0-9]+}} 0, i{{[0-9]+}} 1
+// CHECK: [[LVAR_REF:%.+]] = load i32*, i32** [[LVAR_PTR_REF]],
+// CHECK: [[LVAR_VAL:%.+]] = load i32, i32* [[LVAR_REF]],
+// CHECK: store i32 [[LVAR_VAL]], i32* [[LVAR_START]],
+// CHECK: call {{.+}} @__kmpc_for_static_init_4(%{{.+}}* @{{.+}}, i32 [[GTID:%.+]], i32 34, i32* [[IS_LAST_ADDR:%.+]], i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1)
+// CHECK: [[PVAR_VAL:%.+]] = load i32*, i32** [[PVAR_START]],
+// CHECK: [[CNT:%.+]] = load i32, i32*
+// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 1
+// CHECK: [[IDX:%.+]] = sext i32 [[MUL]] to i64
+// CHECK: [[PTR:%.+]] = getelementptr inbounds i32, i32* [[PVAR_VAL]], i64 [[IDX]]
+// CHECK: store i32* [[PTR]], i32** [[PVAR_PRIV]],
+// CHECK: [[LVAR_VAL:%.+]] = load i32, i32* [[LVAR_START]],
+// CHECK: [[CNT:%.+]] = load i32, i32*
+// CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT]], 1
+// CHECK: [[VAL:%.+]] = add nsw i32 [[LVAR_VAL]], [[MUL]]
+// CHECK: store i32 [[VAL]], i32* [[LVAR_PRIV]],
+// CHECK: [[PVAR_VAL:%.+]] = load i32*, i32** [[PVAR_PRIV]]
+// CHECK: [[PTR:%.+]] = getelementptr inbounds i32, i32* [[PVAR_VAL]], i32 1
+// CHECK: store i32* [[PTR]], i32** [[PVAR_PRIV]],
+// CHECK: [[LVAR_VAL:%.+]] = load i32, i32* [[LVAR_PRIV]],
+// CHECK: [[ADD:%.+]] = add nsw i32 [[LVAR_VAL]], 1
+// CHECK: store i32 [[ADD]], i32* [[LVAR_PRIV]],
+// CHECK: call void @__kmpc_for_static_fini(%{{.+}}* @{{.+}}, i32 %{{.+}})
+// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
+// CHECK: ret void
+#endif
+

Propchange: cfe/trunk/test/OpenMP/parallel_for_linear_codegen.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/parallel_for_linear_codegen.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/parallel_for_linear_codegen.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp?rev=243969&view=auto
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp (added)
+++ cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp Tue Aug  4 06:18:19 2015
@@ -0,0 +1,269 @@
+// RUN: %clang_cc1 -verify -fopenmp %s
+
+namespace X {
+int x;
+};
+
+struct B {
+  static int ib; // expected-note {{'B::ib' declared here}}
+  static int bfoo() { return 8; }
+};
+
+int bfoo() { return 4; }
+
+int z;
+const int C1 = 1;
+const int C2 = 2;
+void test_linear_colons() {
+  int B = 0;
+#pragma omp parallel for linear(B : bfoo())
+  for (int i = 0; i < 10; ++i)
+    ;
+// expected-error at +1 {{unexpected ':' in nested name specifier; did you mean '::'}}
+#pragma omp parallel for linear(B::ib : B : bfoo())
+  for (int i = 0; i < 10; ++i)
+    ;
+// expected-error at +1 {{use of undeclared identifier 'ib'; did you mean 'B::ib'}}
+#pragma omp parallel for linear(B : ib)
+  for (int i = 0; i < 10; ++i)
+    ;
+// expected-error at +1 {{unexpected ':' in nested name specifier; did you mean '::'?}}
+#pragma omp parallel for linear(z : B : ib)
+  for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp parallel for linear(B : B::bfoo())
+  for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp parallel for linear(X::x : ::z)
+  for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp parallel for linear(B, ::z, X::x)
+  for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp parallel for linear(::z)
+  for (int i = 0; i < 10; ++i)
+    ;
+// expected-error at +1 {{expected variable name}}
+#pragma omp parallel for linear(B::bfoo())
+  for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp parallel for linear(B::ib, B : C1 + C2)
+  for (int i = 0; i < 10; ++i)
+    ;
+}
+
+template <int L, class T, class N>
+T test_template(T *arr, N num) {
+  N i;
+  T sum = (T)0;
+  T ind2 = -num * L; // expected-note {{'ind2' defined here}}
+// expected-error at +1 {{argument of a linear clause should be of integral or pointer type}}
+#pragma omp parallel for linear(ind2 : L)
+  for (i = 0; i < num; ++i) {
+    T cur = arr[(int)ind2];
+    ind2 += L;
+    sum += cur;
+  }
+  return T();
+}
+
+template <int LEN>
+int test_warn() {
+  int ind2 = 0;
+// expected-warning at +1 {{zero linear step (ind2 should probably be const)}}
+#pragma omp parallel for linear(ind2 : LEN)
+  for (int i = 0; i < 100; i++) {
+    ind2 += LEN;
+  }
+  return ind2;
+}
+
+struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
+extern S1 a;
+class S2 {
+  mutable int a;
+
+public:
+  S2() : a(0) {}
+};
+const S2 b; // expected-note 2 {{'b' defined here}}
+const S2 ba[5];
+class S3 {
+  int a;
+
+public:
+  S3() : a(0) {}
+};
+const S3 ca[5];
+class S4 {
+  int a;
+  S4();
+
+public:
+  S4(int v) : a(v) {}
+};
+class S5 {
+  int a;
+  S5() : a(0) {}
+
+public:
+  S5(int v) : a(v) {}
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+template <class I, class C>
+int foomain(I argc, C **argv) {
+  I e(4);
+  I g(5);
+  int i;
+  int &j = i;                   // expected-note {{'j' defined here}}
+#pragma omp parallel for linear // expected-error {{expected '(' after 'linear'}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear() // expected-error {{expected expression}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(argc : 5)
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(S1) // expected-error {{'S1' does not refer to a value}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+// expected-error at +2 {{linear variable with incomplete type 'S1'}}
+// expected-error at +1 {{const-qualified variable cannot be linear}}
+#pragma omp parallel for linear(a, b : B::ib)
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(argv[1]) // expected-error {{expected variable name}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(e, g)
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(i)
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel
+  {
+    int v = 0;
+    int i;
+#pragma omp parallel for linear(v : i)
+    for (int k = 0; k < argc; ++k) {
+      i = k;
+      v += i;
+    }
+  }
+#pragma omp parallel for linear(j) // expected-error {{arguments of OpenMP clause 'linear' cannot be of reference type}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+  int v = 0;
+#pragma omp parallel for linear(v : j)
+  for (int k = 0; k < argc; ++k) {
+    ++k;
+    v += j;
+  }
+#pragma omp parallel for linear(i)
+  for (int k = 0; k < argc; ++k)
+    ++k;
+  return 0;
+}
+
+namespace A {
+double x;
+#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
+}
+namespace C {
+using A::x;
+}
+
+int main(int argc, char **argv) {
+  double darr[100];
+  // expected-note at +1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
+  test_template<-4>(darr, 4);
+  // expected-note at +1 {{in instantiation of function template specialization 'test_warn<0>' requested here}}
+  test_warn<0>();
+
+  S4 e(4); // expected-note {{'e' defined here}}
+  S5 g(5); // expected-note {{'g' defined here}}
+  int i;
+  int &j = i;                   // expected-note {{'j' defined here}}
+#pragma omp parallel for linear // expected-error {{expected '(' after 'linear'}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear() // expected-error {{expected expression}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(argc)
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(S1) // expected-error {{'S1' does not refer to a value}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+// expected-error at +2 {{linear variable with incomplete type 'S1'}}
+// expected-error at +1 {{const-qualified variable cannot be linear}}
+#pragma omp parallel for linear(a, b)
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(argv[1]) // expected-error {{expected variable name}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+// expected-error at +2 {{argument of a linear clause should be of integral or pointer type, not 'S4'}}
+// expected-error at +1 {{argument of a linear clause should be of integral or pointer type, not 'S5'}}
+#pragma omp parallel for linear(e, g)
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(h, C::x) // expected-error 2 {{threadprivate or thread local variable cannot be linear}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel
+  {
+    int i;
+#pragma omp parallel for linear(i)
+    for (int k = 0; k < argc; ++k)
+      ++k;
+#pragma omp parallel for linear(i : 4)
+    for (int k = 0; k < argc; ++k) {
+      ++k;
+      i += 4;
+    }
+  }
+#pragma omp parallel for linear(j) // expected-error {{arguments of OpenMP clause 'linear' cannot be of reference type 'int &'}}
+  for (int k = 0; k < argc; ++k)
+    ++k;
+#pragma omp parallel for linear(i)
+  for (int k = 0; k < argc; ++k)
+    ++k;
+
+  foomain<int, char>(argc, argv);
+  return 0;
+}
+

Propchange: cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: cfe/trunk/test/OpenMP/parallel_for_linear_messages.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/test/OpenMP/parallel_for_loop_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_loop_messages.cpp?rev=243969&r1=243968&r2=243969&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_loop_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_for_loop_messages.cpp Tue Aug  4 06:18:19 2015
@@ -242,7 +242,6 @@ int test_iteration_spaces() {
   for (ii = 0; ii < 10; ii++)
     c[ii] = a[ii];
 
-// expected-error at +3 {{unexpected OpenMP clause 'linear' in directive '#pragma omp parallel for'}}
 // expected-note at +2  {{defined as linear}}
 // expected-error at +2 {{loop iteration variable in the associated loop of 'omp parallel for' directive may not be linear, predetermined as private}}
 #pragma omp parallel for linear(ii)

Modified: cfe/trunk/test/OpenMP/parallel_for_misc_messages.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_for_misc_messages.c?rev=243969&r1=243968&r2=243969&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_for_misc_messages.c (original)
+++ cfe/trunk/test/OpenMP/parallel_for_misc_messages.c Tue Aug  4 06:18:19 2015
@@ -59,11 +59,6 @@ void test_non_identifiers() {
 #pragma omp parallel for;
   for (i = 0; i < 16; ++i)
     ;
-// expected-error at +2 {{unexpected OpenMP clause 'linear' in directive '#pragma omp parallel for'}}
-// expected-warning at +1 {{extra tokens at the end of '#pragma omp parallel for' are ignored}}
-#pragma omp parallel for linear(x);
-  for (i = 0; i < 16; ++i)
-    ;
 
 // expected-warning at +1 {{extra tokens at the end of '#pragma omp parallel for' are ignored}}
 #pragma omp parallel for private(x);





More information about the cfe-commits mailing list