11 changes: 11 additions & 0 deletions clang/lib/Serialization/ASTReaderStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2371,6 +2371,12 @@ void ASTStmtReader::VisitOMPParallelMasterDirective(
VisitOMPExecutableDirective(D);
}

void ASTStmtReader::VisitOMPParallelMaskedDirective(
OMPParallelMaskedDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
}

void ASTStmtReader::VisitOMPParallelSectionsDirective(
OMPParallelSectionsDirective *D) {
VisitStmt(D);
Expand Down Expand Up @@ -3297,6 +3303,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;

case STMT_OMP_PARALLEL_MASKED_DIRECTIVE:
S = OMPParallelMaskedDirective::CreateEmpty(
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;

case STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE:
S = OMPParallelSectionsDirective::CreateEmpty(
Context, Record[ASTStmtReader::NumStmtFields], Empty);
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Serialization/ASTWriterStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2298,6 +2298,13 @@ void ASTStmtWriter::VisitOMPParallelMasterDirective(
Code = serialization::STMT_OMP_PARALLEL_MASTER_DIRECTIVE;
}

void ASTStmtWriter::VisitOMPParallelMaskedDirective(
OMPParallelMaskedDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
Code = serialization::STMT_OMP_PARALLEL_MASKED_DIRECTIVE;
}

void ASTStmtWriter::VisitOMPParallelSectionsDirective(
OMPParallelSectionsDirective *D) {
VisitStmt(D);
Expand Down
1 change: 1 addition & 0 deletions clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::OMPParallelForSimdDirectiveClass:
case Stmt::OMPParallelSectionsDirectiveClass:
case Stmt::OMPParallelMasterDirectiveClass:
case Stmt::OMPParallelMaskedDirectiveClass:
case Stmt::OMPTaskDirectiveClass:
case Stmt::OMPTaskyieldDirectiveClass:
case Stmt::OMPBarrierDirectiveClass:
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Analysis/cfg-openmp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -893,4 +893,18 @@ void targetparallelloop(int argc) {
argc = x;
}

// CHECK-LABEL: void parallelmasked(int argc)
void parallelmasked(int argc) {
int x = 0;
// CHECK: [B1]
// CHECK-NEXT: 1: 0
// CHECK-NEXT: 2: int x = 0;
// CHECK-NEXT: [[#MASKED:]]: x
// CHECK-NEXT: [[#MASKED+1]]: [B1.[[#MASKED]]] (ImplicitCastExpr, LValueToRValue, int)
// CHECK-NEXT: [[#MASKED+2]]: argc
// CHECK-NEXT: [[#MASKED+3]]: [B1.[[#MASKED+2]]] = [B1.[[#MASKED+1]]]
// CHECK-NEXT: [[#MASKED+4]]: #pragma omp parallel masked
#pragma omp parallel masked
argc = x;
}
#endif // _OPENMP
352 changes: 352 additions & 0 deletions clang/test/OpenMP/nesting_of_regions.cpp

Large diffs are not rendered by default.

224 changes: 224 additions & 0 deletions clang/test/OpenMP/parallel_masked_ast_print.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s

// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics

#ifndef HEADER
#define HEADER

void foo() {}

struct S1 {
S1(): a(0) {}
S1(int v) : a(v) {}
int a;
typedef int type;
S1& operator +(const S1&);
S1& operator *(const S1&);
S1& operator &&(const S1&);
S1& operator ^(const S1&);
};

template <typename T>
class S7 : public T {
protected:
T a;
T b[100];
S7() : a(0) {}

public:
S7(typename T::type v) : a(v) {
int tid = 0;
// CHECK: #pragma omp parallel masked filter(tid) private(this->a) private(this->a) private(T::a)
#pragma omp parallel masked filter(tid) private(a) private(this->a) private(T::a)
for (int k = 0; k < a.a; ++k)
++this->a.a;
// CHECK: #pragma omp parallel masked filter(tid) firstprivate(this->a) firstprivate(this->a) firstprivate(T::a)
#pragma omp parallel masked filter(tid) firstprivate(a) firstprivate(this->a) firstprivate(T::a)
for (int k = 0; k < a.a; ++k)
++this->a.a;
// CHECK: #pragma omp parallel masked filter(tid) shared(this->a) shared(this->a) shared(T::a)
#pragma omp parallel masked filter(tid) shared(a) shared(this->a) shared(T::a)
for (int k = 0; k < a.a; ++k)
++this->a.a;
// CHECK: #pragma omp parallel masked filter(tid) reduction(+: this->a) reduction(*: this->b[:])
#pragma omp parallel masked filter(tid) reduction(+ : a) reduction(*: b[:])
for (int k = 0; k < a.a; ++k)
++this->a.a;
}
S7 &operator=(S7 &s) {
int tid = 0;
// CHECK: #pragma omp parallel masked filter(tid) private(this->a) private(this->a)
#pragma omp parallel masked filter(tid) private(a) private(this->a)
for (int k = 0; k < s.a.a; ++k)
++s.a.a;
// CHECK: #pragma omp parallel masked filter(tid) firstprivate(this->a) firstprivate(this->a)
#pragma omp parallel masked filter(tid) firstprivate(a) firstprivate(this->a)
for (int k = 0; k < s.a.a; ++k)
++s.a.a;
// CHECK: #pragma omp parallel masked filter(tid) shared(this->a) shared(this->a)
#pragma omp parallel masked filter(tid) shared(a) shared(this->a)
for (int k = 0; k < s.a.a; ++k)
++s.a.a;
// CHECK: #pragma omp parallel masked filter(tid) reduction(&&: this->a) reduction(^: this->b[s.a.a])
#pragma omp parallel masked filter(tid) reduction(&& : this->a) reduction(^: b[s.a.a])
for (int k = 0; k < s.a.a; ++k)
++s.a.a;
return *this;
}
};

// CHECK: #pragma omp parallel masked filter(tid) private(this->a) private(this->a) private(this->S1::a)
// CHECK: #pragma omp parallel masked filter(tid) firstprivate(this->a) firstprivate(this->a) firstprivate(this->S1::a)
// CHECK: #pragma omp parallel masked filter(tid) shared(this->a) shared(this->a) shared(this->S1::a)
// CHECK: #pragma omp parallel masked filter(tid) reduction(+: this->a) reduction(*: this->b[:])

class S8 : public S7<S1> {
S8() {}

public:
S8(int v) : S7<S1>(v){
// CHECK: #pragma omp parallel masked private(this->a) private(this->a) private(this->S7<S1>::a)
#pragma omp parallel masked private(a) private(this->a) private(S7 < S1 > ::a)
for (int k = 0; k < a.a; ++k)
++this->a.a;
// CHECK: #pragma omp parallel masked firstprivate(this->a) firstprivate(this->a) firstprivate(this->S7<S1>::a)
#pragma omp parallel masked firstprivate(a) firstprivate(this->a) firstprivate(S7 < S1 > ::a)
for (int k = 0; k < a.a; ++k)
++this->a.a;
// CHECK: #pragma omp parallel masked shared(this->a) shared(this->a) shared(this->S7<S1>::a)
#pragma omp parallel masked shared(a) shared(this->a) shared(S7 < S1 > ::a)
for (int k = 0; k < a.a; ++k)
++this->a.a;
// CHECK: #pragma omp parallel masked reduction(^: this->S7<S1>::a) reduction(+: this->S7<S1>::b[:this->S7<S1>::a.a])
#pragma omp parallel masked reduction(^ : S7 < S1 > ::a) reduction(+ : S7 < S1 > ::b[ : S7 < S1 > ::a.a])
for (int k = 0; k < a.a; ++k)
++this->a.a;
}
S8 &operator=(S8 &s) {
// CHECK: #pragma omp parallel masked private(this->a) private(this->a)
#pragma omp parallel masked private(a) private(this->a)
for (int k = 0; k < s.a.a; ++k)
++s.a.a;
// CHECK: #pragma omp parallel masked firstprivate(this->a) firstprivate(this->a)
#pragma omp parallel masked firstprivate(a) firstprivate(this->a)
for (int k = 0; k < s.a.a; ++k)
++s.a.a;
// CHECK: #pragma omp parallel masked shared(this->a) shared(this->a)
#pragma omp parallel masked shared(a) shared(this->a)
for (int k = 0; k < s.a.a; ++k)
++s.a.a;
// CHECK: #pragma omp parallel masked reduction(*: this->a) reduction(&&: this->b[this->a.a:])
#pragma omp parallel masked reduction(* : this->a) reduction(&&:this->b[a.a:])
for (int k = 0; k < s.a.a; ++k)
++s.a.a;
return *this;
}
};


template <class T>
struct S {
operator T() {return T();}
static T TS;
#pragma omp threadprivate(TS)
};

// CHECK: template <class T> struct S {
// CHECK: static T TS;
// CHECK-NEXT: #pragma omp threadprivate(S::TS)
// CHECK: };
// CHECK: template<> struct S<int> {
// CHECK: static int TS;
// CHECK-NEXT: #pragma omp threadprivate(S<int>::TS)
// CHECK-NEXT: }
// CHECK: template<> struct S<long> {
// CHECK: static long TS;
// CHECK-NEXT: #pragma omp threadprivate(S<long>::TS)
// CHECK-NEXT: }

int thrp;
#pragma omp threadprivate(thrp)

template <typename T, int C>
T tmain(T argc, T *argv) {
T b = argc, c, d, e, f, g;
static T a;
S<T> s;
T arr[C][10], arr1[C];
#pragma omp parallel masked
a=2;
#pragma omp parallel masked default(none), private(argc,b) firstprivate(argv) shared (d) if (parallel:argc > 0) num_threads(C) copyin(S<T>::TS, thrp) proc_bind(master) reduction(+:c, arr1[argc]) reduction(max:e, arr[:C][0:10])
foo();
#pragma omp parallel masked if (C) num_threads(s) proc_bind(close) reduction(^:e, f, arr[0:C][:argc]) reduction(task, && : g)
foo();
return 0;
}

// CHECK: template <typename T, int C> T tmain(T argc, T *argv) {
// CHECK-NEXT: T b = argc, c, d, e, f, g;
// CHECK-NEXT: static T a;
// CHECK-NEXT: S<T> s;
// CHECK-NEXT: T arr[C][10], arr1[C];
// CHECK-NEXT: #pragma omp parallel masked
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp parallel masked default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(C) copyin(S<T>::TS,thrp) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:C][0:10])
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp parallel masked if(C) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:C][:argc]) reduction(task, &&: g)
// CHECK-NEXT: foo()
// CHECK: template<> int tmain<int, 5>(int argc, int *argv) {
// CHECK-NEXT: int b = argc, c, d, e, f, g;
// CHECK-NEXT: static int a;
// CHECK-NEXT: S<int> s;
// CHECK-NEXT: int arr[5][10], arr1[5];
// CHECK-NEXT: #pragma omp parallel masked
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp parallel masked default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(5) copyin(S<int>::TS,thrp) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:5][0:10])
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp parallel masked if(5) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:5][:argc]) reduction(task, &&: g)
// CHECK-NEXT: foo()
// CHECK: template<> long tmain<long, 1>(long argc, long *argv) {
// CHECK-NEXT: long b = argc, c, d, e, f, g;
// CHECK-NEXT: static long a;
// CHECK-NEXT: S<long> s;
// CHECK-NEXT: long arr[1][10], arr1[1];
// CHECK-NEXT: #pragma omp parallel masked
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp parallel masked default(none) private(argc,b) firstprivate(argv) shared(d) if(parallel: argc > 0) num_threads(1) copyin(S<long>::TS,thrp) proc_bind(master) reduction(+: c,arr1[argc]) reduction(max: e,arr[:1][0:10])
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp parallel masked if(1) num_threads(s) proc_bind(close) reduction(^: e,f,arr[0:1][:argc]) reduction(task, &&: g)
// CHECK-NEXT: foo()

