The first patch fixes the warning about mangled name changes for some current testcases to associate a mangled name with the right ABI version; they had been swapped around.
The second patch changes that warning to be given when mangling external references, not just when mangling a definition. The third patch simplifies some code dealing with ABI tags by factoring out the code for looking up ABI tags on a decl or type. Tested x86_64-pc-linux-gnu, applying to trunk.
commit 07a860836dfff34c8d4d891ffdd2da84d5cb77bb Author: Jason Merrill <ja...@redhat.com> Date: Fri Jul 29 22:30:01 2016 -0400 * mangle.c (mangle_decl): Fix mangled name change warning. diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index d5b26d6..e0bbfc9 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1,4 +1,4 @@ -/* Name mangling for the 3.0 C++ ABI. +/* Name mangling for the 3.0 -*- C++ -*- ABI. Copyright (C) 2000-2016 Free Software Foundation, Inc. Written by Alex Samuel <sam...@codesourcery.com> @@ -3732,6 +3732,7 @@ mangle_decl (const tree decl) id2 = mangle_decl_string (decl); id2 = targetm.mangle_decl_assembler_name (decl, id2); } + flag_abi_version = save_ver; if (id2 == id) /* OK. */; @@ -3740,8 +3741,8 @@ mangle_decl (const tree decl) warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi, "the mangled name of %qD changed between " "-fabi-version=%d (%D) and -fabi-version=%d (%D)", - G.entity, save_ver, id2, - warn_abi_version, id); + G.entity, warn_abi_version, id2, + save_ver, id); else warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi, "the mangled name of %qD changes between " diff --git a/gcc/testsuite/g++.dg/abi/Wabi-2-3.C b/gcc/testsuite/g++.dg/abi/Wabi-2-3.C index 5aadf5d..96a0f22 100644 --- a/gcc/testsuite/g++.dg/abi/Wabi-2-3.C +++ b/gcc/testsuite/g++.dg/abi/Wabi-2-3.C @@ -12,5 +12,5 @@ template <int &> struct S { }; // Expect the diagnostic to reference the ABI version specified via // -fabi-version=3 and the ABI version specified via -Wabi=2. -void foo (S<N>) { } // { dg-warning "the mangled name of .void foo\\(S<N>\\). changed between -fabi-version=3 \\(_Z3foo1SILZ1NEE\\) and -fabi-version=2 \\(_Z3foo1SIL_Z1NEE\\)" } +void foo (S<N>) { } // { dg-warning "the mangled name of .void foo\\(S<N>\\). changed between -fabi-version=2 \\(_Z3foo1SILZ1NEE\\) and -fabi-version=3 \\(_Z3foo1SIL_Z1NEE\\)" } diff --git a/gcc/testsuite/g++.dg/abi/Wabi-3-2.C b/gcc/testsuite/g++.dg/abi/Wabi-3-2.C index c65e3b6..46bd713 100644 --- a/gcc/testsuite/g++.dg/abi/Wabi-3-2.C +++ b/gcc/testsuite/g++.dg/abi/Wabi-3-2.C @@ -12,5 +12,5 @@ template <int &> struct S { }; // Expect the diagnostic to reference the ABI version specified via // -fabi-version=2 and the ABI version specified via -Wabi=3. -void foo (S<N>) { } // { dg-warning "the mangled name of .void foo\\(S<N>\\). changed between -fabi-version=2 \\(_Z3foo1SIL_Z1NEE\\) and -fabi-version=3 \\(_Z3foo1SILZ1NEE\\)" } +void foo (S<N>) { } // { dg-warning "the mangled name of .void foo\\(S<N>\\). changes between -fabi-version=2 \\(_Z3foo1SILZ1NEE\\) and -fabi-version=3 \\(_Z3foo1SIL_Z1NEE\\)" }
commit 136f83de4c5c144e1671f823a3cf0a397ef28e22 Author: Jason Merrill <ja...@redhat.com> Date: Fri Jul 29 22:09:28 2016 -0400 Warn about mangled name change even if DECL_REALLY_EXTERN. * mangle.c (mangle_decl): Warn about mangled name change even if DECL_REALLY_EXTERN. diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 29be7fd..d1bf3ef 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -3700,50 +3700,52 @@ mangle_decl (const tree decl) SET_DECL_ASSEMBLER_NAME (decl, id); if (id != DECL_NAME (decl) - && !DECL_REALLY_EXTERN (decl) /* Don't do this for a fake symbol we aren't going to emit anyway. */ && TREE_CODE (decl) != TYPE_DECL && !DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)) { - bool set = false; + int save_ver = flag_abi_version; + tree id2 = NULL_TREE; - /* Check IDENTIFIER_GLOBAL_VALUE before setting to avoid redundant - errors from multiple definitions. */ - tree d = IDENTIFIER_GLOBAL_VALUE (id); - if (!d || decl_implicit_alias_p (d)) + if (!DECL_REALLY_EXTERN (decl)) { - set = true; - SET_IDENTIFIER_GLOBAL_VALUE (id, decl); - } + bool set = false; - if (!G.need_abi_warning) - return; + /* Check IDENTIFIER_GLOBAL_VALUE before setting to avoid redundant + errors from multiple definitions. */ + tree d = IDENTIFIER_GLOBAL_VALUE (id); + if (!d || decl_implicit_alias_p (d)) + { + set = true; + SET_IDENTIFIER_GLOBAL_VALUE (id, decl); + } - /* If the mangling will change in the future, emit an alias with the - future mangled name for forward-compatibility. */ - int save_ver; - tree id2; + if (!G.need_abi_warning) + return; - if (!set) - { - SET_IDENTIFIER_GLOBAL_VALUE (id, decl); - inform (DECL_SOURCE_LOCATION (decl), "a later -fabi-version= (or " - "=0) avoids this error with a change in mangling"); - } + /* If the mangling will change in the future, emit an alias with the + future mangled name for forward-compatibility. */ + if (!set) + { + SET_IDENTIFIER_GLOBAL_VALUE (id, decl); + inform (DECL_SOURCE_LOCATION (decl), "a later -fabi-version= (or " + "=0) avoids this error with a change in mangling"); + } - save_ver = flag_abi_version; + flag_abi_version = flag_abi_compat_version; + id2 = mangle_decl_string (decl); + id2 = targetm.mangle_decl_assembler_name (decl, id2); + flag_abi_version = save_ver; - flag_abi_version = flag_abi_compat_version; - id2 = mangle_decl_string (decl); - id2 = targetm.mangle_decl_assembler_name (decl, id2); - - if (id2 != id) - note_mangling_alias (decl, id2); + if (id2 != id) + note_mangling_alias (decl, id2); + } if (warn_abi) { - if (flag_abi_compat_version != warn_abi_version) + if (flag_abi_compat_version != warn_abi_version + || id2 == NULL_TREE) { flag_abi_version = warn_abi_version; id2 = mangle_decl_string (decl);
commit e11fe61691789dc6e9f3cade319c8c50adf4eeb7 Author: Jason Merrill <ja...@redhat.com> Date: Fri Jul 29 22:30:07 2016 -0400 * mangle.c (get_abi_tags): New. (find_substitution, write_unqualified_name, write_abi_tags) (maybe_check_abi_tags): Use it. diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index e0bbfc9..29be7fd 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -447,6 +447,30 @@ is_std_substitution (const tree node, == subst_identifiers[index])); } +/* Return the ABI tags (the TREE_VALUE of the "abi_tag" attribute entry) for T, + which can be a decl or type. */ + +static tree +get_abi_tags (tree t) +{ + if (!t || TREE_CODE (t) == NAMESPACE_DECL) + return NULL_TREE; + + if (DECL_P (t) && DECL_DECLARES_TYPE_P (t)) + t = TREE_TYPE (t); + + tree attrs; + if (TYPE_P (t)) + attrs = TYPE_ATTRIBUTES (t); + else + attrs = DECL_ATTRIBUTES (t); + + tree tags = lookup_attribute ("abi_tag", attrs); + if (tags) + tags = TREE_VALUE (tags); + return tags; +} + /* Helper function for find_substitution. Returns nonzero if NODE, which may be a decl or a CLASS_TYPE, is the template-id ::std::identifier<char>, where identifier is @@ -601,7 +625,7 @@ find_substitution (tree node) tree tags = NULL_TREE; if (OVERLOAD_TYPE_P (node) || DECL_CLASS_TEMPLATE_P (node)) - tags = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (type)); + tags = get_abi_tags (type); /* Now check the list of available substitutions for this mangling operation. */ if (!abbr || tags) for (i = 0; i < size; ++i) @@ -667,7 +691,7 @@ unmangled_name_p (const tree decl) return false; /* Declarations with ABI tags are mangled. */ - if (lookup_attribute ("abi_tag", DECL_ATTRIBUTES (decl))) + if (get_abi_tags (decl)) return false; /* The names of non-static global variables aren't mangled. */ @@ -1314,12 +1338,7 @@ write_unqualified_name (tree decl) decl = DECL_TEMPLATE_RESULT (tmpl); /* Don't crash on an unbound class template. */ if (decl && TREE_CODE (decl) != NAMESPACE_DECL) - { - tree attrs = (TREE_CODE (decl) == TYPE_DECL - ? TYPE_ATTRIBUTES (TREE_TYPE (decl)) - : DECL_ATTRIBUTES (decl)); - write_abi_tags (lookup_attribute ("abi_tag", attrs)); - } + write_abi_tags (get_abi_tags (decl)); } /* Write the unqualified-name for a conversion operator to TYPE. */ @@ -1371,8 +1390,6 @@ write_abi_tags (tree tags) if (tags == NULL_TREE) return; - tags = TREE_VALUE (tags); - vec<tree, va_gc> * vec = make_tree_vector(); for (tree t = tags; t; t = TREE_CHAIN (t)) @@ -4027,16 +4044,12 @@ maybe_check_abi_tags (tree t, tree for_decl) if (DECL_ASSEMBLER_NAME_SET_P (t)) return; - tree attr = lookup_attribute ("abi_tag", DECL_ATTRIBUTES (t)); - tree oldtags = NULL_TREE; - if (attr) - oldtags = TREE_VALUE (attr); + tree oldtags = get_abi_tags (t); mangle_decl (t); - if (!attr) - attr = lookup_attribute ("abi_tag", DECL_ATTRIBUTES (t)); - if (attr && TREE_VALUE (attr) != oldtags + tree newtags = get_abi_tags (t); + if (newtags && newtags != oldtags && abi_version_crosses (10)) { if (for_decl)