aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2019-04-13 01:03:55 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-04-13 01:03:55 +0000
commitfdc59f56c1038ce194b72aebe29ac9cd4150205c (patch)
tree8a84c446c3b83550be24819a0adf3496f802642f
parentb15937488e5738ae2d4653dcc10acbd95eb649b5 (diff)
downloadgcc-fdc59f56c1038ce194b72aebe29ac9cd4150205c.zip
gcc-fdc59f56c1038ce194b72aebe29ac9cd4150205c.tar.gz
gcc-fdc59f56c1038ce194b72aebe29ac9cd4150205c.tar.bz2
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
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc32
-rw-r--r--gcc/go/gofrontend/expressions.h8
3 files changed, 34 insertions, 8 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 74e811b..381d791 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -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.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 018fdbb..6f9775d 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -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);
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index c521d9b..43aaccf 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -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&