From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7139 invoked by alias); 13 Apr 2004 18:36:52 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 7111 invoked by alias); 13 Apr 2004 18:36:50 -0000 Date: Tue, 13 Apr 2004 18:56:00 -0000 Message-ID: <20040413183650.7110.qmail@sources.redhat.com> From: "jason at redhat dot com" To: gcc-bugs@gcc.gnu.org In-Reply-To: <20031204043712.13294.bkoz@gcc.gnu.org> References: <20031204043712.13294.bkoz@gcc.gnu.org> Reply-To: gcc-bugzilla@gcc.gnu.org Subject: [Bug c++/13294] [3.4 Regression] namespace associations vs. specializations X-Bugzilla-Reason: CC X-SW-Source: 2004-04/txt/msg01093.txt.bz2 List-Id: ------- 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 struct X { typedef T A; }; template typename X::A f(X&); // #1 } namespace B { using namespace A __attribute__((strong)); template<> struct X { typedef int A; }; template<> int f(X&) { } // #2 void f (X&) {} } int main() { B::X 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