-e76c26059585433ce44e50cd7f8f504c6676f453
+46329dd9e6473fff46df6b310c11116d1558e470
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
do_is_zero_value() const
{ return this->val_ == false; }
+ bool
+ do_boolean_constant_value(bool* val) const
+ {
+ *val = this->val_;
+ return true;
+ }
+
bool
do_is_static_initializer() const
{ return true; }
bool
do_string_constant_value(std::string* val) const;
+ bool
+ do_boolean_constant_value(bool* val) const;
+
Type*
do_type();
return ok;
}
+bool
+Const_expression::do_boolean_constant_value(bool* val) const
+{
+ if (this->seen_)
+ return false;
+
+ Expression* e = this->constant_->const_value()->expr();
+
+ this->seen_ = true;
+ bool ok = e->boolean_constant_value(val);
+ this->seen_ = false;
+
+ return ok;
+}
+
// Return the type of the const reference.
Type*
return false;
}
+// Return the constant boolean value if there is one.
+
+bool
+Type_conversion_expression::do_boolean_constant_value(bool* val) const
+{
+ if (!this->type_->is_boolean_type())
+ return false;
+ return this->expr_->boolean_constant_value(val);
+}
+
// Determine the resulting type of the conversion.
void
nc, &issued_error);
}
+// Return the boolean constant value of a unary expression, if it has one.
+
+bool
+Unary_expression::do_boolean_constant_value(bool* val) const
+{
+ if (this->op_ == OPERATOR_NOT
+ && this->expr_->boolean_constant_value(val))
+ {
+ *val = !*val;
+ return true;
+ }
+ return false;
+}
+
// Return the type of a unary expression.
Type*
this->location(), nc, &issued_error);
}
+// Return the boolean constant value, if it has one.
+
+bool
+Binary_expression::do_boolean_constant_value(bool* val) const
+{
+ bool is_comparison = false;
+ switch (this->op_)
+ {
+ case OPERATOR_EQEQ:
+ case OPERATOR_NOTEQ:
+ case OPERATOR_LT:
+ case OPERATOR_LE:
+ case OPERATOR_GT:
+ case OPERATOR_GE:
+ is_comparison = true;
+ break;
+ case OPERATOR_ANDAND:
+ case OPERATOR_OROR:
+ break;
+ default:
+ return false;
+ }
+
+ Numeric_constant left_nc, right_nc;
+ if (is_comparison
+ && this->left_->numeric_constant_value(&left_nc)
+ && this->right_->numeric_constant_value(&right_nc))
+ return Binary_expression::compare_constant(this->op_, &left_nc,
+ &right_nc,
+ this->location(),
+ val);
+
+ std::string left_str, right_str;
+ if (is_comparison
+ && this->left_->string_constant_value(&left_str)
+ && this->right_->string_constant_value(&right_str))
+ {
+ *val = Binary_expression::cmp_to_bool(this->op_,
+ left_str.compare(right_str));
+ return true;
+ }
+
+ bool left_bval;
+ if (this->left_->boolean_constant_value(&left_bval))
+ {
+ if (this->op_ == OPERATOR_ANDAND && !left_bval)
+ {
+ *val = false;
+ return true;
+ }
+ else if (this->op_ == OPERATOR_OROR && left_bval)
+ {
+ *val = true;
+ return true;
+ }
+
+ bool right_bval;
+ if (this->right_->boolean_constant_value(&right_bval))
+ {
+ switch (this->op_)
+ {
+ case OPERATOR_EQEQ:
+ *val = (left_bval == right_bval);
+ return true;
+ case OPERATOR_NOTEQ:
+ *val = (left_bval != right_bval);
+ return true;
+ case OPERATOR_ANDAND:
+ case OPERATOR_OROR:
+ *val = right_bval;
+ return true;
+ default:
+ go_unreachable();
+ }
+ }
+ }
+
+ return false;
+}
+
// Note that the value is being discarded.
bool
string_constant_value(std::string* val) const
{ return this->do_string_constant_value(val); }
+ // If this is not a constant expression with boolean type, return
+ // false. If it is one, return true, and set VAL to the value.
+ bool
+ boolean_constant_value(bool* val) const
+ { return this->do_boolean_constant_value(val); }
+
// This is called if the value of this expression is being
// discarded. This issues warnings about computed values being
// unused. This returns true if all is well, false if it issued an
do_string_constant_value(std::string*) const
{ return false; }
+ // Return whether this is a constant expression of boolean type, and
+ // set VAL to the value.
+ virtual bool
+ do_boolean_constant_value(bool*) const
+ { return false; }
+
// Called by the parser if the value is being discarded.
virtual bool
do_discarding_value();
bool
do_string_constant_value(std::string*) const;
+ bool
+ do_boolean_constant_value(bool*) const;
+
Type*
do_type()
{ return this->type_; }
bool
do_numeric_constant_value(Numeric_constant*) const;
+ bool
+ do_boolean_constant_value(bool*) const;
+
Type*
do_type();
bool
do_numeric_constant_value(Numeric_constant*) const;
+ bool
+ do_boolean_constant_value(bool*) const;
+
bool
do_discarding_value();
if (only_check_syntax)
return;
+ // Do simple deadcode elimination.
+ ::gogo->remove_deadcode();
+
// Make implicit type conversions explicit.
::gogo->add_conversions();
b->traverse(&add_conversions);
}
+// Traversal class for simple deadcode elimination.
+
+class Remove_deadcode : public Traverse
+{
+ public:
+ Remove_deadcode()
+ : Traverse(traverse_statements
+ | traverse_expressions)
+ { }
+
+ int
+ statement(Block*, size_t* pindex, Statement*);
+
+ int
+ expression(Expression**);
+};
+
+// Remove deadcode in a statement.
+
+int
+Remove_deadcode::statement(Block* block, size_t* pindex, Statement* sorig)
+{
+ Location loc = sorig->location();
+ If_statement* ifs = sorig->if_statement();
+ if (ifs != NULL)
+ {
+ // Remove the dead branch of an if statement.
+ bool bval;
+ if (ifs->condition()->boolean_constant_value(&bval))
+ {
+ Statement* s;
+ if (bval)
+ s = Statement::make_block_statement(ifs->then_block(),
+ loc);
+ else
+ if (ifs->else_block() != NULL)
+ s = Statement::make_block_statement(ifs->else_block(),
+ loc);
+ else
+ // Make a dummy statement.
+ s = Statement::make_statement(Expression::make_boolean(false, loc),
+ true);
+
+ block->replace_statement(*pindex, s);
+ }
+ }
+ return TRAVERSE_CONTINUE;
+}
+
+// Remove deadcode in an expression.
+
+int
+Remove_deadcode::expression(Expression** pexpr)
+{
+ // Discard the right arm of a shortcut expression of constant value.
+ Binary_expression* be = (*pexpr)->binary_expression();
+ bool bval;
+ if (be != NULL
+ && be->boolean_constant_value(&bval)
+ && (be->op() == OPERATOR_ANDAND
+ || be->op() == OPERATOR_OROR))
+ *pexpr = Expression::make_boolean(bval, be->location());
+ return TRAVERSE_CONTINUE;
+}
+
+// Remove deadcode.
+
+void
+Gogo::remove_deadcode()
+{
+ Remove_deadcode remove_deadcode;
+ this->traverse(&remove_deadcode);
+}
+
// Traverse the tree to create function descriptors as needed.
class Create_function_descriptors : public Traverse
void
check_return_statements();
+ // Remove deadcode.
+ void
+ remove_deadcode();
+
// Make implicit type conversions explicit.
void
add_conversions();
condition() const
{ return this->cond_; }
+ Block*
+ then_block() const
+ { return this->then_block_; }
+
+ Block*
+ else_block() const
+ { return this->else_block_; }
+
protected:
int
do_traverse(Traverse*);