In this testcase, we have multiple declarations of malloc.  The one in
the "system header" has a non-throwing exception specification, while
the one in user code has none.  By default we allow this mismatch when
the old declaration is in a system header, but we mean to prefer the
type of the user declaration.  In this testcase that was breaking
because the old declaration had attributes added by the compiler, and
the code at the bottom of merge_types decided to throw away the work
earlier in the function to build up a new FUNCTION_TYPE in t1 because
t2 had the right attributes.  This is a C++17 regression.

Fixed by limiting the attribute checking code to the case where we
aren't building up a new type in t1.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 0249b02abba1c309eaf118a0ef158a32f6833cb3
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon Apr 2 17:49:06 2018 -0400

    Fix noexcept merging with system headers.
    
            * typeck.c (merge_types): Limit matching attribute shortcut to
            the default case.

diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d454c6c5a29..e33f2c34c7f 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -899,14 +899,14 @@ merge_types (tree t1, tree t2)
       return t1;
 
     default:;
+      if (attribute_list_equal (TYPE_ATTRIBUTES (t1), attributes))
+	return t1;
+      else if (attribute_list_equal (TYPE_ATTRIBUTES (t2), attributes))
+	return t2;
+      break;
     }
 
-  if (attribute_list_equal (TYPE_ATTRIBUTES (t1), attributes))
-    return t1;
-  else if (attribute_list_equal (TYPE_ATTRIBUTES (t2), attributes))
-    return t2;
-  else
-    return cp_build_type_attribute_variant (t1, attributes);
+  return cp_build_type_attribute_variant (t1, attributes);
 }
 
 /* Return the ARRAY_TYPE type without its domain.  */
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type19.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type19.C
new file mode 100644
index 00000000000..571c426aa67
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type19.C
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++11 } }
+
+#include "noexcept-type19.h"
+
+extern "C" void *malloc (size_t);
+
+template<class T> void f(T*);
+
+void *g(size_t);
+
+int main()
+{
+  f<decltype(malloc)>(g);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type19.h b/gcc/testsuite/g++.dg/cpp1z/noexcept-type19.h
new file mode 100644
index 00000000000..33a29357e7f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type19.h
@@ -0,0 +1,4 @@
+#pragma GCC system_header
+
+typedef decltype(sizeof(0)) size_t;
+extern "C" void *malloc (size_t) throw();

Reply via email to