This patch to the Go frontend and the runtime library handles the package path like the other Go compiler. Gccgo needs to canonicalize type names based on the reflection string, so that types defined in shared libraries work correctly. That means that it needs to include the package path in the reflection string. But the other Go compiler does not include the full path in the reflection string, only the package name. So this patch changes gccgo to store the package path in the reflection string within double quotes, and to strip out double quoted strings when the reflect.Type.String method is called. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r 2ab3869bedd1 go/gogo.cc --- a/go/gogo.cc Thu Jun 07 01:05:45 2012 -0700 +++ b/go/gogo.cc Tue Jun 12 11:47:12 2012 -0700 @@ -339,9 +339,14 @@ // symbol names. if (!this->pkgpath_set_) { - if (!this->prefix_from_option_) - this->prefix_ = "go"; - this->pkgpath_ = this->prefix_ + '.' + package_name; + if (!this->prefix_from_option_ && package_name == "main") + this->pkgpath_ = package_name; + else + { + if (!this->prefix_from_option_) + this->prefix_ = "go"; + this->pkgpath_ = this->prefix_ + '.' + package_name; + } this->pkgpath_set_ = true; } diff -r 2ab3869bedd1 go/types.cc --- a/go/types.cc Thu Jun 07 01:05:45 2012 -0700 +++ b/go/types.cc Tue Jun 12 11:47:12 2012 -0700 @@ -8337,14 +8337,23 @@ { // We handle -fgo-prefix and -fgo-pkgpath differently here for // compatibility with how the compiler worked before - // -fgo-pkgpath was introduced. + // -fgo-pkgpath was introduced. When -fgo-pkgpath is specified, + // we use it to make a unique reflection string, so that the + // type canonicalization in the reflect package will work. In + // order to be compatible with the gc compiler, we quote the + // package path, so that the reflect methods can discard it. const Package* package = this->named_object_->package(); if (gogo->pkgpath_from_option()) - ret->append(package != NULL ? package->pkgpath() : gogo->pkgpath()); - else - ret->append(package != NULL - ? package->package_name() - : gogo->package_name()); + { + ret->push_back('"'); + ret->append(package != NULL + ? package->pkgpath_symbol() + : gogo->pkgpath_symbol()); + ret->push_back('"'); + } + ret->append(package != NULL + ? package->package_name() + : gogo->package_name()); ret->push_back('.'); } if (this->in_function_ != NULL) diff -r 2ab3869bedd1 libgo/go/encoding/xml/marshal_test.go --- a/libgo/go/encoding/xml/marshal_test.go Thu Jun 07 01:05:45 2012 -0700 +++ b/libgo/go/encoding/xml/marshal_test.go Tue Jun 12 11:47:12 2012 -0700 @@ -726,7 +726,7 @@ }, { Value: map[*Ship]bool{nil: false}, - Err: "xml: unsupported type: map[*encoding/xml.Ship]bool", + Err: "xml: unsupported type: map[*xml.Ship]bool", Kind: reflect.Map, }, { diff -r 2ab3869bedd1 libgo/go/html/template/escape_test.go --- a/libgo/go/html/template/escape_test.go Thu Jun 07 01:05:45 2012 -0700 +++ b/libgo/go/html/template/escape_test.go Tue Jun 12 11:47:12 2012 -0700 @@ -226,7 +226,7 @@ { "badMarshaler", `<button onclick='alert(1/{{.B}}in numbers)'>`, - `<button onclick='alert(1/ /* json: error calling MarshalJSON for type *html/template.badMarshaler: invalid character 'f' looking for beginning of object key string */null in numbers)'>`, + `<button onclick='alert(1/ /* json: error calling MarshalJSON for type *template.badMarshaler: invalid character 'f' looking for beginning of object key string */null in numbers)'>`, }, { "jsMarshaler", diff -r 2ab3869bedd1 libgo/go/reflect/type.go --- a/libgo/go/reflect/type.go Thu Jun 07 01:05:45 2012 -0700 +++ b/libgo/go/reflect/type.go Tue Jun 12 11:47:12 2012 -0700 @@ -83,6 +83,9 @@ // compare the Types directly. String() string + // Used internally by gccgo--the string retaining quoting. + rawString() string + // Kind returns the specific kind of this type. Kind() Kind @@ -432,7 +435,24 @@ return canonicalize(t) } -func (t *commonType) String() string { return *t.string } +func (t *commonType) rawString() string { return *t.string } + +func (t *commonType) String() string { + // For gccgo, strip out quoted strings. + s := *t.string + var q bool + r := make([]byte, len(s)) + j := 0 + for i := 0; i < len(s); i++ { + if s[i] == '"' { + q = !q + } else if !q { + r[j] = s[i] + j++ + } + } + return string(r[:j]) +} func (t *commonType) Size() uintptr { return t.size } @@ -942,7 +962,7 @@ u := t.uncommon() var s string if u == nil || u.PkgPath() == "" { - s = t.String() + s = t.rawString() } else { s = u.PkgPath() + "." + u.Name() }