compiler: encode user visible names if necessary
authorIan Lance Taylor <iant@golang.org>
Fri, 11 Dec 2020 05:07:27 +0000 (21:07 -0800)
committerIan Lance Taylor <iant@golang.org>
Fri, 11 Dec 2020 17:57:30 +0000 (09:57 -0800)
Avoid putting weird characters into the user visible name.
It breaks stabs in particular, and may also cause debugger problems.
Instead, encode those names, and use a "g." prefix to tell the debugger.

Also dereference the type for the name of a recover thunk, to avoid a
pointless '*' that gets encoded.

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/277232

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/names.cc
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h

index dc2682d95d1d655acd97984508bb544f4b1eae73..681debb0392d76883746b0636a5c794c0ab9d757 100644 (file)
@@ -1,4 +1,4 @@
-0d0b423739b2fee9788cb6cb8af9ced29375e545
+3e8f49a2137a87fdaba51c3002ddbe41ab18ed46
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index f22d47656db04977b81f6a13ae31f607bd0bac4c..49d7bd9b98ad6b7dc83ab24c663210872b8402f1 100644 (file)
@@ -67,7 +67,7 @@ class Backend_name
  public:
   Backend_name()
     : prefix_(NULL), components_(), count_(0), suffix_(),
-      is_asm_name_(false)
+      is_asm_name_(false), is_non_identifier_(false)
   {}
 
   // Set the prefix.  Prefixes are always constant strings.
@@ -120,6 +120,18 @@ class Backend_name
     this->is_asm_name_ = true;
   }
 
+  // Whether some component includes some characters that can't appear
+  // in an identifier.
+  bool
+  is_non_identifier() const
+  { return this->is_non_identifier_; }
+
+  // Record that some component includes some character that can't
+  // appear in an identifier.
+  void
+  set_is_non_identifier()
+  { this->is_non_identifier_ = true; }
+
   // Get the user visible name.
   std::string
   name() const;
@@ -150,6 +162,9 @@ class Backend_name
   std::string suffix_;
   // True if components_[0] is an assembler name specified by the user.
   bool is_asm_name_;
+  // True if some component includes some character that can't
+  // normally appear in an identifier.
+  bool is_non_identifier_;
 };
 
 // An initialization function for an imported package.  This is a
index 8e73e5e157c2418647b44d6fb5264ff71a773402..f85d84ceadf86055a530f7242d929cf23836f914 100644 (file)
 // struct tag, the brace or backslash will be backslash quoted, before
 // underscore encoding.
 //
+// Many of these names will be visible in the debugger.  The debugger
+// will be given these names before applying any underscore encoding.
+// These user names do not have to be unique--they are only used by
+// the debugger, not the linker--so this is OK.  However, there is an
+// exception: if the name would otherwise include characters that
+// can't normally appear in an identifier, then the user name will
+// also be underscore encoded.  This avoids problems with
+// communicating the debug info to the assembler and with handling the
+// debug info in the debugger.  A Go-aware debugger will need to know
+// whether to apply underscore decoding to a name before showing it to
+// the user.  We indicate this by adding a prefix of "g.", and
+// assuming that cases of a package path of "g" are unusual.  This
+// prefix will only appear in the user name, not the assembler name.
+//
 // The underscore encoding is, naturally, an underscore followed by
 // other characters.  As there are various characters that commonly
 // appear in type literals and in package paths, we have a set of
@@ -512,7 +526,7 @@ Gogo::recover_thunk_name(const std::string& name, const Type* rtype)
   if (rtype != NULL)
     {
       Backend_name bname;
-      rtype->backend_name(this, &bname);
+      rtype->deref()->backend_name(this, &bname);
       ret = bname.name();
       ret.append(1, '.');
     }
@@ -634,37 +648,45 @@ Type::backend_name(Gogo* gogo, Backend_name* bname) const
     }
 
   std::string name;
+  bool is_non_identifier = false;
 
   // The do_symbol_name virtual function will set RET to the mangled
   // name before encoding.
-  this->do_mangled_name(gogo, &name);
+  this->do_mangled_name(gogo, &name, &is_non_identifier);
 
   bname->add(name);
+  if (is_non_identifier)
+    bname->set_is_non_identifier();
 }
 
 // The mangled name is implemented as a method on each instance of
 // Type.
 
 void
-Error_type::do_mangled_name(Gogo*, std::string* ret) const
+Error_type::do_mangled_name(Gogo*, std::string* ret,
+                           bool* is_non_identifier) const
 {
   ret->append("{error}");
+  *is_non_identifier = true;
 }
 
 void
-Void_type::do_mangled_name(Gogo*, std::string* ret) const
+Void_type::do_mangled_name(Gogo*, std::string* ret,
+                          bool* is_non_identifier) const
 {
   ret->append("{void}");
+  *is_non_identifier = true;
 }
 
 void
