* typeck.c (build_c_cast): Don't decay arrays and functions to
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 10 May 1998 23:46:36 +0000 (23:46 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 10 May 1998 23:46:36 +0000 (23:46 +0000)
pointer type when converting to a class type.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@19659 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/g++.old-deja/g++.other/cvt1.C [new file with mode: 0644]

index 95eb36e..315feea 100644 (file)
@@ -1,3 +1,8 @@
+Sun May 10 23:43:13 1998  Mark Mitchell  <mmitchell@usa.net>
+
+       * 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  <jason@yorick.cygnus.com>
 
        * cp-tree.h (DECL_NAMESPACE_SCOPE): New macro.
index 6c1a1a6..fe66a3b 100644 (file)
@@ -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 (file)
index 0000000..f448cc1
--- /dev/null
@@ -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();
+}