From 4785faf11744c7e86ac93032075b23becebef200 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sun, 10 May 1998 23:46:36 +0000 Subject: typeck.c (build_c_cast): Don't decay arrays and functions to pointer type when converting to a class type. * typeck.c (build_c_cast): Don't decay arrays and functions to pointer type when converting to a class type. From-SVN: r19659 --- gcc/cp/ChangeLog | 5 ++++ gcc/cp/typeck.c | 40 +++++++++++++++++++++-------- gcc/testsuite/g++.old-deja/g++.other/cvt1.C | 23 +++++++++++++++++ 3 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.other/cvt1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 95eb36e..315feea 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +Sun May 10 23:43:13 1998 Mark Mitchell + + * typeck.c (build_c_cast): Don't decay arrays and functions to + pointer type when converting to a class type. + Sun May 10 22:53:56 1998 Jason Merrill * cp-tree.h (DECL_NAMESPACE_SCOPE): New macro. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 6c1a1a6..fe66a3b 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5633,16 +5633,36 @@ build_c_cast (type, expr) /* Convert functions and arrays to pointers and convert references to their expanded types, - but don't convert any other types. */ - if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE - || (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE - /* Don't do the default conversion if we want a - pointer to a function. */ - && ! (TREE_CODE (type) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)) - || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE - || TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE) - value = default_conversion (value); + but don't convert any other types. If, however, we are + casting to a class type, there's no reason to do this: the + cast will only succeed if there is a converting constructor, + and the default conversions will be done at that point. In + fact, doing the default conversion here is actually harmful + in cases like this: + + typedef int A[2]; + struct S { S(const A&); }; + + since we don't want the array-to-pointer conversion done. */ + if (!IS_AGGR_TYPE (type)) + { + if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE + || (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE + /* Don't do the default conversion if we want a + pointer to a function. */ + && ! (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)) + || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE + || TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE) + value = default_conversion (value); + } + else if (TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE) + /* However, even for class types, we still need to strip away + the reference type, since the call to convert_force below + does not expect the input expression to be of reference + type. */ + value = convert_from_reference (value); + otype = TREE_TYPE (value); /* Optionally warn about potentially worrisome casts. */ diff --git a/gcc/testsuite/g++.old-deja/g++.other/cvt1.C b/gcc/testsuite/g++.old-deja/g++.other/cvt1.C new file mode 100644 index 0000000..f448cc1a --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/cvt1.C @@ -0,0 +1,23 @@ +// Build don't link: + +typedef int Array_T[2]; + +struct S1 { + S1(const Array_T&); +}; + +struct S2 { + S1 g(); + Array_T a; +}; + +S1 S2::g() +{ + return S1(a); +} + +void h() +{ + S2 s2; + s2.g(); +} -- cgit v1.1