-Boolean_type::do_mangled_name(Gogo*, std::string* ret) const
+Boolean_type::do_mangled_name(Gogo*, std::string* ret, bool*) const
 {
   ret->append("bool");
 }
 
 void
-Integer_type::do_mangled_name(Gogo*, std::string* ret) const
+Integer_type::do_mangled_name(Gogo*, std::string* ret,
+                             bool* is_non_identifier) const
 {
   char buf[100];
   snprintf(buf, sizeof buf, "%s%si%d",
@@ -672,43 +694,53 @@ Integer_type::do_mangled_name(Gogo*, std::string* ret) const
           this->is_unsigned_ ? "u" : "",
           this->bits_);
   ret->append(buf);
+  if (this->is_abstract_)
+    *is_non_identifier = true;
 }
 
 void
-Float_type::do_mangled_name(Gogo*, std::string* ret) const
+Float_type::do_mangled_name(Gogo*, std::string* ret,
+                           bool* is_non_identifier) const
 {
   char buf[100];
   snprintf(buf, sizeof buf, "%sfloat%d",
           this->is_abstract_ ? "{abstract}" : "",
           this->bits_);
   ret->append(buf);
+  if (this->is_abstract_)
+    *is_non_identifier = true;
 }
 
 void
-Complex_type::do_mangled_name(Gogo*, std::string* ret) const
+Complex_type::do_mangled_name(Gogo*, std::string* ret,
+                             bool* is_non_identifier) const
 {
   char buf[100];
   snprintf(buf, sizeof buf, "%sc%d",
           this->is_abstract_ ? "{abstract}" : "",
           this->bits_);
   ret->append(buf);
+  if (this->is_abstract_)
+    *is_non_identifier = true;
 }
 
 void
-String_type::do_mangled_name(Gogo*, std::string* ret) const
+String_type::do_mangled_name(Gogo*, std::string* ret, bool*) const
 {
   ret->append("string");
 }
 
 void
-Function_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Function_type::do_mangled_name(Gogo* gogo, std::string* ret,
+                              bool* is_non_identifier) const
 {
   ret->append("func");
 
   if (this->receiver_ != NULL)
     {
       ret->push_back('(');
-      this->append_mangled_name(this->receiver_->type(), gogo, ret);
+      this->append_mangled_name(this->receiver_->type(), gogo, ret,
+                               is_non_identifier);
       ret->append(")");
     }
 
@@ -727,7 +759,8 @@ Function_type::do_mangled_name(Gogo* gogo, std::string* ret) const
            ret->push_back(',');
          if (this->is_varargs_ && p + 1 == params->end())
            ret->append("...");
-         this->append_mangled_name(p->type(), gogo, ret);
+         this->append_mangled_name(p->type(), gogo, ret,
+                                   is_non_identifier);
        }
     }
   ret->push_back(')');
@@ -745,27 +778,34 @@ Function_type::do_mangled_name(Gogo* gogo, std::string* ret) const
            first = false;
          else
            ret->append(",");
-         this->append_mangled_name(p->type(), gogo, ret);
+         this->append_mangled_name(p->type(), gogo, ret, is_non_identifier);
        }
     }
   ret->push_back(')');
+
+  *is_non_identifier = true;
 }
 
 void
-Pointer_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Pointer_type::do_mangled_name(Gogo* gogo, std::string* ret,
+                             bool* is_non_identifier) const
 {
   ret->push_back('*');
-  this->append_mangled_name(this->to_type_, gogo, ret);
+  this->append_mangled_name(this->to_type_, gogo, ret, is_non_identifier);
+  *is_non_identifier = true;
 }
 
 void
-Nil_type::do_mangled_name(Gogo*, std::string* ret) const
+Nil_type::do_mangled_name(Gogo*, std::string* ret,
+                         bool* is_non_identifier) const
 {
   ret->append("{nil}");
+  *is_non_identifier = true;
 }
 
 void
-Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Struct_type::do_mangled_name(Gogo* gogo, std::string* ret,
+                            bool* is_non_identifier) const
 {
   ret->append("struct{");
 
@@ -796,9 +836,10 @@ Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
          if (p->is_anonymous()
              && p->type()->named_type() != NULL
              && p->type()->named_type()->is_alias())
-           p->type()->named_type()->append_symbol_type_name(gogo, true, ret);
+           p->type()->named_type()->append_symbol_type_name(gogo, true, ret,
+                                                            is_non_identifier);
          else
-           this->append_mangled_name(p->type(), gogo, ret);
+           this->append_mangled_name(p->type(), gogo, ret, is_non_identifier);
 
          if (p->has_tag())
            {
@@ -813,10 +854,13 @@ Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
     }
 
   ret->push_back('}');
+
+  *is_non_identifier = true;
 }
 
 void
-Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Array_type::do_mangled_name(Gogo* gogo, std::string* ret,
+                           bool* is_non_identifier) const
 {
   ret->push_back('[');
   if (this->length_ != NULL)
@@ -841,20 +885,24 @@ Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const
        ret->append("x");
     }
   ret->push_back(']');
-  this->append_mangled_name(this->element_type_, gogo, ret);
+  this->append_mangled_name(this->element_type_, gogo, ret, is_non_identifier);
+  *is_non_identifier = true;
 }
 
 void
-Map_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Map_type::do_mangled_name(Gogo* gogo, std::string* ret,
+                         bool* is_non_identifier) const
 {
   ret->append("map[");
-  this->append_mangled_name(this->key_type_, gogo, ret);
+  this->append_mangled_name(this->key_type_, gogo, ret, is_non_identifier);
   ret->push_back(']');
-  this->append_mangled_name(this->val_type_, gogo, ret);
+  this->append_mangled_name(this->val_type_, gogo, ret, is_non_identifier);
+  *is_non_identifier = true;
 }
 
 void
-Channel_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Channel_type::do_mangled_name(Gogo* gogo, std::string* ret,
+                             bool* is_non_identifier) const
 {
   if (!this->may_send_)
     ret->append("<-");
@@ -862,11 +910,13 @@ Channel_type::do_mangled_name(Gogo* gogo, std::string* ret) const
   if (!this->may_receive_)
     ret->append("<-");
   ret->push_back(' ');
-  this->append_mangled_name(this->element_type_, gogo, ret);
+  this->append_mangled_name(this->element_type_, gogo, ret, is_non_identifier);
+  *is_non_identifier = true;
 }
 
 void
-Interface_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Interface_type::do_mangled_name(Gogo* gogo, std::string* ret,
+                               bool* is_non_identifier) const
 {
   go_assert(this->methods_are_finalized_);
 
@@ -892,25 +942,29 @@ Interface_type::do_mangled_name(Gogo* gogo, std::string* ret) const
              ret->push_back(' ');
            }
 
-         this->append_mangled_name(p->type(), gogo, ret);
+         this->append_mangled_name(p->type(), gogo, ret, is_non_identifier);
        }
       this->seen_ = false;
     }
 
   ret->push_back('}');
+
+  *is_non_identifier = true;
 }
 
 void
-Named_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Named_type::do_mangled_name(Gogo* gogo, std::string* ret,
+                           bool* is_non_identifier) const
 {
-  this->append_symbol_type_name(gogo, false, ret);
+  this->append_symbol_type_name(gogo, false, ret, is_non_identifier);
 }
 
 void
-Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const
+Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret,
+                                         bool *is_non_identifier) const
 {
   if (this->is_defined())
-    this->append_mangled_name(this->real_type(), gogo, ret);
+    this->append_mangled_name(this->real_type(), gogo, ret, is_non_identifier);
   else
     {
       const Named_object* no = this->named_object();
@@ -929,7 +983,8 @@ Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const
 
 void
 Named_type::append_symbol_type_name(Gogo* gogo, bool use_alias,
-                                   std::string* ret) const
+                                   std::string* ret,
+                                   bool* is_non_identifier) const
 {
   if (this->is_error_)
     return;
@@ -938,7 +993,7 @@ Named_type::append_symbol_type_name(Gogo* gogo, bool use_alias,
       if (this->seen_alias_)
        return;
       this->seen_alias_ = true;
-      this->append_mangled_name(this->type_, gogo, ret);
+      this->append_mangled_name(this->type_, gogo, ret, is_non_identifier);
       this->seen_alias_ = false;
       return;
     }
@@ -957,6 +1012,8 @@ Named_type::append_symbol_type_name(Gogo* gogo, bool use_alias,
              Backend_name bname;
              rcvr->type()->deref()->backend_name(gogo, &bname);
              ret->append(bname.name());
+             if (bname.is_non_identifier())
+               *is_non_identifier = true;
            }
          else if (this->in_function_->package() == NULL)
            ret->append(gogo->pkgpath());
@@ -1160,6 +1217,15 @@ Backend_name::name() const
 {
   if (this->is_asm_name_)
     return this->components_[0];
+
+  // If there is some character in the name that can't appear in an
+  // identifier, use the assembler name as the user name.  This avoids
+  // possible problems in the assembler or debugger.  The usual
+  // demangling scheme will still work.  We use a prefix of "g." to
+  // tell the debugger about this.
+  if (this->is_non_identifier_)
+    return "g." + this->asm_name();
+
   std::string ret;
   if (this->prefix_ != NULL)
     ret.append(this->prefix_);
@@ -1203,6 +1269,8 @@ Backend_name::optional_asm_name() const
 {
   if (this->is_asm_name_)
     return "";
+  if (this->is_non_identifier_)
+    return this->asm_name();
   for (int i = 0; i < this->count_; i++)
     if (go_id_needs_encoding(this->components_[i]))
       return this->asm_name();
index d2741f6db58c0c890548cd23056efdae5aaaa967..f9097d5e130d57011955c31b849b1ecbced9cd0b 100644 (file)
@@ -4602,7 +4602,7 @@ class Sink_type : public Type
   { go_unreachable(); }
 
   void
-  do_mangled_name(Gogo*, std::string*) const
+  do_mangled_name(Gogo*, std::string*, bool*) const
   { go_unreachable(); }
 };
 
@@ -5712,7 +5712,7 @@ class Call_multiple_result_type : public Type
   { go_assert(saw_errors()); }
 
   void
-  do_mangled_name(Gogo*, std::string*) const
+  do_mangled_name(Gogo*, std::string*, bool*) const
   { go_assert(saw_errors()); }
 
  private:
index b7dd391d321ccccc3264e3b895aab15d88033aa7..f2880f9c5d80e098d61e93c524afcbfa227047b4 100644 (file)
@@ -1140,7 +1140,7 @@ class Type
   do_reflection(Gogo*, std::string*) const = 0;
 
   virtual void
-  do_mangled_name(Gogo*, std::string*) const = 0;
+  do_mangled_name(Gogo*, std::string*, bool*) const = 0;
 
   virtual void
   do_export(Export*) const;
@@ -1202,8 +1202,9 @@ class Type
 
   // For the benefit of child class mangling.
   void
-  append_mangled_name(const Type* type, Gogo* gogo, std::string* ret) const
-  { type->do_mangled_name(gogo, ret); }
+  append_mangled_name(const Type* type, Gogo* gogo, std::string* ret,
+                     bool *is_non_identifier) const
+  { type->do_mangled_name(gogo, ret, is_non_identifier); }
 
   // Return the backend representation for the underlying type of a
   // named type.
@@ -1664,7 +1665,7 @@ class Error_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string* ret) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 };
 
 // The void type.
@@ -1693,7 +1694,7 @@ class Void_type : public Type
   { }
 
   void
-  do_mangled_name(Gogo*, std::string* ret) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 };
 
 // The boolean type.
