summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2014-06-27 10:37:06 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2014-06-27 10:37:06 +0000
commit3b54d86f4f0bedfffb6305b6f12283f9c62682db (patch)
tree04730260ddc52d65d4452d6e651786058fd92015 /lib
parent11a33cee19725d88b474912665c72835db03a87f (diff)
downloadclang-3b54d86f4f0bedfffb6305b6f12283f9c62682db.tar.gz
clang-3b54d86f4f0bedfffb6305b6f12283f9c62682db.tar.bz2
clang-3b54d86f4f0bedfffb6305b6f12283f9c62682db.tar.xz
[OPENMP] Parsing and sema analysis for 'copyprivate' clause.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@211886 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/Stmt.cpp22
-rw-r--r--lib/AST/StmtPrinter.cpp8
-rw-r--r--lib/AST/StmtProfile.cpp4
-rw-r--r--lib/Basic/OpenMPKinds.cpp6
-rw-r--r--lib/Parse/ParseOpenMP.cpp8
-rw-r--r--lib/Sema/SemaOpenMP.cpp196
-rw-r--r--lib/Sema/TreeTransform.h45
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp13
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp7
9 files changed, 270 insertions, 39 deletions
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 5245944e85..102d14b475 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -1280,6 +1280,28 @@ OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPCopyinClause(N);
}
+OMPCopyprivateClause *OMPCopyprivateClause::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc,
+ ArrayRef<Expr *> VL) {
+ void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),
+ llvm::alignOf<Expr *>()) +
+ sizeof(Expr *) * VL.size());
+ OMPCopyprivateClause *Clause =
+ new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
+ Clause->setVarRefs(VL);
+ return Clause;
+}
+
+OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C,
+ unsigned N) {
+ void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),
+ llvm::alignOf<Expr *>()) +
+ sizeof(Expr *) * N);
+ return new (Mem) OMPCopyprivateClause(N);
+}
+
void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) {
assert(Clauses.size() == getNumClauses() &&
"Number of clauses is not the same as the preallocated buffer");
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 4a46063df3..28ce174207 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -748,6 +748,14 @@ void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) {
}
}
+void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "copyprivate";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
}
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index f3f3c7ba8e..f562ed6aa7 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -335,6 +335,10 @@ void OMPClauseProfiler::VisitOMPAlignedClause(const OMPAlignedClause *C) {
void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) {
VisitOMPClauseList(C);
}
+void
+OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) {
+ VisitOMPClauseList(C);
+}
}
void
diff --git a/lib/Basic/OpenMPKinds.cpp b/lib/Basic/OpenMPKinds.cpp
index 623af2df60..07121215e7 100644
--- a/lib/Basic/OpenMPKinds.cpp
+++ b/lib/Basic/OpenMPKinds.cpp
@@ -95,6 +95,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
+ case OMPC_copyprivate:
case OMPC_ordered:
case OMPC_nowait:
break;
@@ -149,6 +150,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
+ case OMPC_copyprivate:
case OMPC_ordered:
case OMPC_nowait:
break;
@@ -193,7 +195,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
case OMPD_sections:
switch (CKind) {
-#define OPENMP_SECTIONS_CLAUSE(Name) \
+#define OPENMP_SECTIONS_CLAUSE(Name) \
case OMPC_##Name: \
return true;
#include "clang/Basic/OpenMPKinds.def"
@@ -203,7 +205,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
break;
case OMPD_single:
switch (CKind) {
-#define OPENMP_SINGLE_CLAUSE(Name) \
+#define OPENMP_SINGLE_CLAUSE(Name) \
case OMPC_##Name: \
return true;
#include "clang/Basic/OpenMPKinds.def"
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index 102cab36e9..b35082e6c4 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -131,7 +131,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
if (isOpenMPSimdDirective(DKind))
ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
ParseScope OMPDirectiveScope(this, ScopeFlags);
- Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope());
+ Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OpenMPClauseKind CKind = Tok.isAnnotation()
@@ -159,7 +159,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
{
// The body is a block scope like in Lambdas and Blocks.
Sema::CompoundScopeRAII CompoundScope(Actions);
- Actions.ActOnOpenMPRegionStart(DKind, Loc, getCurScope());
+ Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
Actions.ActOnStartOfCompoundStmt();
// Parse statement
AssociatedStmt = ParseStatement();
@@ -269,7 +269,8 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
/// if-clause | num_threads-clause | safelen-clause | default-clause |
/// private-clause | firstprivate-clause | shared-clause | linear-clause |
/// aligned-clause | collapse-clause | lastprivate-clause |
-/// reduction-clause | proc_bind-clause | schedule-clause
+/// reduction-clause | proc_bind-clause | schedule-clause |
+/// copyin-clause | copyprivate-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@@ -345,6 +346,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
+ case OMPC_copyprivate:
Clause = ParseOpenMPVarListClause(CKind);
break;
case OMPC_unknown:
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index 7f3560fc01..6ff617fc17 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -68,7 +68,10 @@ public:
OpenMPDirectiveKind DKind;
OpenMPClauseKind CKind;
DeclRefExpr *RefExpr;
- DSAVarData() : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr) {}
+ SourceLocation ImplicitDSALoc;
+ DSAVarData()
+ : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr),
+ ImplicitDSALoc() {}
};
private:
@@ -83,17 +86,20 @@ private:
DeclSAMapTy SharingMap;
AlignedMapTy AlignedMap;
DefaultDataSharingAttributes DefaultAttr;
+ SourceLocation DefaultAttrLoc;
OpenMPDirectiveKind Directive;
DeclarationNameInfo DirectiveName;
Scope *CurScope;
+ SourceLocation ConstructLoc;
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
- Scope *CurScope)
+ Scope *CurScope, SourceLocation Loc)
: SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
- Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope) {
- }
+ Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope),
+ ConstructLoc(Loc) {}
SharingMapTy()
: SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
- Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr) {}
+ Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr),
+ ConstructLoc() {}
};
typedef SmallVector<SharingMapTy, 64> StackTy;
@@ -113,8 +119,9 @@ public:
explicit DSAStackTy(Sema &S) : Stack(1), SemaRef(S) {}
void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
- Scope *CurScope) {
- Stack.push_back(SharingMapTy(DKind, DirName, CurScope));
+ Scope *CurScope, SourceLocation Loc) {
+ Stack.push_back(SharingMapTy(DKind, DirName, CurScope, Loc));
+ Stack.back().DefaultAttrLoc = Loc;
}
void pop() {
@@ -160,13 +167,22 @@ public:
}
/// \brief Set default data sharing attribute to none.
- void setDefaultDSANone() { Stack.back().DefaultAttr = DSA_none; }
+ void setDefaultDSANone(SourceLocation Loc) {
+ Stack.back().DefaultAttr = DSA_none;
+ Stack.back().DefaultAttrLoc = Loc;
+ }
/// \brief Set default data sharing attribute to shared.
- void setDefaultDSAShared() { Stack.back().DefaultAttr = DSA_shared; }
+ void setDefaultDSAShared(SourceLocation Loc) {
+ Stack.back().DefaultAttr = DSA_shared;
+ Stack.back().DefaultAttrLoc = Loc;
+ }
DefaultDataSharingAttributes getDefaultDSA() const {
return Stack.back().DefaultAttr;
}
+ SourceLocation getDefaultDSALocation() const {
+ return Stack.back().DefaultAttrLoc;
+ }
/// \brief Checks if the specified variable is a threadprivate.
bool isThreadPrivate(VarDecl *D) {
@@ -176,6 +192,7 @@ public:
Scope *getCurScope() const { return Stack.back().CurScope; }
Scope *getCurScope() { return Stack.back().CurScope; }
+ SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
};
} // namespace
@@ -227,6 +244,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
switch (Iter->DefaultAttr) {
case DSA_shared:
DVar.CKind = OMPC_shared;
+ DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
return DVar;
case DSA_none:
return DVar;
@@ -235,6 +253,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
// in a Construct, implicitly determined, p.2]
// In a parallel construct, if no default clause is present, these
// variables are shared.
+ DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
if (isOpenMPParallelDirective(DVar.DKind)) {
DVar.CKind = OMPC_shared;
return DVar;
@@ -456,8 +475,8 @@ void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
const DeclarationNameInfo &DirName,
- Scope *CurScope) {
- DSAStack->push(DKind, DirName, CurScope);
+ Scope *CurScope, SourceLocation Loc) {
+ DSAStack->push(DKind, DirName, CurScope, Loc);
PushExpressionEvaluationContext(PotentiallyEvaluated);
}
@@ -776,8 +795,9 @@ static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
PDSA_LoopIterVarLastprivate,
PDSA_ConstVarShared,
PDSA_GlobalVarShared,
- PDSA_LocalVarPrivate
- } Reason;
+ PDSA_LocalVarPrivate,
+ PDSA_Implicit
+ } Reason = PDSA_Implicit;
bool ReportHint = false;
if (IsLoopIterVar) {
if (DVar.CKind == OMPC_private)
@@ -794,14 +814,18 @@ static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
Reason = PDSA_GlobalVarShared;
else if (VD->getType().isConstant(SemaRef.getASTContext()))
Reason = PDSA_ConstVarShared;
- else {
+ else if (VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
ReportHint = true;
Reason = PDSA_LocalVarPrivate;
}
-
- SemaRef.Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
- << Reason << ReportHint
- << getOpenMPDirectiveName(Stack->getCurrentDirective());
+ if (Reason != PDSA_Implicit) {
+ SemaRef.Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
+ << Reason << ReportHint
+ << getOpenMPDirectiveName(Stack->getCurrentDirective());
+ } else if (DVar.ImplicitDSALoc.isValid()) {
+ SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
+ << getOpenMPClauseName(DVar.CKind);
+ }
}
namespace {
@@ -882,8 +906,7 @@ public:
};
} // namespace
-void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, SourceLocation Loc,
- Scope *CurScope) {
+void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
switch (DKind) {
case OMPD_parallel: {
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
@@ -893,42 +916,48 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, SourceLocation Loc,
std::make_pair(".bound_tid.", KmpInt32PtrTy),
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
- ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
break;
}
case OMPD_simd: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
- ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
break;
}
case OMPD_for: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
- ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
break;
}
case OMPD_sections: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
- ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
break;
}
case OMPD_section: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
- ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
break;
}
case OMPD_single: {
Sema::CapturedParamNameType Params[] = {
std::make_pair(StringRef(), QualType()) // __context with shared vars
};
- ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
+ ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
+ Params);
break;
}
case OMPD_threadprivate:
@@ -1695,6 +1724,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
+ case OMPC_copyprivate:
case OMPC_ordered:
case OMPC_nowait:
case OMPC_threadprivate:
@@ -1874,6 +1904,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
+ case OMPC_copyprivate:
case OMPC_ordered:
case OMPC_nowait:
case OMPC_threadprivate:
@@ -1914,10 +1945,10 @@ OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
}
switch (Kind) {
case OMPC_DEFAULT_none:
- DSAStack->setDefaultDSANone();
+ DSAStack->setDefaultDSANone(KindKwLoc);
break;
case OMPC_DEFAULT_shared:
- DSAStack->setDefaultDSAShared();
+ DSAStack->setDefaultDSAShared(KindKwLoc);
break;
case OMPC_DEFAULT_unknown:
llvm_unreachable("Clause kind is not allowed.");
@@ -1984,6 +2015,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
+ case OMPC_copyprivate:
case OMPC_ordered:
case OMPC_nowait:
case OMPC_threadprivate:
@@ -2073,6 +2105,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_linear:
case OMPC_aligned:
case OMPC_copyin:
+ case OMPC_copyprivate:
case OMPC_default:
case OMPC_proc_bind:
case OMPC_threadprivate:
@@ -2126,6 +2159,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_copyin:
Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_copyprivate:
+ Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
@@ -3281,4 +3317,108 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
}
+OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ SmallVector<Expr *, 8> Vars;
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ // OpenMP [2.1, C/C++]
+ // A list item is a variable name.
+ // OpenMP [2.14.4.1, Restrictions, p.1]
+ // A list item that appears in a copyin clause must be threadprivate.
+ DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
+ if (!DE || !isa<VarDecl>(DE->getDecl())) {
+ Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
+ continue;
+ }
+
+ Decl *D = DE->getDecl();
+ VarDecl *VD = cast<VarDecl>(D);
+
+ QualType Type = VD->getType();
+ if (Type->isDependentType() || Type->isInstantiationDependentType()) {
+ // It will be analyzed later.
+ Vars.push_back(DE);
+ continue;
+ }
+
+ // OpenMP [2.14.4.2, Restrictions, p.2]
+ // A list item that appears in a copyprivate clause may not appear in a
+ // private or firstprivate clause on the single construct.
+ if (!DSAStack->isThreadPrivate(VD)) {
+ auto DVar = DSAStack->getTopDSA(VD);
+ if (DVar.CKind != OMPC_copyprivate && DVar.CKind != OMPC_unknown &&
+ !(DVar.CKind == OMPC_private && !DVar.RefExpr)) {
+ Diag(ELoc, diag::err_omp_wrong_dsa)
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPClauseName(OMPC_copyprivate);
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+
+ // OpenMP [2.11.4.2, Restrictions, p.1]
+ // All list items that appear in a copyprivate clause must be either
+ // threadprivate or private in the enclosing context.
+ if (DVar.CKind == OMPC_unknown) {
+ DVar = DSAStack->getImplicitDSA(VD);
+ if (DVar.CKind == OMPC_shared) {
+ Diag(ELoc, diag::err_omp_required_access)
+ << getOpenMPClauseName(OMPC_copyprivate)
+ << "threadprivate or private in the enclosing context";
+ ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ continue;
+ }
+ }
+ }
+
+ // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
+ // A variable of class type (or array thereof) that appears in a
+ // copyin clause requires an accessible, unambiguous copy assignment
+ // operator for the class type.
+ Type = Context.getBaseElementType(Type);
+ CXXRecordDecl *RD =
+ getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
+ // FIXME This code must be replaced by actual assignment of the
+ // threadprivate variable.
+ if (RD) {
+ CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
+ DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
+ if (MD) {
+ if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
+ MD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_copyprivate) << 2;
+ bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
+ VarDecl::DeclarationOnly;
+ Diag(VD->getLocation(),
+ IsDecl ? diag::note_previous_decl : diag::note_defined_here)
+ << VD;
+ Diag(RD->getLocation(), diag::note_previous_decl) << RD;
+ continue;
+ }
+ MarkFunctionReferenced(ELoc, MD);
+ DiagnoseUseOfDecl(MD, ELoc);
+ }
+ }
+
+ // No need to mark vars as copyprivate, they are already threadprivate or
+ // implicitly private.
+ Vars.push_back(DE);
+ }
+
+ if (Vars.empty())
+ return nullptr;
+
+ return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
+}
+
#undef DSAStack
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 974f5e061b..175c4e6502 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1494,6 +1494,18 @@ public:
EndLoc);
}
+ /// \brief Build a new OpenMP 'copyprivate' clause.
+ ///
+ /// By default, performs semantic analysis to build the new OpenMP clause.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPCopyprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -6403,7 +6415,8 @@ template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {
DeclarationNameInfo DirName;
- getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, nullptr);
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, nullptr,
+ D->getLocStart());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -6413,7 +6426,8 @@ template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPSimdDirective(OMPSimdDirective *D) {
DeclarationNameInfo DirName;
- getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, nullptr);
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, nullptr,
+ D->getLocStart());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -6423,7 +6437,8 @@ template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPForDirective(OMPForDirective *D) {
DeclarationNameInfo DirName;
- getDerived().getSema().StartOpenMPDSABlock(OMPD_for, DirName, nullptr);
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_for, DirName, nullptr,
+ D->getLocStart());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -6433,7 +6448,8 @@ template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPSectionsDirective(OMPSectionsDirective *D) {
DeclarationNameInfo DirName;
- getDerived().getSema().StartOpenMPDSABlock(OMPD_sections, DirName, nullptr);
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_sections, DirName, nullptr,
+ D->getLocStart());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -6443,7 +6459,8 @@ template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPSectionDirective(OMPSectionDirective *D) {
DeclarationNameInfo DirName;
- getDerived().getSema().StartOpenMPDSABlock(OMPD_section, DirName, nullptr);
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_section, DirName, nullptr,
+ D->getLocStart());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -6453,7 +6470,8 @@ template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPSingleDirective(OMPSingleDirective *D) {
DeclarationNameInfo DirName;
- getDerived().getSema().StartOpenMPDSABlock(OMPD_single, DirName, nullptr);
+ getDerived().getSema().StartOpenMPDSABlock(OMPD_single, DirName, nullptr,
+ D->getLocStart());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().EndOpenMPDSABlock(Res.get());
return Res;
@@ -6680,6 +6698,21 @@ TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *C) {
C->getLParenLoc(), C->getLocEnd());
}
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPCopyprivateClause(OMPCopyprivateClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return nullptr;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPCopyprivateClause(
+ Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
+}
+
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index ea8d0f3ac9..c94c43578f 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -1724,6 +1724,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_copyin:
C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]);
break;
+ case OMPC_copyprivate:
+ C = OMPCopyprivateClause::CreateEmpty(Context, Record[Idx++]);
+ break;
}
Visit(C);
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
@@ -1871,6 +1874,16 @@ void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) {
C->setVarRefs(Vars);
}
+void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *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.
//===----------------------------------------------------------------------===//
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 1292ec8aa8..8655bc67ed 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -1782,6 +1782,13 @@ void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {
Writer->Writer.AddStmt(VE);
}
+void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
+ Record.push_back(C->varlist_size());
+ Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
+ for (auto *VE : C->varlists())
+ Writer->Writer.AddStmt(VE);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//