This is the mail archive of the gcc-patches@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]

[C++ PATCH] [PR3671] Disallow conversion between enumeration types in template deduction


Hello,

[temp.arg.nontype]/5 says:

----------- QUOTE -----------
The following conversions are performed on each expression used as a non-type
template-argument. If a non-type template-argument cannot be converted to the
type of the corresponding template-parameter then the program is ill-formed.

— for a non-type template-parameter of integral or enumeration type, integral
promotions (4.5) and integral conversions (4.7) are applied
[...]
----------- UNQUOTE -----------

[conv.integral]/1 says that "An rvalue of an enumeration type can be converted
to an rvalue of an integer type", but does not allow conversion between two
different enumeration types. We are currently neglecting to disallow this, and
as a result any variable/constant of enumeration type can be used as an
argument for a template parameter of enumeration type, even if the type
mismatches. See the testcase for an example of this.

Fixed thus. Tested on i686-pc-linux-gnu with no new regressions, OK for
mainline?

Giovanni Bajo



cp/
        PR c++/3671
        * pt.c (convert_nontype_argument): Disallow conversions between
different
        enumeration types.

testsuite/
        PR c++/3671
        * g++.dg/template/spec15.C: New test.


Index: pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.876
diff -c -3 -p -r1.876 pt.c
*** pt.c 26 Jun 2004 21:11:19 -0000 1.876
--- pt.c 5 Jul 2004 17:27:20 -0000
*************** convert_nontype_argument (tree type, tre
*** 3323,3329 ****
           conversions (_conv.integral_) are applied.  */
        if (!INTEGRAL_TYPE_P (expr_type))
   return error_mark_node;
!
        /* It's safe to call digest_init in this case; we know we're
    just converting one integral constant expression to another.  */
        expr = digest_init (type, expr, (tree*) 0);
--- 3323,3336 ----
           conversions (_conv.integral_) are applied.  */
        if (!INTEGRAL_TYPE_P (expr_type))
   return error_mark_node;
!
!       /* [conv.integral] does not allow conversions between two different
!   enumeration types.  */
!       if (TREE_CODE (type) == ENUMERAL_TYPE
!    && TREE_CODE (expr_type) == ENUMERAL_TYPE
!    && !same_type_ignoring_top_level_qualifiers_p (type, expr_type))
!    return error_mark_node;
!
        /* It's safe to call digest_init in this case; we know we're
    just converting one integral constant expression to another.  */
        expr = digest_init (type, expr, (tree*) 0);



// { dg-do compile }
// Origin: <weissr at informatik dot uni-tuebingen dot de>
// PR c++/3671: Non-type enum parameters must not be converted

enum T1 {a};
enum T2 {b};

struct Y {
  template <T1 i> void foo() {}
  template <T2 i> void foo() {}
};

struct Z {
  template <T1 i> void foo() {}
};

template void Y::foo<b> ();
template void Z::foo<b> ();   // { dg-error "" }



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