Hi, We fail here to create a typename_type on dependent using declarations. In fact, facing a USING_DECLs on spotted places, either we want to strip non-dependent USING_DECLs or we want to create a typename_type. The attached patch simply propagates the change made to fix c++/14258 through strip_using_decl.
Bootstrapped & Tested x86_64, OK for trunk and 4.8 / 4.7 ? (even if it is not technically a regression, it is very close to c++/14258 which is anounced fixed in 4.7) 2014-01-25 Fabien Chene <fab...@gcc.gnu.org> PR c++/37140 * parser.c (cp_parser_nonclass_name): Call strip_using_decl and move the code handling dependent USING_DECLs... * name-lookup.c (strip_using_decl): ...Here. 2014-01-25 Fabien Chene <fab...@gcc.gnu.org> PR c++/37140 * g++.dg/template/using27.C: New. * g++.dg/template/using28.C: New. * g++.dg/template/using29.C: New. -- Fabien
Index: gcc/testsuite/g++.dg/template/using28.C =================================================================== --- gcc/testsuite/g++.dg/template/using28.C (revision 0) +++ gcc/testsuite/g++.dg/template/using28.C (revision 0) @@ -0,0 +1,17 @@ +// PR c++/37140 + +struct C +{ + static const int block_size = 1; +}; + +template <typename T> struct A { + typedef C type; +}; + +template <typename T> struct B : public A<T> { + using typename A<T>::type; + static const int block_size = type::block_size; +}; + +template class B<int>; Index: gcc/testsuite/g++.dg/template/using27.C =================================================================== --- gcc/testsuite/g++.dg/template/using27.C (revision 0) +++ gcc/testsuite/g++.dg/template/using27.C (revision 0) @@ -0,0 +1,30 @@ +// PR c++/37140 + +struct X +{ + typedef int nested_type; +}; + +template <class T> +struct A +{ + typedef X type; +}; + +template <class T> +struct B : A<T> +{ + using typename A<T>::type; + typename type::nested_type x; +}; + +template <class T> +struct C : B<T> +{ + using typename B<T>::type; + typename type::nested_type y; +}; + +template class A<int>; +template class B<int>; +template class C<int>; Index: gcc/testsuite/g++.dg/template/using29.C =================================================================== --- gcc/testsuite/g++.dg/template/using29.C (revision 0) +++ gcc/testsuite/g++.dg/template/using29.C (revision 0) @@ -0,0 +1,21 @@ +// PR c++/58047 + +template <int N> +struct print_arg { }; + +struct const_holder { + static const int CONSTANT = 42; +}; + +template <typename T> +struct identity { + typedef T type; +}; + +template <class T> +struct test_case : public identity<T> { + using typename identity<T>::type; + print_arg<type::CONSTANT> printer; +}; + +template struct test_case<const_holder>; Index: gcc/cp/name-lookup.c =================================================================== --- gcc/cp/name-lookup.c (revision 207035) +++ gcc/cp/name-lookup.c (working copy) @@ -406,7 +406,8 @@ pop_bindings_and_leave_scope (void) leave_scope (); } -/* Strip non dependent using declarations. */ +/* Strip non dependent using declarations. If DECL is dependent, + surreptitiously create a typename_type and return it. */ tree strip_using_decl (tree decl) @@ -414,8 +415,29 @@ strip_using_decl (tree decl) if (decl == NULL_TREE) return NULL_TREE; + if (TREE_CODE (decl) != USING_DECL) + return decl; + + if (DECL_DEPENDENT_P (decl) && USING_DECL_TYPENAME_P (decl)) + { + /* We have found a type introduced by a using + declaration at class scope that refers to a dependent + type. + + using typename :: [opt] nested-name-specifier unqualified-id ; + */ + decl = make_typename_type (TREE_TYPE (decl), + DECL_NAME (decl), + typename_type, tf_error); + if (decl != error_mark_node) + decl = TYPE_NAME (decl); + + return decl; + } + while (TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl)) decl = USING_DECL_DECLS (decl); + return decl; } Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 207035) +++ gcc/cp/parser.c (working copy) @@ -14824,25 +14824,7 @@ cp_parser_nonclass_name (cp_parser* pars /* Look up the type-name. */ type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location); - if (TREE_CODE (type_decl) == USING_DECL) - { - if (!DECL_DEPENDENT_P (type_decl)) - type_decl = strip_using_decl (type_decl); - else if (USING_DECL_TYPENAME_P (type_decl)) - { - /* We have found a type introduced by a using - declaration at class scope that refers to a dependent - type. - - using typename :: [opt] nested-name-specifier unqualified-id ; - */ - type_decl = make_typename_type (TREE_TYPE (type_decl), - DECL_NAME (type_decl), - typename_type, tf_error); - if (type_decl != error_mark_node) - type_decl = TYPE_NAME (type_decl); - } - } + type_decl = strip_using_decl (type_decl); if (TREE_CODE (type_decl) != TYPE_DECL && (objc_is_id (identifier) || objc_is_class_name (identifier)))