CFGStmtMap.cpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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. #include <optional>
  18. using namespace clang;
  19. typedef llvm::DenseMap<const Stmt*, CFGBlock*> SMap;
  20. static SMap *AsMap(void *m) { return (SMap*) m; }
  21. CFGStmtMap::~CFGStmtMap() { delete AsMap(M); }
  22. CFGBlock *CFGStmtMap::getBlock(Stmt *S) {
  23. SMap *SM = AsMap(M);
  24. Stmt *X = S;
  25. // If 'S' isn't in the map, walk the ParentMap to see if one of its ancestors
  26. // is in the map.
  27. while (X) {
  28. SMap::iterator I = SM->find(X);
  29. if (I != SM->end()) {
  30. CFGBlock *B = I->second;
  31. // Memoize this lookup.
  32. if (X != S)
  33. (*SM)[X] = B;
  34. return B;
  35. }
  36. X = PM->getParentIgnoreParens(X);
  37. }
  38. return nullptr;
  39. }
  40. static void Accumulate(SMap &SM, CFGBlock *B) {
  41. // First walk the block-level expressions.
  42. for (CFGBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) {
  43. const CFGElement &CE = *I;
  44. std::optional<CFGStmt> CS = CE.getAs<CFGStmt>();
  45. if (!CS)
  46. continue;
  47. CFGBlock *&Entry = SM[CS->getStmt()];
  48. // If 'Entry' is already initialized (e.g., a terminator was already),
  49. // skip.
  50. if (Entry)
  51. continue;
  52. Entry = B;
  53. }
  54. // Look at the label of the block.
  55. if (Stmt *Label = B->getLabel())
  56. SM[Label] = B;
  57. // Finally, look at the terminator. If the terminator was already added
  58. // because it is a block-level expression in another block, overwrite
  59. // that mapping.
  60. if (Stmt *Term = B->getTerminatorStmt())
  61. SM[Term] = B;
  62. }
  63. CFGStmtMap *CFGStmtMap::Build(CFG *C, ParentMap *PM) {
  64. if (!C || !PM)
  65. return nullptr;
  66. SMap *SM = new SMap();
  67. // Walk all blocks, accumulating the block-level expressions, labels,
  68. // and terminators.
  69. for (CFG::iterator I = C->begin(), E = C->end(); I != E; ++I)
  70. Accumulate(*SM, *I);
  71. return new CFGStmtMap(PM, SM);
  72. }