diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-04-13 01:03:55 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-04-13 01:03:55 +0000 |
commit | fdc59f56c1038ce194b72aebe29ac9cd4150205c (patch) | |
tree | 8a84c446c3b83550be24819a0adf3496f802642f | |
parent | b15937488e5738ae2d4653dcc10acbd95eb649b5 (diff) | |
download | gcc-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/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 32 | ||||
-rw-r--r-- | 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 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& |