Re: C++ PATCH for c++/63942 (mangling compat alias problems)

2014-11-24 Thread Jason Merrill

On 11/21/2014 04:32 PM, Jason Merrill wrote:

In this testcase, the wrong old mangling for one constructor matches the
correct mangling for the other constructor, and the testcase was failing
to compile as a result.  But compatibility aliases should not be treated
as conflicting with real declarations; they should be discarded.


We also need to avoid creating the alias declarations if they aren't 
going to become symbol aliases.


Tested x86_64-pc-linux-gnu, applying to trunk.


commit 58386ef80f1ab5d7ec49dc96b23e365e5750a3a0
Author: Jason Merrill 
Date:   Sun Nov 23 22:23:44 2014 -0500

	PR c++/63942
	* mangle.c (mangle_decl): If we aren't going to create a symbol
	alias, don't build the alias DECL either.

diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index a244669..71a6e3b 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -3518,6 +3518,12 @@ mangle_decl (const tree decl)
   if (IDENTIFIER_GLOBAL_VALUE (id2))
 	return;
 
+  struct cgraph_node *n = NULL;
+  if (TREE_CODE (decl) == FUNCTION_DECL
+	  && !(n = cgraph_node::get (decl)))
+	/* Don't create an alias to an unreferenced function.  */
+	return;
+
   tree alias = make_alias_for (decl, id2);
   SET_IDENTIFIER_GLOBAL_VALUE (id2, alias);
   DECL_IGNORED_P (alias) = 1;
@@ -3526,11 +3532,7 @@ mangle_decl (const tree decl)
   if (vague_linkage_p (decl))
 	DECL_WEAK (alias) = 1;
   if (TREE_CODE (decl) == FUNCTION_DECL)
-	{
-	  /* Don't create an alias to an unreferenced function.  */
-	  if (struct cgraph_node *n = cgraph_node::get (decl))
-	n->create_same_body_alias (alias, decl);
-	}
+	n->create_same_body_alias (alias, decl);
   else
 	varpool_node::create_extra_name_alias (alias, decl);
 #endif


C++ PATCH for c++/63942 (mangling compat alias problems)

2014-11-21 Thread Jason Merrill
In this testcase, the wrong old mangling for one constructor matches the 
correct mangling for the other constructor, and the testcase was failing 
to compile as a result.  But compatibility aliases should not be treated 
as conflicting with real declarations; they should be discarded.


Tested x86_64-pc-linux-gnu, applying to trunk.
commit 60d85d4330713bb62a6830be0016b5b9accf0911
Author: Jason Merrill 
Date:   Fri Nov 21 13:05:02 2014 -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.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b3781ab..428d559 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 9f0d9d8..a244669 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 d42bcac..71b359e 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 000..a1e6710
--- /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();
+}