diff mbox series

Go patch committed: Improve type handling for constant string concatenation

Message ID CAOyqgcU2RSU7YHfGoYVJgbah0rQTRoXXQ35cWLfCUMOJu0vubw@mail.gmail.com
State New
Headers show
Series Go patch committed: Improve type handling for constant string concatenation | expand

Commit Message

Ian Lance Taylor April 13, 2019, 1:03 a.m. UTC
This patch to the Go frontend by Than McIntosh improves type handling
for string concat ops on constants.  This resolves 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, ensure that the
result has X's type, and disable folding if the both sides have a
concrete type that does not match.  This fixes
https://golang.org/issue/31412.  Bootstrapped and ran Go testsuite on
x86_64-pc-linux-gnu.  Committed to mainline.

Ian
diff mbox series

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 270263)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -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.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 270263)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -1846,12 +1846,20 @@  String_expression::do_dump_expression(As
   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,
   }
 
   // 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,
 	  && 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);
Index: gcc/go/gofrontend/expressions.h
===================================================================
--- gcc/go/gofrontend/expressions.h	(revision 270263)
+++ gcc/go/gofrontend/expressions.h	(working copy)
@@ -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 :
 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&