summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2014-03-31 03:36:38 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2014-03-31 03:36:38 +0000
commitd48bcd8a4693b4adedd1db4be64a6998d490fa9a (patch)
tree74e5c8eb6bb796ab67ab519ddbc8362fc1f1c6a8 /clang/lib/Sema
parent79cfed55fc923b137a1a41702534b6830c4f5851 (diff)
downloadbcm5719-llvm-d48bcd8a4693b4adedd1db4be64a6998d490fa9a.tar.gz
bcm5719-llvm-d48bcd8a4693b4adedd1db4be64a6998d490fa9a.zip
[OPENMP] Implemented 'copyin' clause
llvm-svn: 205164
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp98
-rw-r--r--clang/lib/Sema/TreeTransform.h31
2 files changed, 126 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index dc2a68d418d..78f73c0c263 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -111,7 +111,6 @@ public:
DSAVarData hasDSA(VarDecl *D, OpenMPClauseKind CKind,
OpenMPDirectiveKind DKind = OMPD_unknown);
-
/// \brief Returns currently analyzed directive.
OpenMPDirectiveKind getCurrentDirective() const {
return Stack.back().Directive;
@@ -126,6 +125,13 @@ public:
return Stack.back().DefaultAttr;
}
+ /// \brief Checks if the spewcified variable is threadprivate.
+ bool isThreadPrivate(VarDecl *D) {
+ DSAVarData DVar = getTopDSA(D);
+ return (DVar.CKind == OMPC_threadprivate || DVar.CKind == OMPC_copyin);
+ }
+
+ Scope *getCurScope() const { return Stack.back().CurScope; }
Scope *getCurScope() { return Stack.back().CurScope; }
};
} // end anonymous namespace.
@@ -245,7 +251,8 @@ void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
}
}
-bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
+bool
+DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
if (Stack.size() > 2) {
reverse_iterator I = Iter, E = Stack.rend() - 1;
Scope *TopScope = 0;
@@ -611,7 +618,7 @@ public:
DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD);
if (DVar.CKind != OMPC_unknown) {
if (DKind == OMPD_task && DVar.CKind != OMPC_shared &&
- DVar.CKind != OMPC_threadprivate && !DVar.RefExpr)
+ !Stack->isThreadPrivate(VD) && !DVar.RefExpr)
ImplicitFirstprivate.push_back(DVar.RefExpr);
return;
}
@@ -768,6 +775,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
+ case OMPC_copyin:
case OMPC_threadprivate:
case OMPC_unknown:
case NUM_OPENMP_CLAUSES:
@@ -922,6 +930,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
case OMPC_private:
case OMPC_firstprivate:
case OMPC_shared:
+ case OMPC_copyin:
case OMPC_threadprivate:
case OMPC_unknown:
case NUM_OPENMP_CLAUSES:
@@ -992,6 +1001,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
case OMPC_shared:
Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_copyin:
+ Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_num_threads:
case OMPC_safelen:
@@ -1371,4 +1383,84 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
}
+OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ SmallVector<Expr *, 8> Vars;
+ for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
+ I != E; ++I) {
+ assert(*I && "NULL expr in OpenMP copyin clause.");
+ if (isa<DependentScopeDeclRefExpr>(*I)) {
+ // It will be analyzed later.
+ Vars.push_back(*I);
+ continue;
+ }
+
+ SourceLocation ELoc = (*I)->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>(*I);
+ if (!DE || !isa<VarDecl>(DE->getDecl())) {
+ Diag(ELoc, diag::err_omp_expected_var_name)
+ << (*I)->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.1, Restrictions, C/C++, p.1]
+ // A list item that appears in a copyin clause must be threadprivate.
+ if (!DSAStack->isThreadPrivate(VD)) {
+ Diag(ELoc, diag::err_omp_required_access)
+ << getOpenMPClauseName(OMPC_copyin)
+ << getOpenMPDirectiveName(OMPD_threadprivate);
+ 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 accesible, unambiguous copy assignment
+ // operator for the class type.
+ Type = Context.getBaseElementType(Type);
+ CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
+ Type->getAsCXXRecordDecl() : 0;
+ if (RD) {
+ CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
+ DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
+ if (!MD ||
+ CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
+ MD->isDeleted()) {
+ Diag(ELoc, diag::err_omp_required_method)
+ << getOpenMPClauseName(OMPC_copyin) << 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);
+ }
+
+ DSAStack->addDSA(VD, DE, OMPC_copyin);
+ Vars.push_back(DE);
+ }
+
+ if (Vars.empty()) return 0;
+
+ return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
+}
+
#undef DSAStack
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index a8ec18c7404..2c7328983a3 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1382,6 +1382,18 @@ public:
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.
@@ -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
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud