diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2014-03-31 03:36:38 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2014-03-31 03:36:38 +0000 |
commit | d48bcd8a4693b4adedd1db4be64a6998d490fa9a (patch) | |
tree | 74e5c8eb6bb796ab67ab519ddbc8362fc1f1c6a8 /clang/lib/Sema | |
parent | 79cfed55fc923b137a1a41702534b6830c4f5851 (diff) | |
download | bcm5719-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.cpp | 98 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 31 |
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 //===----------------------------------------------------------------------===// |