int BinaryOpExpression::getConcatList(ExpressionPtrVec &ev, ExpressionPtr exp,
                                      bool &hasVoid) {
  if (!exp->hasCPPTemp()) {
    if (exp->is(Expression::KindOfUnaryOpExpression)) {
      UnaryOpExpressionPtr u = static_pointer_cast<UnaryOpExpression>(exp);
      if (u->getOp() == '(') {
        return getConcatList(ev, u->getExpression(), hasVoid);
      }
    } else if (exp->is(Expression::KindOfBinaryOpExpression)) {
      BinaryOpExpressionPtr b = static_pointer_cast<BinaryOpExpression>(exp);
      if (b->getOp() == '.') {
        return getConcatList(ev, b->getExp1(), hasVoid) +
          getConcatList(ev, b->getExp2(), hasVoid);
      }
    } else if (exp->is(Expression::KindOfEncapsListExpression)) {
      EncapsListExpressionPtr e =
        static_pointer_cast<EncapsListExpression>(exp);
      if (e->getType() != '`') {
        ExpressionListPtr el = e->getExpressions();
        int num = 0;
        for (int i = 0, s = el->getCount(); i < s; i++) {
          ExpressionPtr exp = (*el)[i];
          num += getConcatList(ev, exp, hasVoid);
        }
        return num;
      }
    }
  }

  ev.push_back(exp);
  bool isVoid = !exp->getActualType();
  hasVoid |= isVoid;
  return isVoid ? 0 : 1;
}
Esempio n. 2
0
/**
 * If the binary operation is not PHP specific, but something a query
 * processor can handle (+ - * and so on), then rewrite the operands to
 * something the query processor can evaluate (such as a query parameter
 * references) and rewrite the entire expression to use the rewritten operands.
 * If the rewritten operands are the same as the original operands, just
 * return the expression as is.
 */
