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 <[email protected]>
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 <[email protected]>
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)))