public function getVariableForRead($name, CompilationContext $compilationContext = null, array $statement = null)
{
/**
* Validate that 'this' cannot be used in a static function
*/
if ($name == 'this' || $name == 'this_ptr') {
if ($compilationContext->staticContext) {
throw new CompilerException("Cannot use variable 'this' in static context", $statement);
}
}
/**
* Create superglobals just in time
*/
if ($this->isSuperGlobal($name)) {
if (!$this->hasVariable($name)) {
/**
* @TODO, injecting globals, initialize to null and check first?
*/
$variable = new Variable('variable', $name, $compilationContext->currentBranch);
$variable->setIsInitialized(true, $compilationContext, $statement);
$variable->setDynamicTypes('array');
$variable->setIsExternal(true);
$this->addRawVariable($variable);
} else {
$variable = $this->getVariable($name);
}
$variable->increaseUses();
return $variable;
}
if (!$this->hasVariable($name)) {
throw new CompilerException("Cannot read variable '" . $name . "' because it wasn't declared", $statement);
}
$variable = $this->getVariable($name);
if (!$variable->isInitialized()) {
/* DON'T REMOVE THIS!! */
throw new CompilerException("Variable '" . $name . "' cannot be read because it's not initialized", $statement);
}
$variable->increaseUses();
/**
* Analise branches to detect possible initialization of variables in conditional branches
*/
if (!$variable->isTemporal() && !$variable->getSkipVariant()) {
if ($name != 'return_value' && $name != 'this') {
if (is_object($compilationContext) && is_object($compilationContext->branchManager)) {
if ($compilationContext->config->get('check-invalid-reads', 'optimizations')) {
switch ($variable->getType()) {
case 'variable':
case 'string':
case 'array':
if (!$variable->isLocalOnly()) {
$variable->setMustInitNull(true);
$compilationContext->codePrinter->output('ZEPHIR_CHECK_POINTER(' . $variable->getName() . ');');
}
break;
}
}
$initBranches = $variable->getInitBranches();
$currentBranch = $compilationContext->branchManager->getCurrentBranch();
$branches = array_reverse($initBranches);
if (count($branches) == 1) {
if (Branch::TYPE_CONDITIONAL_TRUE == $branches[0]->getType()) {
if ($branches[0]->isUnreachable() === true) {
throw new CompilerException('Initialization of variable "' . $name . '" depends on unreachable branch, consider initialize it at its declaration', $statement);
}
} else {
if (Branch::TYPE_CONDITIONAL_FALSE == $branches[0]->getType()) {
if ($branches[0]->isUnreachable() === false) {
throw new CompilerException('Initialization of variable "' . $name . '" depends on unreachable branch, consider initialize at its declaration', $statement);
}
}
}
$tempBranch = $branches[0]->getParentBranch();
while ($tempBranch) {
if ($tempBranch->getType() == Branch::TYPE_CONDITIONAL_TRUE) {
if ($tempBranch->isUnreachable() === true) {
throw new CompilerException('Initialization of variable "' . $name . '" depends on unreachable branch, consider initialize it at its declaration', $statement);
}
}
$tempBranch = $tempBranch->getParentBranch();
}
}
$found = false;
foreach ($branches as $branch) {
/*+
* Variable was initialized in the same current branch
*/
if ($branch == $currentBranch) {
$found = true;
break;
}
/**
* 'root' and 'external' branches are safe branches
*/
if ($branch->getType() == Branch::TYPE_ROOT || $branch->getType() == Branch::TYPE_EXTERNAL) {
$found = true;
break;
}
}
if (!$found) {
/**
* Check if last assignment
* Variable was initialized in a sub-branch and it's being used in a parent branch
*/
$possibleBadAssignment = false;
if ($currentBranch->getLevel() < $branches[0]->getLevel()) {
$possibleBadAssignment = true;
}
if ($possibleBadAssignment) {
if (count($branches) > 1) {
$graph = new BranchGraph();
foreach ($branches as $branch) {
$graph->addLeaf($branch);
}
//echo $graph->getRoot()->show();
} else {
/**
* Variable is assigned just once and it's assigned in a conditional branch
*/
if ($branches[0]->getType() == Branch::TYPE_CONDITIONAL_TRUE) {
$evalExpression = $branches[0]->getRelatedStatement()->getEvalExpression();
if ($evalExpression->isUnreachable() === true) {
throw new CompilerException("Variable '" . $name . "' was assigned for the first time in conditional branch, consider initialize it at its declaration", $statement);
} else {
$variable->enableDefaultAutoInitValue();
$compilationContext->logger->warning("Variable '" . $name . "' was assigned for the first time in conditional branch, consider initialize it at its declaration", 'conditional-initialization', $statement);
}
} else {
if ($branches[0]->getType() == Branch::TYPE_CONDITIONAL_FALSE) {
$evalExpression = $branches[0]->getRelatedStatement()->getEvalExpression();
if ($evalExpression->isUnreachableElse() === true) {
throw new CompilerException("Variable '" . $name . "' was assigned for the first time in conditional branch, consider initialize it at its declaration", $statement);
} else {
$variable->enableDefaultAutoInitValue();
$compilationContext->logger->warning("Variable '" . $name . "' was assigned for the first time in conditional branch, consider initialize it at its declaration", 'conditional-initialization', $statement);
}
}
}
}
}
}
}
}
}
/**
* Saves the latest place where the variable was used
*/
$variable->setUsed(true, $statement);
return $variable;
}