diff options
Diffstat (limited to 'clang/lib/Analysis/CFGStmtMap.cpp')
| -rw-r--r-- | clang/lib/Analysis/CFGStmtMap.cpp | 90 | 
1 files changed, 90 insertions, 0 deletions
diff --git a/clang/lib/Analysis/CFGStmtMap.cpp b/clang/lib/Analysis/CFGStmtMap.cpp new file mode 100644 index 0000000000000..d1c23e3c879b4 --- /dev/null +++ b/clang/lib/Analysis/CFGStmtMap.cpp @@ -0,0 +1,90 @@ +//===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +//  This file defines the CFGStmtMap class, which defines a mapping from +//  Stmt* to CFGBlock* +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseMap.h" +#include "clang/AST/ParentMap.h" +#include "clang/Analysis/CFG.h" +#include "clang/Analysis/CFGStmtMap.h" + +using namespace clang; + +typedef llvm::DenseMap<const Stmt*, CFGBlock*> SMap; +static SMap *AsMap(void *m) { return (SMap*) m; } + +CFGStmtMap::~CFGStmtMap() { delete AsMap(M); } + +CFGBlock *CFGStmtMap::getBlock(Stmt *S) { +  SMap *SM = AsMap(M); +  Stmt *X = S; + +  // If 'S' isn't in the map, walk the ParentMap to see if one of its ancestors +  // is in the map. +  while (X) { +    SMap::iterator I = SM->find(X); +    if (I != SM->end()) { +      CFGBlock *B = I->second; +      // Memoize this lookup. +      if (X != S) +        (*SM)[X] = B; +      return B; +    } + +    X = PM->getParentIgnoreParens(X); +  } + +  return nullptr; +} + +static void Accumulate(SMap &SM, CFGBlock *B) { +  // First walk the block-level expressions. +  for (CFGBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) { +    const CFGElement &CE = *I; +    Optional<CFGStmt> CS = CE.getAs<CFGStmt>(); +    if (!CS) +      continue; + +    CFGBlock *&Entry = SM[CS->getStmt()]; +    // If 'Entry' is already initialized (e.g., a terminator was already), +    // skip. +    if (Entry) +      continue; + +    Entry = B; + +  } + +  // Look at the label of the block. +  if (Stmt *Label = B->getLabel()) +    SM[Label] = B; + +  // Finally, look at the terminator.  If the terminator was already added +  // because it is a block-level expression in another block, overwrite +  // that mapping. +  if (Stmt *Term = B->getTerminatorStmt()) +    SM[Term] = B; +} + +CFGStmtMap *CFGStmtMap::Build(CFG *C, ParentMap *PM) { +  if (!C || !PM) +    return nullptr; + +  SMap *SM = new SMap(); + +  // Walk all blocks, accumulating the block-level expressions, labels, +  // and terminators. +  for (CFG::iterator I = C->begin(), E = C->end(); I != E; ++I) +    Accumulate(*SM, *I); + +  return new CFGStmtMap(PM, SM); +} +  | 
