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.
}
// 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;
&& 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);
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.
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&