Commit fdc59f56 by Ian Lance Taylor

compiler: improve type handling for string concat ops on constants

    
    Resolve a small problem with concatenation of string constants: in a
    string concat X + Y where X has named type and Y has abstract string
    type, insure that the result has X's type, and disable folding if the
    both sides have a concrete type that does not match.
    
    Fixes golang/go#31412.
    
    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/171797

From-SVN: r270336
parent b1593748
8822487ed776d55eafed44de7d89ee54bbfbab47 20010e494f46d8fd58cfd372093b059578d3379a
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -1846,12 +1846,20 @@ String_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const ...@@ -1846,12 +1846,20 @@ String_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
String_expression::export_string(ast_dump_context, this); String_expression::export_string(ast_dump_context, this);
} }
// Make a string expression. // Make a string expression with abstract string type (common case).
Expression* Expression*
Expression::make_string(const std::string& val, Location location) Expression::make_string(const std::string& val, Location location)
{ {
return new String_expression(val, location); return new String_expression(val, NULL, location);
}
// Make a string expression with a specific string type.
Expression*
Expression::make_string_typed(const std::string& val, Type* type, Location location)
{
return new String_expression(val, type, location);
} }
// An expression that evaluates to some characteristic of a string. // An expression that evaluates to some characteristic of a string.
...@@ -5485,7 +5493,16 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*, ...@@ -5485,7 +5493,16 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*,
} }
// String constant expressions. // String constant expressions.
if (left->type()->is_string_type() && right->type()->is_string_type()) //
// Avoid constant folding here if the left and right types are incompatible
// (leave the operation intact so that the type checker can complain about it
// later on). If concatenating an abstract string with a named string type,
// result type needs to be of the named type (see issue 31412).
if (left->type()->is_string_type()
&& right->type()->is_string_type()
&& (left->type()->named_type() == NULL
|| right->type()->named_type() == NULL
|| left->type()->named_type() == right->type()->named_type()))
{ {
std::string left_string; std::string left_string;
std::string right_string; std::string right_string;
...@@ -5493,8 +5510,13 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*, ...@@ -5493,8 +5510,13 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*,
&& right->string_constant_value(&right_string)) && right->string_constant_value(&right_string))
{ {
if (op == OPERATOR_PLUS) if (op == OPERATOR_PLUS)
return Expression::make_string(left_string + right_string, {
location); Type* result_type = (left->type()->named_type() != NULL
? left->type()
: right->type());
return Expression::make_string_typed(left_string + right_string,
result_type, location);
}
else if (is_comparison) else if (is_comparison)
{ {
int cmp = left_string.compare(right_string); int cmp = left_string.compare(right_string);
......
...@@ -230,6 +230,10 @@ class Expression ...@@ -230,6 +230,10 @@ class Expression
static Expression* static Expression*
make_string(const std::string&, Location); make_string(const std::string&, Location);
// Make a constant string expression with a specific string subtype.
static Expression*
make_string_typed(const std::string&, Type*, Location);
// Make an expression that evaluates to some characteristic of an string. // Make an expression that evaluates to some characteristic of an string.
// For simplicity, the enum values must match the field indexes in the // For simplicity, the enum values must match the field indexes in the
// underlying struct. // underlying struct.
...@@ -1570,9 +1574,9 @@ class Set_and_use_temporary_expression : public Expression ...@@ -1570,9 +1574,9 @@ class Set_and_use_temporary_expression : public Expression
class String_expression : public Expression class String_expression : public Expression
{ {
public: public:
String_expression(const std::string& val, Location location) String_expression(const std::string& val, Type* type, Location location)
: Expression(EXPRESSION_STRING, location), : Expression(EXPRESSION_STRING, location),
val_(val), type_(NULL) val_(val), type_(type)
{ } { }
const std::string& const std::string&
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment