diff options
| author | Alexey Bataev <a.bataev@hotmail.com> | 2013-07-19 03:13:43 +0000 |
|---|---|---|
| committer | Alexey Bataev <a.bataev@hotmail.com> | 2013-07-19 03:13:43 +0000 |
| commit | 5ec3eb11fcb86c9b65588315dec2898d9be39499 (patch) | |
| tree | 47db933e9ac15e1d4378e63c5b8b70c7b5daf4e9 /clang/lib/Sema | |
| parent | 63c5c2a0d8258ed4fb6b536ad2e60f26f946675c (diff) | |
| download | bcm5719-llvm-5ec3eb11fcb86c9b65588315dec2898d9be39499.tar.gz bcm5719-llvm-5ec3eb11fcb86c9b65588315dec2898d9be39499.zip | |
OpenMP: basic support for #pragma omp parallel
llvm-svn: 186647
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaAccess.cpp | 15 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 222 | ||||
| -rw-r--r-- | clang/lib/Sema/TreeTransform.h | 130 |
3 files changed, 366 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index a99992748db..020787b39a7 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1710,6 +1710,21 @@ Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, return CheckAccess(*this, OpLoc, Entity); } +/// \brief Checks access to a member. +Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc, + CXXRecordDecl *NamingClass, + NamedDecl *D) { + if (!getLangOpts().AccessControl || + !NamingClass || + D->getAccess() == AS_public) + return AR_accessible; + + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, + DeclAccessPair::make(D, D->getAccess()), QualType()); + + return CheckAccess(*this, UseLoc, Entity); +} + /// Checks access to an overloaded member operator, including /// conversion operators. Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 4953d2d14e7..993eaba86e6 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -14,10 +14,17 @@ #include "clang/Basic/OpenMPKinds.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclOpenMP.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtOpenMP.h" +#include "clang/AST/StmtVisitor.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Initialization.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" using namespace clang; namespace { @@ -165,7 +172,8 @@ OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl( // A threadprivate variable must not have a reference type. if (VD->getType()->isReferenceType()) { Diag(ILoc, diag::err_omp_ref_type_arg) - << getOpenMPDirectiveName(OMPD_threadprivate); + << getOpenMPDirectiveName(OMPD_threadprivate) + << VD->getType(); bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : @@ -191,3 +199,215 @@ OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl( Loc, Vars); } +StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, + ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc) { + StmtResult Res = StmtError(); + switch (Kind) { + case OMPD_parallel: + Res = ActOnOpenMPParallelDirective(Clauses, AStmt, StartLoc, EndLoc); + break; + case OMPD_threadprivate: + case OMPD_task: + llvm_unreachable("OpenMP Directive is not allowed"); + case OMPD_unknown: + case NUM_OPENMP_DIRECTIVES: + llvm_unreachable("Unknown OpenMP directive"); + } + return Res; +} + +StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc) { + getCurFunction()->setHasBranchProtectedScope(); + + return Owned(OMPParallelDirective::Create(Context, StartLoc, EndLoc, + Clauses, AStmt)); +} + +OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, + unsigned Argument, + SourceLocation ArgumentLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + OMPClause *Res = 0; + switch (Kind) { + case OMPC_default: + Res = ActOnOpenMPDefaultClause( + static_cast<OpenMPDefaultClauseKind>(Argument), + ArgumentLoc, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_private: + case OMPC_threadprivate: + case OMPC_unknown: + case NUM_OPENMP_CLAUSES: + llvm_unreachable("Clause is not allowed."); + } + return Res; +} + +OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind, + SourceLocation KindKwLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + if (Kind == OMPC_DEFAULT_unknown) { + std::string Values; + std::string Sep(NUM_OPENMP_DEFAULT_KINDS > 1 ? ", " : ""); + for (unsigned i = OMPC_DEFAULT_unknown + 1; + i < NUM_OPENMP_DEFAULT_KINDS; ++i) { + Values += "'"; + Values += getOpenMPSimpleClauseTypeName(OMPC_default, i); + Values += "'"; + switch (i) { + case NUM_OPENMP_DEFAULT_KINDS - 2: + Values += " or "; + break; + case NUM_OPENMP_DEFAULT_KINDS - 1: + break; + default: + Values += Sep; + break; + } + } + Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) + << Values << getOpenMPClauseName(OMPC_default); + return 0; + } + return new (Context) OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, + EndLoc); +} + +OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind, + ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + OMPClause *Res = 0; + switch (Kind) { + case OMPC_private: + Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc); + break; + case OMPC_default: + case OMPC_threadprivate: + case OMPC_unknown: + case NUM_OPENMP_CLAUSES: + llvm_unreachable("Clause is not allowed."); + } + return Res; +} + +OMPClause *Sema::ActOnOpenMPPrivateClause(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) { + if (*I && 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.9.3.3, Restrictions, p.1] + // A variable that is part of another variable (as an array or + // structure element) cannot appear in a private clause. + DeclRefExpr *DE = dyn_cast_or_null<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.9.3.3, Restrictions, C/C++, p.3] + // A variable that appears in a private clause must not have an incomplete + // type or a reference type. + if (RequireCompleteType(ELoc, Type, + diag::err_omp_private_incomplete_type)) { + continue; + } + if (Type->isReferenceType()) { + Diag(ELoc, diag::err_omp_clause_ref_type_arg) + << getOpenMPClauseName(OMPC_private) << Type; + bool IsDecl = VD->isThisDeclarationADefinition(Context) == + VarDecl::DeclarationOnly; + Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : + diag::note_defined_here) << VD; + continue; + } + + // OpenMP [2.9.3.3, Restrictions, C/C++, p.1] + // A variable of class type (or array thereof) that appears in a private + // clause requires an accesible, unambiguous default constructor for the + // class type. + while (Type.getNonReferenceType()->isArrayType()) { + Type = cast<ArrayType>( + Type.getNonReferenceType().getTypePtr())->getElementType(); + } + CXXRecordDecl *RD = getLangOpts().CPlusPlus ? + Type.getNonReferenceType()->getAsCXXRecordDecl() : 0; + if (RD) { + CXXConstructorDecl *CD = LookupDefaultConstructor(RD); + PartialDiagnostic PD = + PartialDiagnostic(PartialDiagnostic::NullDiagnostic()); + if (!CD || + CheckConstructorAccess(ELoc, CD, + InitializedEntity::InitializeTemporary(Type), + CD->getAccess(), PD) == AR_inaccessible || + CD->isDeleted()) { + Diag(ELoc, diag::err_omp_required_method) + << getOpenMPClauseName(OMPC_private) << 0; + 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, CD); + DiagnoseUseOfDecl(CD, ELoc); + + CXXDestructorDecl *DD = RD->getDestructor(); + if (DD) { + if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible || + DD->isDeleted()) { + Diag(ELoc, diag::err_omp_required_method) + << getOpenMPClauseName(OMPC_private) << 4; + 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, DD); + DiagnoseUseOfDecl(DD, ELoc); + } + } + + Vars.push_back(DE); + } + + if (Vars.empty()) return 0; + + return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); +} + diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 5b4716f5be2..ef8049af843 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -24,6 +24,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenMP.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Designator.h" #include "clang/Sema/Lookup.h" @@ -313,6 +314,16 @@ public: /// \returns the transformed statement. StmtResult TransformStmt(Stmt *S); + /// \brief Transform the given statement. + /// + /// By default, this routine transforms a statement by delegating to the + /// appropriate TransformOMPXXXClause function to transform a specific kind + /// of clause. Subclasses may override this function to transform statements + /// using some other mechanism. + /// + /// \returns the transformed OpenMP clause. + OMPClause *TransformOMPClause(OMPClause *S); + /// \brief Transform the given expression. /// /// By default, this routine transforms an expression by delegating to the @@ -594,6 +605,10 @@ public: #define ABSTRACT_STMT(Stmt) #include "clang/AST/StmtNodes.inc" +#define OPENMP_CLAUSE(Name, Class) \ + OMPClause *Transform ## Class(Class *S); +#include "clang/Basic/OpenMPKinds.def" + /// \brief Build a new pointer type given its pointee type. /// /// By default, performs semantic analysis when building the pointer type. @@ -1255,6 +1270,43 @@ public: return getSema().BuildObjCAtThrowStmt(AtLoc, Operand); } + /// \brief Build a new OpenMP parallel directive. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildOMPParallelDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPParallelDirective(Clauses, AStmt, + StartLoc, EndLoc); + } + + /// \brief Build a new OpenMP 'default' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPDefaultClause(OpenMPDefaultClauseKind Kind, + SourceLocation KindKwLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPDefaultClause(Kind, KindKwLoc, + StartLoc, LParenLoc, EndLoc); + } + + /// \brief Build a new OpenMP 'private' clause. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OMPClause *RebuildOMPPrivateClause(ArrayRef<Expr *> VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc) { + return getSema().ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, + EndLoc); + } + /// \brief Rebuild the operand to an Objective-C \@synchronized statement. /// /// By default, performs semantic analysis to build the new statement. @@ -2600,6 +2652,23 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) { return SemaRef.Owned(S); } +template<typename Derived> +OMPClause *TreeTransform<Derived>::TransformOMPClause(OMPClause *S) { + if (!S) + return S; + + switch (S->getClauseKind()) { + default: break; + // Transform individual clause nodes +#define OPENMP_CLAUSE(Name, Class) \ + case OMPC_ ## Name : \ + return getDerived().Transform ## Class(cast<Class>(S)); +#include "clang/Basic/OpenMPKinds.def" + } + + return S; +} + template<typename Derived> ExprResult TreeTransform<Derived>::TransformExpr(Expr *E) { @@ -6178,6 +6247,67 @@ TreeTransform<Derived>::TransformSEHHandler(Stmt *Handler) { return getDerived().TransformSEHExceptStmt(cast<SEHExceptStmt>(Handler)); } +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) { + // Transform the clauses + llvm::SmallVector<OMPClause *, 5> TClauses; + ArrayRef<OMPClause *> Clauses = D->clauses(); + TClauses.reserve(Clauses.size()); + for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end(); + I != E; ++I) { + if (*I) { + OMPClause *Clause = getDerived().TransformOMPClause(*I); + if (!Clause) + return StmtError(); + TClauses.push_back(Clause); + } + else { + TClauses.push_back(0); + } + } + if (!D->getAssociatedStmt()) + return StmtError(); + StmtResult AssociatedStmt = + getDerived().TransformStmt(D->getAssociatedStmt()); + if (AssociatedStmt.isInvalid()) + return StmtError(); + + return getDerived().RebuildOMPParallelDirective(TClauses, + AssociatedStmt.take(), + D->getLocStart(), + D->getLocEnd()); +} + +template<typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) { + return getDerived().RebuildOMPDefaultClause(C->getDefaultKind(), + C->getDefaultKindKwLoc(), + C->getLocStart(), + C->getLParenLoc(), + C->getLocEnd()); +} + +template<typename Derived> +OMPClause * +TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) { + llvm::SmallVector<Expr *, 5> Vars; + Vars.reserve(C->varlist_size()); + for (OMPVarList<OMPPrivateClause>::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().RebuildOMPPrivateClause(Vars, + C->getLocStart(), + C->getLParenLoc(), + C->getLocEnd()); +} + //===----------------------------------------------------------------------===// // Expression transformation //===----------------------------------------------------------------------===// |

