From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5237 invoked by alias); 22 Aug 2009 15:05:21 -0000 Received: (qmail 5102 invoked by uid 22791); 22 Aug 2009 15:05:20 -0000 X-SWARE-Spam-Status: No, hits=-1.3 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_16,J_CHICKENPOX_65 X-Spam-Check-By: sourceware.org Received: from mta4.srv.hcvlny.cv.net (HELO mta4.srv.hcvlny.cv.net) (167.206.4.199) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 22 Aug 2009 15:05:12 +0000 Received: from [192.168.1.10] (ool-44c60ac6.dyn.optonline.net [68.198.10.198]) by mta4.srv.hcvlny.cv.net (Sun Java System Messaging Server 6.2-8.04 (built Feb 28 2007)) with ESMTP id <0KOS004AY9WLCH00@mta4.srv.hcvlny.cv.net>; Sat, 22 Aug 2009 11:05:10 -0400 (EDT) Date: Sat, 22 Aug 2009 16:33:00 -0000 From: Jerry Quinn Subject: Re: enable-build-with-cxx bootstrap compare broken by r149964 In-reply-to: <4A8F1EE7.9030001@redhat.com> To: Richard Henderson Cc: Dave Korn , Jason Merrill , "gcc@gcc.gnu.org" , Pedro =?ISO-8859-1?Q?Lamar=E3o?= , "gcc-patches@gcc.gnu.org" Message-id: <1250953509.4312.1029.camel@cerberus.qb5.org> MIME-version: 1.0 Content-type: text/plain Content-transfer-encoding: 7BIT References: <1250345548.19163.155.camel@cerberus.qb5.org> <4A89BA99.1000900@redhat.com> <1250563251.4312.6.camel@cerberus.qb5.org> <4A8ACC37.8020200@redhat.com> <1250743680.4312.38.camel@cerberus.qb5.org> <4A8D218D.20209@gmail.com> <1250771594.4312.40.camel@cerberus.qb5.org> <4A8D4A1A.4080902@gmail.com> <1250775261.4312.48.camel@cerberus.qb5.org> <4A8D5C3B.7010604@gmail.com> <1250890624.4312.54.camel@cerberus.qb5.org> <4A8F1EE7.9030001@redhat.com> Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org X-SW-Source: 2009-08/txt/msg00408.txt.bz2 On Fri, 2009-08-21 at 15:25 -0700, Richard Henderson wrote: > On 08/21/2009 02:37 PM, Jerry Quinn wrote: > > OK, I've gotten almost this far and can bootstrap (the asterisk is > > actually not the very first char and I have to figure that out). > > However, in the referenced test case, both typeinfos are apparently > > merged, thus returning the same pointer for their name strings, so > > pointer comparison still wouldn't work. > > > > Therefore, I guess I'll need to do the following: > > > >> You might also need to take steps to ensure that the typeinfo gets emitted > >> as non-COMDAT with local symbols, so that each object does indeed end up with > >> its own separate copy. > > > > Where should I look to do this? > > First thing you should do is make sure you're emitting a VAR_DECL > with the string contents, rather than a STRING_CST constant. The > later will be merged within an object file within the compiler. > > Second, make sure the VAR_DECL for the typeinfo is no DECL_ONE_ONLY. > That flag sets up COMDAT sections, which will be merged by the linker. It looks like I"ve got a working patch now. It bootstraps and has no reqressions from make check, nor from make check in the libstdc++ directory. Any thoughts? Jerry 2009-08-22 Jerry Quinn * name-lookup.c (get_anonymous_namespace_name): Use fixed namespace "cxx_anon_ns". * mangle.c (write_nested_name): Insert '*' to mark fake anonymous namespace. (get_mangled_string_length): New function. (mangle_type_string_for_rtti): Put '*' at start of mangled namestring. * rtti.c (tinfo_base_init): Disable DECL_COMDAT for fake anonymous namespaces. 2009-08-22 Jerry Quinn * libsupc++/tinfo.cc (typeinfo::operator==): Compare names starting with '*' by pointer. * libsupc++/tinfo2.cc (typeinfo::before): Same. * libsupc++/typeinfo (typeinfo::operator==): Same. * libsupc++/typeinfo (typeinfo::before): Same. Index: gcc/cp/rtti.c =================================================================== --- gcc/cp/rtti.c (revision 151008) +++ gcc/cp/rtti.c (working copy) @@ -862,9 +862,12 @@ DECL_TINFO_P (name_decl) = 1; set_linkage_according_to_type (target, name_decl); import_export_decl (name_decl); + /* Disable DECL_COMDAT if we have an anonymous namspace here. */ + if (TREE_STRING_POINTER (name_string)[0] == '*') + DECL_COMDAT (name_decl) = 0; DECL_INITIAL (name_decl) = name_string; mark_used (name_decl); pushdecl_top_level_and_finish (name_decl, name_string); 2009-08-21 Jakub Jelinek PR c++/41131 Index: gcc/cp/mangle.c =================================================================== --- gcc/cp/mangle.c (revision 151008) +++ gcc/cp/mangle.c (working copy) @@ -935,8 +935,14 @@ /* No, just use */ write_prefix (DECL_CONTEXT (decl)); if (needs_fake_anon (decl)) - /* Pretend this static function is in an anonymous namespace. */ - write_source_name (get_anonymous_namespace_name ()); + { + /* Add a * to mark fake anonymous namespaces in typeinfos as + compare-by-pointer. This * is used to put another one at the + front when done building the string. */ + write_char ('*'); + /* Pretend this static function is in an anonymous namespace. */ + write_source_name (get_anonymous_namespace_name ()); + } write_unqualified_name (decl); } write_char ('E'); @@ -2755,6 +2761,14 @@ name_base = obstack_alloc (&name_obstack, 0); } +/* Returns the length of the mangled string array. */ + +static inline int +get_mangled_string_length (void) +{ + return obstack_object_size (mangle_obstack); +} + /* Done with mangling. If WARN is true, and the name of G.entity will be mangled differently in a future version of the ABI, issue a warning. */ @@ -2851,13 +2865,20 @@ mangle_type_string_for_rtti (const tree type) { const char *result; + int result_len; start_mangling (type); /* Mangle in a fake anonymous namespace if necessary. */ fake_anon_scope = true; + /* Place marker to be removed if not dealing with a nested name. */ + write_char('*'); write_type (type); fake_anon_scope = false; + result_len = get_mangled_string_length (); result = finish_mangling (/*warn=*/false); + /* Remove the marker if not needed. */ + if (!strchr(result + 1, '*')) + result++; if (DEBUG_MANGLE) fprintf (stderr, "mangle_type_string = '%s'\n\n", result); return result; Index: gcc/cp/name-lookup.c =================================================================== --- gcc/cp/name-lookup.c (revision 151008) +++ gcc/cp/name-lookup.c (working copy) @@ -69,7 +69,7 @@ { /* The anonymous namespace has to have a unique name if typeinfo objects are being compared by name. */ - anonymous_namespace_name = get_file_function_name ("N"); + anonymous_namespace_name = get_identifier ("cxx_anon_ns"); } return anonymous_namespace_name; } Index: libstdc++-v3/libsupc++/tinfo2.cc =================================================================== --- libstdc++-v3/libsupc++/tinfo2.cc (revision 151008) +++ libstdc++-v3/libsupc++/tinfo2.cc (working copy) @@ -37,7 +37,9 @@ #if __GXX_MERGED_TYPEINFO_NAMES return name () < arg.name (); #else - return __builtin_strcmp (name (), arg.name ()) < 0; + return (name ()[0] == '*' && arg.name()[0] == '*') + ? name () < arg.name () + : __builtin_strcmp (name (), arg.name ()) < 0; #endif } Index: libstdc++-v3/libsupc++/typeinfo =================================================================== --- libstdc++-v3/libsupc++/typeinfo (revision 151008) +++ libstdc++-v3/libsupc++/typeinfo (working copy) @@ -110,12 +110,15 @@ // we can run into cases where type_info names aren't merged, // so we still need to do string comparison. bool before(const type_info& __arg) const - { return __builtin_strcmp (__name, __arg.__name) < 0; } + { return (__name[0] == '*' && __arg.__name[0] == '*') + ? __name < __arg.__name + : __builtin_strcmp (__name, __arg.__name) < 0; } bool operator==(const type_info& __arg) const { return ((__name == __arg.__name) - || __builtin_strcmp (__name, __arg.__name) == 0); + || (__name[0] != '*' && __arg.__name[0] != '*' && + __builtin_strcmp (__name, __arg.__name) == 0)); } #else // On some targets we can rely on type_info's NTBS being unique, Index: libstdc++-v3/libsupc++/tinfo.cc =================================================================== --- libstdc++-v3/libsupc++/tinfo.cc (revision 151008) +++ libstdc++-v3/libsupc++/tinfo.cc (working copy) @@ -41,7 +41,9 @@ #if __GXX_MERGED_TYPEINFO_NAMES return name () == arg.name (); #else - return (&arg == this) || (__builtin_strcmp (name (), arg.name ()) == 0); + return (&arg == this) + || (name ()[0] != '*' && arg.name ()[0] != '*' + && (__builtin_strcmp (name (), arg.name ()) == 0)); #endif }