enum Enum { };

int main (int argc, char **argv) {
long x;
int b = argc, c, d, e, f, g;
static int a;
#pragma omp threadprivate(a)
int arr[10][argc], arr1[2];
Enum ee;
// CHECK: Enum ee;
#pragma omp parallel masked
// CHECK-NEXT: #pragma omp parallel masked
a=2;
// CHECK-NEXT: a = 2;
#pragma omp parallel masked default(none), private(argc,b) firstprivate(argv) if (parallel: argc > 0) num_threads(ee) copyin(a) proc_bind(spread) reduction(| : c, d, arr1[argc]) reduction(* : e, arr[:10][0:argc]) allocate(e)
// CHECK-NEXT: #pragma omp parallel masked default(none) private(argc,b) firstprivate(argv) if(parallel: argc > 0) num_threads(ee) copyin(a) proc_bind(spread) reduction(|: c,d,arr1[argc]) reduction(*: e,arr[:10][0:argc]) allocate(e)
foo();
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp parallel masked allocate(e) if(b) num_threads(c) proc_bind(close) reduction(^: e,f) reduction(&&: g,arr[0:argc][:10])
// CHECK-NEXT: foo()
#pragma omp parallel masked allocate(e) if (b) num_threads(c) proc_bind(close) reduction(^:e, f) reduction(&& : g, arr[0:argc][:10])
foo();
return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
}

