This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/13294] [3.4 Regression] namespace associations vs. specializations


------- Additional Comments From jason at redhat dot com  2004-04-13 18:36 -------
Subject: Re:  [3.4 Regression] namespace associations vs.
 specializations

Here is a patch which fixes more cases.  But this still isn't enough to
handle this testcase:

namespace A {
  template<class T> struct X { typedef T A; };
  template<class T> typename X<T>::A f(X<T>&); // #1
}

namespace B {
  using namespace A __attribute__((strong));

  template<> struct X<int> { typedef int A; };
  template<> int f(X<int>&) { }   // #2

  void f (X<int>&) {}
}

int main()
{
  B::X<int> x;
  B::f(x);
}

Doing better would mean intercepting the specialization much earlier.  At
this point, I'm feeling pretty strongly that this is not worth doing, and
that we should revert my earlier patch.

*** cp/pt.c.~1~	2004-04-12 16:03:23.000000000 -0400
--- cp/pt.c	2004-04-12 17:55:53.000000000 -0400
*************** tsubst_enum (tree tag, tree newtag, tree
*** 11439,11444 ****
--- 11454,11615 ----
      = DECL_SOURCE_LOCATION (TYPE_NAME (tag));
  }
  
+ static tree
+ make_spoof_type (tree type)
+ {
+   int is_main = (type == TYPE_MAIN_VARIANT (type));
+   type = copy_node (type);  
+   if (is_main)
+     {
+       TYPE_MAIN_VARIANT (type) = type;
+       TYPE_NAME (type) = copy_node (TYPE_NAME (type));
+     }
+   else
+     {
+       TYPE_MAIN_VARIANT (type) = make_spoof_type (TYPE_MAIN_VARIANT (type));
+       TYPE_NAME (type) = TYPE_NAME (TYPE_MAIN_VARIANT (type));
+     }
+ 
+   return type;
+ }
+ 
+ static tree fake_fn_type (tree, tree);
+ 
+ static tree
+ fake_arg_type (tree tmpl_type, tree spec_type)
+ {
+   tree type = tmpl_type;
+   tree sub;
+   int i;
+ 
+   ++processing_template_decl;
+   i = dependent_type_p (type);
+   --processing_template_decl;
+   if (!i)
+     return type;
+ 
+   switch (TREE_CODE (type))
+     {
+     case POINTER_TYPE:
+     case REFERENCE_TYPE:
+     case ARRAY_TYPE:
+       sub = fake_arg_type (TREE_TYPE (type), TREE_TYPE (spec_type));
+       if (sub != TREE_TYPE (type))
+ 	{
+ 	  type = copy_node (type);
+ 	  TREE_TYPE (type) = sub;
+ 	}
+       break;
+ 
+     case OFFSET_TYPE:
+       {
+ 	tree base = fake_arg_type (TYPE_OFFSET_BASETYPE (type),
+ 				   TYPE_OFFSET_BASETYPE (spec_type));
+ 	sub = fake_arg_type (TREE_TYPE (type), TREE_TYPE (spec_type));
+ 	if (sub != TREE_TYPE (type) || base != TYPE_OFFSET_BASETYPE (type))
+ 	  {
+ 	    type = copy_node (type);
+ 	    TREE_TYPE (type) = sub;
+ 	    TYPE_OFFSET_BASETYPE (type) = base;
+ 	  }
+       }
+       break;
+ 
+     case FUNCTION_TYPE:
+     case METHOD_TYPE:
+       type = fake_fn_type (tmpl_type, spec_type);
+       break;
+ 
+     case TYPENAME_TYPE:
+ #if 0
+       /* FIXME how do I derive the desired context from a resolved type?  */
+       sub = fake_arg_type (TYPE_CONTEXT (type), TYPE_CONTEXT (spec_type));
+       if (sub != TYPE_CONTEXT (type))
+ 	{
+ 	  type = copy_node (type);
+ 	  TYPE_CONTEXT (type) = sub;
+ 	}
+ #endif
+       break;
+ 
+     case RECORD_TYPE:
+       if (TYPE_PTRMEMFUNC_P (type))
+ 	{
+ 	  sub = fake_arg_type (TYPE_PTRMEMFUNC_FN_TYPE (type),
+ 			       TYPE_PTRMEMFUNC_FN_TYPE (spec_type));
+ 	  if (sub != TYPE_PTRMEMFUNC_FN_TYPE (type))
+ 	    type = build_ptrmemfunc_type (sub);
+ 	  break;
+ 	}
+       /* else FALLTHROUGH */
+     case UNION_TYPE:
+     case ENUMERAL_TYPE:
+       if (TYPE_CONTEXT (type) != TYPE_CONTEXT (spec_type))
+ 	{
+ 	  type = copy_node (type);
+ 	  TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_NAME (type))
+ 	    = TYPE_CONTEXT (spec_type);
+ 	}
+       break;
+ 
+     default:
+       break;
+     }
+ 
+   return type;
+ }
+ 
+ /* Subroutine of get_mostly_instantiated_function_type.  If any types
+    in TMPL_ARGS have
+ 
+    FIXME I don't think this will work yet for nested types */
+ 
+ static tree
+ fake_arg_types (tree tmpl_args, tree spec_args)
+ {
+   tree chain;
+   tree type;
+ 
+   if (tmpl_args == NULL_TREE)
+     return NULL_TREE;
+ 
+   chain = fake_arg_types (TREE_CHAIN (tmpl_args), TREE_CHAIN (spec_args));
+   type = fake_arg_type (TREE_VALUE (tmpl_args), TREE_VALUE (spec_args));
+   if (chain != TREE_CHAIN (tmpl_args) || type != TREE_TYPE (tmpl_args))
+     return tree_cons (NULL_TREE, type, chain);
+ 
+   return tmpl_args;
+ }
+ 
+ static tree
+ fake_fn_type (tree tmpl_type, tree spec_type)
+ {
+   tree type = tmpl_type;
+   tree tmpl_args = TYPE_ARG_TYPES (type);
+   tree args = fake_arg_types (tmpl_args, TYPE_ARG_TYPES (spec_type));
+   tree ret = fake_arg_type (TREE_TYPE (type), TREE_TYPE (spec_type));
+   tree tmpl_base, base;
+ 
+   if (TREE_CODE (type) == METHOD_TYPE)
+     {
+       tmpl_base = TYPE_METHOD_BASETYPE (type);
+       base = fake_arg_type (tmpl_base, TYPE_METHOD_BASETYPE (spec_type));
+     }
+   else
+     base = tmpl_base = NULL_TREE;
+ 
+   if (args != tmpl_args || ret != TREE_TYPE (type) || base != tmpl_base)
+     {
+       type = copy_node (type);
+       TYPE_ARG_TYPES (type) = args;
+       TREE_TYPE (type) = ret;
+       if (base)
+ 	TYPE_METHOD_BASETYPE (type) = base;
+     }
+ 
+   return type;
+ }
+ 
  /* DECL is a FUNCTION_DECL that is a template specialization.  Return
     its type -- but without substituting the innermost set of template
     arguments.  So, innermost set of template parameters will appear in
*************** get_mostly_instantiated_function_type (t
*** 11505,11511 ****
        pop_access_scope (decl);
      }
  
!   return fn_type;
  }
  
  /* Return truthvalue if we're processing a template different from
--- 11676,11682 ----
        pop_access_scope (decl);
      }
  
!   return fake_fn_type (fn_type, TREE_TYPE (decl));
  }
  
  /* Return truthvalue if we're processing a template different from


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13294


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]