From 64bec774eda78d9b51cc1210eb9ce9c24c878016 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 21 Nov 2014 16:35:09 -0500 Subject: [PATCH] re PR c++/63942 (constexpr conflicts with previous declaration) PR c++/63942 * name-lookup.c (supplement_binding_1): Override a mangling alias. * mangle.c (implicit_alias_p, remove_implicit_alias): New. (mangle_decl): Avoid creating conflicting alias with -fabi-compat-version=0, too. * cp-tree.h: Adjust. From-SVN: r217950 --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/mangle.c | 27 ++++++++++++++++++++++++-- gcc/cp/name-lookup.c | 6 ++++++ gcc/testsuite/g++.dg/cpp0x/nullptr32.C | 21 ++++++++++++++++++++ 5 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/nullptr32.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 652ec9ca63e..b1d9cea6ed7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2014-11-21 Jason Merrill + PR c++/63942 + * name-lookup.c (supplement_binding_1): Override a mangling alias. + * mangle.c (maybe_remove_implicit_alias): New. + (mangle_decl): Always avoid creating conflicting alias. + * cp-tree.h: Adjust. + PR c++/63849 * mangle.c (decl_mangling_context): Use template_type_parameter_p. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b3781ab7a72..428d559a3d8 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6299,6 +6299,7 @@ extern tree add_exception_specifier (tree, tree, int); extern tree merge_exception_specifiers (tree, tree); /* in mangle.c */ +extern bool maybe_remove_implicit_alias (tree); extern void init_mangle (void); extern void mangle_decl (tree); extern const char *mangle_type_string (tree); diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 9f0d9d8ed77..a24466994f0 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -3428,6 +3428,28 @@ get_mangled_id (tree decl) return targetm.mangle_decl_assembler_name (decl, id); } +/* If DECL is a mangling alias, remove it from the symbol table and return + true; otherwise return false. */ + +bool +maybe_remove_implicit_alias (tree decl) +{ + if (DECL_P (decl) && DECL_ARTIFICIAL (decl) + && DECL_IGNORED_P (decl) + && (TREE_CODE (decl) == FUNCTION_DECL + || (TREE_CODE (decl) == VAR_DECL + && TREE_STATIC (decl)))) + { + symtab_node *n = symtab_node::get (decl); + if (n && n->cpp_implicit_alias) + { + n->remove(); + return true; + } + } + return false; +} + /* Create an identifier for the external mangled name of DECL. */ void @@ -3491,8 +3513,9 @@ mangle_decl (const tree decl) } #ifdef ASM_OUTPUT_DEF - if (flag_abi_compat_version != 0 - && IDENTIFIER_GLOBAL_VALUE (id2)) + /* If there's a declaration already using this mangled name, + don't create a compatibility alias that conflicts. */ + if (IDENTIFIER_GLOBAL_VALUE (id2)) return; tree alias = make_alias_for (decl, id2); diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index d42bcac9219..71b359eeca8 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -561,6 +561,12 @@ supplement_binding_1 (cxx_binding *binding, tree decl) region to refer only to the namespace to which it already refers. */ ok = false; + else if (maybe_remove_implicit_alias (bval)) + { + /* There was a mangling compatibility alias using this mangled name, + but now we have a real decl that wants to use it instead. */ + binding->value = decl; + } else { diagnose_name_conflict (decl, bval); diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr32.C b/gcc/testsuite/g++.dg/cpp0x/nullptr32.C new file mode 100644 index 00000000000..a1e6710fd84 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr32.C @@ -0,0 +1,21 @@ +// PR c++/63942 +// A mangling alias for the first constructor was conflicting with the second. +// { dg-do compile { target c++11 } } +// { dg-options "-fno-inline" } + +int i; +template struct A +{ + A(const T&) { i = 42; } + A(const A&) { i = 36; } +}; + +typedef A An; + +int main() +{ + An a (nullptr); + if (i != 42) __builtin_abort(); + An a2 (a); + if (i != 36) __builtin_abort(); +} -- 2.30.2