31 changes: 31 additions & 0 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -1382,6 +1382,18 @@ class TreeTransform {
EndLoc);
}

/// \brief Build a new OpenMP 'copyin' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPCopyinClause(ArrayRef<Expr *> VarList,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
return getSema().ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc,
EndLoc);
}

/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
Expand Down Expand Up @@ -6422,6 +6434,25 @@ TreeTransform<Derived>::TransformOMPSharedClause(OMPSharedClause *C) {
C->getLocEnd());
}

template<typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
Vars.reserve(C->varlist_size());
for (OMPCopyinClause::varlist_iterator I = C->varlist_begin(),
E = C->varlist_end();
I != E; ++I) {
ExprResult EVar = getDerived().TransformExpr(cast<Expr>(*I));
if (EVar.isInvalid())
return 0;
Vars.push_back(EVar.take());
}
return getDerived().RebuildOMPCopyinClause(Vars,
C->getLocStart(),
C->getLParenLoc(),
C->getLocEnd());
}

//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//
Expand Down
13 changes: 13 additions & 0 deletions clang/lib/Serialization/ASTReaderStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1692,6 +1692,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_shared:
C = OMPSharedClause::CreateEmpty(Context, Record[Idx++]);
break;
case OMPC_copyin:
C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]);
break;
}
Visit(C);
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
Expand Down Expand Up @@ -1752,6 +1755,16 @@ void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) {
C->setVarRefs(Vars);
}

void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
unsigned NumVars = C->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i)
Vars.push_back(Reader->Reader.ReadSubExpr());
C->setVarRefs(Vars);
}

//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Serialization/ASTWriterStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1716,6 +1716,15 @@ void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {
Writer->Writer.AddStmt(I);
}

void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {
Record.push_back(C->varlist_size());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
for (OMPCopyinClause::varlist_iterator I = C->varlist_begin(),
E = C->varlist_end();
I != E; ++I)
Writer->Writer.AddStmt(*I);
}

//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
Expand Down
29 changes: 23 additions & 6 deletions clang/test/OpenMP/parallel_ast_print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,44 @@ void foo() {}
template <class T>
struct S {
operator T() {return T();}
static T TS;
#pragma omp threadprivate(TS)
};

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

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;
#pragma omp parallel
a=2;
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (argc > 0) num_threads(C)
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (argc > 0) num_threads(C) copyin(S<T>::TS)
foo();
#pragma omp parallel if (C) num_threads(s)
foo();
return 0;
}

// CHECK: template <typename T = int, int C = 5> int tmain(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: #pragma omp parallel
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(5)
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(5) copyin(S<int>::TS)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s)
// CHECK-NEXT: foo()
Expand All @@ -42,7 +58,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: S<long> s;
// CHECK-NEXT: #pragma omp parallel
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(1)
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(1) copyin(S<long>::TS)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s)
// CHECK-NEXT: foo()
Expand All @@ -52,7 +68,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: S<T> s;
// CHECK-NEXT: #pragma omp parallel
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(C)
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(C) copyin(S<T>::TS)
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s)
// CHECK-NEXT: foo()
Expand All @@ -63,14 +79,15 @@ int main (int argc, char **argv) {
long x;
int b = argc, c, d, e, f, g;
static int a;
#pragma omp threadprivate(a)
Enum ee;
// CHECK: Enum ee;
#pragma omp parallel
// CHECK-NEXT: #pragma omp parallel
a=2;
// CHECK-NEXT: a = 2;
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) if (argc > 0) num_threads(ee)
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(argc > 0) num_threads(ee)
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) if (argc > 0) num_threads(ee) copyin(a)
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(argc > 0) num_threads(ee) copyin(a)
foo();
// CHECK-NEXT: foo();
return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
Expand Down
67 changes: 67 additions & 0 deletions clang/test/OpenMP/parallel_copyin_messages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 -o - %s

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 { // expected-note {{'S4' declared here}}
int a;
S4();
S4 &operator =(const S4 &s4);
public:
S4(int v):a(v) { }
};
class S5 { // expected-note {{'S5' declared here}}
int a;
S5():a(0) {}
S5 &operator =(const S5 &s5) { return *this; }
public:
S5(int v):a(v) { }
};
template <class T>
class ST {
public:
static T s;
};


S2 k;
S3 h;
S4 l(3); // expected-note {{'l' defined here}}
S5 m(4); // expected-note {{'m' defined here}}
#pragma omp threadprivate(h, k, l, m)

int main(int argc, char **argv) {
int i;
#pragma omp parallel copyin // expected-error {{expected '(' after 'copyin'}}
#pragma omp parallel copyin ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel copyin () // expected-error {{expected expression}}
#pragma omp parallel copyin (k // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel copyin (h, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp parallel copyin (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
#pragma omp parallel copyin (l) // expected-error {{copyin variable must have an accessible, unambiguous copy assignment operator}}
#pragma omp parallel copyin (S1) // expected-error {{'S1' does not refer to a value}}
#pragma omp parallel copyin (argv[1]) // expected-error {{expected variable name}}
#pragma omp parallel copyin(i) // expected-error {{copyin variable must be threadprivate}}
#pragma omp parallel copyin(m) // expected-error {{copyin variable must have an accessible, unambiguous copy assignment operator}}
#pragma omp parallel copyin(ST<int>::s) // expected-error {{copyin variable must be threadprivate}}
foo();

return 0;
}
3 changes: 3 additions & 0 deletions clang/tools/libclang/CIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1954,6 +1954,9 @@ void OMPClauseEnqueue::VisitOMPFirstprivateClause(
void OMPClauseEnqueue::VisitOMPSharedClause(const OMPSharedClause *C) {
VisitOMPClauseList(C);
}
void OMPClauseEnqueue::VisitOMPCopyinClause(const OMPCopyinClause *C) {
VisitOMPClauseList(C);
}
}

void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {
Expand Down