aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/expressions.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go/gofrontend/expressions.cc')
-rw-r--r--gcc/go/gofrontend/expressions.cc129
1 files changed, 129 insertions, 0 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 273c8f0..3481d00 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -1764,6 +1764,13 @@ class Boolean_expression : public Expression
{ 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; }
@@ -3132,6 +3139,9 @@ class Const_expression : public Expression
bool
do_string_constant_value(std::string* val) const;
+ bool
+ do_boolean_constant_value(bool* val) const;
+
Type*
do_type();
@@ -3250,6 +3260,21 @@ Const_expression::do_string_constant_value(std::string* val) const
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*
@@ -3841,6 +3866,16 @@ Type_conversion_expression::do_string_constant_value(std::string* val) const
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
@@ -4710,6 +4745,20 @@ Unary_expression::do_numeric_constant_value(Numeric_constant* nc) const
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*
@@ -6187,6 +6236,86 @@ Binary_expression::do_numeric_constant_value(Numeric_constant* nc) const
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