]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/11867 (static_cast ignores ambiguity)
authorMark Mitchell <mark@codesourcery.com>
Sun, 7 Sep 2003 04:10:10 +0000 (04:10 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 7 Sep 2003 04:10:10 +0000 (04:10 +0000)
PR c++/11687
* call.c (standard_conversion): Improve comments.
(perform_direct_initialization): Make sure we return an expression
of the correct type.
* typeck.c (build_static_cast): Check for ambiguity and
accessibility when performing conversions.

PR c++/11687
* g++.dg/expr/static_cast5.C: New test.

From-SVN: r71157

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/expr/static_cast5.C [new file with mode: 0644]

index 755168e59b236e5dc5365e3a450a771ea7563e6c..1c8fef025733c3bcfb72d9e2c48d73b02695937a 100644 (file)
@@ -1,3 +1,12 @@
+2003-09-06  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/11687
+       * call.c (standard_conversion): Improve comments.
+       (perform_direct_initialization): Make sure we return an expression
+       of the correct type.
+       * typeck.c (build_static_cast): Check for ambiguity and
+       accessibility when performing conversions.
+
 2003-09-06  Gabriel Dos Reis  <gdr@integrable-solutions.net>
 
        * cp-tree.h (add_binding): Remove declaration.
index cc03adc6f57014ec4fdec3964865c0b5e1ed0b0a..bc7e3b8ab5bd0a72cff7f40a99764990f9210150 100644 (file)
@@ -701,16 +701,25 @@ standard_conversion (tree to, tree from, tree expr)
            }
        }
       else if (IS_AGGR_TYPE (TREE_TYPE (from))
-              && IS_AGGR_TYPE (TREE_TYPE (to)))
+              && IS_AGGR_TYPE (TREE_TYPE (to))
+              /* [conv.ptr]
+                 
+                 An rvalue of type "pointer to cv D," where D is a
+                 class type, can be converted to an rvalue of type
+                 "pointer to cv B," where B is a base class (clause
+                 _class.derived_) of D.  If B is an inaccessible
+                 (clause _class.access_) or ambiguous
+                 (_class.member.lookup_) base class of D, a program
+                 that necessitates this conversion is ill-formed.  */
+              /* Therefore, we use DERIVED_FROM_P, and not
+                 ACESSIBLY_UNIQUELY_DERIVED_FROM_P, in this test.  */
+              && DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
        {
-         if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
-           {
-             from = 
-               cp_build_qualified_type (TREE_TYPE (to),
-                                        cp_type_quals (TREE_TYPE (from)));
-             from = build_pointer_type (from);
-             conv = build_conv (PTR_CONV, from, conv);
-           }
+         from = 
+           cp_build_qualified_type (TREE_TYPE (to),
+                                    cp_type_quals (TREE_TYPE (from)));
+         from = build_pointer_type (from);
+         conv = build_conv (PTR_CONV, from, conv);
        }
 
       if (tcode == POINTER_TYPE)
@@ -5970,10 +5979,13 @@ perform_direct_initialization_if_possible (tree type, tree expr)
      the overload resolution is ambiguous, the initialization is
      ill-formed.  */
   if (CLASS_TYPE_P (type))
-    return build_special_member_call (NULL_TREE, complete_ctor_identifier,
-                                     build_tree_list (NULL_TREE, expr),
-                                     TYPE_BINFO (type),
-                                     LOOKUP_NORMAL);
+    {
+      expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+                                       build_tree_list (NULL_TREE, expr),
+                                       TYPE_BINFO (type),
+                                       LOOKUP_NORMAL);
+      return build_cplus_new (type, expr);
+    }
   conv = implicit_conversion (type, TREE_TYPE (expr), expr,
                              LOOKUP_NORMAL);
   if (!conv || ICS_BAD_FLAG (conv))
index da07fea0c5fe7992896effe8b7fc99c9580634b4..8b391b8448d8513b1e340f3b303fb1808152a2ba 100644 (file)
@@ -4427,12 +4427,13 @@ build_static_cast (tree type, tree expr)
                                          (TREE_TYPE (type))))
       && at_least_as_qualified_p (TREE_TYPE (type), intype))
     {
-      /* At this point we have checked all of the conditions except
-        that B is not a virtual base class of D.  That will be
-        checked by build_base_path.  */
-      tree base = lookup_base (TREE_TYPE (type), intype, ba_any, NULL);
+      /* There is a standard conversion from "D*" to "B*" even if "B"
+        is ambiguous or inaccessible.  Therefore, we ask lookup_base
+        to check these conditions.  */
+      tree base = lookup_base (TREE_TYPE (type), intype, ba_check, NULL);
 
-      /* Convert from B* to D*.  */
+      /* Convert from "B*" to "D*".  This function will check that "B"
+        is not a virtual base of "D".  */
       expr = build_base_path (MINUS_EXPR, build_address (expr), 
                              base, /*nonnull=*/false);
       /* Convert the pointer to a reference -- but then remember that
@@ -4491,8 +4492,8 @@ build_static_cast (tree type, tree expr)
       tree base;
 
       check_for_casting_away_constness (intype, type, "static_cast");
-      base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), 
-                         ba_check | ba_quiet, NULL);
+      base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), ba_check, 
+                         NULL);
       return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
     }
   
index 331c00d8cbcb1c0b91a7eb4800aef982e3f155f6..d5b929a674dbc94979b213e5efee9be4d1c77fc2 100644 (file)
@@ -1,3 +1,8 @@
+2003-09-06  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/11687
+       * g++.dg/expr/static_cast5.C: New test.
+
 2003-09-06  Nathan Sidwell  <nathan@codesourcery.com>
 
        PR c++/11794
diff --git a/gcc/testsuite/g++.dg/expr/static_cast5.C b/gcc/testsuite/g++.dg/expr/static_cast5.C
new file mode 100644 (file)
index 0000000..1a51f15
--- /dev/null
@@ -0,0 +1,17 @@
+void ambig()
+{
+  struct A {};
+  struct B : A {};
+  struct C : A {};
+  struct D : B, C {};
+
+  D d;
+  A* ap = static_cast<B*> (&d);
+  D* db = static_cast<D*> (ap); // { dg-error "" }
+  
+  D& dr1 = static_cast<D&> (*ap); // { dg-error "" }
+  
+  A& ar = static_cast<C&> (d);
+  D& dr = static_cast<D&> (ar);  // { dg-error "" }
+}
+