The problem here is that we aren't properly checking what's been passed to __underlying_type. It needs an enum, which the code checks, but that enum mustn't be incomplete, otherwise we crash because ENUM_UNDERLYING_TYPE will be null until the definition of the enum is completed by finish_enum.
Bootstrapped/regtested on x86_64-linux, ok for trunk? 2017-02-22 Marek Polacek <pola...@redhat.com> PR c++/79657 * semantics.c (finish_underlying_type): Bail out for incomplete enums. * g++.dg/ext/underlying_type12.C: New test. diff --git gcc/cp/semantics.c gcc/cp/semantics.c index 6ba7c13..67f8b92 100644 --- gcc/cp/semantics.c +++ gcc/cp/semantics.c @@ -3838,7 +3838,8 @@ finish_underlying_type (tree type) return underlying_type; } - complete_type (type); + if (!complete_type_or_else (type, NULL_TREE)) + return error_mark_node; if (TREE_CODE (type) != ENUMERAL_TYPE) { diff --git gcc/testsuite/g++.dg/ext/underlying_type12.C gcc/testsuite/g++.dg/ext/underlying_type12.C index e69de29..050ecf2 100644 --- gcc/testsuite/g++.dg/ext/underlying_type12.C +++ gcc/testsuite/g++.dg/ext/underlying_type12.C @@ -0,0 +1,6 @@ +// PR c++/79657 +// { dg-do compile { target c++11 } } + +enum A { x }; +enum B { a = (__underlying_type (A)) 1 }; +enum C { b = (__underlying_type (C)) 1 }; // { dg-error "incomplete" } Marek