mangle.c (mangle_type_string_for_rtti): Rename to be clearer.
* mangle.c (mangle_type_string_for_rtti): Rename to be clearer. (needs_fake_anon): New. (write_name): Check it. (write_nested_name): Add a fake anonymous namespace scope if true. * name-lookup.c (get_anonymous_namespace_name): No longer static. * rtti.c, cp-tree.h: Adjust. * libsupc++/typeinfo (__GXX_MERGED_TYPEINFO_NAMES): Default to 0. From-SVN: r149964
This commit is contained in:
parent
db1a8d9889
commit
61e6d522e0
@ -1,3 +1,12 @@
|
|||||||
|
2009-07-22 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* mangle.c (mangle_type_string_for_rtti): Rename to be clearer.
|
||||||
|
(needs_fake_anon): New.
|
||||||
|
(write_name): Check it.
|
||||||
|
(write_nested_name): Add a fake anonymous namespace scope if true.
|
||||||
|
* name-lookup.c (get_anonymous_namespace_name): No longer static.
|
||||||
|
* rtti.c, cp-tree.h: Adjust.
|
||||||
|
|
||||||
2009-07-22 Richard Guenther <rguenther@suse.de>
|
2009-07-22 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
PR c++/40799
|
PR c++/40799
|
||||||
|
@ -4345,6 +4345,7 @@ extern tree type_promotes_to (tree);
|
|||||||
extern tree perform_qualification_conversions (tree, tree);
|
extern tree perform_qualification_conversions (tree, tree);
|
||||||
|
|
||||||
/* in name-lookup.c */
|
/* in name-lookup.c */
|
||||||
|
extern tree get_anonymous_namespace_name (void);
|
||||||
extern tree pushdecl (tree);
|
extern tree pushdecl (tree);
|
||||||
extern tree pushdecl_maybe_friend (tree, bool);
|
extern tree pushdecl_maybe_friend (tree, bool);
|
||||||
extern void maybe_push_cleanup_level (tree);
|
extern void maybe_push_cleanup_level (tree);
|
||||||
@ -5095,7 +5096,7 @@ extern tree merge_exception_specifiers (tree, tree);
|
|||||||
/* in mangle.c */
|
/* in mangle.c */
|
||||||
extern void init_mangle (void);
|
extern void init_mangle (void);
|
||||||
extern void mangle_decl (tree);
|
extern void mangle_decl (tree);
|
||||||
extern const char *mangle_type_string (tree);
|
extern const char *mangle_type_string_for_rtti (tree);
|
||||||
extern tree mangle_typeinfo_for_type (tree);
|
extern tree mangle_typeinfo_for_type (tree);
|
||||||
extern tree mangle_typeinfo_string_for_type (tree);
|
extern tree mangle_typeinfo_string_for_type (tree);
|
||||||
extern tree mangle_vtbl_for_type (tree);
|
extern tree mangle_vtbl_for_type (tree);
|
||||||
|
@ -105,6 +105,10 @@ typedef struct GTY(()) globals {
|
|||||||
|
|
||||||
static GTY (()) globals G;
|
static GTY (()) globals G;
|
||||||
|
|
||||||
|
/* Whether or not to pretend that a static function is in an anonymous
|
||||||
|
namespace. */
|
||||||
|
static bool fake_anon_scope;
|
||||||
|
|
||||||
/* The obstack on which we build mangled names. */
|
/* The obstack on which we build mangled names. */
|
||||||
static struct obstack *mangle_obstack;
|
static struct obstack *mangle_obstack;
|
||||||
|
|
||||||
@ -726,6 +730,20 @@ write_encoding (const tree decl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Since we now use strcmp to compare typeinfos on all targets because of
|
||||||
|
the RTLD_LOCAL problem, we need to munge the typeinfo name used for
|
||||||
|
local classes of static functions to fix g++.dg/abi/local1.C. We do
|
||||||
|
that by pretending that the function is in an anonymous namespace. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
needs_fake_anon (const_tree decl)
|
||||||
|
{
|
||||||
|
/* Pretend there's an anonymous namespace right around a static
|
||||||
|
function if we're mangling for RTTI. */
|
||||||
|
return (fake_anon_scope && !TREE_PUBLIC (decl)
|
||||||
|
&& TREE_CODE (decl) == FUNCTION_DECL);
|
||||||
|
}
|
||||||
|
|
||||||
/* <name> ::= <unscoped-name>
|
/* <name> ::= <unscoped-name>
|
||||||
::= <unscoped-template-name> <template-args>
|
::= <unscoped-template-name> <template-args>
|
||||||
::= <nested-name>
|
::= <nested-name>
|
||||||
@ -749,18 +767,23 @@ write_name (tree decl, const int ignore_local_scope)
|
|||||||
/* In case this is a typedef, fish out the corresponding
|
/* In case this is a typedef, fish out the corresponding
|
||||||
TYPE_DECL for the main variant. */
|
TYPE_DECL for the main variant. */
|
||||||
decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
|
decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
|
||||||
context = TYPE_CONTEXT (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
|
context = CP_TYPE_CONTEXT (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
context = (DECL_CONTEXT (decl) == NULL) ? NULL : CP_DECL_CONTEXT (decl);
|
context = CP_DECL_CONTEXT (decl);
|
||||||
|
|
||||||
|
gcc_assert (context != NULL_TREE);
|
||||||
|
|
||||||
|
/* If we need a fake anonymous namespace, force the nested name path. */
|
||||||
|
if (needs_fake_anon (decl) && context == global_namespace)
|
||||||
|
context = error_mark_node;
|
||||||
|
|
||||||
/* A decl in :: or ::std scope is treated specially. The former is
|
/* A decl in :: or ::std scope is treated specially. The former is
|
||||||
mangled using <unscoped-name> or <unscoped-template-name>, the
|
mangled using <unscoped-name> or <unscoped-template-name>, the
|
||||||
latter with a special substitution. Also, a name that is
|
latter with a special substitution. Also, a name that is
|
||||||
directly in a local function scope is also mangled with
|
directly in a local function scope is also mangled with
|
||||||
<unscoped-name> rather than a full <nested-name>. */
|
<unscoped-name> rather than a full <nested-name>. */
|
||||||
if (context == NULL
|
if (context == global_namespace
|
||||||
|| context == global_namespace
|
|
||||||
|| DECL_NAMESPACE_STD_P (context)
|
|| DECL_NAMESPACE_STD_P (context)
|
||||||
|| (ignore_local_scope && TREE_CODE (context) == FUNCTION_DECL))
|
|| (ignore_local_scope && TREE_CODE (context) == FUNCTION_DECL))
|
||||||
{
|
{
|
||||||
@ -778,6 +801,9 @@ write_name (tree decl, const int ignore_local_scope)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (context == error_mark_node)
|
||||||
|
context = global_namespace;
|
||||||
|
|
||||||
/* Handle local names, unless we asked not to (that is, invoked
|
/* Handle local names, unless we asked not to (that is, invoked
|
||||||
under <local-name>, to handle only the part of the name under
|
under <local-name>, to handle only the part of the name under
|
||||||
the local scope). */
|
the local scope). */
|
||||||
@ -790,10 +816,10 @@ write_name (tree decl, const int ignore_local_scope)
|
|||||||
directly in that function's scope, either decl or one of
|
directly in that function's scope, either decl or one of
|
||||||
its enclosing scopes. */
|
its enclosing scopes. */
|
||||||
tree local_entity = decl;
|
tree local_entity = decl;
|
||||||
while (context != NULL && context != global_namespace)
|
while (context != global_namespace)
|
||||||
{
|
{
|
||||||
/* Make sure we're always dealing with decls. */
|
/* Make sure we're always dealing with decls. */
|
||||||
if (context != NULL && TYPE_P (context))
|
if (TYPE_P (context))
|
||||||
context = TYPE_NAME (context);
|
context = TYPE_NAME (context);
|
||||||
/* Is this a function? */
|
/* Is this a function? */
|
||||||
if (TREE_CODE (context) == FUNCTION_DECL)
|
if (TREE_CODE (context) == FUNCTION_DECL)
|
||||||
@ -837,7 +863,6 @@ write_unscoped_name (const tree decl)
|
|||||||
/* If not, it should be either in the global namespace, or directly
|
/* If not, it should be either in the global namespace, or directly
|
||||||
in a local function scope. */
|
in a local function scope. */
|
||||||
gcc_assert (context == global_namespace
|
gcc_assert (context == global_namespace
|
||||||
|| context == NULL
|
|
||||||
|| TREE_CODE (context) == FUNCTION_DECL);
|
|| TREE_CODE (context) == FUNCTION_DECL);
|
||||||
|
|
||||||
write_unqualified_name (decl);
|
write_unqualified_name (decl);
|
||||||
@ -909,6 +934,9 @@ write_nested_name (const tree decl)
|
|||||||
{
|
{
|
||||||
/* No, just use <prefix> */
|
/* No, just use <prefix> */
|
||||||
write_prefix (DECL_CONTEXT (decl));
|
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 ());
|
||||||
write_unqualified_name (decl);
|
write_unqualified_name (decl);
|
||||||
}
|
}
|
||||||
write_char ('E');
|
write_char ('E');
|
||||||
@ -2817,15 +2845,18 @@ mangle_decl (const tree decl)
|
|||||||
SET_DECL_ASSEMBLER_NAME (decl, id);
|
SET_DECL_ASSEMBLER_NAME (decl, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate the mangled representation of TYPE. */
|
/* Generate the mangled representation of TYPE for the typeinfo name. */
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
mangle_type_string (const tree type)
|
mangle_type_string_for_rtti (const tree type)
|
||||||
{
|
{
|
||||||
const char *result;
|
const char *result;
|
||||||
|
|
||||||
start_mangling (type);
|
start_mangling (type);
|
||||||
|
/* Mangle in a fake anonymous namespace if necessary. */
|
||||||
|
fake_anon_scope = true;
|
||||||
write_type (type);
|
write_type (type);
|
||||||
|
fake_anon_scope = false;
|
||||||
result = finish_mangling (/*warn=*/false);
|
result = finish_mangling (/*warn=*/false);
|
||||||
if (DEBUG_MANGLE)
|
if (DEBUG_MANGLE)
|
||||||
fprintf (stderr, "mangle_type_string = '%s'\n\n", result);
|
fprintf (stderr, "mangle_type_string = '%s'\n\n", result);
|
||||||
|
@ -62,19 +62,14 @@ static GTY(()) tree anonymous_namespace_name;
|
|||||||
|
|
||||||
/* Initialize anonymous_namespace_name if necessary, and return it. */
|
/* Initialize anonymous_namespace_name if necessary, and return it. */
|
||||||
|
|
||||||
static tree
|
tree
|
||||||
get_anonymous_namespace_name(void)
|
get_anonymous_namespace_name (void)
|
||||||
{
|
{
|
||||||
if (!anonymous_namespace_name)
|
if (!anonymous_namespace_name)
|
||||||
{
|
{
|
||||||
/* The anonymous namespace has to have a unique name
|
/* The anonymous namespace has to have a unique name
|
||||||
if typeinfo objects are being compared by name. */
|
if typeinfo objects are being compared by name. */
|
||||||
if (! flag_weak || ! SUPPORTS_ONE_ONLY)
|
anonymous_namespace_name = get_file_function_name ("N");
|
||||||
anonymous_namespace_name = get_file_function_name ("N");
|
|
||||||
else
|
|
||||||
/* The demangler expects anonymous namespaces to be called
|
|
||||||
something starting with '_GLOBAL__N_'. */
|
|
||||||
anonymous_namespace_name = get_identifier ("_GLOBAL__N_1");
|
|
||||||
}
|
}
|
||||||
return anonymous_namespace_name;
|
return anonymous_namespace_name;
|
||||||
}
|
}
|
||||||
|
@ -356,7 +356,7 @@ tinfo_name (tree type)
|
|||||||
const char *name;
|
const char *name;
|
||||||
tree name_string;
|
tree name_string;
|
||||||
|
|
||||||
name = mangle_type_string (type);
|
name = mangle_type_string_for_rtti (type);
|
||||||
name_string = fix_string_type (build_string (strlen (name) + 1, name));
|
name_string = fix_string_type (build_string (strlen (name) + 1, name));
|
||||||
return name_string;
|
return name_string;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2009-07-22 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
* libsupc++/typeinfo (__GXX_MERGED_TYPEINFO_NAMES): Default to 0.
|
||||||
|
|
||||||
2009-07-22 Paolo Carlini <paolo.carlini@oracle.com>
|
2009-07-22 Paolo Carlini <paolo.carlini@oracle.com>
|
||||||
|
|
||||||
* include/std/valarray (valarray<>::operator=(const valarray<>&),
|
* include/std/valarray (valarray<>::operator=(const valarray<>&),
|
||||||
|
@ -43,32 +43,29 @@ namespace __cxxabiv1
|
|||||||
} // namespace __cxxabiv1
|
} // namespace __cxxabiv1
|
||||||
|
|
||||||
// Determine whether typeinfo names for the same type are merged (in which
|
// Determine whether typeinfo names for the same type are merged (in which
|
||||||
// case comparison can just compare pointers) or not (in which case
|
// case comparison can just compare pointers) or not (in which case strings
|
||||||
// strings must be compared and g++.dg/abi/local1.C will fail), and
|
// must be compared), and whether comparison is to be implemented inline or
|
||||||
// whether comparison is to be implemented inline or not. By default we
|
// not. We used to do inline pointer comparison by default if weak symbols
|
||||||
// use inline pointer comparison if weak symbols are available, and
|
// are available, but even with weak symbols sometimes names are not merged
|
||||||
// out-of-line strcmp if not. Out-of-line pointer comparison is used
|
// when objects are loaded with RTLD_LOCAL, so now we always use strcmp by
|
||||||
// where the object files are to be portable to multiple systems, some of
|
// default. For ABI compatibility, we do the strcmp inline if weak symbols
|
||||||
// which may not be able to use pointer comparison, but the particular
|
// are available, and out-of-line if not. Out-of-line pointer comparison
|
||||||
// system for which libstdc++ is being built can use pointer comparison;
|
// is used where the object files are to be portable to multiple systems,
|
||||||
// in particular for most ARM EABI systems, where the ABI specifies
|
// some of which may not be able to use pointer comparison, but the
|
||||||
// out-of-line comparison. Inline strcmp is not currently supported. The
|
// particular system for which libstdc++ is being built can use pointer
|
||||||
// compiler's target configuration can override the defaults by defining
|
// comparison; in particular for most ARM EABI systems, where the ABI
|
||||||
// __GXX_TYPEINFO_EQUALITY_INLINE to 1 or 0 to indicate whether or not
|
// specifies out-of-line comparison. The compiler's target configuration
|
||||||
// comparison is inline, and __GXX_MERGED_TYPEINFO_NAMES to 1 or 0 to
|
// can override the defaults by defining __GXX_TYPEINFO_EQUALITY_INLINE to
|
||||||
// indicate whether or not pointer comparison can be used.
|
// 1 or 0 to indicate whether or not comparison is inline, and
|
||||||
|
// __GXX_MERGED_TYPEINFO_NAMES to 1 or 0 to indicate whether or not pointer
|
||||||
|
// comparison can be used.
|
||||||
|
|
||||||
#ifndef __GXX_MERGED_TYPEINFO_NAMES
|
#ifndef __GXX_MERGED_TYPEINFO_NAMES
|
||||||
#if !__GXX_WEAK__
|
// By default, typeinfo names are not merged.
|
||||||
// If weak symbols are not supported, typeinfo names are not merged.
|
#define __GXX_MERGED_TYPEINFO_NAMES 0
|
||||||
#define __GXX_MERGED_TYPEINFO_NAMES 0
|
|
||||||
#else
|
|
||||||
// On platforms that support weak symbols, typeinfo names are merged.
|
|
||||||
#define __GXX_MERGED_TYPEINFO_NAMES 1
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// By default follow the same rules as for __GXX_MERGED_TYPEINFO_NAMES.
|
// By default follow the old inline rules to avoid ABI changes.
|
||||||
#ifndef __GXX_TYPEINFO_EQUALITY_INLINE
|
#ifndef __GXX_TYPEINFO_EQUALITY_INLINE
|
||||||
#if !__GXX_WEAK__
|
#if !__GXX_WEAK__
|
||||||
#define __GXX_TYPEINFO_EQUALITY_INLINE 0
|
#define __GXX_TYPEINFO_EQUALITY_INLINE 0
|
||||||
@ -100,25 +97,35 @@ namespace std
|
|||||||
{ return __name; }
|
{ return __name; }
|
||||||
|
|
||||||
#if !__GXX_TYPEINFO_EQUALITY_INLINE
|
#if !__GXX_TYPEINFO_EQUALITY_INLINE
|
||||||
bool before(const type_info& __arg) const;
|
|
||||||
|
|
||||||
// In old abi, or when weak symbols are not supported, there can
|
// In old abi, or when weak symbols are not supported, there can
|
||||||
// be multiple instances of a type_info object for one
|
// be multiple instances of a type_info object for one
|
||||||
// type. Uniqueness must use the _name value, not object address.
|
// type. Uniqueness must use the _name value, not object address.
|
||||||
|
bool before(const type_info& __arg) const;
|
||||||
bool operator==(const type_info& __arg) const;
|
bool operator==(const type_info& __arg) const;
|
||||||
#else
|
#else
|
||||||
#if !__GXX_MERGED_TYPEINFO_NAMES
|
#if !__GXX_MERGED_TYPEINFO_NAMES
|
||||||
#error "Inline implementation of type_info comparision requires merging of type_info objects"
|
|
||||||
#endif
|
|
||||||
/** Returns true if @c *this precedes @c __arg in the implementation's
|
/** Returns true if @c *this precedes @c __arg in the implementation's
|
||||||
* collation order. */
|
* collation order. */
|
||||||
// In new abi we can rely on type_info's NTBS being unique,
|
// Even with the new abi, on systems that support dlopen
|
||||||
|
// 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; }
|
||||||
|
|
||||||
|
bool operator==(const type_info& __arg) const
|
||||||
|
{
|
||||||
|
return ((__name == __arg.__name)
|
||||||
|
|| __builtin_strcmp (__name, __arg.__name) == 0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// On some targets we can rely on type_info's NTBS being unique,
|
||||||
// and therefore address comparisons are sufficient.
|
// and therefore address comparisons are sufficient.
|
||||||
bool before(const type_info& __arg) const
|
bool before(const type_info& __arg) const
|
||||||
{ return __name < __arg.__name; }
|
{ return __name < __arg.__name; }
|
||||||
|
|
||||||
bool operator==(const type_info& __arg) const
|
bool operator==(const type_info& __arg) const
|
||||||
{ return __name == __arg.__name; }
|
{ return __name == __arg.__name; }
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
bool operator!=(const type_info& __arg) const
|
bool operator!=(const type_info& __arg) const
|
||||||
{ return !operator==(__arg); }
|
{ return !operator==(__arg); }
|
||||||
|
Loading…
Reference in New Issue
Block a user