This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix bug 1509
- To: gcc-patches at gcc dot gnu dot org
- Subject: [C++ PATCH] Fix bug 1509
- From: Nathan Sidwell <nathan at codesourcery dot com>
- Date: Mon, 15 Jan 2001 09:33:45 +0000
- Organization: Codesourcery LLC
Hi,
I've installed this obvious patch for 1509 where we ICE'd on a non-type
template parm. We only checked nontype parms when declaring the template,
we'd not check the deduced T on something like
template <typename T, T v> ....
I commonized that code.
built & tested on i686-pc-linux-gnu
nathan
--
Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2001-01-12 Nathan Sidwell <nathan@codesourcery.com>
* pt.c (check_nontype_parm): New function.
(process_template_parm): Use it.
(convert_template_argument): Use it.
(convert_nontype_argument, RECORD_TYPE): Assert it's a ptr to
member.
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v
retrieving revision 1.503
diff -c -3 -p -r1.503 pt.c
*** pt.c 2001/01/11 11:45:01 1.503
--- pt.c 2001/01/14 16:49:15
*************** static tree for_each_template_parm_r PAR
*** 169,174 ****
--- 169,175 ----
static tree instantiate_clone PARAMS ((tree, tree));
static tree copy_default_args_to_explicit_spec_1 PARAMS ((tree, tree));
static void copy_default_args_to_explicit_spec PARAMS ((tree));
+ static int check_nontype_parm PARAMS ((tree, int));
/* Called once to initialize pt.c. */
*************** process_template_parm (list, next)
*** 1933,1953 ****
/* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1;
! if (IS_AGGR_TYPE (TREE_TYPE (parm))
! && TREE_CODE (TREE_TYPE (parm)) != TEMPLATE_TYPE_PARM
! && TREE_CODE (TREE_TYPE (parm)) != TYPENAME_TYPE)
! {
! cp_error ("`%#T' is not a valid type for a template constant parameter",
! TREE_TYPE (parm));
! if (DECL_NAME (parm) == NULL_TREE)
! error (" a template type parameter must begin with `class' or `typename'");
! TREE_TYPE (parm) = void_type_node;
! }
! else if (pedantic
! && (TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE
! || TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE))
! cp_pedwarn ("`%T' is not a valid type for a template constant parameter",
! TREE_TYPE (parm));
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
DECL_INITIAL (parm) = DECL_INITIAL (decl)
= build_template_parm_index (idx, processing_template_decl,
--- 1934,1941 ----
/* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1;
! if (check_nontype_parm (TREE_TYPE (parm), 1))
! TREE_TYPE (parm) = void_type_node;
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
DECL_INITIAL (parm) = DECL_INITIAL (decl)
= build_template_parm_index (idx, processing_template_decl,
*************** convert_nontype_argument (type, expr)
*** 3134,3146 ****
case RECORD_TYPE:
{
! if (!TYPE_PTRMEMFUNC_P (type))
! /* This handles templates like
! template<class T, T t> void f();
! when T is substituted with any class. The second template
! parameter becomes invalid and the template candidate is
! rejected. */
! return error_mark_node;
/* For a non-type template-parameter of type pointer to member
function, no conversions apply. If the template-argument
--- 3124,3130 ----
case RECORD_TYPE:
{
! my_friendly_assert (TYPE_PTRMEMFUNC_P (type), 20010112);
/* For a non-type template-parameter of type pointer to member
function, no conversions apply. If the template-argument
*************** convert_template_argument (parm, arg, ar
*** 3435,3440 ****
--- 3419,3427 ----
{
tree t = tsubst (TREE_TYPE (parm), args, complain, in_decl);
+ if (check_nontype_parm (t, complain))
+ return error_mark_node;
+
if (processing_template_decl)
arg = maybe_fold_nontype_arg (arg);
*************** tree
*** 10315,10318 ****
--- 10302,10337 ----
current_instantiation ()
{
return current_tinst_level;
+ }
+
+ /* [temp.param] Check that template non-type parm TYPE is of an allowable
+ type. Return zero for ok, non-zero for disallowed. If COMPLAIN is
+ non-zero, then complain. */
+
+ static int
+ check_nontype_parm (type, complain)
+ tree type;
+ int complain;
+ {
+ if (INTEGRAL_TYPE_P (type))
+ return 0;
+ else if (POINTER_TYPE_P (type))
+ return 0;
+ else if (TYPE_PTRMEM_P (type))
+ return 0;
+ else if (TYPE_PTRMEMFUNC_P (type))
+ return 0;
+ else if (!pedantic && TREE_CODE (type) == REAL_TYPE)
+ return 0; /* GNU extension */
+ else if (!pedantic && TREE_CODE (type) == COMPLEX_TYPE)
+ return 0; /* GNU extension */
+ else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ return 0;
+ else if (TREE_CODE (type) == TYPENAME_TYPE)
+ return 0;
+
+ if (complain)
+ cp_error ("`%#T' is not a valid type for a template constant parameter",
+ type);
+ return 1;
}
// Build don't link:
// Copyright (C) 2000 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 10 Jan 2001 <nathan@codesourcery.com>
// Bug 1509. We ICE'd on trying to coerce a non-type template parm
// that wouldn't.
template<class T>
struct A {
typedef int F();
};
template<class T, A<T>::F f>
struct B {
static int g() { return f(); };
};
int f() { return 0; };
int main() {
return B<int,&f>::g(); // ERROR - could not convert arg
};