ExpressionPtr CaptureExtractor::rewriteBinary(BinaryOpExpressionPtr be) {
  assert(be != nullptr);
  switch (be->getOp()) {
    case '+':
    case '-':
    case '*':
    case '/':
    case '%':
    case '&':
    case '|':
    case '^':
    case T_IS_IDENTICAL:
    case T_IS_EQUAL:
    case '>':
    case '<':
    case T_IS_GREATER_OR_EQUAL:
    case T_IS_SMALLER_OR_EQUAL:
    case T_IS_NOT_IDENTICAL:
    case T_IS_NOT_EQUAL:
    case T_BOOLEAN_OR:
    case T_BOOLEAN_AND:
    case T_LOGICAL_OR:
    case T_LOGICAL_AND:
    case '.':
      break; // Could be something the query processor can handle

    default:
      return newQueryParamRef(be);
  }
  auto expr1 = be->getExp1();
  auto expr2 = be->getExp2();
  auto newExpr1 = rewrite(expr1);
  auto newExpr2 = rewrite(expr2);
  if (expr1 == newExpr1 && expr2 == newExpr2) return be;
  return
    std::make_shared<BinaryOpExpression>(
      be->getScope(), be->getRange(), newExpr1, newExpr2, be->getOp());
}
int BinaryOpExpression::getConcatList(ExpressionPtrVec &ev, ExpressionPtr exp,
                                      bool &hasVoid) {
  if (!exp->hasCPPTemp()) {
    if (exp->is(Expression::KindOfUnaryOpExpression)) {
      UnaryOpExpressionPtr u = static_pointer_cast<UnaryOpExpression>(exp);
      if (u->getOp() == '(') {
        return getConcatList(ev, u->getExpression(), hasVoid);
      }
    } else if (exp->is(Expression::KindOfBinaryOpExpression)) {
      BinaryOpExpressionPtr b = static_pointer_cast<BinaryOpExpression>(exp);
      if (b->getOp() == '.') {
        if (b->getExp1()->is(Expression::KindOfSimpleVariable) &&
            b->getExp1()->isLocalExprAltered() &&
            !b->getExp1()->hasCPPTemp() &&
            b->getExp2()->hasEffect() &&
            !b->getExp2()->hasCPPTemp()) {
          /*
            In this case, the simple variable must be evaluated
            after b->getExp2(). But when we output a concat list we
            explicitly order the expressions from left to right.
          */
        } else {
          return getConcatList(ev, b->getExp1(), hasVoid) +
            getConcatList(ev, b->getExp2(), hasVoid);
        }
      }
    } else if (exp->is(Expression::KindOfEncapsListExpression)) {
      EncapsListExpressionPtr e =
        static_pointer_cast<EncapsListExpression>(exp);
      if (e->getType() != '`') {
        ExpressionListPtr el = e->getExpressions();
        int num = 0;
        for (int i = 0, s = el->getCount(); i < s; i++) {
          ExpressionPtr exp = (*el)[i];
          num += getConcatList(ev, exp, hasVoid);
        }
        return num;
      }
    }
  } else if (!exp->getActualType()) {
    return 0;
  }

  ev.push_back(exp);
  bool isVoid = !exp->getActualType();
  hasVoid |= isVoid;
  return isVoid ? 0 : 1;
}
Esempio n. 4
0
void ExpressionList::stripConcat() {
  ExpressionList &el = *this;
  for (int i = 0; i < el.getCount(); ) {
    ExpressionPtr &e = el[i];
    if (e->is(Expression::KindOfUnaryOpExpression)) {
      UnaryOpExpressionPtr u(boost::static_pointer_cast<UnaryOpExpression>(e));
      if (u->getOp() == '(') {
        e = u->getExpression();
      }
    }
    if (e->is(Expression::KindOfBinaryOpExpression)) {
      BinaryOpExpressionPtr b
        (boost::static_pointer_cast<BinaryOpExpression>(e));
      if (b->getOp() == '.') {
        e = b->getExp1();
        el.insertElement(b->getExp2(), i + 1);
        continue;
      }
    }
    i++;
  }
}
Esempio n. 5
0
bool StatementList::mergeConcatAssign() {
  if (Option::LocalCopyProp) {
    return false;
  } else {
    // check for vector string concat assignment such as
    //   $space = " ";
    //   $a .= "hello";
    //   $a .= $space;
    //   $a .= "world!";
    // turn into (for constant folding and concat sequence)
    //   $a .= " " . "hello " . $space . "world!";
    unsigned int i = 0;
    bool merged = false;
    do {
      std::string lhsName;
      int length = 0;
      for (; i < m_stmts.size(); i++) {
        StatementPtr stmt = m_stmts[i];
        if (!stmt->is(Statement::KindOfExpStatement)) break;
        ExpStatementPtr expStmt = dynamic_pointer_cast<ExpStatement>(stmt);
        ExpressionPtr exp = expStmt->getExpression();

        // check the first assignment
        if (exp->is(Expression::KindOfAssignmentExpression)) {
          AssignmentExpressionPtr assignment_exp =
            dynamic_pointer_cast<AssignmentExpression>(exp);
          ExpressionPtr variable = assignment_exp->getVariable();
          ExpressionPtr value = assignment_exp->getValue();
          std::string variableName = variable->getText();
          if (variableName.find("->") != std::string::npos) break;
          if (value->hasEffect()) break;
          // cannot turn $a .= $b; a .= $a into $a .= $b . $a;
          if (value->getText().find(variableName) != std::string::npos) break;
          if (lhsName.empty()) {
            lhsName = variable->getText();
            length++;
            continue;
          } else {
            break;
          }
        } else if (!exp->is(Expression::KindOfBinaryOpExpression)) {
          break;
        }
        BinaryOpExpressionPtr binaryOpExp =
          dynamic_pointer_cast<BinaryOpExpression>(exp);
        if (binaryOpExp->getOp() != T_CONCAT_EQUAL) break;
        ExpressionPtr exp1 = binaryOpExp->getExp1();
        std::string exp1Text = exp1->getText();
        if (exp1Text.find("->") != std::string::npos) break;
        ExpressionPtr exp2 = binaryOpExp->getExp2();
        if (exp2->hasEffect()) break;
        if (exp2->getText().find(exp1Text) != std::string::npos) break;
        if (lhsName.empty()) {
          lhsName = exp1Text;
          length++;
        } else if (lhsName == exp1Text) {
          length++;
        } else {
          break;
        }
      }
      if (length > 1) {
        // replace m_stmts[j] to m_stmts[i - 1] with a new statement
        unsigned j = i - length;
        ExpStatementPtr expStmt;
        ExpressionPtr exp;
        BinaryOpExpressionPtr binaryOpExp;
        ExpressionPtr var;
        ExpressionPtr exp1;
        ExpressionPtr exp2;
        bool isAssignment = false;
        expStmt = dynamic_pointer_cast<ExpStatement>(m_stmts[j++]);
        exp = expStmt->getExpression();
        if (exp->is(Expression::KindOfAssignmentExpression)) {
          isAssignment = true;
          AssignmentExpressionPtr assignment_exp =
            dynamic_pointer_cast<AssignmentExpression>(exp);
          var = assignment_exp->getVariable();
          exp1 = assignment_exp->getValue();
        } else {
          binaryOpExp = dynamic_pointer_cast<BinaryOpExpression>(exp);
          var = binaryOpExp->getExp1();
          exp1 = binaryOpExp->getExp2();
        }

        for (; j < i; j++) {
          expStmt = dynamic_pointer_cast<ExpStatement>(m_stmts[j]);
          exp = expStmt->getExpression();
          binaryOpExp = dynamic_pointer_cast<BinaryOpExpression>(exp);
          exp2 = binaryOpExp->getExp2();
          exp1 = BinaryOpExpressionPtr
            (new BinaryOpExpression(getScope(), getLocation(),
                                    Expression::KindOfBinaryOpExpression,
                                    exp1, exp2, '.'));
        }
        if (isAssignment) {
          exp = AssignmentExpressionPtr
            (new AssignmentExpression(exp->getScope(), exp->getLocation(),
                                      Expression::KindOfAssignmentExpression,
                                      var, exp1,
                                      false));
        } else {
          exp = BinaryOpExpressionPtr
            (new BinaryOpExpression(getScope(), getLocation(),
                                    Expression::KindOfBinaryOpExpression,
                                    var, exp1, T_CONCAT_EQUAL));
        }
        expStmt = ExpStatementPtr
          (new ExpStatement(getScope(), getLocation(),
                            Statement::KindOfExpStatement, exp));

        m_stmts[i - length] = expStmt;
        for (j = i - (length - 1); i > j; i--) removeElement(j);
        merged = true;
      } else if (length == 0) {
        i++;
      }
    } while (i < m_stmts.size());
    return merged;
  }
}
Esempio n. 6
0
ExpressionPtr AliasManager::canonicalizeNode(ExpressionPtr e) {
  e->setCanonPtr(ExpressionPtr());
  e->setCanonID(0);

  switch (e->getKindOf()) {
  case Expression::KindOfObjectMethodExpression:
  case Expression::KindOfDynamicFunctionCall:
  case Expression::KindOfSimpleFunctionCall:
  case Expression::KindOfNewObjectExpression:
    add(m_bucketMap[0], e);
    break;

  case Expression::KindOfListAssignment:
    add(m_bucketMap[0], e);
    break;

  case Expression::KindOfAssignmentExpression: {
    AssignmentExpressionPtr ae = spc(AssignmentExpression,e);
    if (e->getContext() & Expression::DeadStore) {
      Construct::recomputeEffects();
      return ae->getValue();
    }
    ExpressionPtr rep;
    int interf = findInterf(ae->getVariable(), false, rep);
    if (interf == SameAccess) {
      switch (rep->getKindOf()) {
      default:
        break;
      case Expression::KindOfAssignmentExpression:
        {
          AssignmentExpressionPtr a = spc(AssignmentExpression, rep);
          ExpressionPtr value = a->getValue();
          if (a->getValue()->getContext() & Expression::RefValue) {
            break;
          }
        }
      case Expression::KindOfUnaryOpExpression:
      case Expression::KindOfBinaryOpExpression:
        rep->setContext(Expression::DeadStore);
        break;
      }
    }
    add(m_bucketMap[0], e);
    break;
  }

  case Expression::KindOfConstantExpression:
  case Expression::KindOfSimpleVariable:
  case Expression::KindOfDynamicVariable:
  case Expression::KindOfArrayElementExpression:
  case Expression::KindOfObjectPropertyExpression:
  case Expression::KindOfStaticMemberExpression:
    if (!(e->getContext() & (Expression::AssignmentLHS|
                             Expression::DeepAssignmentLHS|
                             Expression::OprLValue))) {
      if (!(e->getContext() & (Expression::LValue|
                               Expression::RefValue|
                               Expression::RefParameter|
                               Expression::UnsetContext))) {
        ExpressionPtr rep;
        int interf = findInterf(e, true, rep);
        if (interf == SameAccess) {
          if (rep->getKindOf() == e->getKindOf()) {
            e->setCanonID(rep->getCanonID());
            e->setCanonPtr(rep);
            return ExpressionPtr();
          }
          if (rep->getKindOf() == Expression::KindOfAssignmentExpression) {
            ExpressionPtr rhs = spc(AssignmentExpression,rep)->getValue();
            if (rhs->is(Expression::KindOfScalarExpression)) {
              rhs = rhs->clone();
              getCanonical(rhs);
              return rhs;
            }
            e->setCanonPtr(rhs);
          }
        }
      }
      add(m_bucketMap[0], e);
    } else {
      getCanonical(e);
    }
    break;

  case Expression::KindOfBinaryOpExpression: {
    BinaryOpExpressionPtr bop = spc(BinaryOpExpression, e);

    int rop = getOpForAssignmentOp(bop->getOp());
    if (rop) {
      ExpressionPtr lhs = bop->getExp1();
      ExpressionPtr rep;
      if (bop->getContext() & Expression::DeadStore) {
        Construct::recomputeEffects();
        ExpressionPtr rhs = bop->getExp2()->clone();
        lhs = lhs->clone();
        lhs->clearContext(Expression::LValue);
        lhs->clearContext(Expression::NoLValueWrapper);
        lhs->clearContext(Expression::OprLValue);
        rep = ExpressionPtr
          (new BinaryOpExpression(e->getLocation(),
                                  Expression::KindOfBinaryOpExpression,
                                  lhs, rhs, rop));

      } else {
        ExpressionPtr alt;
        int interf = findInterf(lhs, true, alt);
        if (interf == SameAccess &&
            alt->is(Expression::KindOfAssignmentExpression)) {
          ExpressionPtr op0 = spc(AssignmentExpression,alt)->getValue();
          if (op0->is(Expression::KindOfScalarExpression)) {
            ExpressionPtr op1 = bop->getExp2();
            ExpressionPtr rhs
              (new BinaryOpExpression(e->getLocation(),
                                      Expression::KindOfBinaryOpExpression,
                                      op0->clone(), op1->clone(), rop));

            lhs = lhs->clone();
            lhs->clearContext(Expression::OprLValue);
            rep = ExpressionPtr
              (new AssignmentExpression(e->getLocation(),
                                        Expression::KindOfAssignmentExpression,
                                        lhs, rhs, false));
          }
        }
      }
      if (rep) {
        ExpressionPtr c = canonicalizeRecur(rep);
        return c ? c : rep;
      }
      add(m_bucketMap[0], e);
    } else {
      getCanonical(e);
    }
    break;
  }

  case Expression::KindOfUnaryOpExpression:
    {
      UnaryOpExpressionPtr uop = spc(UnaryOpExpression, e);
      switch (uop->getOp()) {
      case T_INC:
      case T_DEC:
        if (uop->getContext() & Expression::DeadStore) {
          Construct::recomputeEffects();
          ExpressionPtr val = uop->getExpression()->clone();
          val->clearContext(Expression::LValue);
          val->clearContext(Expression::NoLValueWrapper);
          val->clearContext(Expression::OprLValue);
          if (uop->getFront()) {
            ExpressionPtr inc
              (new ScalarExpression(uop->getLocation(),
                                    Expression::KindOfScalarExpression,
                                    T_LNUMBER, string("1")));

            val = ExpressionPtr
              (new BinaryOpExpression(uop->getLocation(),
                                      Expression::KindOfBinaryOpExpression,
                                      val, inc,
                                      uop->getOp() == T_INC ? '+' : '-'));

          }

          ExpressionPtr r = canonicalizeRecur(val);
          return r ? r : val;
        }
        add(m_bucketMap[0], e);
        break;
      default:
        getCanonical(e);
        break;
      }
      break;
    }

  default:
    getCanonical(e);
    break;
  }

  return ExpressionPtr();
}