re PR c++/63942 (constexpr conflicts with previous declaration)
authorJason Merrill <jason@redhat.com>
Fri, 21 Nov 2014 21:35:09 +0000 (16:35 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 21 Nov 2014 21:35:09 +0000 (16:35 -0500)
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
gcc/cp/cp-tree.h
gcc/cp/mangle.c
gcc/cp/name-lookup.c
gcc/testsuite/g++.dg/cpp0x/nullptr32.C [new file with mode: 0644]

index 652ec9ca63e7f3f409dea1ca06288fa6ff20f5b7..b1d9cea6ed727ea1b8b48b26b342ea6f47d790c0 100644 (file)
@@ -1,5 +1,11 @@
 2014-11-21  Jason Merrill  <jason@redhat.com>
 
+       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.
 
index b3781ab7a72aee25dc7ee40696d0f108b6903bcb..428d559a3d8339534c9ff784d5222cb9614101c3 100644 (file)
@@ -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);
index 9f0d9d8ed778c75feee697780bea0504c54ed221..a24466994f0dd1d504a78ff4ad9758934f1a59aa 100644 (file)
@@ -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);
index d42bcac92197b3669e255126eac690132ea0e80d..71b359eeca887ba83d360f5a937e74d0f6f4f03c 100644 (file)
@@ -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 (file)
index 0000000..a1e6710
--- /dev/null
@@ -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 <class T> struct A
+{
+  A(const T&) { i = 42; }
+  A(const A&) { i = 36; }
+};
+
+typedef A<decltype(nullptr)> An;
+
+int main()
+{
+  An a (nullptr);
+  if (i != 42) __builtin_abort();
+  An a2 (a);
+  if (i != 36) __builtin_abort();
+}