We hit the bug in this testcase because build_over_call replaces the constructor with a dispatcher function, and then build_aggr_init_expr doesn't recognize it as a constructor.
Messing with the DECL_NAME of the dispatcher seems messy, but copying the DECL_CXX_CONSTRUCTOR_P flag is easy. So we can change the test in build_aggr_init_expr, or change the definition of DECL_CONSTRUCTOR_P. I lean toward the latter as more uniform, but not strongly. Do you have an opinion?
commit 8bc517d8acbb898aa7776c420e2ba65cc5f8d31a Author: Jason Merrill <ja...@redhat.com> Date: Fri Feb 16 16:53:47 2018 -0500 PR c++/83911 - ICE with multiversioned constructor. * cp-tree.h (DECL_CONSTRUCTOR_P): Use DECL_CXX_CONSTRUCTOR_P. (DECL_DESTRUCTOR_P): Use DECL_CXX_DESTRUCTOR_P. * mangle.c (write_unqualified_name): Check IDENTIFIER_[CD]TOR_P. * call.c (get_function_version_dispatcher): Copy DECL_CXX_CONSTRUCTOR_P. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 7c93c6d8290..35496528aa6 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7489,7 +7489,10 @@ get_function_version_dispatcher (tree fn) } retrofit_lang_decl (dispatcher_decl); - gcc_assert (dispatcher_decl != NULL); + + if (DECL_CXX_CONSTRUCTOR_P (fn)) + DECL_CXX_CONSTRUCTOR_P (dispatcher_decl) = true; + return dispatcher_decl; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9038d677b2d..77ae2e94187 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2695,7 +2695,7 @@ struct GTY(()) lang_decl { /* For FUNCTION_DECLs and TEMPLATE_DECLs: nonzero means that this function is a constructor. */ #define DECL_CONSTRUCTOR_P(NODE) \ - IDENTIFIER_CTOR_P (DECL_NAME (NODE)) + DECL_CXX_CONSTRUCTOR_P (STRIP_TEMPLATE (NODE)) /* Nonzero if NODE (a FUNCTION_DECL) is a constructor for a complete object. */ @@ -2724,7 +2724,7 @@ struct GTY(()) lang_decl { /* Nonzero if NODE (a FUNCTION_DECL or TEMPLATE_DECL) is a destructor. */ #define DECL_DESTRUCTOR_P(NODE) \ - IDENTIFIER_DTOR_P (DECL_NAME (NODE)) + DECL_CXX_DESTRUCTOR_P (STRIP_TEMPLATE (NODE)) /* Nonzero if NODE (a FUNCTION_DECL) is a destructor, but not the specialized in-charge constructor, in-charge deleting constructor, diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 94c4bed2848..ecd4eb066d4 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1351,9 +1351,9 @@ write_unqualified_name (tree decl) else if (DECL_DECLARES_FUNCTION_P (decl)) { found = true; - if (DECL_CONSTRUCTOR_P (decl)) + if (IDENTIFIER_CTOR_P (DECL_NAME (decl))) write_special_name_constructor (decl); - else if (DECL_DESTRUCTOR_P (decl)) + else if (IDENTIFIER_DTOR_P (DECL_NAME (decl))) write_special_name_destructor (decl); else if (DECL_CONV_FN_P (decl)) { diff --git a/gcc/testsuite/g++.dg/ext/mv27.C b/gcc/testsuite/g++.dg/ext/mv27.C new file mode 100644 index 00000000000..443a54be765 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/mv27.C @@ -0,0 +1,18 @@ +// PR c++/83911 +// { dg-do compile { target i?86-*-* x86_64-*-* } } +// { dg-require-ifunc "" } + +class SimdFloat +{ +public: + __attribute__ ((target ("default"))) + SimdFloat(float x) {} + + __attribute__ ((target ("avx2"))) + SimdFloat(float x) {} +}; + +SimdFloat foo() +{ + return 1; +}