func DeclaredInMain() {
 }
 
+type C struct {
+}
+
+func F() *C {
+       return nil
+}
+
 func main() {
        defer depBase.ImplementedInAsm()
        // This code below causes various go.itab.* symbols to be generated in
        reflect.TypeOf(os.Stdout).Elem()
        runtime.GC()
        depBase.V = depBase.F() + 1
+
+       var c *C
+       if reflect.TypeOf(F).Out(0) != reflect.TypeOf(c) {
+               panic("bad reflection results, see golang.org/issue/18252")
+       }
 }
 
                Fatalf("itabname(%v, %v)", t, itype)
        }
        s := Pkglookup(t.tconv(FmtLeft)+","+itype.tconv(FmtLeft), itabpkg)
-       Linksym(s).Set(obj.AttrLocal, true)
        if s.Def == nil {
                n := newname(s)
                n.Type = Types[TUINT8]
                // }
                o := dsymptr(i.sym, 0, dtypesym(i.itype), 0)
                o = dsymptr(i.sym, o, dtypesym(i.t), 0)
-               o += Widthptr + 8                      // skip link/bad/unused fields
+               o += Widthptr + 8                      // skip link/bad/inhash fields
                o += len(imethods(i.itype)) * Widthptr // skip fun method pointers
                // at runtime the itab will contain pointers to types, other itabs and
                // method functions. None are allocated on heap, so we can use obj.NOPTR.
-               ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR|obj.LOCAL))
+               ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR))
 
                ilink := Pkglookup(i.t.tconv(FmtLeft)+","+i.itype.tconv(FmtLeft), itablinkpkg)
                dsymptr(ilink, 0, i.sym, 0)
-               ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA|obj.LOCAL))
+               ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA))
        }
 
        // process ptabs
 
                throw("invalid itab locking")
        }
        h := itabhash(inter, typ)
-       if m == hash[h] {
-               println("duplicate itab for", typ.string(), "and", inter.typ.string())
-               throw("duplicate itabs")
-       }
        m.link = hash[h]
+       m.inhash = 1
        atomicstorep(unsafe.Pointer(&hash[h]), unsafe.Pointer(m))
 }
 
        lock(&ifaceLock)
        for _, md := range activeModules() {
                for _, i := range md.itablinks {
-                       additab(i, true, false)
+                       // itablinks is a slice of pointers to the itabs used in this
+                       // module. A given itab may be used in more than one module
+                       // and thanks to the way global symbol resolution works, the
+                       // pointed-to itab may already have been inserted into the
+                       // global 'hash'.
+                       if i.inhash == 0 {
+                               additab(i, true, false)
+                       }
                }
        }
        unlock(&ifaceLock)