Hi again,

On 08/22/2012 05:13 PM, Jason Merrill wrote:
On 08/22/2012 10:55 AM, Paolo Carlini wrote:
. thus, in short, what is happening is that, for this testcase:

class B
{
protected:
   enum E { E1, E2, E3 };
};

class D : private B
{
public:
   using B::E;

private:
   enum E { };
};

we parse the new declaration enum E { }; and we reach
supplement_binding_1 before setting the underlying type of the new
declaration. The old declaration is fine, would not ICE
dependent_type_p.
So with your change would we still ICE if D were a template?  It seems
like what we should be checking for is null underlying type.

In the meanwhile, I tried to actually write a patch doing away with the processing_template_decl check but failed.

The problem is: if, as in the below patch "3", I don't call dependent_type_p when the underlying type is null and the check overall fails, I see regressions for testcases like forw_enum7.C, because when templates are involved we actually want to call dependent_type_p and return true; if, as in the below "4", a null underlying type means that overall the check succeeds, then we don't error out anymore for the new testcases, we don't ICE but we don't have the diagnostics either.

I see the outcome of these experiments as an indication that we want the processing_template_decl check...

Paolo.

//////////////////////

Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c    (revision 190590)
+++ cp/name-lookup.c    (working copy)
@@ -433,20 +433,25 @@ supplement_binding_1 (cxx_binding *binding, tree d
   bool ok = true;
   tree target_bval = strip_using_decl (bval);
   tree target_decl = strip_using_decl (decl);
+  tree target_bval_type = TREE_TYPE (target_bval);
+  tree target_decl_type = TREE_TYPE (target_decl);
 
-  if (TREE_CODE (target_decl) == TYPE_DECL && DECL_ARTIFICIAL (target_decl)
+  if (TREE_CODE (target_decl) == TYPE_DECL
+      && DECL_ARTIFICIAL (target_decl)
       && target_decl != target_bval
       && (TREE_CODE (target_bval) != TYPE_DECL
          /* We allow pushing an enum multiple times in a class
             template in order to handle late matching of underlying
             type on an opaque-enum-declaration followed by an
             enum-specifier.  */
-         || (TREE_CODE (TREE_TYPE (target_decl)) == ENUMERAL_TYPE
-             && TREE_CODE (TREE_TYPE (target_bval)) == ENUMERAL_TYPE
-             && (dependent_type_p (ENUM_UNDERLYING_TYPE
-                                   (TREE_TYPE (target_decl)))
-                 || dependent_type_p (ENUM_UNDERLYING_TYPE
-                                      (TREE_TYPE (target_bval)))))))
+         || (TREE_CODE (target_decl_type) == ENUMERAL_TYPE
+             && TREE_CODE (target_bval_type) == ENUMERAL_TYPE
+             && ((ENUM_UNDERLYING_TYPE (target_decl_type)
+                  && dependent_type_p (ENUM_UNDERLYING_TYPE
+                                       (target_decl_type)))
+                 || (ENUM_UNDERLYING_TYPE (target_bval_type)
+                     && dependent_type_p (ENUM_UNDERLYING_TYPE
+                                          (target_bval_type)))))))
     /* The new name is the type name.  */
     binding->type = decl;
   else if (/* TARGET_BVAL is null when push_class_level_binding moves
@@ -469,8 +474,7 @@ supplement_binding_1 (cxx_binding *binding, tree d
           && DECL_ARTIFICIAL (target_bval)
           && target_decl != target_bval
           && (TREE_CODE (target_decl) != TYPE_DECL
-              || same_type_p (TREE_TYPE (target_decl),
-                              TREE_TYPE (target_bval))))
+              || same_type_p (target_decl_type, target_bval_type)))
     {
       /* The old binding was a type name.  It was placed in
         VALUE field because it was thought, at the point it was
@@ -485,11 +489,11 @@ supplement_binding_1 (cxx_binding *binding, tree d
           && TREE_CODE (target_decl) == TYPE_DECL
           && DECL_NAME (target_decl) == DECL_NAME (target_bval)
           && binding->scope->kind != sk_class
-          && (same_type_p (TREE_TYPE (target_decl), TREE_TYPE (target_bval))
+          && (same_type_p (target_decl_type, target_bval_type)
               /* If either type involves template parameters, we must
                  wait until instantiation.  */
-              || uses_template_parms (TREE_TYPE (target_decl))
-              || uses_template_parms (TREE_TYPE (target_bval))))
+              || uses_template_parms (target_decl_type)
+              || uses_template_parms (target_bval_type)))
     /* We have two typedef-names, both naming the same type to have
        the same name.  In general, this is OK because of:
 
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c    (revision 190590)
+++ cp/name-lookup.c    (working copy)
@@ -433,20 +433,25 @@ supplement_binding_1 (cxx_binding *binding, tree d
   bool ok = true;
   tree target_bval = strip_using_decl (bval);
   tree target_decl = strip_using_decl (decl);
+  tree target_bval_type = TREE_TYPE (target_bval);
+  tree target_decl_type = TREE_TYPE (target_decl);
 
-  if (TREE_CODE (target_decl) == TYPE_DECL && DECL_ARTIFICIAL (target_decl)
+  if (TREE_CODE (target_decl) == TYPE_DECL
+      && DECL_ARTIFICIAL (target_decl)
       && target_decl != target_bval
       && (TREE_CODE (target_bval) != TYPE_DECL
          /* We allow pushing an enum multiple times in a class
             template in order to handle late matching of underlying
             type on an opaque-enum-declaration followed by an
             enum-specifier.  */
