diff mbox

[C++] for c++/37140

Message ID CAFH4-dgfeVJJQqsxY2y2Jg7uoCBHAnGWAGeeTqVdUzK4GAXq9Q@mail.gmail.com
State New
Headers show

Commit Message

Fabien Chêne Jan. 31, 2014, 2:07 p.m. UTC
2014-01-28 Jason Merrill <jason@redhat.com>:
> On 01/27/2014 04:28 PM, Fabien Chêne wrote:
>>
>> +  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);
>
>
> Shouldn't the new code be after the while loop?

Actually, as a non-dependent USING_DECL may refer to a dependent one,
that would make sense.
I have failed however to find a testcase where the code above does not
work, probably because as in the example below, a non-dependent
USING_DECL refering to a dependent one implicitly requires the base
class to be parsed before, so that the instanciation can be performed.
Thus, the typename_type is already created.

template <class> struct B
{
  typedef char type;
};

template <class T> struct C : B<T>
{
  using typename B<T>::type;
};

struct D : C<int>
{
  using C<int>::type;
  type z;
};

Anyway, your suggestion makes sense to me, and I have successfully
tested the attached patch on x86_64 linux.


2014-01-31  Fabien Chêne  <fabien@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-31  Fabien Chêne  <fabien@gcc.gnu.org>

        PR c++/37140
        * g++.dg/template/using27.C: New.
        * g++.dg/template/using28.C: New.
        * g++.dg/template/using29.C: New.

Comments

Jason Merrill Jan. 31, 2014, 6:31 p.m. UTC | #1
OK, thanks.

Jason
diff mbox

Patch

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,33 @@ 
+// 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;
+};
+
+struct D : C<int>
+{
+  using C<int>::type;
+  type::nested_type z;
+};
+
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/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/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)
@@ -416,6 +417,23 @@  strip_using_decl (tree decl)
 
   while (TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
     decl = USING_DECL_DECLS (decl);
+
+  if (TREE_CODE (decl) == USING_DECL && 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;
 }
 
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)))