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

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

llvm-svn: 243969
This commit is contained in:
Alexey Bataev 2015-08-04 11:18:19 +00:00
parent 323dc2d064
commit 54acd40591
16 changed files with 1085 additions and 78 deletions

View File

@ -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)

View File

@ -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::ActOnOpenMPParallelForDirective(
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);

View File

@ -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();

View File

@ -114,10 +114,6 @@ int foomain(int argc, char **argv) {
#pragma omp for firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
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;

View File

@ -116,10 +116,6 @@ int foomain(int argc, char **argv) {
#pragma omp for lastprivate(h) // expected-error {{threadprivate or thread local variable cannot be lastprivate}}
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;

View File

@ -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

View File

@ -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@+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@+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@+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@+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@+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@+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@+2 {{linear variable with incomplete type 'S1'}}
// expected-error@+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@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
test_template<-4>(darr, 4);
// expected-note@+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@+2 {{linear variable with incomplete type 'S1'}}
// expected-error@+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@+2 {{argument of a linear clause should be of integral or pointer type, not 'S4'}}
// expected-error@+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;
}

View File

@ -289,7 +289,6 @@ int test_iteration_spaces() {
c[ii] = a[ii];
#pragma omp parallel
// expected-error@+3 {{unexpected OpenMP clause 'linear' in directive '#pragma omp for'}}
// expected-note@+2 {{defined as linear}}
// expected-error@+2 {{loop iteration variable in the associated loop of 'omp for' directive may not be linear, predetermined as private}}
#pragma omp for linear(ii)

View File

@ -62,9 +62,8 @@ void test_non_identifiers() {
#pragma omp for;
for (i = 0; i < 16; ++i)
;
// expected-warning@+2 {{extra tokens at the end of '#pragma omp for' are ignored}}
#pragma omp parallel
// expected-error@+2 {{unexpected OpenMP clause 'linear' in directive '#pragma omp for'}}
// expected-warning@+1 {{extra tokens at the end of '#pragma omp for' are ignored}}
#pragma omp for linear(x);
for (i = 0; i < 16; ++i)
;

View File

@ -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]));

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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@+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@+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@+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@+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@+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@+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@+2 {{linear variable with incomplete type 'S1'}}
// expected-error@+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@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
test_template<-4>(darr, 4);
// expected-note@+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@+2 {{linear variable with incomplete type 'S1'}}
// expected-error@+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@+2 {{argument of a linear clause should be of integral or pointer type, not 'S4'}}
// expected-error@+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;
}

View File

@ -242,7 +242,6 @@ int test_iteration_spaces() {
for (ii = 0; ii < 10; ii++)
c[ii] = a[ii];
// expected-error@+3 {{unexpected OpenMP clause 'linear' in directive '#pragma omp parallel for'}}
// expected-note@+2 {{defined as linear}}
// expected-error@+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)

View File

@ -59,11 +59,6 @@ void test_non_identifiers() {
#pragma omp parallel for;
for (i = 0; i < 16; ++i)
;
// expected-error@+2 {{unexpected OpenMP clause 'linear' in directive '#pragma omp parallel for'}}
// expected-warning@+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@+1 {{extra tokens at the end of '#pragma omp parallel for' are ignored}}
#pragma omp parallel for private(x);