template<typename T>
T S<T>::TS = 0;

#endif
115 changes: 115 additions & 0 deletions clang/test/OpenMP/parallel_masked_copyin_messages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s -Wuninitialized

// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized

void foo() {
}

bool foobool(int argc) {
return argc;
}

struct S1; // expected-note {{declared here}}
class S2 {
mutable int a;

public:
S2() : a(0) {}
S2 &operator=(S2 &s2) { return *this; }
};
class S3 {
int a;

public:
S3() : a(0) {}
S3 &operator=(S3 &s3) { return *this; }
};
class S4 {
int a;
S4();
S4 &operator=(const S4 &s4); // expected-note {{implicitly declared private here}}

public:
S4(int v) : a(v) {}
};
class S5 {
int a;
S5() : a(0) {}
S5 &operator=(const S5 &s5) { return *this; } // expected-note {{implicitly declared private here}}

public:
S5(int v) : a(v) {}
};
template <class T>
class ST {
public:
static T s;
};

S2 k;
S3 h;
S4 l(3);
S5 m(4);
#pragma omp threadprivate(h, k, l, m)

namespace A {
double x;
#pragma omp threadprivate(x)
}
namespace B {
using A::x;
}

int main(int argc, char **argv) {
int i;
#pragma omp parallel masked copyin // expected-error {{expected '(' after 'copyin'}}
{
foo();
}
#pragma omp parallel masked copyin( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked copyin() // expected-error {{expected expression}}
{
foo();
}
#pragma omp parallel masked copyin(k // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked copyin(h, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked copyin(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
{
foo();
}
#pragma omp parallel masked copyin(l) // expected-error {{'operator=' is a private member of 'S4'}}
{
foo();
}
#pragma omp parallel masked copyin(S1) // expected-error {{'S1' does not refer to a value}}
{
foo();
}
#pragma omp parallel masked copyin(argv[1]) // expected-error {{expected variable name}}
{
foo();
}
#pragma omp parallel masked copyin(i) // expected-error {{copyin variable must be threadprivate}}
{
foo();
}
#pragma omp parallel masked copyin(m) // expected-error {{'operator=' is a private member of 'S5'}}
{
foo();
}
#pragma omp parallel masked copyin(ST < int > ::s, B::x) // expected-error {{copyin variable must be threadprivate}}
{
foo();
}

return 0;
}
63 changes: 63 additions & 0 deletions clang/test/OpenMP/parallel_masked_default_messages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s -Wuninitialized

// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized

// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp -ferror-limit 100 -o - %s -Wuninitialized

// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized

void foo();

namespace {
static int y = 0;
}
static int x = 0;

int main(int argc, char **argv) {
#pragma omp parallel masked default // expected-error {{expected '(' after 'default'}}
{
#pragma omp parallel masked default( // expected-error {{expected 'none', 'shared', 'private' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
#pragma omp parallel masked default() // expected-error {{expected 'none', 'shared', 'private' or 'firstprivate' in OpenMP clause 'default'}}
{
#pragma omp parallel masked default(none // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
#pragma omp parallel masked default(shared), default(shared) // expected-error {{directive '#pragma omp parallel masked' cannot contain more than one 'default' clause}}
{
#pragma omp parallel masked default(x) // expected-error {{expected 'none', 'shared', 'private' or 'firstprivate' in OpenMP clause 'default'}}
{foo();
}
}
}
}
}
}

#pragma omp parallel masked default(none) // expected-note {{explicit data sharing attribute requested here}}
{
++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
}

#pragma omp parallel masked default(none) // expected-note {{explicit data sharing attribute requested here}}
{
#pragma omp parallel masked default(shared)
{
++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
}
}

#ifdef OMP51
#pragma omp parallel masked default(firstprivate) // expected-note 2 {{explicit data sharing attribute requested here}}
{
++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
}
#pragma omp parallel masked default(private) // expected-note 2 {{explicit data sharing attribute requested here}}
{
++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
}
#endif

return 0;
}
320 changes: 320 additions & 0 deletions clang/test/OpenMP/parallel_masked_firstprivate_messages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized

// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized

extern int omp_default_mem_alloc;
void foo() {
}

