diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclOpenMP.cpp | 1 | ||||
-rw-r--r-- | clang/lib/AST/Stmt.cpp | 52 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 61 | ||||
-rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 34 | ||||
-rw-r--r-- | clang/lib/Basic/OpenMPKinds.cpp | 87 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 243 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 5 | ||||
-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 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 85 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 62 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 |
14 files changed, 987 insertions, 12 deletions
diff --git a/clang/lib/AST/DeclOpenMP.cpp b/clang/lib/AST/DeclOpenMP.cpp index 522caefe3bd..0d195f74623 100644 --- a/clang/lib/AST/DeclOpenMP.cpp +++ b/clang/lib/AST/DeclOpenMP.cpp @@ -58,3 +58,4 @@ void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) { Expr **Vars = reinterpret_cast<Expr **>(this + 1); std::copy(VL.begin(), VL.end(), Vars); } + diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index d9d79f4cccd..6a39996cac3 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -18,6 +18,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenMP.h" #include "clang/AST/Type.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/TargetInfo.h" @@ -1118,3 +1119,54 @@ bool CapturedStmt::capturesVariable(const VarDecl *Var) const { return false; } + +OMPPrivateClause *OMPPrivateClause::Create(ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef<Expr *> VL) { + void *Mem = C.Allocate(sizeof(OMPPrivateClause) + sizeof(Expr *) * VL.size(), + llvm::alignOf<OMPPrivateClause>()); + OMPPrivateClause *Clause = new (Mem) OMPPrivateClause(StartLoc, LParenLoc, + EndLoc, VL.size()); + Clause->setVarRefs(VL); + return Clause; +} + +OMPPrivateClause *OMPPrivateClause::CreateEmpty(ASTContext &C, + unsigned N) { + void *Mem = C.Allocate(sizeof(OMPPrivateClause) + sizeof(Expr *) * N, + llvm::alignOf<OMPPrivateClause>()); + return new (Mem) OMPPrivateClause(N); +} + +void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) { + assert(Clauses.size() == this->Clauses.size() && + "Number of clauses is not the same as the preallocated buffer"); + std::copy(Clauses.begin(), Clauses.end(), this->Clauses.begin()); +} + +OMPParallelDirective *OMPParallelDirective::Create( + ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt) { + void *Mem = C.Allocate(sizeof(OMPParallelDirective) + + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *), + llvm::alignOf<OMPParallelDirective>()); + OMPParallelDirective *Dir = new (Mem) OMPParallelDirective(StartLoc, EndLoc, + Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPParallelDirective *OMPParallelDirective::CreateEmpty(ASTContext &C, + unsigned N, + EmptyShell) { + void *Mem = C.Allocate(sizeof(OMPParallelDirective) + + sizeof(OMPClause *) * N + sizeof(Stmt *), + llvm::alignOf<OMPParallelDirective>()); + return new (Mem) OMPParallelDirective(N); +} diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index d6358023907..c1732cdfd11 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -580,6 +580,67 @@ void StmtPrinter::VisitSEHFinallyStmt(SEHFinallyStmt *Node) { } //===----------------------------------------------------------------------===// +// OpenMP clauses printing methods +//===----------------------------------------------------------------------===// + +namespace { +class OMPClausePrinter : public OMPClauseVisitor<OMPClausePrinter> { + raw_ostream &OS; +public: + OMPClausePrinter(raw_ostream &OS) : OS(OS) { } +#define OPENMP_CLAUSE(Name, Class) \ + void Visit##Class(Class *S); +#include "clang/Basic/OpenMPKinds.def" +}; + +void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) { + OS << "default(" + << getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind()) + << ")"; +} + +#define PROCESS_OMP_CLAUSE_LIST(Class, Node, StartSym) \ + for (OMPVarList<Class>::varlist_iterator I = Node->varlist_begin(), \ + E = Node->varlist_end(); \ + I != E; ++I) \ + OS << (I == Node->varlist_begin() ? StartSym : ',') \ + << *cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl()); + +void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) { + if (!Node->varlist_empty()) { + OS << "private"; + PROCESS_OMP_CLAUSE_LIST(OMPPrivateClause, Node, '(') + OS << ")"; + } +} + +#undef PROCESS_OMP_CLAUSE_LIST +} + +//===----------------------------------------------------------------------===// +// OpenMP directives printing methods +//===----------------------------------------------------------------------===// + +void StmtPrinter::VisitOMPParallelDirective(OMPParallelDirective *Node) { + Indent() << "#pragma omp parallel "; + + OMPClausePrinter Printer(OS); + ArrayRef<OMPClause *> Clauses = Node->clauses(); + for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end(); + I != E; ++I) + if (*I && !(*I)->isImplicit()) { + Printer.Visit(*I); + OS << ' '; + } + OS << "\n"; + if (Node->getAssociatedStmt()) { + assert(isa<CapturedStmt>(Node->getAssociatedStmt()) && + "Expected captured statement!"); + Stmt *CS = cast<CapturedStmt>(Node->getAssociatedStmt())->getCapturedStmt(); + PrintStmt(CS); + } +} +//===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 391c1e60abe..a626f68aa58 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -252,6 +252,40 @@ StmtProfiler::VisitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt *S) { VisitStmt(S); } +namespace { +class OMPClauseProfiler : public ConstOMPClauseVisitor<OMPClauseProfiler> { + StmtProfiler *Profiler; +public: + OMPClauseProfiler(StmtProfiler *P) : Profiler(P) { } +#define OPENMP_CLAUSE(Name, Class) \ + void Visit##Class(const Class *C); +#include "clang/Basic/OpenMPKinds.def" +}; + +void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { } +#define PROCESS_OMP_CLAUSE_LIST(Class, Node) \ + for (OMPVarList<Class>::varlist_const_iterator I = Node->varlist_begin(), \ + E = Node->varlist_end(); \ + I != E; ++I) \ + Profiler->VisitStmt(*I); + +void OMPClauseProfiler::VisitOMPPrivateClause(const OMPPrivateClause *C) { + PROCESS_OMP_CLAUSE_LIST(OMPPrivateClause, C) +} +#undef PROCESS_OMP_CLAUSE_LIST +} + +void +StmtProfiler::VisitOMPParallelDirective(const OMPParallelDirective *S) { + VisitStmt(S); + OMPClauseProfiler P(this); + ArrayRef<OMPClause *> Clauses = S->clauses(); + for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end(); + I != E; ++I) + if (*I) + P.Visit(*I); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index b90fbc7a7c7..8f2d74d6fa4 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -36,9 +36,94 @@ const char *clang::getOpenMPDirectiveName(OpenMPDirectiveKind Kind) { #define OPENMP_DIRECTIVE(Name) \ case OMPD_##Name : return #Name; #include "clang/Basic/OpenMPKinds.def" - default: + case NUM_OPENMP_DIRECTIVES: break; } llvm_unreachable("Invalid OpenMP directive kind"); } +OpenMPClauseKind clang::getOpenMPClauseKind(StringRef Str) { + return llvm::StringSwitch<OpenMPClauseKind>(Str) +#define OPENMP_CLAUSE(Name, Class) \ + .Case(#Name, OMPC_##Name) +#include "clang/Basic/OpenMPKinds.def" + .Default(OMPC_unknown); +} + +const char *clang::getOpenMPClauseName(OpenMPClauseKind Kind) { + assert(Kind < NUM_OPENMP_CLAUSES); + switch (Kind) { + case OMPC_unknown: + return "unknown"; +#define OPENMP_CLAUSE(Name, Class) \ + case OMPC_##Name : return #Name; +#include "clang/Basic/OpenMPKinds.def" + case OMPC_threadprivate: + return "threadprivate or thread local"; + case NUM_OPENMP_CLAUSES: + break; + } + llvm_unreachable("Invalid OpenMP clause kind"); +} + +unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, + StringRef Str) { + switch (Kind) { + case OMPC_default: + return llvm::StringSwitch<OpenMPDefaultClauseKind>(Str) +#define OPENMP_DEFAULT_KIND(Name) \ + .Case(#Name, OMPC_DEFAULT_##Name) +#include "clang/Basic/OpenMPKinds.def" + .Default(OMPC_DEFAULT_unknown); + case OMPC_unknown: + case OMPC_threadprivate: + case OMPC_private: + case NUM_OPENMP_CLAUSES: + break; + } + llvm_unreachable("Invalid OpenMP simple clause kind"); +} + +const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, + unsigned Type) { + switch (Kind) { + case OMPC_default: + switch (Type) { + case OMPC_DEFAULT_unknown: + return "unknown"; +#define OPENMP_DEFAULT_KIND(Name) \ + case OMPC_DEFAULT_##Name : return #Name; +#include "clang/Basic/OpenMPKinds.def" + } + llvm_unreachable("Invalid OpenMP 'default' clause type"); + case OMPC_unknown: + case OMPC_threadprivate: + case OMPC_private: + case NUM_OPENMP_CLAUSES: + break; + } + llvm_unreachable("Invalid OpenMP simple clause kind"); +} + +bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, + OpenMPClauseKind CKind) { + assert(DKind < NUM_OPENMP_DIRECTIVES); + assert(CKind < NUM_OPENMP_CLAUSES); + switch (DKind) { + case OMPD_parallel: + switch (CKind) { +#define OPENMP_PARALLEL_CLAUSE(Name) \ + case OMPC_##Name: return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; + case OMPD_unknown: + case OMPD_threadprivate: + case OMPD_task: + case NUM_OPENMP_DIRECTIVES: + break; + } + return false; +} diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 8ee919754b0..6c7bd88c0c4 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -75,6 +75,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::SEHExceptStmtClass: case Stmt::SEHFinallyStmtClass: case Stmt::MSDependentExistsStmtClass: + case Stmt::OMPParallelDirectiveClass: llvm_unreachable("invalid statement class to emit generically"); case Stmt::NullStmtClass: case Stmt::CompoundStmtClass: diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index e192ae2e234..2f6be9e7876 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTConsumer.h" +#include "clang/AST/StmtOpenMP.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Sema/Scope.h" @@ -57,7 +58,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_unknown: Diag(Tok, diag::err_omp_unknown_directive); break; - default: + case OMPD_parallel: + case OMPD_task: + case NUM_OPENMP_DIRECTIVES: Diag(Tok, diag::err_omp_unexpected_directive) << getOpenMPDirectiveName(DKind); break; @@ -66,6 +69,111 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { return DeclGroupPtrTy(); } +/// \brief Parsing of declarative or executable OpenMP directives. +/// +/// threadprivate-directive: +/// annot_pragma_openmp 'threadprivate' simple-variable-list +/// annot_pragma_openmp_end +/// +/// parallel-directive: +/// annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end +/// +StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { + assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); + SmallVector<Expr *, 5> Identifiers; + SmallVector<OMPClause *, 5> Clauses; + SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES> + FirstClauses(NUM_OPENMP_CLAUSES); + const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope; + SourceLocation Loc = ConsumeToken(), EndLoc; + OpenMPDirectiveKind DKind = Tok.isAnnotation() ? + OMPD_unknown : + getOpenMPDirectiveKind(PP.getSpelling(Tok)); + StmtResult Directive = StmtError(); + + switch (DKind) { + case OMPD_threadprivate: + ConsumeToken(); + if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) { + // The last seen token is annot_pragma_openmp_end - need to check for + // extra tokens. + if (Tok.isNot(tok::annot_pragma_openmp_end)) { + Diag(Tok, diag::warn_omp_extra_tokens_at_eol) + << getOpenMPDirectiveName(OMPD_threadprivate); + SkipUntil(tok::annot_pragma_openmp_end, false, true); + } + DeclGroupPtrTy Res = + Actions.ActOnOpenMPThreadprivateDirective(Loc, + Identifiers); + Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); + } + SkipUntil(tok::annot_pragma_openmp_end, false); + break; + case OMPD_parallel: { + ConsumeToken(); + while (Tok.isNot(tok::annot_pragma_openmp_end)) { + OpenMPClauseKind CKind = Tok.isAnnotation() ? + OMPC_unknown : + getOpenMPClauseKind(PP.getSpelling(Tok)); + OMPClause *Clause = ParseOpenMPClause(DKind, CKind, + !FirstClauses[CKind].getInt()); + FirstClauses[CKind].setInt(true); + if (Clause) { + FirstClauses[CKind].setPointer(Clause); + Clauses.push_back(Clause); + } + + // Skip ',' if any. + if (Tok.is(tok::comma)) + ConsumeToken(); + } + // End location of the directive. + EndLoc = Tok.getLocation(); + // Consume final annot_pragma_openmp_end. + ConsumeToken(); + + StmtResult AssociatedStmt; + bool CreateDirective = true; + ParseScope OMPDirectiveScope(this, ScopeFlags); + { + // The body is a block scope like in Lambdas and Blocks. + Sema::CompoundScopeRAII CompoundScope(Actions); + Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default, 1); + Actions.ActOnStartOfCompoundStmt(); + // Parse statement + AssociatedStmt = ParseStatement(); + Actions.ActOnFinishOfCompoundStmt(); + if (!AssociatedStmt.isUsable()) { + Actions.ActOnCapturedRegionError(); + CreateDirective = false; + } else { + AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take()); + CreateDirective = AssociatedStmt.isUsable(); + } + } + if (CreateDirective) + Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses, + AssociatedStmt.take(), + Loc, EndLoc); + + // Exit scope. + OMPDirectiveScope.Exit(); + } + break; + case OMPD_unknown: + Diag(Tok, diag::err_omp_unknown_directive); + SkipUntil(tok::annot_pragma_openmp_end, false); + break; + case OMPD_task: + case NUM_OPENMP_DIRECTIVES: + Diag(Tok, diag::err_omp_unexpected_directive) + << getOpenMPDirectiveName(DKind); + SkipUntil(tok::annot_pragma_openmp_end, false); + break; + } + return Directive; +} + /// \brief Parses list of simple variables for '#pragma omp threadprivate' /// directive. /// @@ -78,9 +186,10 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, VarList.clear(); // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); - bool LParen = !T.expectAndConsume(diag::err_expected_lparen_after, - getOpenMPDirectiveName(Kind)); - bool IsCorrect = LParen; + if (T.expectAndConsume(diag::err_expected_lparen_after, + getOpenMPDirectiveName(Kind))) + return true; + bool IsCorrect = true; bool NoIdentIsFound = true; // Read tokens while ')' or annot_pragma_openmp_end is not found. @@ -128,8 +237,130 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, } // Parse ')'. - IsCorrect = ((LParen || Tok.is(tok::r_paren)) && !T.consumeClose()) - && IsCorrect; + IsCorrect = !T.consumeClose() && IsCorrect; return !IsCorrect && VarList.empty(); } + +/// \brief Parsing of OpenMP clauses. +/// +/// clause: +/// default-clause|private-clause +/// +OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, + OpenMPClauseKind CKind, bool FirstClause) { + OMPClause *Clause = 0; + bool ErrorFound = false; + // Check if clause is allowed for the given directive. + if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { + Diag(Tok, diag::err_omp_unexpected_clause) + << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); + ErrorFound = true; + } + + switch (CKind) { + case OMPC_default: + // OpenMP [2.9.3.1, Restrictions] + // Only a single default clause may be specified on a parallel or task + // directive. + if (!FirstClause) { + Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind); + } + + Clause = ParseOpenMPSimpleClause(CKind); + break; + case OMPC_private: + Clause = ParseOpenMPVarListClause(CKind); + break; + case OMPC_unknown: + Diag(Tok, diag::warn_omp_extra_tokens_at_eol) + << getOpenMPDirectiveName(DKind); + SkipUntil(tok::annot_pragma_openmp_end, false, true); + break; + case OMPC_threadprivate: + case NUM_OPENMP_CLAUSES: + Diag(Tok, diag::err_omp_unexpected_clause) + << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); + SkipUntil(tok::comma, tok::annot_pragma_openmp_end, false, true); + break; + } + return ErrorFound ? 0 : Clause; +} + +/// \brief Parsing of simple OpenMP clauses like 'default'. +/// +/// default-clause: +/// 'default' '(' 'none' | 'shared' ') +/// +OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { + SourceLocation Loc = Tok.getLocation(); + SourceLocation LOpen = ConsumeToken(); + // Parse '('. + BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); + if (T.expectAndConsume(diag::err_expected_lparen_after, + getOpenMPClauseName(Kind))) + return 0; + + unsigned Type = Tok.isAnnotation() ? + OMPC_DEFAULT_unknown : + getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); + SourceLocation TypeLoc = Tok.getLocation(); + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && + Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + + // Parse ')'. + T.consumeClose(); + + return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, + Tok.getLocation()); +} + +/// \brief Parsing of OpenMP clause 'private', 'firstprivate', +/// 'shared', 'copyin', or 'reduction'. +/// +/// private-clause: +/// 'private' '(' list ')' +/// +OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { + SourceLocation Loc = Tok.getLocation(); + SourceLocation LOpen = ConsumeToken(); + // Parse '('. + BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); + if (T.expectAndConsume(diag::err_expected_lparen_after, + getOpenMPClauseName(Kind))) + return 0; + + SmallVector<Expr *, 5> Vars; + bool IsComma = true; + while (IsComma || (Tok.isNot(tok::r_paren) && + Tok.isNot(tok::annot_pragma_openmp_end))) { + // Parse variable + ExprResult VarExpr = ParseAssignmentExpression(); + if (VarExpr.isUsable()) { + Vars.push_back(VarExpr.take()); + } else { + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, + false, true); + } + // Skip ',' if any + IsComma = Tok.is(tok::comma); + if (IsComma) { + ConsumeToken(); + } else if (Tok.isNot(tok::r_paren) && + Tok.isNot(tok::annot_pragma_openmp_end)) { + Diag(Tok, diag::err_omp_expected_punc) + << 1 << getOpenMPClauseName(Kind); + } + } + + // Parse ')'. + T.consumeClose(); + if (Vars.empty()) + return 0; + + return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen, + Tok.getLocation()); +} + diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 749fec3026e..b03891082f4 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -306,9 +306,8 @@ Retry: return HandlePragmaCaptured(); case tok::annot_pragma_openmp: - SourceLocation DeclStart = Tok.getLocation(); - DeclGroupPtrTy Res = ParseOpenMPDeclarativeDirective(); - return Actions.ActOnDeclStmt(Res, DeclStart, Tok.getLocation()); + return ParseOpenMPDeclarativeOrExecutableDirective(); + } // If we reached this code, the statement must end in a semicolon. 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 //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 2f5dee8282d..113b12ff59b 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -25,6 +25,7 @@ using namespace clang::serialization; namespace clang { class ASTStmtReader : public StmtVisitor<ASTStmtReader> { + friend class OMPClauseReader; typedef ASTReader::RecordData RecordData; ASTReader &Reader; @@ -382,6 +383,7 @@ void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) { void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) { VisitStmt(S); + ++Idx; S->setCapturedDecl(ReadDeclAs<CapturedDecl>(Record, Idx)); S->setCapturedRegionKind(static_cast<CapturedRegionKind>(Record[Idx++])); S->setCapturedRecordDecl(ReadDeclAs<RecordDecl>(Record, Idx)); @@ -1656,6 +1658,81 @@ void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) { } //===----------------------------------------------------------------------===// +// OpenMP Clauses. +//===----------------------------------------------------------------------===// + +namespace clang { +class OMPClauseReader : public OMPClauseVisitor<OMPClauseReader> { + ASTStmtReader *Reader; + ASTContext &Context; + const ASTReader::RecordData &Record; + unsigned &Idx; +public: + OMPClauseReader(ASTStmtReader *R, ASTContext &C, + const ASTReader::RecordData &Record, unsigned &Idx) + : Reader(R), Context(C), Record(Record), Idx(Idx) { } +#define OPENMP_CLAUSE(Name, Class) \ + void Visit##Class(Class *S); +#include "clang/Basic/OpenMPKinds.def" + OMPClause *readClause(); +}; +} + +OMPClause *OMPClauseReader::readClause() { + OMPClause *C; + switch (Record[Idx++]) { + case OMPC_default: + C = new (Context) OMPDefaultClause(); + break; + case OMPC_private: + C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]); + break; + } + Visit(C); + C->setLocStart(Reader->ReadSourceLocation(Record, Idx)); + C->setLocEnd(Reader->ReadSourceLocation(Record, Idx)); + + return C; +} + +void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) { + C->setDefaultKind( + static_cast<OpenMPDefaultClauseKind>(Record[Idx++])); + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + C->setDefaultKindKwLoc(Reader->ReadSourceLocation(Record, Idx)); +} + +void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *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. +//===----------------------------------------------------------------------===// +void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) { + VisitStmt(E); + ++Idx; + E->setLocStart(ReadSourceLocation(Record, Idx)); + E->setLocEnd(ReadSourceLocation(Record, Idx)); + OMPClauseReader ClauseReader(this, Reader.getContext(), Record, Idx); + SmallVector<OMPClause *, 5> Clauses; + for (unsigned i = 0; i < E->getNumClauses(); ++i) + Clauses.push_back(ClauseReader.readClause()); + E->setClauses(Clauses); + E->setAssociatedStmt(Reader.ReadSubStmt()); +} + +void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) { + VisitOMPExecutableDirective(D); +} + +//===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -1821,7 +1898,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case STMT_CAPTURED: S = CapturedStmt::CreateDeserialized(Context, - Record[ASTStmtReader::NumExprFields]); + Record[ASTStmtReader::NumStmtFields]); break; case EXPR_PREDEFINED: @@ -2121,6 +2198,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { DeclarationNameInfo(), 0); break; + case STMT_OMP_PARALLEL_DIRECTIVE: + S = + OMPParallelDirective::CreateEmpty(Context, + Record[ASTStmtReader::NumStmtFields], + Empty); + break; case EXPR_CXX_OPERATOR_CALL: S = new (Context) CXXOperatorCallExpr(Context, Empty); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 4b01a218f56..8d47158f941 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -26,7 +26,9 @@ using namespace clang; //===----------------------------------------------------------------------===// namespace clang { + class ASTStmtWriter : public StmtVisitor<ASTStmtWriter, void> { + friend class OMPClauseWriter; ASTWriter &Writer; ASTWriter::RecordData &Record; @@ -1659,6 +1661,66 @@ void ASTStmtWriter::VisitSEHTryStmt(SEHTryStmt *S) { } //===----------------------------------------------------------------------===// +// OpenMP Clauses. +//===----------------------------------------------------------------------===// + +namespace clang { +class OMPClauseWriter : public OMPClauseVisitor<OMPClauseWriter> { + ASTStmtWriter *Writer; + ASTWriter::RecordData &Record; +public: + OMPClauseWriter(ASTStmtWriter *W, ASTWriter::RecordData &Record) + : Writer(W), Record(Record) { } +#define OPENMP_CLAUSE(Name, Class) \ + void Visit##Class(Class *S); +#include "clang/Basic/OpenMPKinds.def" + void writeClause(OMPClause *C); +}; +} + +void OMPClauseWriter::writeClause(OMPClause *C) { + Record.push_back(C->getClauseKind()); + Visit(C); + Writer->Writer.AddSourceLocation(C->getLocStart(), Record); + Writer->Writer.AddSourceLocation(C->getLocEnd(), Record); +} + +void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) { + Record.push_back(C->getDefaultKind()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + Writer->Writer.AddSourceLocation(C->getDefaultKindKwLoc(), Record); +} + +void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + for (OMPVarList<OMPPrivateClause>::varlist_iterator I = C->varlist_begin(), + E = C->varlist_end(); + I != E; ++I) + Writer->Writer.AddStmt(*I); +} + +//===----------------------------------------------------------------------===// +// OpenMP Directives. +//===----------------------------------------------------------------------===// +void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) { + VisitStmt(E); + Record.push_back(E->getNumClauses()); + Writer.AddSourceLocation(E->getLocStart(), Record); + Writer.AddSourceLocation(E->getLocEnd(), Record); + OMPClauseWriter ClauseWriter(this, Record); + for (unsigned i = 0; i < E->getNumClauses(); ++i) { + ClauseWriter.writeClause(E->getClause(i)); + } + Writer.AddStmt(E->getAssociatedStmt()); +} + +void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) { + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_PARALLEL_DIRECTIVE; +} + +//===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 74ffa1c9af7..d42291da9cd 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -665,6 +665,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::WhileStmtClass: case Expr::MSDependentExistsStmtClass: case Stmt::CapturedStmtClass: + case Stmt::OMPParallelDirectiveClass: llvm_unreachable("Stmt should not be in analyzer evaluation loop"); case Stmt::ObjCSubscriptRefExprClass: |