compiler: handle int-to-string conversion with large integer constant

Currently, Type_conversion_expression::do_is_constant thinks the
int-to-string conversion is constant if the integer operand is
constant, but Type_conversion_expression::do_get_backend actually
generates a call to runtime.intstring if the integer does not fit
in a "ushort", which makes it not suitable in constant context,
such as static initializer.

This CL makes it handle all constant integer input as constant,
generating constant string.

Fixes golang/go#32347.

Change-Id: I64502e2fec034d5081be395ee7636791e5601215
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/179777
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/go/expressions.cc b/go/expressions.cc
index e3a6627..f0c12f4 100644
--- a/go/expressions.cc
+++ b/go/expressions.cc
@@ -3842,11 +3842,20 @@
       mpz_t intval;
       Numeric_constant nc;
       if (this->expr_->numeric_constant_value(&nc)
-	  && nc.to_int(&intval)
-	  && mpz_fits_ushort_p(intval))
+	  && nc.to_int(&intval))
 	{
 	  std::string s;
-	  Lex::append_char(mpz_get_ui(intval), true, &s, loc);
+          unsigned int x;
+          if (mpz_fits_uint_p(intval))
+            x = mpz_get_ui(intval);
+          else
+            {
+              char* s = mpz_get_str(NULL, 16, intval);
+              go_warning_at(loc, 0,
+                            "unicode code point 0x%s out of range in string", s);
+              x = 0xfffd;
+            }
+	  Lex::append_char(x, true, &s, loc);
 	  mpz_clear(intval);
 	  Expression* se = Expression::make_string(s, loc);
 	  return se->get_backend(context);