This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
PATCH for Re: foo.cc:15: Internal compiler error.
- To: njs3 at doc dot ic dot ac dot uk
- Subject: PATCH for Re: foo.cc:15: Internal compiler error.
- From: Mark Mitchell <mark at markmitchell dot com>
- Date: Sat, 23 May 1998 16:39:01 -0700
- CC: egcs-bugs at cygnus dot com, Jason Merrill <jason at cygnus dot com>
- References: <E0ydF9K-0003EP-00@oak66.doc.ic.ac.uk>
- Reply-to: mark at markmitchell dot com
> I've been playing around with template specialisation, the following
> code is likely wrong but in any case it causes an internal compiler error:
Here's a fix for your problem. Your code is actually legal:
template <class A*>
void f();
is not a specialization, but a declares an (anonymous) non-type
parameter of type `class A*', and forward-declares `class A'. Would
you believe it?
Jason, is this ok to check in?
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com
1998-05-23 Mark Mitchell <mark@markmitchell.com>
* cp-tree.h (processing_template_parmlist): Declare.
* decl.c (pushtag): Don't call push_template_decl when we
shouldn't.
* pt.c (processing_template_parmlist): New variable.
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS): New macro.
(complete_template_args): Use it.
(add_to_template_args): Likewise.
(innermost_args): Likewise.
(tsubst): Likewise.
(begin_template_parm_list): Use processing_template_parmlist.
(end_template_parm_list): Likewise.
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.74
diff -c -p -r1.74 cp-tree.h
*** cp-tree.h 1998/05/23 02:18:29 1.74
--- cp-tree.h 1998/05/23 23:15:55
*************** extern int comp_template_args
*** 2644,2649 ****
--- 2661,2667 ----
extern int processing_specialization;
extern int processing_explicit_instantiation;
+ extern int processing_template_parmlist;
/* in repo.c */
extern void repo_template_used PROTO((tree));
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.117
diff -c -p -r1.117 decl.c
*** decl.c 1998/05/22 23:13:27 1.117
--- decl.c 1998/05/23 23:16:34
*************** pushtag (name, type, globalize)
*** 2291,2299 ****
friend class S2;
};
! declares S2 to be at global scope. */
! || (processing_template_decl >
! template_class_depth (current_class_type))))
{
d = push_template_decl_real (d, globalize);
/* If the current binding level is the binding level for
--- 2291,2305 ----
friend class S2;
};
! declares S2 to be at global scope. We must be
! careful, however, of the following case:
!
! template <class A*> struct S;
!
! which declares a non-template class `A'. */
! || (!processing_template_parmlist
! && (processing_template_decl >
! template_class_depth (current_class_type)))))
{
d = push_template_decl_real (d, globalize);
/* If the current binding level is the binding level for
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.143
diff -c -p -r1.143 pt.c
*** pt.c 1998/05/23 02:18:31 1.143
--- pt.c 1998/05/23 23:17:28
*************** int minimal_parse_mode;
*** 63,68 ****
--- 63,69 ----
int processing_specialization;
int processing_explicit_instantiation;
+ int processing_template_parmlist;
static int template_header_count;
static tree saved_trees;
*************** static int check_cv_quals_for_unify PROT
*** 115,120 ****
--- 116,129 ----
static tree tsubst_template_arg_vector PROTO((tree, tree));
static void regenerate_decl_from_template PROTO((tree, tree));
+ /* Nonzero if ARGVEC contains multiple levels of template arguments. */
+ #define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \
+ (NODE != NULL_TREE \
+ && TREE_CODE (NODE) == TREE_VEC \
+ && TREE_VEC_LENGTH (NODE) > 0 \
+ && TREE_VEC_ELT (NODE, 0) != NULL_TREE \
+ && TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC)
+
/* Do any processing required when DECL (a member template declaration
using TEMPLATE_PARAMETERS as its innermost parameter list) is
finished. Returns the TEMPLATE_DECL corresponding to DECL, unless
*************** complete_template_args (tmpl, extra_args
*** 388,394 ****
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0);
! if (TREE_CODE (TREE_VEC_ELT (extra_args, 0)) == TREE_VEC)
extra_arg_depth = TREE_VEC_LENGTH (extra_args);
else
extra_arg_depth = 1;
--- 397,403 ----
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0);
! if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (extra_args))
extra_arg_depth = TREE_VEC_LENGTH (extra_args);
else
extra_arg_depth = 1;
*************** complete_template_args (tmpl, extra_args
*** 411,417 ****
TEMPLATE_DECL with DECL_TEMPLATE_INFO. DECL_TI_ARGS is
all the bound template arguments. */
args = DECL_TI_ARGS (tmpl);
! if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
depth = 1;
else
depth = TREE_VEC_LENGTH (args);
--- 420,426 ----
TEMPLATE_DECL with DECL_TEMPLATE_INFO. DECL_TI_ARGS is
all the bound template arguments. */
args = DECL_TI_ARGS (tmpl);
! if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
depth = 1;
else
depth = TREE_VEC_LENGTH (args);
*************** add_to_template_args (args, extra_args)
*** 485,491 ****
{
tree new_args;
! if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
{
new_args = make_tree_vec (2);
TREE_VEC_ELT (new_args, 0) = args;
--- 494,500 ----
{
tree new_args;
! if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
{
new_args = make_tree_vec (2);
TREE_VEC_ELT (new_args, 0) = args;
*************** begin_template_parm_list ()
*** 529,534 ****
--- 538,544 ----
pushlevel (0);
declare_pseudo_global_level ();
++processing_template_decl;
+ ++processing_template_parmlist;
note_template_header (0);
}
*************** end_template_parm_list (parms)
*** 1452,1457 ****
--- 1462,1469 ----
for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
TREE_VEC_ELT (saved_parmlist, nparms) = parm;
+ --processing_template_parmlist;
+
return saved_parmlist;
}
*************** innermost_args (args, is_spec)
*** 3993,3999 ****
tree args;
int is_spec;
{
! if (args != NULL_TREE && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
return TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec);
return args;
}
--- 4005,4011 ----
tree args;
int is_spec;
{
! if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
return TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec);
return args;
}
*************** tsubst (t, args, in_decl)
*** 4189,4196 ****
{
tree arg = NULL_TREE;
! if (TREE_VEC_ELT (args, 0) != NULL_TREE
! && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
{
levels = TREE_VEC_LENGTH (args);
if (level <= levels)
--- 4201,4207 ----
{
tree arg = NULL_TREE;
! if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
{
levels = TREE_VEC_LENGTH (args);
if (level <= levels)
Index: spec18.C
===================================================================
RCS file: spec18.C
diff -N spec18.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- spec18.C Sat May 23 16:34:25 1998
***************
*** 0 ****
--- 1,30 ----
+ // Build don't link:
+
+ template<class A, class B>
+ void foo(const A& a, const B& b)
+ {
+ }
+
+ template<class A, class B>
+ void foo(const A& a, const int& b)
+ {
+ }
+
+ template<class A*, class B>
+ void foo(const A*& a, const B& b)
+ {
+ }
+
+ template<>
+ void foo(const int&, const double&)
+ {
+ }
+
+
+ int
+ main()
+ {
+ foo("98239", 23);
+ foo(232, 1.022);
+ }
+