@@ -1722,7 +1723,7 @@ class Boolean_type : public Type
   { ret->append("bool"); }
 
   void
-  do_mangled_name(Gogo*, std::string* ret) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 };
 
 // The type of an integer.
@@ -1808,7 +1809,7 @@ protected:
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string*) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
  private:
   Integer_type(bool is_abstract, bool is_unsigned, int bits,
@@ -1894,7 +1895,7 @@ class Float_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string*) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
  private:
   Float_type(bool is_abstract, int bits, int runtime_type_kind)
@@ -1972,7 +1973,7 @@ class Complex_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string*) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
  private:
   Complex_type(bool is_abstract, int bits, int runtime_type_kind)
@@ -2026,7 +2027,7 @@ class String_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string* ret) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
  private:
   // The named string type.
@@ -2186,7 +2187,7 @@ class Function_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string*) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
   void
   do_export(Export*) const;
@@ -2315,7 +2316,7 @@ class Pointer_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string*) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
   void
   do_export(Export*) const;
@@ -2353,7 +2354,7 @@ class Nil_type : public Type
   { go_unreachable(); }
 
   void
-  do_mangled_name(Gogo*, std::string* ret) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 };
 
 // The type of a field in a struct.
@@ -2687,7 +2688,7 @@ class Struct_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string*) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
   void
   do_export(Export*) const;
@@ -2870,7 +2871,7 @@ class Array_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string*) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
   void
   do_export(Export*) const;
@@ -3008,7 +3009,7 @@ class Map_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string*) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
   void
   do_export(Export*) const;
@@ -3122,7 +3123,7 @@ class Channel_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string*) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
   void
   do_export(Export*) const;
@@ -3298,7 +3299,7 @@ class Interface_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string*) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
   void
   do_export(Export*) const;
@@ -3572,7 +3573,8 @@ class Named_type : public Type
   // Append the symbol type name as for Type::append_mangled_name,
   // but if USE_ALIAS use the alias name rather than the alias target.
   void
-  append_symbol_type_name(Gogo*, bool use_alias, std::string*) const;
+  append_symbol_type_name(Gogo*, bool use_alias, std::string*,
+                         bool* is_non_identifier) const;
 
   // Import a named type.
   static void
@@ -3619,7 +3621,7 @@ class Named_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string* ret) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
   void
   do_export(Export*) const;
@@ -3783,7 +3785,7 @@ class Forward_declaration_type : public Type
   do_reflection(Gogo*, std::string*) const;
 
   void
-  do_mangled_name(Gogo*, std::string* ret) const;
+  do_mangled_name(Gogo*, std::string*, bool*) const;
 
   void
   do_export(Export*) const;