In this PR, we find ourselves in a curious situation. When parsing this enum:
enum E { x = 1, y = x << 1 }; we process the LSHIFT_EXPR in cp_build_binary_op and call fold_non_dependent_expr on each of the operands. Then fold_non_dependent_expr calls maybe_constant_value which, for CONST_DECL x, sticks 1 of INTEGER_TYPE to the cache. But, as explained in finish_enum_value_list: /* [dcl.enum]: Following the closing brace of an enum-specifier, each enumerator has the type of its enumeration. Prior to the closing brace, the type of each enumerator is the type of its initializing value. */ the type of CONST_DECL x will be different after the whole enumerator-specifier has been parsed. This discrepancy can cause problems down the line, as seen in the testcase. (It's standard_conversion that says that integer -> unscoped enum conversion is bad.) That's why I think we shouldn't put CONST_DECLs into the cache while parsing an enum. I feel uneasy about the new check, but I couldn't find anything better; TYPE_BEING_DEFINED is for classes only, and COMPLETE_TYPE_P won't work here. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2016-01-18 Marek Polacek <pola...@redhat.com> PR c++/68586 * constexpr.c (maybe_constant_value): Don't put enumerators into the cv_cache while parsing an enumerator-list. * g++.dg/cpp0x/enum30.C: New test. diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c index 6ab4696..d52005b 100644 --- gcc/cp/constexpr.c +++ gcc/cp/constexpr.c @@ -4022,7 +4022,13 @@ maybe_constant_value (tree t, tree decl) if (!ret) { ret = maybe_constant_value_1 (t, decl); - cv_cache.put (t, ret); + /* While parsing an enumerator-list, the type of each enumerator + is the type of its initializing value. After the parsing has + been done, it will have the type of its enumeration. And this + discrepancy could get us in trouble later. */ + if (TREE_CODE (t) != CONST_DECL + || TREE_TYPE (t) == DECL_CONTEXT (t)) + cv_cache.put (t, ret); } return ret; } diff --git gcc/testsuite/g++.dg/cpp0x/enum30.C gcc/testsuite/g++.dg/cpp0x/enum30.C index e69de29..b9bdfd4 100644 --- gcc/testsuite/g++.dg/cpp0x/enum30.C +++ gcc/testsuite/g++.dg/cpp0x/enum30.C @@ -0,0 +1,14 @@ +// PR c++/68586 +// { dg-do compile { target c++11 } } + +enum E { x = 1, y = x << 1 }; +template<E> struct A {}; +A<x> a; + +enum E2 : int { x2 = 1, y2 = x2 << 1 }; +template<E2> struct A2 {}; +A2<x2> a2; + +enum class E3 { x3 = 1, y3 = x3 << 1 }; +template<E3> struct A3 {}; +A3<E3::x3> a3; Marek