Add `lvalue::set_name` (#78)

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 9e7ce00..bc739bb 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -473,3 +473,10 @@
 of an lvalue.
 
  * :func:`gcc_jit_lvalue_get_name`
+
+``LIBGCCJIT_ABI_45``
+--------------------
+``LIBGCCJIT_ABI_45`` covers the addition of a function to set the name
+of an lvalue.
+
+ * :func:`gcc_jit_lvalue_set_name`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 2525e88..7e60cd0 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -929,12 +929,21 @@
     Returns the name of an lvalue.
 
    This entrypoint was added in :ref:`LIBGCCJIT_ABI_44`; you can test for
-   its present using
+   its presence using
 
    .. code-block:: c
 
       #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_get_name
 
+    Sets the name of an lvalue.
+
+   This entrypoint was added in :ref:`LIBGCCJIT_ABI_45`; you can test for
+   its presence using
+
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_name
+
 Global variables
 ****************
 
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 2175892..8f2e2a8 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -1512,6 +1512,7 @@
   void set_alignment (unsigned bytes);
   unsigned get_alignment () const { return m_alignment; }
   virtual string * get_name () const { return NULL; }
+  virtual void set_name (const char *new_name) = 0;
 
 protected:
   string *m_link_section;
@@ -1553,6 +1554,9 @@
   const char *access_as_lvalue (reproducer &r) final override;
 
   string * get_name () const final override { return m_name; }
+  void set_name (const char *new_name) final override {
+    m_name = m_ctxt->new_string (new_name);
+  }
 
 private:
   string * make_debug_string () final override { return m_name; }
@@ -1823,6 +1827,9 @@
   void set_rvalue_init (rvalue *val) { m_rvalue_init = val; }
 
   string * get_name () const final override { return m_name; }
+  void set_name (const char *new_name) final override {
+    m_name = m_ctxt->new_string (new_name);
+  }
 
 private:
   string * make_debug_string () final override { return m_name; }
@@ -2267,6 +2274,10 @@
 
   void replay_into (replayer *r) final override;
 
+  void set_name (const char *new_name) final override {
+    m_ctxt->add_error (NULL, "cannot change the name of type `array_access`");
+  }
+
   void visit_children (rvalue_visitor *v) final override;
 
 private:
@@ -2328,6 +2339,10 @@
 
   void visit_children (rvalue_visitor *v) final override;
 
+  void set_name (const char *new_name) final override {
+    m_ctxt->add_error (NULL, "cannot change the name of type `vector_access`");
+  }
+
 private:
   string * make_debug_string () final override;
   void write_reproducer (reproducer &r) final override;
@@ -2357,6 +2372,11 @@
 
   void visit_children (rvalue_visitor *v) final override;
 
+  void set_name (const char *new_name) final override {
+    m_ctxt->add_error (
+      NULL, "cannot change the name of type `access_field_of_lvalue`");
+  }
+
 private:
   string * make_debug_string () final override;
   void write_reproducer (reproducer &r) final override;
@@ -2415,6 +2435,11 @@
 
   void visit_children (rvalue_visitor *v) final override;
 
+  void set_name (const char *new_name) final override {
+    m_ctxt->add_error (
+      NULL, "cannot change the name of type `dereference_field_rvalue`");
+  }
+
 private:
   string * make_debug_string () final override;
   void write_reproducer (reproducer &r) final override;
@@ -2441,6 +2466,11 @@
 
   void visit_children (rvalue_visitor *v) final override;
 
+  void set_name (const char *new_name) final override {
+    m_ctxt->add_error (
+      NULL, "cannot change the name of type `dereference_rvalue`");
+  }
+
 private:
   string * make_debug_string () final override;
   void write_reproducer (reproducer &r) final override;
@@ -2524,6 +2554,11 @@
 
   void write_to_dump (dump &d) final override;
 
+  string * get_name () const final override { return m_name; }
+  void set_name (const char *new_name) final override {
+    m_name = m_ctxt->new_string (new_name);
+  }
+
 private:
   string * make_debug_string () final override {
     if (m_name)
diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc
index d26f21f..5fd5f5c 100644
--- a/gcc/jit/libgccjit.cc
+++ b/gcc/jit/libgccjit.cc
@@ -4868,6 +4868,19 @@
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, this calls the trivial
+   gcc::jit::recording::lvalue::set_name method, in jit-recording.h.  */
+
+extern void
+gcc_jit_lvalue_set_name (gcc_jit_lvalue *lvalue, const char *new_name)
+{
+  RETURN_IF_FAIL (lvalue, NULL, NULL, "NULL lvalue");
+  RETURN_IF_FAIL (new_name, NULL, NULL, "NULL new_name");
+  lvalue->set_name (new_name);
+}
+
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, this calls the trivial
    gcc::jit::recording::field::set_loc method, in jit-recording.h.  */
 
 void
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index e24acb9..cc98965 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -2296,6 +2296,12 @@
 
 #define LIBGCCJIT_HAVE_gcc_jit_lvalue_get_name
 
+/* Set a new name to the `lvalue`.  */
+extern void
+gcc_jit_lvalue_set_name (gcc_jit_lvalue *lvalue, const char *new_name);
+
+#define LIBGCCJIT_HAVE_gcc_jit_lvalue_set_name
+
 extern void
 gcc_jit_context_set_output_ident (gcc_jit_context *ctxt,
 				  const char* output_ident);
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 9cbe709..5b11f9c 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -383,3 +383,8 @@
   global:
     gcc_jit_lvalue_get_name;
 } LIBGCCJIT_ABI_43;
+
+LIBGCCJIT_ABI_45{
+  global:
+    gcc_jit_lvalue_set_name;
+} LIBGCCJIT_ABI_44;
diff --git a/gcc/testsuite/jit.dg/test-name.c b/gcc/testsuite/jit.dg/test-name.c
new file mode 100644
index 0000000..3e1705c
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-name.c
@@ -0,0 +1,81 @@
+/* { dg-do compile { target x86_64-*-* } } */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+// We want the debug info to check the function variable's name.
+#define TEST_ESCHEWS_SET_OPTIONS
+static void set_options (gcc_jit_context *ctxt, const char *argv0)
+{
+    gcc_jit_context_set_bool_option(ctxt, GCC_JIT_BOOL_OPTION_DEBUGINFO, 1);
+}
+
+#define TEST_COMPILING_TO_FILE
+#define OUTPUT_KIND      GCC_JIT_OUTPUT_KIND_ASSEMBLER
+#define OUTPUT_FILENAME  "output-of-test-name.c.s"
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Let's try to inject the equivalent of:
+
+int original_foo = 10;
+  */
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  gcc_jit_lvalue *foo =
+    gcc_jit_context_new_global (ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED,
+                                int_type, "original_foo");
+  gcc_jit_rvalue *ten = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 10);
+  gcc_jit_global_set_initializer_rvalue (foo, ten);
+
+  CHECK_STRING_VALUE (gcc_jit_lvalue_get_name (foo), "original_foo");
+  gcc_jit_lvalue_set_name (foo, "new_one");
+  CHECK_STRING_VALUE (gcc_jit_lvalue_get_name (foo), "new_one");
+
+  /* Let's try to inject te equivalent of:
+int blabla() {
+  int the_var = 12;
+
+  return the_var;
+}
+  */
+  gcc_jit_function *blabla_func =
+    gcc_jit_context_new_function (ctxt, NULL,
+          GCC_JIT_FUNCTION_EXPORTED,
+          int_type,
+          "blabla",
+          0, NULL,
+          0);
+
+  gcc_jit_block *blabla_block = gcc_jit_function_new_block (blabla_func, NULL);
+
+  /* Build locals:  */
+  gcc_jit_lvalue *the_var =
+    gcc_jit_function_new_local (blabla_func, NULL, int_type, "the_var");
+
+  /* int the_var = 0; */
+  gcc_jit_block_add_assignment (
+    blabla_block, NULL,
+    the_var,
+    gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 0));
+
+  gcc_jit_block_end_with_return (
+    blabla_block, NULL,
+    gcc_jit_lvalue_as_rvalue (the_var));
+
+  CHECK_STRING_VALUE (gcc_jit_lvalue_get_name (the_var), "the_var");
+  gcc_jit_lvalue_set_name (the_var, "confiture");
+  CHECK_STRING_VALUE (gcc_jit_lvalue_get_name (the_var), "confiture");
+}
+
+/* { dg-final { jit-verify-output-file-was-created "" } } */
+/* Check that the global was correctly renamed */
+/* { dg-final { jit-verify-assembler-output-not "original_foo:" } } */
+/* { dg-final { jit-verify-assembler-output "new_one:" } } */
+
+/* { dg-final { jit-verify-assembler-output-not ".string\\s+\"the_var\"" } } */
+/* { dg-final { jit-verify-assembler-output ".string\\s+\"confiture\"" } } */