Someone found a sneaky way to use an anonymous union type as a template argument. That seems to me like it ought to be ill-formed, but this patch is a simple enough way to make this testcase work.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 4f51a88ed61f69fd483a46b93f0ba9cff352324a Author: Jason Merrill <ja...@redhat.com> Date: Mon Jun 18 21:20:29 2018 -0400 PR c++/86192 - ICE with anonymous union passed to template. * pt.c (tsubst_expr) [DECL_EXPR]: Handle an anonymous union type used to declare a named variable. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1ecc6fb373d..3386385b3f8 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16678,7 +16678,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, do. */ if (VAR_P (decl)) DECL_TEMPLATE_INSTANTIATED (decl) = 1; - if (VAR_P (decl) + if (VAR_P (decl) && !DECL_NAME (decl) && ANON_AGGR_TYPE_P (TREE_TYPE (decl))) /* Anonymous aggregates are a special case. */ finish_anon_union (decl); diff --git a/gcc/testsuite/g++.dg/template/anonunion3.C b/gcc/testsuite/g++.dg/template/anonunion3.C new file mode 100644 index 00000000000..1ac8165fa78 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/anonunion3.C @@ -0,0 +1,16 @@ +// PR c++/86192 +// { dg-do compile { target c++11 } } + +extern "C" int printf (const char *, ...); + +template<typename T> static char const * f(T *t) { + T u(*t); + u.x = "hello world"; + printf("%s\n", u.x); + return "initialized"; +} + +int main() { + union { char const *x = f(this); }; + printf("%s\n", x); +}