-         || (TREE_CODE (TREE_TYPE (target_decl)) == ENUMERAL_TYPE
-             && TREE_CODE (TREE_TYPE (target_bval)) == ENUMERAL_TYPE
-             && (dependent_type_p (ENUM_UNDERLYING_TYPE
-                                   (TREE_TYPE (target_decl)))
-                 || dependent_type_p (ENUM_UNDERLYING_TYPE
-                                      (TREE_TYPE (target_bval)))))))
+         || (TREE_CODE (target_decl_type) == ENUMERAL_TYPE
+             && TREE_CODE (target_bval_type) == ENUMERAL_TYPE
+             && ((! ENUM_UNDERLYING_TYPE (target_decl_type)
+                  || dependent_type_p (ENUM_UNDERLYING_TYPE
+                                       (target_decl_type)))
+                 || (! ENUM_UNDERLYING_TYPE (target_bval_type)
+                     || dependent_type_p (ENUM_UNDERLYING_TYPE
+                                          (target_bval_type)))))))
     /* The new name is the type name.  */
     binding->type = decl;
   else if (/* TARGET_BVAL is null when push_class_level_binding moves
@@ -469,8 +474,7 @@ supplement_binding_1 (cxx_binding *binding, tree d
           && DECL_ARTIFICIAL (target_bval)
           && target_decl != target_bval
           && (TREE_CODE (target_decl) != TYPE_DECL
-              || same_type_p (TREE_TYPE (target_decl),
-                              TREE_TYPE (target_bval))))
+              || same_type_p (target_decl_type, target_bval_type)))
     {
       /* The old binding was a type name.  It was placed in
         VALUE field because it was thought, at the point it was
@@ -485,11 +489,11 @@ supplement_binding_1 (cxx_binding *binding, tree d
           && TREE_CODE (target_decl) == TYPE_DECL
           && DECL_NAME (target_decl) == DECL_NAME (target_bval)
           && binding->scope->kind != sk_class
-          && (same_type_p (TREE_TYPE (target_decl), TREE_TYPE (target_bval))
+          && (same_type_p (target_decl_type, target_bval_type)
               /* If either type involves template parameters, we must
                  wait until instantiation.  */
-              || uses_template_parms (TREE_TYPE (target_decl))
-              || uses_template_parms (TREE_TYPE (target_bval))))
+              || uses_template_parms (target_decl_type)
+              || uses_template_parms (target_bval_type)))
     /* We have two typedef-names, both naming the same type to have
        the same name.  In general, this is OK because of:
 

Reply via email to