From fdc59f56c1038ce194b72aebe29ac9cd4150205c Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 13 Apr 2019 01:03:55 +0000 Subject: [PATCH] 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 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/expressions.cc | 32 +++++++++++++++++++++++++++----- gcc/go/gofrontend/expressions.h | 8 ++++++-- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 74e811b8a23..381d791da8c 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 018fdbbec77..6f9775dd5a2 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 c521d9bf775..43aaccf9769 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&