bool foobool(int argc) {
return argc;
}

void xxx(int argc) {
int fp; // expected-note {{initialize the variable 'fp' to silence this warning}}
#pragma omp parallel masked firstprivate(fp) // expected-warning {{variable 'fp' is uninitialized when used here}}
{
for (int i = 0; i < 10; ++i)
;
}
}

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) {}
S2(const S2 &s2) : a(s2.a) {}
static float S2s;
static const float S2sc;
};
const float S2::S2sc = 0;
const S2 b;
const S2 ba[5];
class S3 {
int a;
S3 &operator=(const S3 &s3);

public:
S3() : a(0) {}
S3(const S3 &s3) : a(s3.a) {}
};
const S3 c;
const S3 ca[5];
extern const int f;
class S4 {
int a;
S4();
S4(const S4 &s4); // expected-note 2 {{implicitly declared private here}}

public:
S4(int v) : a(v) {}
};
class S5 {
int a;
S5(const S5 &s5) : a(s5.a) {} // expected-note 4 {{implicitly declared private here}}

public:
S5() : a(0) {}
S5(int v) : a(v) {}
};
class S6 {
int a;
S6() : a(0) {}

public:
S6(const S6 &s6) : a(s6.a) {}
S6(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(int argc, char **argv) {
I e(4);
C g(5);
int i, z;
int &j = i;
#pragma omp parallel masked firstprivate // expected-error {{expected '(' after 'firstprivate'}}
{
foo();
}
#pragma omp parallel masked firstprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked firstprivate() // expected-error {{expected expression}}
{
foo();
}
#pragma omp parallel masked firstprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked firstprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked firstprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
{
foo();
}
#pragma omp parallel masked firstprivate(argc) allocate , allocate(, allocate(omp_default , allocate(omp_default_mem_alloc, allocate(omp_default_mem_alloc:, allocate(omp_default_mem_alloc: argc, allocate(omp_default_mem_alloc: argv), allocate(argv) // expected-error {{expected '(' after 'allocate'}} expected-error 2 {{expected expression}} expected-error 2 {{expected ')'}} expected-error {{use of undeclared identifier 'omp_default'}} expected-note 2 {{to match this '('}}
{
foo();
}
#pragma omp parallel masked firstprivate(S1) // expected-error {{'S1' does not refer to a value}}
{
foo();
}
#pragma omp parallel masked firstprivate(z, a, b) // expected-error {{firstprivate variable with incomplete type 'S1'}}
{
foo();
}
#pragma omp parallel masked firstprivate(argv[1]) // expected-error {{expected variable name}}
{
foo();
}
#pragma omp parallel masked firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
{
foo();
}
#pragma omp parallel masked firstprivate(h) // expected-error {{threadprivate or thread local variable cannot be firstprivate}}
{
foo();
}
#pragma omp parallel masked linear(i) // expected-error {{unexpected OpenMP clause 'linear' in directive '#pragma omp parallel masked'}}
{
foo();
}
#pragma omp parallel
{
int v = 0;
int i;
#pragma omp parallel masked firstprivate(i)
{
foo();
}
v += i;
}
#pragma omp parallel shared(i)
#pragma omp parallel private(i)
#pragma omp parallel masked firstprivate(j)
{
foo();
}
#pragma omp parallel masked firstprivate(i)
{
foo();
}
#pragma omp parallel masked firstprivate(g) // expected-error {{calling a private constructor of class 'S5'}}
{
foo();
}
#pragma omp parallel private(i)
#pragma omp parallel masked firstprivate(i)
{
foo();
}
#pragma omp parallel reduction(+ : i)
#pragma omp parallel masked firstprivate(i)
{
foo();
}
return 0;
}

namespace A {
double x;
#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
}
namespace B {
using A::x;
}

int main(int argc, char **argv) {
const int d = 5;
const int da[5] = {0};
S4 e(4);
S5 g(5);
S3 m;
S6 n(2);
int i, z;
int &j = i;
#pragma omp parallel masked firstprivate // expected-error {{expected '(' after 'firstprivate'}}
{
foo();
}
#pragma omp parallel masked firstprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked firstprivate() // expected-error {{expected expression}}
{
foo();
}
#pragma omp parallel masked firstprivate(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked firstprivate(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked firstprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
{
foo();
}
#pragma omp parallel masked firstprivate(argc, z)
{
foo();
}
#pragma omp parallel masked firstprivate(S1) // expected-error {{'S1' does not refer to a value}}
{
foo();
}
#pragma omp parallel masked firstprivate(a, b, c, d, f) // expected-error {{firstprivate variable with incomplete type 'S1'}}
{
foo();
}
#pragma omp parallel masked firstprivate(argv[1]) // expected-error {{expected variable name}}
{
foo();
}
#pragma omp parallel masked firstprivate(2 * 2) // expected-error {{expected variable name}}
{
foo();
}
#pragma omp parallel masked firstprivate(ba) // OK
{
foo();
}
#pragma omp parallel masked firstprivate(ca) // OK
{
foo();
}
#pragma omp parallel masked firstprivate(da) // OK
{
foo();
}
int xa;
#pragma omp parallel masked firstprivate(xa) // OK
{
foo();
}
#pragma omp parallel masked firstprivate(S2::S2s) // OK
{
foo();
}
#pragma omp parallel masked firstprivate(S2::S2sc) // OK
{
foo();
}
#pragma omp parallel masked safelen(5) // expected-error {{unexpected OpenMP clause 'safelen' in directive '#pragma omp parallel masked'}}
{
foo();
}
#pragma omp parallel masked firstprivate(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
{
foo();
}
#pragma omp parallel masked firstprivate(m) // OK
{
foo();
}
#pragma omp parallel masked firstprivate(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be firstprivate}}
{
foo();
}
#pragma omp parallel masked private(xa), firstprivate(xa) // expected-error {{private variable cannot be firstprivate}} expected-note {{defined as private}}
{
foo();
}
#pragma omp parallel shared(xa)
#pragma omp parallel masked firstprivate(xa) // OK: may be firstprivate
{
foo();
}
#pragma omp parallel masked firstprivate(j)
{
foo();
}
#pragma omp parallel masked firstprivate(g) // expected-error {{calling a private constructor of class 'S5'}}
{
foo();
}
#pragma omp parallel masked firstprivate(n) // OK
{
foo();
}
#pragma omp parallel
{
int v = 0;
int i;
#pragma omp parallel masked firstprivate(i)
{
foo();
}
v += i;
}
#pragma omp parallel private(i)
#pragma omp parallel masked firstprivate(i)
{
foo();
}
#pragma omp parallel reduction(+ : i)
#pragma omp parallel masked firstprivate(i)
{
foo();
}
static int r;
#pragma omp parallel masked firstprivate(r) // OK
{
foo();
}

return foomain<S4, S5>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<S4, S5>' requested here}}
}
176 changes: 176 additions & 0 deletions clang/test/OpenMP/parallel_masked_if_messages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s -Wuninitialized

// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s -Wuninitialized

// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wuninitialized
// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wuninitialized

void foo() {
}

bool foobool(int argc) {
return argc;
}

void xxx(int argc) {
int cond; // expected-note {{initialize the variable 'cond' to silence this warning}}
#pragma omp parallel masked if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}}
{
;
}
}

struct S1; // expected-note {{declared here}}

template <class T, class S> // expected-note {{declared here}}
int tmain(T argc, S **argv) {
T z;
#pragma omp parallel masked if // expected-error {{expected '(' after 'if'}}
{
foo();
}
#pragma omp parallel masked if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if () // expected-error {{expected expression}}
{
foo();
}
#pragma omp parallel masked if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp parallel masked' are ignored}}
{
foo();
}
#pragma omp parallel masked if (argc > 0 ? argv[1] : argv[2])
{
foo();
}
#pragma omp parallel masked if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp parallel masked' cannot contain more than one 'if' clause}}
{
foo();
}
#pragma omp parallel masked if (S) // expected-error {{'S' does not refer to a value}}
{
foo();
}
#pragma omp parallel masked if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if(argc + z)
{
foo();
}
#pragma omp parallel masked if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if(parallel : argc)
{
foo();
}
#pragma omp parallel masked if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp parallel masked'}}
{
foo();
}
#pragma omp parallel masked if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp parallel masked' cannot contain more than one 'if' clause with 'parallel' name modifier}}
{
foo();
}
#pragma omp parallel masked if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}}
{
foo();
}

return 0;
}

int main(int argc, char **argv) {
int z;
#pragma omp parallel masked if // expected-error {{expected '(' after 'if'}}
{
foo();
}
#pragma omp parallel masked if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if () // expected-error {{expected expression}}
{
foo();
}
#pragma omp parallel masked if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp parallel masked' are ignored}}
{
foo();
}
#pragma omp parallel masked if (argc > 0 ? argv[1] : argv[2] + z)
{
foo();
}
#pragma omp parallel masked if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp parallel masked' cannot contain more than one 'if' clause}}
{
foo();
}
#pragma omp parallel masked if (S1) // expected-error {{'S1' does not refer to a value}}
{
foo();
}
#pragma omp parallel masked if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if(parallel : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if(parallel : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked if(parallel : argc)
{
foo();
}
#pragma omp parallel masked if(parallel : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp parallel masked'}}
{
foo();
}
#pragma omp parallel masked if(parallel : argc) if (parallel:argc) // expected-error {{directive '#pragma omp parallel masked' cannot contain more than one 'if' clause with 'parallel' name modifier}}
{
foo();
}
#pragma omp parallel masked if(parallel : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}}
{
foo();
}

return tmain(argc, argv);
}
89 changes: 89 additions & 0 deletions clang/test/OpenMP/parallel_masked_message.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized

// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized

void xxx(int argc) {
int x; // expected-note {{initialize the variable 'x' to silence this warning}}
#pragma omp parallel masked
argc = x; // expected-warning {{variable 'x' is uninitialized when used here}}
}

#pragma omp parallel masked // expected-error {{unexpected OpenMP directive '#pragma omp parallel masked'}}

int foo() {
return 0;
}

int a;
struct S;
S& bar();
int main(int argc, char **argv) {
#pragma omp parallel masked nowait // expected-error {{unexpected OpenMP clause 'nowait' in directive '#pragma omp parallel masked'}}
#pragma omp parallel masked unknown // expected-warning {{extra tokens at the end of '#pragma omp parallel masked' are ignored}}
foo();
{
#pragma omp masked
} // expected-error {{expected statement}}
{
#pragma omp parallel masked
} // expected-error {{expected statement}}

S &s = bar();
int tid = 0;
#pragma omp parallel masked filter(tid)
(void)&s;
#pragma omp parallel masked { // expected-warning {{extra tokens at the end of '#pragma omp parallel masked' are ignored}}
foo();
#pragma omp parallel masked ( // expected-warning {{extra tokens at the end of '#pragma omp parallel masked' are ignored}}
foo();
#pragma omp parallel masked [ // expected-warning {{extra tokens at the end of '#pragma omp parallel masked' are ignored}}
foo();
#pragma omp parallel masked ] // expected-warning {{extra tokens at the end of '#pragma omp parallel masked' are ignored}}
foo();
#pragma omp parallel masked ) // expected-warning {{extra tokens at the end of '#pragma omp parallel masked' are ignored}}
foo();
#pragma omp parallel masked } // expected-warning {{extra tokens at the end of '#pragma omp parallel masked' are ignored}}
foo();
#pragma omp parallel masked
// expected-warning@+1 {{extra tokens at the end of '#pragma omp parallel masked' are ignored}}
#pragma omp parallel masked unknown()
foo();
L1:
foo();
#pragma omp parallel masked
;
#pragma omp parallel masked
{

for (int i = 0; i < 10; ++i) {
switch(argc) {
case (0):
#pragma omp parallel masked
{
foo();
break; // expected-error {{'break' statement not in loop or switch statement}}
continue; // expected-error {{'continue' statement not in loop statement}}
}
default:
break;
}
}
goto L1; // expected-error {{use of undeclared label 'L1'}}
argc++;
}
#pragma omp parallel masked default(none) // expected-note 2 {{explicit data sharing attribute requested here}}
{
++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
++a; // expected-error {{variable 'a' must have explicitly specified data sharing attributes}}
}

goto L2; // expected-error {{use of undeclared label 'L2'}}
#pragma omp parallel masked
L2:
foo();
#pragma omp parallel masked
{
return 1; // expected-error {{cannot return from OpenMP region}}
}
return 0;
}
67 changes: 67 additions & 0 deletions clang/test/OpenMP/parallel_masked_num_threads_messages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wuninitialized

// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wuninitialized

void foo() {
}

bool foobool(int argc) {
return argc;
}

struct S1; // expected-note {{declared here}}

template <class T, typename S, int N> // expected-note {{declared here}}
T tmain(T argc, S **argv) {
T z;
#pragma omp parallel masked num_threads // expected-error {{expected '(' after 'num_threads'}}
{foo();}
#pragma omp parallel masked num_threads ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{foo();}
#pragma omp parallel masked num_threads () // expected-error {{expected expression}}
{foo();}
#pragma omp parallel masked num_threads (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{foo();}
#pragma omp parallel masked num_threads (argc)) // expected-warning {{extra tokens at the end of '#pragma omp parallel masked' are ignored}}
{foo();}
#pragma omp parallel masked num_threads ((argc > 0) ? argv[1] : argv[2]) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
{foo();}
#pragma omp parallel masked num_threads (foobool(argc)), num_threads (true), num_threads (-5) // expected-error 2 {{directive '#pragma omp parallel masked' cannot contain more than one 'num_threads' clause}} expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}}
{foo();}
#pragma omp parallel masked num_threads (S) // expected-error {{'S' does not refer to a value}}
{foo();}
#pragma omp parallel masked num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error 2 {{expression must have integral or unscoped enumeration type, not 'char *'}}
{foo();}
#pragma omp parallel masked num_threads (argc + z)
{foo();}
#pragma omp parallel masked num_threads (N) // expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}}
{foo();}

return argc;
}

int main(int argc, char **argv) {
int z;
#pragma omp parallel masked num_threads // expected-error {{expected '(' after 'num_threads'}}
{foo();}
#pragma omp parallel masked num_threads ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{foo();}
#pragma omp parallel masked num_threads () // expected-error {{expected expression}}
{foo();}
#pragma omp parallel masked num_threads (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{foo();}
#pragma omp parallel masked num_threads (argc / z)) // expected-warning {{extra tokens at the end of '#pragma omp parallel masked' are ignored}}
{foo();}
#pragma omp parallel masked num_threads (argc > 0 ? argv[1] : argv[2]) // expected-error {{integral }}
{foo();}
#pragma omp parallel masked num_threads (foobool(argc)), num_threads (true), num_threads (-5) // expected-error 2 {{directive '#pragma omp parallel masked' cannot contain more than one 'num_threads' clause}} expected-error {{argument to 'num_threads' clause must be a strictly positive integer value}}
{foo();}
#pragma omp parallel masked num_threads (S1) // expected-error {{'S1' does not refer to a value}}
{foo();}
#pragma omp parallel masked num_threads (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
{foo();}
#pragma omp parallel masked num_threads (num_threads(tmain<int, char, -1>(argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} expected-note {{in instantiation of function template specialization 'tmain<int, char, -1>' requested here}}
{foo();}

return tmain<int, char, 3>(argc, argv); // expected-note {{in instantiation of function template specialization 'tmain<int, char, 3>' requested here}}
}
284 changes: 284 additions & 0 deletions clang/test/OpenMP/parallel_masked_private_messages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized

// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized

extern int omp_default_mem_alloc;
void foo() {
}

bool foobool(int argc) {
return argc;
}

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;
const S2 ba[5];
class S3 {
int a;

public:
S3() : a(0) {}
};
const S3 ca[5];
class S4 {
int a;
S4(); // expected-note {{implicitly declared private here}}

public:
S4(int v) : a(v) {
#pragma omp parallel masked private(a) private(this->a)
{
for (int k = 0; k < v; ++k)
++this->a;
}
}
};
class S5 {
int a;
S5() : a(0) {} // expected-note {{implicitly declared private here}}

public:
S5(int v) : a(v) {}
S5 &operator=(S5 &s) {
#pragma omp parallel masked private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
{
for (int k = 0; k < s.a; ++k)
++s.a;
}
return *this;
}
};

template <typename T>
class S6 {
public:
T a;

S6() : a(0) {}
S6(T v) : a(v) {
#pragma omp parallel masked private(a) private(this->a)
{
for (int k = 0; k < v; ++k)
++this->a;
}
}
S6 &operator=(S6 &s) {
#pragma omp parallel masked private(a) private(this->a) private(s.a) // expected-error {{expected variable name or data member of current class}}
{
for (int k = 0; k < s.a; ++k)
++s.a;
}
return *this;
}
};

template <typename T>
class S7 : public T {
T a;
S7() : a(0) {}

public:
S7(T v) : a(v) {
#pragma omp parallel masked private(a) private(this->a) private(T::a)
{
for (int k = 0; k < a.a; ++k)
++this->a.a;
}
}
S7 &operator=(S7 &s) {
#pragma omp parallel masked private(a) private(this->a) private(s.a) private(s.T::a) // expected-error 2 {{expected variable name or data member of current class}}
{
for (int k = 0; k < s.a.a; ++k)
++s.a.a;
}
return *this;
}
};

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, z;
int &j = i;
#pragma omp parallel masked private // expected-error {{expected '(' after 'private'}}
{
foo();
}
#pragma omp parallel masked private( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked private() // expected-error {{expected expression}}
{
foo();
}
#pragma omp parallel masked private(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked private(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked private(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
{
foo();
}
#pragma omp parallel masked private(argc) allocate , allocate(, allocate(omp_default , allocate(omp_default_mem_alloc, allocate(omp_default_mem_alloc:, allocate(omp_default_mem_alloc: argc, allocate(omp_default_mem_alloc: argv), allocate(argv) // expected-error {{expected '(' after 'allocate'}} expected-error 2 {{expected expression}} expected-error 2 {{expected ')'}} expected-error {{use of undeclared identifier 'omp_default'}} expected-note 2 {{to match this '('}}
{
foo();
}
#pragma omp parallel masked private(S1) // expected-error {{'S1' does not refer to a value}}
{
foo();
}
#pragma omp parallel masked private(a, b) // expected-error {{private variable with incomplete type 'S1'}}
{
foo();
}
#pragma omp parallel masked private(argv[1]) // expected-error {{expected variable name}}
{
foo();
}
#pragma omp parallel masked private(e, g, z)
{
foo();
}
#pragma omp parallel masked private(h) // expected-error {{threadprivate or thread local variable cannot be private}}
{
foo();
}
#pragma omp parallel masked copyprivate(h) // expected-error {{unexpected OpenMP clause 'copyprivate' in directive '#pragma omp parallel masked'}}
{
foo();
}
#pragma omp parallel
{
int v = 0;
int i;
#pragma omp parallel masked private(i)
{
foo();
}
v += i;
}
#pragma omp parallel shared(i)
#pragma omp parallel private(i)
#pragma omp parallel masked private(j)
{
foo();
}
#pragma omp parallel masked private(i)
{
foo();
}
return 0;
}

namespace A {
double x;
#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
}
namespace B {
using A::x;
}

int main(int argc, char **argv) {
S4 e(4);
S5 g(5);
S6<float> s6(0.0) , s6_0(1.0);
S7<S6<float> > s7(0.0) , s7_0(1.0);
int i, z;
int &j = i;
#pragma omp parallel masked private // expected-error {{expected '(' after 'private'}}
{
foo();
}
#pragma omp parallel masked private( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked private() // expected-error {{expected expression}}
{
foo();
}
#pragma omp parallel masked private(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked private(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{
foo();
}
#pragma omp parallel masked private(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
{
foo();
}
#pragma omp parallel masked private(argc, z)
{
foo();
}
#pragma omp parallel masked private(S1) // expected-error {{'S1' does not refer to a value}}
{
foo();
}
#pragma omp parallel masked private(a, b) // expected-error {{private variable with incomplete type 'S1'}}
{
foo();
}
#pragma omp parallel masked private(argv[1]) // expected-error {{expected variable name}}
{
foo();
}
#pragma omp parallel masked private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}}
{
foo();
}
#pragma omp parallel masked private(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be private}}
{
foo();
}
#pragma omp parallel masked copyprivate(h) // expected-error {{unexpected OpenMP clause 'copyprivate' in directive '#pragma omp parallel masked'}}
{
foo();
}
#pragma omp parallel
{
int i;
#pragma omp parallel masked private(i)
{
foo();
}
}
#pragma omp parallel shared(i)
#pragma omp parallel private(i)
#pragma omp parallel masked private(j)
{
foo();
}
#pragma omp parallel masked private(i)
{
foo();
}
static int m;
#pragma omp parallel masked private(m)
{
foo();
}

s6 = s6_0; // expected-note {{in instantiation of member function 'S6<float>::operator=' requested here}}
s7 = s7_0; // expected-note {{in instantiation of member function 'S7<S6<float>>::operator=' requested here}}
return foomain(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
}

30 changes: 30 additions & 0 deletions clang/test/OpenMP/parallel_masked_proc_bind_messages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s -Wuninitialized

// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized

void foo();

int main(int argc, char **argv) {
#pragma omp parallel masked proc_bind // expected-error {{expected '(' after 'proc_bind'}}
{ foo(); }
#pragma omp parallel masked proc_bind( // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{ foo(); }
#pragma omp parallel masked proc_bind() // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
{ foo(); }
#pragma omp parallel masked proc_bind(master // expected-error {{expected ')'}} expected-note {{to match this '('}}
{ foo(); }
#pragma omp parallel masked proc_bind(close), proc_bind(spread) // expected-error {{directive '#pragma omp parallel masked' cannot contain more than one 'proc_bind' clause}}
{ foo(); }
#pragma omp parallel masked proc_bind(x) // expected-error {{expected 'master', 'close' or 'spread' in OpenMP clause 'proc_bind'}}
{ foo(); }

#pragma omp parallel masked proc_bind(master)
{ ++argc; }

#pragma omp parallel masked proc_bind(close)
{
#pragma omp parallel masked proc_bind(spread)
{ ++argc; }
}
return 0;
}
408 changes: 408 additions & 0 deletions clang/test/OpenMP/parallel_masked_reduction_messages.cpp

Large diffs are not rendered by default.

120 changes: 120 additions & 0 deletions clang/test/OpenMP/parallel_masked_shared_messages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wuninitialized

// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wuninitialized

void foo() {
}

bool foobool(int argc) {
return argc;
}

struct S1; // expected-note {{declared here}}
extern S1 a;
class S2 {
mutable int a;

public:
S2() : a(0) {}
S2(S2 &s2) : a(s2.a) {}
};
const S2 b;
const S2 ba[5];
class S3 {
int a;

public:
S3() : a(0) {}
S3(S3 &s3) : a(s3.a) {}
};
const S3 c;
const S3 ca[5];
extern const int f;
class S4 {
int a;
S4();
S4(const S4 &s4);

public:
S4(int v) : a(v) {}
};
class S5 {
int a;
S5() : a(0) {}
S5(const S5 &s5) : a(s5.a) {}

public:
S5(int v) : a(v) {}
};

S3 h;
#pragma omp threadprivate(h) // expected-note {{defined as threadprivate or thread local}}

namespace A {
double x;
#pragma omp threadprivate(x) // expected-note {{defined as threadprivate or thread local}}
}
namespace B {
using A::x;
}

int main(int argc, char **argv) {
const int d = 5;
const int da[5] = {0};
S4 e(4);
S5 g(5);
int i, k;
int &j = i;
#pragma omp parallel masked shared // expected-error {{expected '(' after 'shared'}}
{ foo(); }
#pragma omp parallel masked shared( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{ foo(); }
#pragma omp parallel masked shared() // expected-error {{expected expression}}
{ foo(); }
#pragma omp parallel masked shared(argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
{ foo(); }
#pragma omp parallel masked shared(argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
{ foo(); }
#pragma omp parallel masked shared(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
{ foo(); }
#pragma omp parallel masked shared(argc)
{ foo(); }
#pragma omp parallel masked shared(S1) // expected-error {{'S1' does not refer to a value}}
{ foo(); }
#pragma omp parallel masked shared(a, b, c, d, f, k)
{ foo(); }
#pragma omp parallel masked shared(argv[1]) // expected-error {{expected variable name}}
{ foo(); }
#pragma omp parallel masked shared(ba)
{ foo(); }
#pragma omp parallel masked shared(ca)
{ foo(); }
#pragma omp parallel masked shared(da)
{ foo(); }
#pragma omp parallel masked shared(e, g)
{ foo(); }
#pragma omp parallel masked shared(h, B::x) // expected-error 2 {{threadprivate or thread local variable cannot be shared}}
{ foo(); }
#pragma omp parallel masked private(i), shared(i) // expected-error {{private variable cannot be shared}} expected-note {{defined as private}}
{ foo(); }
#pragma omp parallel masked firstprivate(i), shared(i) // expected-error {{firstprivate variable cannot be shared}} expected-note {{defined as firstprivate}}
{ foo(); }
#pragma omp parallel masked private(i)
{
#pragma omp parallel masked shared(i)
{
#pragma omp parallel masked shared(j)
{ foo(); }
}
}
#pragma omp parallel masked firstprivate(i)
{
#pragma omp parallel masked shared(i)
{
#pragma omp parallel masked shared(j)
{ foo(); }
}
}

return 0;
}
8 changes: 8 additions & 0 deletions clang/tools/libclang/CIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2152,6 +2152,7 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void> {
void VisitOMPParallelForDirective(const OMPParallelForDirective *D);
void VisitOMPParallelForSimdDirective(const OMPParallelForSimdDirective *D);
void VisitOMPParallelMasterDirective(const OMPParallelMasterDirective *D);
void VisitOMPParallelMaskedDirective(const OMPParallelMaskedDirective *D);
void VisitOMPParallelSectionsDirective(const OMPParallelSectionsDirective *D);
void VisitOMPTaskDirective(const OMPTaskDirective *D);
void VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D);
Expand Down Expand Up @@ -3073,6 +3074,11 @@ void EnqueueVisitor::VisitOMPParallelMasterDirective(
VisitOMPExecutableDirective(D);
}

void EnqueueVisitor::VisitOMPParallelMaskedDirective(
const OMPParallelMaskedDirective *D) {
VisitOMPExecutableDirective(D);
}

void EnqueueVisitor::VisitOMPParallelSectionsDirective(
const OMPParallelSectionsDirective *D) {
VisitOMPExecutableDirective(D);
Expand Down Expand Up @@ -5766,6 +5772,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OMPParallelForSimdDirective");
case CXCursor_OMPParallelMasterDirective:
return cxstring::createRef("OMPParallelMasterDirective");
case CXCursor_OMPParallelMaskedDirective:
return cxstring::createRef("OMPParallelMaskedDirective");
case CXCursor_OMPParallelSectionsDirective:
return cxstring::createRef("OMPParallelSectionsDirective");
case CXCursor_OMPTaskDirective:
Expand Down
3 changes: 3 additions & 0 deletions clang/tools/libclang/CXCursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::OMPParallelMasterDirectiveClass:
K = CXCursor_OMPParallelMasterDirective;
break;
case Stmt::OMPParallelMaskedDirectiveClass:
K = CXCursor_OMPParallelMaskedDirective;
break;
case Stmt::OMPParallelSectionsDirectiveClass:
K = CXCursor_OMPParallelSectionsDirective;
break;
Expand Down
15 changes: 15 additions & 0 deletions llvm/include/llvm/Frontend/OpenMP/OMP.td
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,21 @@ def OMP_ParallelMaster : Directive<"parallel master"> {
VersionedClause<OMPC_Allocate>
];
}
def OMP_ParallelMasked : Directive<"parallel masked"> {
let allowedClauses = [
VersionedClause<OMPC_If>,
VersionedClause<OMPC_NumThreads>,
VersionedClause<OMPC_Default>,
VersionedClause<OMPC_Private>,
VersionedClause<OMPC_FirstPrivate>,
VersionedClause<OMPC_Shared>,
VersionedClause<OMPC_Copyin>,
VersionedClause<OMPC_Reduction>,
VersionedClause<OMPC_ProcBind>,
VersionedClause<OMPC_Allocate>,
VersionedClause<OMPC_Filter>
];
}
def OMP_ParallelSections : Directive<"parallel sections"> {
let allowedClauses = [
VersionedClause<OMPC_If>,
Expand Down