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();