This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/13294] [3.4 Regression] namespace associations vs. specializations
- From: "jason at redhat dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 13 Apr 2004 18:36:50 -0000
- Subject: [Bug c++/13294] [3.4 Regression] namespace associations vs. specializations
- References: <20031204043712.13294.bkoz@gcc.gnu.org>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- 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