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] |

*From*: Mark Mitchell <mark at codesourcery dot com>*To*: libstdc++ at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org*Cc*: jason at redhat dot com, nathan at codesourcery dot com, ncm at codesourcery dot com*Date*: Sun, 29 May 2005 13:06:46 -0700*Subject*: Problems with PR 21210*Reply-to*: mark at codesourcery dot com

PR 21210 is a complaint that G++ 4.0 has stopped allowing conversions from integers to "__complex__ float". This is a perfectly reasonable complaint, as in C99 such conversions are permitted, so if we are going to support __complex__ in C++ we should have the same semantics. Besides the breakage noted in the PR, other things that do not work -- but should -- are pseudo-destrutors for __complex__ types and implicit conversions from __complex__ types to their real-subparts, as these conversions are permitted in C99. The right fix, from a C++ language point of view, is to treat conversions to __complex__ types from other types as standard conversions, if the conversion could be made to the type used for the components of the complex type. Furthermore, __complex__ types should be treated as "arithmetic" types. All that works just fine -- except that we run into problems with: complex<double> d(3); The libstdc++ std::complex templates contain a non-standard constructor: complex(__complex__ double); in addition to the standard: complex(double = 0.0, double = 0.0); So, we get an overload ambiguity; converting to double is no better than converting to __complex__ double. I really don't like the idea of creating a new class of conversions that is worse than a standard conversion, but better than a user-defined conversion, for interactions with complex types. From a language-design point of view, we really should be treating __complex__ types as an "arithmetic" type. Removing the extra libstdc++ constructor is not ideal, because then __complex__ double can still be converted to complex<double> -- but the conversion happens via the implicit conversion from __complex__ double to double, so the imaginary part of the value is lost. So, I think that what we should do is add constructors. For example, for double, we would add: complex(int); complex(long); complex(long long): complex(unsigned int); complex(unsigned long); complex(unsigned long long); complex(long double); (We don't need bool, char, short, or float because they will promote to one of the other types, and promotions are better conversions than standard conversions, so there's no ambiguity.) I can't see how adding these constructors will break anything, relative to the standard, in that all of these conversions were already permitted, but it's definitely possible I'm overlooking something. I've attached the draft patch I've been using for the front end, but before I start making library changes I'd like to get some buy-in from the V3 deveopers. Thoughts? -- Mark Mitchell CodeSourcery, LLC mark@codesourcery.com Index: gcc/cp/call.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v retrieving revision 1.537 diff -c -5 -p -r1.537 call.c *** gcc/cp/call.c 27 May 2005 23:17:05 -0000 1.537 --- gcc/cp/call.c 29 May 2005 19:24:02 -0000 *************** standard_conversion (tree to, tree from, *** 628,648 **** if (tcode == COMPLEX_TYPE && fcode == COMPLEX_TYPE) { /* The standard conversion sequence to convert FROM to TO is the standard conversion sequence to perform componentwise conversion. */ ! conversion *part_conv = standard_conversion ! (TREE_TYPE (to), TREE_TYPE (from), NULL_TREE, flags); ! ! if (part_conv) ! { ! conv = build_conv (part_conv->kind, to, conv); ! conv->rank = part_conv->rank; ! } ! else ! conv = NULL; ! return conv; } if (same_type_p (from, to)) return conv; --- 628,641 ---- if (tcode == COMPLEX_TYPE && fcode == COMPLEX_TYPE) { /* The standard conversion sequence to convert FROM to TO is the standard conversion sequence to perform componentwise conversion. */ ! conv = standard_conversion (TREE_TYPE (to), TREE_TYPE (from), ! NULL_TREE, flags); ! if (conv) ! conv->type = to; return conv; } if (same_type_p (from, to)) return conv; *************** standard_conversion (tree to, tree from, *** 799,817 **** /* We don't check for ENUMERAL_TYPE here because there are no standard conversions to enum type. */ else if (tcode == INTEGER_TYPE || tcode == BOOLEAN_TYPE || tcode == REAL_TYPE) { ! if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE)) ! return 0; conv = build_conv (ck_std, to, conv); /* Give this a better rank if it's a promotion. */ if (same_type_p (to, type_promotes_to (from)) && conv->u.next->rank <= cr_promotion) conv->rank = cr_promotion; } else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE && vector_types_convertible_p (from, to)) return build_conv (ck_std, to, conv); else if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE) && IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) --- 792,832 ---- /* We don't check for ENUMERAL_TYPE here because there are no standard conversions to enum type. */ else if (tcode == INTEGER_TYPE || tcode == BOOLEAN_TYPE || tcode == REAL_TYPE) { ! if (!ARITHMETIC_TYPE_P (from) && fcode != ENUMERAL_TYPE) ! return NULL; conv = build_conv (ck_std, to, conv); /* Give this a better rank if it's a promotion. */ if (same_type_p (to, type_promotes_to (from)) && conv->u.next->rank <= cr_promotion) conv->rank = cr_promotion; } + else if (tcode == COMPLEX_TYPE) + { + /* Complex types are a GNU extension. Permit conversions to + complex types iff conversions to the corresponding scalar + type are permitted. The semantics of such a conversion is + that the imaginary type of the result is implicitly zero. */ + conv = standard_conversion (TREE_TYPE (to), from, expr, flags); + if (conv) + { + /* The conversion is never better than a standard + conversion. */ + if (!conv->bad_p) + { + if (conv->kind == ck_identity) + conv->kind = ck_std; + if (conv->rank < cr_std) + conv->rank = cr_std; + } + conv->type = to; + } + return conv; + } else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE && vector_types_convertible_p (from, to)) return build_conv (ck_std, to, conv); else if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE) && IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) Index: gcc/cp/cp-tree.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v retrieving revision 1.1139 diff -c -5 -p -r1.1139 cp-tree.h *** gcc/cp/cp-tree.h 28 May 2005 01:38:10 -0000 1.1139 --- gcc/cp/cp-tree.h 29 May 2005 19:24:02 -0000 *************** struct lang_decl GTY(()) *** 2344,2356 **** (TREE_CODE (TYPE) == ENUMERAL_TYPE || CP_INTEGRAL_TYPE_P (TYPE)) /* [basic.fundamental] Integral and floating types are collectively called arithmetic ! types. Keep these checks in ascending code order. */ ! #define ARITHMETIC_TYPE_P(TYPE) \ ! (CP_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == REAL_TYPE) /* [basic.types] Arithmetic types, enumeration types, pointer types, and pointer-to-member types, are collectively called scalar types. --- 2344,2362 ---- (TREE_CODE (TYPE) == ENUMERAL_TYPE || CP_INTEGRAL_TYPE_P (TYPE)) /* [basic.fundamental] Integral and floating types are collectively called arithmetic ! types. ! ! As a GNU extension, we also include COMPLEX_TYPEs. ! ! Keep these checks in ascending code order. */ ! #define ARITHMETIC_TYPE_P(TYPE) \ ! (CP_INTEGRAL_TYPE_P (TYPE) \ ! || TREE_CODE (TYPE) == REAL_TYPE \ ! || TREE_CODE (TYPE) == COMPLEX_TYPE) /* [basic.types] Arithmetic types, enumeration types, pointer types, and pointer-to-member types, are collectively called scalar types. Index: gcc/cp/typeck.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v retrieving revision 1.632 diff -c -5 -p -r1.632 typeck.c *** gcc/cp/typeck.c 28 May 2005 02:21:29 -0000 1.632 --- gcc/cp/typeck.c 29 May 2005 19:24:02 -0000 *************** common_type (tree t1, tree t2) *** 732,745 **** return error_mark_node; code1 = TREE_CODE (t1); code2 = TREE_CODE (t2); ! if ((ARITHMETIC_TYPE_P (t1) || code1 == ENUMERAL_TYPE ! || code1 == COMPLEX_TYPE) ! && (ARITHMETIC_TYPE_P (t2) || code2 == ENUMERAL_TYPE ! || code2 == COMPLEX_TYPE)) return type_after_usual_arithmetic_conversions (t1, t2); else if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2)) || (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2)) || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2))) --- 732,743 ---- return error_mark_node; code1 = TREE_CODE (t1); code2 = TREE_CODE (t2); ! if ((ARITHMETIC_TYPE_P (t1) || code1 == ENUMERAL_TYPE) ! && (ARITHMETIC_TYPE_P (t2) || code2 == ENUMERAL_TYPE)) return type_after_usual_arithmetic_conversions (t1, t2); else if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2)) || (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2)) || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2))) Index: gcc/testsuite/g++.dg/ext/complex1.C =================================================================== RCS file: gcc/testsuite/g++.dg/ext/complex1.C diff -N gcc/testsuite/g++.dg/ext/complex1.C *** /dev/null 1 Jan 1970 00:00:00 -0000 --- gcc/testsuite/g++.dg/ext/complex1.C 29 May 2005 19:24:02 -0000 *************** *** 0 **** --- 1,4 ---- + // PR c++/21210 + + typedef float __complex__ fcomplex; + fcomplex cplx = fcomplex();

**Follow-Ups**:**Re: Problems with PR 21210***From:*Gabriel Dos Reis

**Re: Problems with PR 21210***From:*Gabriel Dos Reis

**Re: Problems with PR 21210***From:*Jason Merrill

Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|

Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |