CFGStmtMap.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. //===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines the CFGStmtMap class, which defines a mapping from
  10. // Stmt* to CFGBlock*
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/ADT/DenseMap.h"
  14. #include "clang/AST/ParentMap.h"
  15. #include "clang/Analysis/CFG.h"
  16. #include "clang/Analysis/CFGStmtMap.h"
  17. using namespace clang;
  18. typedef llvm::DenseMap<const Stmt*, CFGBlock*> SMap;
  19. static SMap *AsMap(void *m) { return (SMap*) m; }
  20. CFGStmtMap::~CFGStmtMap() { delete AsMap(M); }
  21. CFGBlock *CFGStmtMap::getBlock(Stmt *S) {
  22. SMap *SM = AsMap(M);
  23. Stmt *X = S;
  24. // If 'S' isn't in the map, walk the ParentMap to see if one of its ancestors
  25. // is in the map.
  26. while (X) {
  27. SMap::iterator I = SM->find(X);
  28. if (I != SM->end()) {
  29. CFGBlock *B = I->second;
  30. // Memoize this lookup.
  31. if (X != S)
  32. (*SM)[X] = B;
  33. return B;
  34. }
  35. X = PM->getParentIgnoreParens(X);
  36. }
  37. return nullptr;
  38. }
  39. static void Accumulate(SMap &SM, CFGBlock *B) {
  40. // First walk the block-level expressions.
  41. for (CFGBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) {
  42. const CFGElement &CE = *I;
  43. Optional<CFGStmt> CS = CE.getAs<CFGStmt>();
  44. if (!CS)
  45. continue;
  46. CFGBlock *&Entry = SM[CS->getStmt()];
  47. // If 'Entry' is already initialized (e.g., a terminator was already),
  48. // skip.
  49. if (Entry)
  50. continue;
  51. Entry = B;
  52. }
  53. // Look at the label of the block.
  54. if (Stmt *Label = B->getLabel())
  55. SM[Label] = B;
  56. // Finally, look at the terminator. If the terminator was already added
  57. // because it is a block-level expression in another block, overwrite
  58. // that mapping.
  59. if (Stmt *Term = B->getTerminatorStmt())
  60. SM[Term] = B;
  61. }
  62. CFGStmtMap *CFGStmtMap::Build(CFG *C, ParentMap *PM) {
  63. if (!C || !PM)
  64. return nullptr;
  65. SMap *SM = new SMap();
  66. // Walk all blocks, accumulating the block-level expressions, labels,
  67. // and terminators.
  68. for (CFG::iterator I = C->begin(), E = C->end(); I != E; ++I)
  69. Accumulate(*SM, *I);
  70. return new CFGStmtMap(PM, SM);
  71. }