compiler: mangle dots in pkgpath
We need to mangle dots to avoid problems with -fgo-pkgpath=a.0.
That will confuse the name mangling, which assumes that names
entering the mangling cannot contain arbitrary dot characters.
We don't need to mangle other characters; go_encode_id will handle them.
Fixes golang/go#33871
Change-Id: Id1810f56fd39b5573621287056afff22be9e54e2
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/200838
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/go/go-encode-id.cc b/go/go-encode-id.cc
index 7c7aa13..550da97 100644
--- a/go/go-encode-id.cc
+++ b/go/go-encode-id.cc
@@ -253,3 +253,16 @@
}
return ret;
}
+
+// Encode a package path.
+
+std::string
+go_mangle_pkgpath(const std::string& pkgpath)
+{
+ std::string s = pkgpath;
+ for (size_t i = s.find('.');
+ i != std::string::npos;
+ i = s.find('.', i + 1))
+ s.replace(i, 1, ".x2e"); // 0x2e is the ASCII encoding for '.'
+ return s;
+}
diff --git a/go/go-encode-id.h b/go/go-encode-id.h
index 70126ba..2d09b0c 100644
--- a/go/go-encode-id.h
+++ b/go/go-encode-id.h
@@ -34,4 +34,12 @@
extern std::string
go_mangle_struct_tag(const std::string& tag);
+// Encode a package path. A package path can contain any arbitrary
+// character, including '.'. go_encode_id expects that any '.' will
+// be inserted by name mangling in a controlled manner. So first
+// translate any '.' using the same .x encoding as used by
+// go_mangle_struct_tag.
+extern std::string
+go_mangle_pkgpath(const std::string& pkgpath);
+
#endif // !defined(GO_ENCODE_ID_H)
diff --git a/go/gogo.cc b/go/gogo.cc
index a79cfc3..1ee49dc 100644
--- a/go/gogo.cc
+++ b/go/gogo.cc
@@ -298,7 +298,7 @@
Gogo::set_pkgpath(const std::string& arg)
{
go_assert(!this->pkgpath_set_);
- this->pkgpath_ = arg;
+ this->pkgpath_ = go_mangle_pkgpath(arg);
this->pkgpath_set_ = true;
this->pkgpath_from_option_ = true;
}
@@ -396,7 +396,8 @@
{
if (!this->prefix_from_option_)
this->prefix_ = "go";
- this->pkgpath_ = this->prefix_ + '.' + package_name;
+ this->pkgpath_ = (go_mangle_pkgpath(this->prefix_) + '.'
+ + package_name);
this->pkgpath_symbol_ = (Gogo::pkgpath_for_symbol(this->prefix_) + '.'
+ Gogo::pkgpath_for_symbol(package_name));
}