diff options
Diffstat (limited to 'clang/lib/Analysis/CFG.cpp')
-rw-r--r-- | clang/lib/Analysis/CFG.cpp | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 80f5a46ceab..f92d311111e 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -589,6 +589,8 @@ private: CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc); CFGBlock *VisitChildren(Stmt *S); CFGBlock *VisitNoRecurse(Expr *E, AddStmtChoice asc); + CFGBlock *VisitOMPExecutableDirective(OMPExecutableDirective *D, + AddStmtChoice asc); void maybeAddScopeBeginForVarDecl(CFGBlock *B, const VarDecl *VD, const Stmt *S) { @@ -2058,6 +2060,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { if (Expr *E = dyn_cast<Expr>(S)) S = E->IgnoreParens(); + if (Context->getLangOpts().OpenMP) + if (auto *D = dyn_cast<OMPExecutableDirective>(S)) + return VisitOMPExecutableDirective(D, asc); + switch (S->getStmtClass()) { default: return VisitStmt(S, asc); @@ -4728,6 +4734,36 @@ CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors( return Block; } +CFGBlock *CFGBuilder::VisitOMPExecutableDirective(OMPExecutableDirective *D, + AddStmtChoice asc) { + if (asc.alwaysAdd(*this, D)) { + autoCreateBlock(); + appendStmt(Block, D); + } + + // Iterate over all used expression in clauses. + CFGBlock *B = Block; + + // Reverse the elements to process them in natural order. Iterators are not + // bidirectional, so we need to create temp vector. + for (Stmt *S : llvm::reverse(llvm::to_vector<8>( + OMPExecutableDirective::used_clauses_children(D->clauses())))) { + assert(S && "Expected non-null used-in-clause child."); + if (CFGBlock *R = Visit(S)) + B = R; + } + // Visit associated structured block if any. + if (!D->isStandaloneDirective()) + if (Stmt *S = D->getStructuredBlock()) { + if (!isa<CompoundStmt>(S)) + addLocalScopeAndDtors(S); + if (CFGBlock *R = addStmt(S)) + B = R; + } + + return B; +} + /// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has /// no successors or predecessors. If this is the first block created in the /// CFG, it is automatically set to be the Entry and Exit of the CFG. |