Пример #1
0
int ControlFlowBuilder::before(ConstructRawPtr cp) {
  int ret = FunctionWalker::before(cp);
  if (ret == WalkContinue) {
    if (m_pass == 1) {
      if (StatementPtr s = dynamic_pointer_cast<Statement>(cp)) {
        Statement::KindOf stype = s->getKindOf();
        switch (stype) {
          case Statement::KindOfFunctionStatement:
          case Statement::KindOfMethodStatement:
          case Statement::KindOfClassStatement:
          case Statement::KindOfInterfaceStatement:
            assert(false);
            break;

          case Statement::KindOfStaticStatement:
            addEdge(s, BeforeConstruct, s, AfterConstruct);
            break;

          case Statement::KindOfClassVariable:
            assert(false);
            break;

          case Statement::KindOfClassConstant:
          case Statement::KindOfGlobalStatement:
          case Statement::KindOfUnsetStatement:
          case Statement::KindOfExpStatement:
          case Statement::KindOfStatementList:
          case Statement::KindOfBlockStatement:
          case Statement::KindOfTryStatement:
            break;

          case Statement::KindOfIfStatement:
            break;

          case Statement::KindOfIfBranchStatement: {
            IfBranchStatementPtr ibr =
              static_pointer_cast<IfBranchStatement>(s);
            if (ibr->getCondition()) {
              if (ibr->getStmt()) {
                addEdge(ibr->getCondition(), AfterConstruct,
                        ibr, AfterConstruct);
                addEdge(ibr->getStmt(), AfterConstruct, top(2), AfterConstruct);
                noFallThrough(ibr);
              } else {
                addEdge(ibr->getCondition(), AfterConstruct,
                        top(2), AfterConstruct);
              }
            }
            break;
          }

          case Statement::KindOfForStatement: {
            ConstructPtr cond(s->getNthKid(ForStatement::CondExpr));
            ConstructPtr body(s->getNthKid(ForStatement::BodyStmt));
            ConstructPtr incr(s->getNthKid(ForStatement::IncExpr));
            if (cond) addEdge(cond, AfterConstruct, s, AfterConstruct);
            ConstructPtr end = incr ? incr : body ? body : cond;
            ConstructPtr start = cond ? cond : body ? body : incr;
            if (end) addEdge(end, AfterConstruct, start, BeforeConstruct);
            noFallThrough(s);
            break;
          }

          case Statement::KindOfWhileStatement: {
            ConstructPtr cond(s->getNthKid(WhileStatement::CondExpr));
            ConstructPtr body(s->getNthKid(WhileStatement::BodyStmt));
            addEdge(cond, AfterConstruct, s, AfterConstruct);
            addEdge(body ? body : cond, AfterConstruct, cond, BeforeConstruct);
            noFallThrough(s);
            break;
          }

          case Statement::KindOfDoStatement: {
            ConstructPtr cond(s->getNthKid(DoStatement::CondExpr));
            addEdge(cond, AfterConstruct, s, BeforeConstruct);
            break;
          }

          case Statement::KindOfForEachStatement: {
            ConstructPtr body(s->getNthKid(ForEachStatement::BodyStmt));
            ConstructPtr name(s->getNthKid(ForEachStatement::NameExpr));
            ConstructPtr value(s->getNthKid(ForEachStatement::ValueExpr));
            ConstructPtr begin = name ? name : value;
            ConstructPtr end = body ? body : value;
            addEdge(end, AfterConstruct, begin, BeforeConstruct);
            addEdge(begin, BeforeConstruct, s, AfterConstruct);
            break;
          }

          case Statement::KindOfSwitchStatement: {
            SwitchStatementPtr sw(static_pointer_cast<SwitchStatement>(s));
            ExpressionPtr exp = sw->getExp();
            if (StatementListPtr cases = sw->getCases()) {
              addEdge(exp, AfterConstruct, s, AfterConstruct);
              for (int n = cases->getCount(), i = 0; i < n; ++i) {
                addEdge(exp, AfterConstruct, (*cases)[i], BeforeConstruct);
              }
            }
            break;
          }

          case Statement::KindOfCaseStatement:
            break;

          case Statement::KindOfReturnStatement:
            addEdge(s, AfterConstruct, root(), AfterConstruct);
            break;

          case Statement::KindOfBreakStatement:
          case Statement::KindOfContinueStatement: {
            int val = dynamic_pointer_cast<BreakStatement>(s)->getDepth();
            size_t d = depth();
            for (size_t i = 1; i < d; i++) {
              ConstructPtr c = top(i);
              if (LoopStatementPtr l = dynamic_pointer_cast<LoopStatement>(c)) {
                if (val <= 1) {
                  if (stype == Statement::KindOfBreakStatement) {
                    addEdge(s, AfterConstruct, l, AfterConstruct);
                  } else {
                    ConstructPtr kid;
                    switch (l->getKindOf()) {
                      case Statement::KindOfForEachStatement:
                        kid = l->getNthKid(ForEachStatement::NameExpr);
                        if (!kid) {
                          kid = l->getNthKid(ForEachStatement::ValueExpr);
                        }
                        break;
                      case Statement::KindOfForStatement:
                        kid = l->getNthKid(ForStatement::IncExpr);
                        if (!kid) kid = l->getNthKid(ForStatement::CondExpr);
                        if (!kid) kid = l->getNthKid(ForStatement::BodyStmt);
                        break;
                      case Statement::KindOfWhileStatement:
                        kid = l->getNthKid(WhileStatement::CondExpr);
                        break;
                      case Statement::KindOfDoStatement:
                        kid = l->getNthKid(DoStatement::CondExpr);
                        break;
                      default:
                        assert(0);
                    }
                    assert(kid);
                    addEdge(s, AfterConstruct, kid, BeforeConstruct);
                  }
                }
                if (val && !--val) break;
              } else if (SwitchStatementPtr sw =
                         dynamic_pointer_cast<SwitchStatement>(c)) {
                if (val <= 1) {
                  addEdge(s, AfterConstruct, sw, AfterConstruct);
                }
                if (val && !--val) break;
              }
            }
            break;
          }

          case Statement::KindOfThrowStatement: {
            size_t d = depth();
            for (size_t i = 1; i < d; i++) {
              TryStatementPtr t = dynamic_pointer_cast<TryStatement>(top(i));
              if (t) {
                StatementListPtr catches = t->getCatches();
                for (int n = catches->getCount(), j = 0; j < n; ++j) {
                  addEdge(s, AfterConstruct, (*catches)[j], BeforeConstruct);
                }
                break;
              }
            }
            break;
          }

          case Statement::KindOfCatchStatement:
          case Statement::KindOfEchoStatement:
            break;
        }
      }


      if (ControlFlowInfo *c = get(cp)) {
        if (c->m_targets[BeforeConstruct].size()) {
          if (!m_cur) newBlock();
          m_ccbpMap[HoldingBlock][cp] = m_cur;
          endBlock(cp, BeforeConstruct);
        } else if (c->m_isTarget[BeforeConstruct]) {
          endBlock(cp, BeforeConstruct);
        }
      }
      if (!m_cur) newBlock();
      m_ccbpMap[BeforeConstruct][cp] = m_cur;
    } else if (m_pass == 2) {
      ControlBlockPtr bb = m_ccbpMap[BeforeConstruct][cp];
      assert(bb);
      if (bb != m_cur) {
        if (m_cur) {
          addCFEdge(m_cur, bb);
        }
        m_cur = bb;
      }
      if (ControlFlowInfo *c = get(cp)) {
        ConstructPtrLocMap &beforeTargets =
          c->m_targets[BeforeConstruct];
        if (beforeTargets.size()) {
          ControlBlockPtr hb = m_ccbpMap[HoldingBlock][cp];
          assert(hb);
          addCFEdge(hb, bb);
          ConstructPtrLocMap::iterator it =
            beforeTargets.begin(), end = beforeTargets.end();
          while (it != end) {
            addCFEdge(hb, it->first, it->second);
            ++it;
          }
        }
      }
    }
  }
  return ret;
}
Пример #2
0
int ControlFlowBuilder::before(ConstructRawPtr cp) {
  int ret = FunctionWalker::before(cp);
  if (ret == WalkContinue) {
    if (m_pass == 1) {
      if (StatementPtr s = dynamic_pointer_cast<Statement>(cp)) {
        if (FunctionWalker::SkipRecurse(s)) not_reached();
        Statement::KindOf stype = s->getKindOf();
        switch (stype) {
          case Statement::KindOfUseTraitStatement:
          case Statement::KindOfTraitPrecStatement:
          case Statement::KindOfTraitAliasStatement:
            not_reached();

          case Statement::KindOfStaticStatement:
            addEdge(s, BeforeConstruct, s, AfterConstruct);
            break;

          case Statement::KindOfClassVariable:
            not_reached();

          case Statement::KindOfClassConstant:
          case Statement::KindOfGlobalStatement:
          case Statement::KindOfUnsetStatement:
          case Statement::KindOfExpStatement:
          case Statement::KindOfStatementList:
          case Statement::KindOfBlockStatement:
            break;

          case Statement::KindOfTryStatement: {
            TryStatementPtr t = static_pointer_cast<TryStatement>(s);
            StatementListPtr catches = t->getCatches();
            StatementPtr body = t->getBody();
            FinallyStatementPtr finally = static_pointer_cast<FinallyStatement>(t->getFinally());
            if (body) {
              for (int n = catches->getCount(), j = 0; j < n; ++j) {
                addEdge(body, BeforeConstruct,
                        (*catches)[j], BeforeConstruct);
                addEdge(body, AfterConstruct,
                        (*catches)[j], BeforeConstruct);
              }
              if (finally) {
                addEdge(body, BeforeConstruct, finally, BeforeConstruct);
                addEdge(body, AfterConstruct, finally, BeforeConstruct);
              }
              addEdge(body, AfterConstruct, t, AfterConstruct);
              noFallThrough(body);
            }
            break;
          }

          case Statement::KindOfThrowStatement: {
            size_t d = depth();
            for (size_t i = 1; i < d; i++) {
              TryStatementPtr t = dynamic_pointer_cast<TryStatement>(top(i));
              if (t) {
                StatementListPtr catches = t->getCatches();
                for (int n = catches->getCount(), j = 0; j < n; ++j) {
                  addEdge(s, AfterConstruct, (*catches)[j], BeforeConstruct);
                }
                break;
              }
            }
            break;
          }

          case Statement::KindOfFinallyStatement:
            break;

          case Statement::KindOfCatchStatement:
            break;

          case Statement::KindOfIfStatement:
            break;

          case Statement::KindOfIfBranchStatement: {
            IfBranchStatementPtr ibr =
              static_pointer_cast<IfBranchStatement>(s);
            if (ibr->getCondition()) {
              if (ibr->getStmt()) {
                addEdge(ibr->getCondition(), AfterConstruct,
                        ibr, AfterConstruct);
                addEdge(ibr->getStmt(), AfterConstruct, top(2), AfterConstruct);
                noFallThrough(ibr);
              } else {
                addEdge(ibr->getCondition(), AfterConstruct,
                        top(2), AfterConstruct);
              }
            }
            break;
          }

          case Statement::KindOfForStatement: {
            ForStatementPtr fs(static_pointer_cast<ForStatement>(s));
            ConstructRawPtr body(fs->getBody());
            ConstructRawPtr cond(fs->getCondExp());
            ConstructRawPtr incr(fs->getIncExp());
            if (cond) addEdge(cond, AfterConstruct, s, AfterConstruct);
            ConstructRawPtr end = incr ? incr : body ? body : cond;
            ConstructRawPtr start = cond ? cond : body ? body : incr;
            if (end) addEdge(end, AfterConstruct, start, BeforeConstruct);
            noFallThrough(s);
            break;
          }

          case Statement::KindOfWhileStatement: {
            WhileStatementPtr ws(static_pointer_cast<WhileStatement>(s));
            ConstructRawPtr body(ws->getBody());
            ConstructRawPtr cond(ws->getCondExp());
            addEdge(cond, AfterConstruct, s, AfterConstruct);
            addEdge(body ? body : cond, AfterConstruct, cond, BeforeConstruct);
            noFallThrough(s);
            break;
          }

          case Statement::KindOfDoStatement: {
            DoStatementPtr ds(static_pointer_cast<DoStatement>(s));
            addEdge(ds->getCondExp(), AfterConstruct, s, BeforeConstruct);
            break;
          }

          case Statement::KindOfForEachStatement: {
            ForEachStatementPtr fs(static_pointer_cast<ForEachStatement>(s));
            ConstructRawPtr body(fs->getBody());
            ConstructRawPtr name(fs->getNameExp());
            ConstructRawPtr value(fs->getValueExp());
            ConstructRawPtr begin = name ? name : value;
            ConstructRawPtr end = body ? body : value;
            addEdge(end, AfterConstruct, begin, BeforeConstruct);
            addEdge(value, AfterConstruct, s, AfterConstruct);
            break;
          }

          case Statement::KindOfSwitchStatement: {
            SwitchStatementPtr sw(static_pointer_cast<SwitchStatement>(s));
            if (StatementListPtr cases = sw->getCases()) {
              ExpressionPtr exp;
              StatementPtr def;
              for (int n = cases->getCount(), i = 0; i < n; ++i) {
                CaseStatementPtr caseStmt =
                  static_pointer_cast<CaseStatement>((*cases)[i]);
                if (!caseStmt->getCondition()) {
                  def = caseStmt->getStatement();
                } else {
                  if (exp) {
                    addEdge(exp, AfterConstruct, caseStmt, BeforeConstruct);
                  }
                  exp = caseStmt->getCondition();
                }
              }
              if (exp) {
                if (def) {
                  addEdge(exp, AfterConstruct, def, BeforeConstruct);
                } else {
                  addEdge(exp, AfterConstruct, s, AfterConstruct);
                }
              }
            }
            break;
          }

          case Statement::KindOfCaseStatement:
            // already handled by switch
            break;

          case Statement::KindOfLabelStatement: {
            LabelStatementPtr l(static_pointer_cast<LabelStatement>(s));
            m_labelInfoMap[l->label()].first = l;
            cfi(l).m_isTarget[BeforeConstruct] = true;
            break;
          }

          case Statement::KindOfGotoStatement: {
            GotoStatementPtr g(static_pointer_cast<GotoStatement>(s));
            m_labelInfoMap[g->label()].second.push_back(g);
            noFallThrough(s);
            break;
          }

          case Statement::KindOfReturnStatement: {
            setEdge(s, AfterConstruct, root(), AfterConstruct);
            if (!m_isGenerator) noFallThrough(s);
            /*
             * Since almost anything in php /might/ throw, we
             * approximate, and add edges from the beginning and
             * end of a try block. But if there's a return, that
             * would kill the edge from the end of the block.
             * Explicitly add them here if the return is in a try
             */
            size_t d = depth();
            for (size_t i = 1; i < d; i++) {
              TryStatementPtr t = dynamic_pointer_cast<TryStatement>(top(i));
              if (t) {
                StatementListPtr catches = t->getCatches();
                for (int n = catches->getCount(), j = 0; j < n; ++j) {
                  addEdge(s, AfterConstruct, (*catches)[j], BeforeConstruct);
                }
                break;
              }
            }
            break;
          }

          case Statement::KindOfBreakStatement:
          case Statement::KindOfContinueStatement: {
            noFallThrough(s);
            int val = dynamic_pointer_cast<BreakStatement>(s)->getDepth();
            size_t d = depth();
            for (size_t i = 1; i < d; i++) {
              ConstructRawPtr c = top(i);
              if (LoopStatementPtr l = dynamic_pointer_cast<LoopStatement>(c)) {
                if (val <= 1) {
                  if (stype == Statement::KindOfBreakStatement) {
                    addEdge(s, AfterConstruct, l, AfterConstruct);
                  } else {
                    ConstructRawPtr kid;
                    switch (l->getKindOf()) {
                      case Statement::KindOfForEachStatement: {
                        ForEachStatementPtr fs(static_pointer_cast<ForEachStatement>(l));
                        kid = fs->getNameExp();
                        if (!kid) {
                          kid = fs->getValueExp();
                        }
                        break;
                      }
                      case Statement::KindOfForStatement: {
                        ForStatementPtr fs(static_pointer_cast<ForStatement>(l));
                        kid = fs->getIncExp();
                        if (!kid) kid = fs->getCondExp();
                        if (!kid) kid = fs->getBody();
                        break;
                      }
                      case Statement::KindOfWhileStatement: {
                        WhileStatementPtr ws(static_pointer_cast<WhileStatement>(l));
                        kid = ws->getCondExp();
                        break;
                      }
                      case Statement::KindOfDoStatement: {
                        DoStatementPtr ds(static_pointer_cast<DoStatement>(l));
                        kid = ds->getCondExp();
                        break;
                      }
                      default:
                        always_assert(0);
                    }
                    always_assert(kid);
                    addEdge(s, AfterConstruct, kid, BeforeConstruct);
                  }
                }
                if (val && !--val) break;
              } else if (SwitchStatementPtr sw =
                         dynamic_pointer_cast<SwitchStatement>(c)) {
                if (val <= 1) {
                  addEdge(s, AfterConstruct, sw, AfterConstruct);
                }
                if (val && !--val) break;
              }
            }
            break;
          }

          case Statement::KindOfEchoStatement:
          case Statement::KindOfTypedefStatement:
            break;

          default:
            not_reached();
        }
      } else {
        ExpressionPtr e(dynamic_pointer_cast<Expression>(cp));
        switch (e->getKindOf()) {
          case Expression::KindOfBinaryOpExpression: {
            BinaryOpExpressionPtr b(static_pointer_cast<BinaryOpExpression>(e));
            if (b->isShortCircuitOperator()) {
              ConstructPtr trueBranch, falseBranch;
              ConstructLocation tLoc, fLoc;
              getTrueFalseBranches(0, trueBranch, tLoc, falseBranch, fLoc);
              assert(trueBranch);
              assert(falseBranch);
              if (b->isLogicalOrOperator()) {
                addEdge(b->getExp1(), AfterConstruct, trueBranch, tLoc);
              } else {
                addEdge(b->getExp1(), AfterConstruct, falseBranch, fLoc);
              }
            }
            break;
          }
          case Expression::KindOfQOpExpression: {
            QOpExpressionPtr q(static_pointer_cast<QOpExpression>(e));
            if (ExpressionPtr e1 = q->getYes()) {
              addEdge(q->getCondition(), AfterConstruct,
                      q->getNo(), BeforeConstruct);
              addEdge(e1, AfterConstruct,
                      q->getNo(), AfterConstruct);
              noFallThrough(e1);
            } else {
              addEdge(q->getCondition(), AfterConstruct,
                      q->getNo(), AfterConstruct);
            }
            break;
          }
          default:
            break;
        }
      }

      if (ControlFlowInfo *c = get(cp)) {
        if (c->m_targets[BeforeConstruct].size()) {
          if (!m_cur) newBlock();
          m_ccbpMap[HoldingBlock][cp] = m_cur;
          endBlock(cp, BeforeConstruct);
        } else if (c->m_isTarget[BeforeConstruct]) {
          endBlock(cp, BeforeConstruct);
        }
      }
      if (!m_cur) newBlock();
      m_ccbpMap[BeforeConstruct][cp] = m_cur;
    } else if (m_pass == 2) {
      ControlBlock *hb = m_ccbpMap[HoldingBlock][cp];
      if (hb) {
        if (hb != m_cur) {
          if (m_cur) {
            addCFEdge(m_cur, hb);
          }
          m_cur = hb;
        }
      }
      ControlBlock *bb = m_ccbpMap[BeforeConstruct][cp];
      always_assert(bb);
      if (bb != m_cur) {
        if (m_cur) {
          addCFEdge(m_cur, bb);
        }
        m_cur = bb;
      }
      if (ControlFlowInfo *c = get(cp)) {
        ConstructPtrLocMap &beforeTargets =
          c->m_targets[BeforeConstruct];
        if (beforeTargets.size()) {
          always_assert(hb);
          addCFEdge(hb, bb);
          ConstructPtrLocMap::iterator it =
            beforeTargets.begin(), end = beforeTargets.end();
          while (it != end) {
            addCFEdge(hb, it->first, it->second);
            ++it;
          }
        }
      }
    }
  }
  return ret;
}