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
This commit is contained in:
parent
b15937488e
commit
fdc59f56c1
|
@ -1,4 +1,4 @@
|
|||
8822487ed776d55eafed44de7d89ee54bbfbab47
|
||||
20010e494f46d8fd58cfd372093b059578d3379a
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
|
|
@ -1846,12 +1846,20 @@ String_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
|
|||
String_expression::export_string(ast_dump_context, this);
|
||||
}
|
||||
|
||||
// Make a string expression.
|
||||
// Make a string expression with abstract string type (common case).
|
||||
|
||||
Expression*
|
||||
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.
|
||||
|
@ -5485,7 +5493,16 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*,
|
|||
}
|
||||
|
||||
// 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 right_string;
|
||||
|
@ -5493,8 +5510,13 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*,
|
|||
&& right->string_constant_value(&right_string))
|
||||
{
|
||||
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)
|
||||
{
|
||||
int cmp = left_string.compare(right_string);
|
||||
|
|
|
@ -230,6 +230,10 @@ class Expression
|
|||
static Expression*
|
||||
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.
|
||||
// For simplicity, the enum values must match the field indexes in the
|
||||
// underlying struct.
|
||||
|
@ -1570,9 +1574,9 @@ class Set_and_use_temporary_expression : public Expression
|
|||
class String_expression : public Expression
|
||||
{
|
||||
public:
|
||||
String_expression(const std::string& val, Location location)
|
||||
String_expression(const std::string& val, Type* type, Location location)
|
||||
: Expression(EXPRESSION_STRING, location),
|
||||
val_(val), type_(NULL)
|
||||
val_(val), type_(type)
|
||||
{ }
|
||||
|
||||
const std::string&
|
||||
|
|
Loading…
Reference in New Issue