re PR c++/44267 (SFINAE does not handle down static_cast over virtual inheritance)
authorPaolo Carlini <paolo.carlini@oracle.com>
Sat, 24 Sep 2011 09:55:01 +0000 (09:55 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Sat, 24 Sep 2011 09:55:01 +0000 (09:55 +0000)
/cp
2011-09-24  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/44267
* class.c (build_base_path): Add a tsubst_flags_t parameter.
(convert_to_base): Adjust call.
* typeck.c (build_class_member_access_expr,
get_member_function_from_ptrfunc, build_static_cast_1): Likewise.
* init.c (dfs_initialize_vtbl_ptrs, emit_mem_initializers): Likewise.
* method.c (do_build_copy_constructor, do_build_copy_assign): Likewise.
* rtti.c (build_dynamic_cast_1): Likewise.
* typeck2.c (build_scoped_ref, build_m_component_ref): Likewise.
* call.c (build_over_call, build_special_member_call): Likewise.
* cvt.c (cp_convert_to_pointer, convert_to_pointer_force,
build_up_reference): Likewise.
* cp-tree.h (build_base_path): Adjust declaration.

/testsuite
2011-09-24  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/44267
* g++.dg/template/sfinae28.C: New.

From-SVN: r179141

12 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/rtti.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/sfinae28.C [new file with mode: 0644]

index 675497783d680b440dae18c70e78cbe4b9a9b9be..76000170a49b1c0a6f153e5c7269ca75aee94994 100644 (file)
@@ -1,3 +1,19 @@
+2011-09-24  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/44267
+       * class.c (build_base_path): Add a tsubst_flags_t parameter.
+       (convert_to_base): Adjust call.
+       * typeck.c (build_class_member_access_expr,
+       get_member_function_from_ptrfunc, build_static_cast_1): Likewise.
+       * init.c (dfs_initialize_vtbl_ptrs, emit_mem_initializers): Likewise.
+       * method.c (do_build_copy_constructor, do_build_copy_assign): Likewise.
+       * rtti.c (build_dynamic_cast_1): Likewise.
+       * typeck2.c (build_scoped_ref, build_m_component_ref): Likewise.
+       * call.c (build_over_call, build_special_member_call): Likewise.
+       * cvt.c (cp_convert_to_pointer, convert_to_pointer_force,
+       build_up_reference): Likewise.
+       * cp-tree.h (build_base_path): Adjust declaration.
+
 2011-09-23  Jason Merrill  <jason@redhat.com>
 
        Core 253 - allow const objects with no initializer or
index b616cffde5da28c038f94312554be69b02a0003c..8c99f7a5440abe6540231bd0546408d3855abfe7 100644 (file)
@@ -6449,7 +6449,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
       converted_arg = build_base_path (PLUS_EXPR,
                                       arg,
                                       cand->conversion_path,
-                                      1);
+                                      1, complain);
       /* Check that the base class is accessible.  */
       if (!accessible_base_p (TREE_TYPE (argtype),
                              BINFO_TYPE (cand->conversion_path), true))
@@ -6462,7 +6462,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
       base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)),
                                TREE_TYPE (parmtype), ba_unique, NULL);
       converted_arg = build_base_path (PLUS_EXPR, converted_arg,
-                                      base_binfo, 1);
+                                      base_binfo, 1, complain);
 
       argarray[j++] = converted_arg;
       parm = TREE_CHAIN (parm);
@@ -6706,7 +6706,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
       if (TREE_DEPRECATED (fn))
        warn_deprecated_use (fn, NULL_TREE);
 
-      argarray[0] = build_base_path (PLUS_EXPR, argarray[0], binfo, 1);
+      argarray[0] = build_base_path (PLUS_EXPR, argarray[0], binfo, 1,
+                                    complain);
       if (TREE_SIDE_EFFECTS (argarray[0]))
        argarray[0] = save_expr (argarray[0]);
       t = build_pointer_type (TREE_TYPE (fn));
@@ -6916,7 +6917,7 @@ build_special_member_call (tree instance, tree name, VEC(tree,gc) **args,
            /* However, for assignment operators, we must convert
               dynamically if the base is virtual.  */
            instance = build_base_path (PLUS_EXPR, instance,
-                                       binfo, /*nonnull=*/1);
+                                       binfo, /*nonnull=*/1, complain);
        }
     }
 
index 188752688085ea455e41f7666428c7a49946e5c8..acfe3f23afae60d561c77b23ee6cc4c28c29ebdf 100644 (file)
@@ -235,7 +235,8 @@ tree
 build_base_path (enum tree_code code,
                 tree expr,
                 tree binfo,
-                int nonnull)
+                int nonnull,
+                tsubst_flags_t complain)
 {
   tree v_binfo = NULL_TREE;
   tree d_binfo = NULL_TREE;
@@ -276,14 +277,16 @@ build_base_path (enum tree_code code,
 
   if (code == MINUS_EXPR && v_binfo)
     {
-      error ("cannot convert from base %qT to derived type %qT via virtual base %qT",
-            BINFO_TYPE (binfo), BINFO_TYPE (d_binfo), BINFO_TYPE (v_binfo));
+      if (complain & tf_error)
+       error ("cannot convert from base %qT to derived type %qT via "
+              "virtual base %qT", BINFO_TYPE (binfo), BINFO_TYPE (d_binfo),
+              BINFO_TYPE (v_binfo));
       return error_mark_node;
     }
 
   if (!want_pointer)
     /* This must happen before the call to save_expr.  */
-    expr = cp_build_addr_expr (expr, tf_warning_or_error);
+    expr = cp_build_addr_expr (expr, complain);
   else
     expr = mark_rvalue_use (expr);
 
@@ -341,7 +344,7 @@ build_base_path (enum tree_code code,
         interesting to the optimizers anyway.  */
       && !has_empty)
     {
-      expr = cp_build_indirect_ref (expr, RO_NULL, tf_warning_or_error);
+      expr = cp_build_indirect_ref (expr, RO_NULL, complain);
       expr = build_simple_base_path (expr, binfo);
       if (want_pointer)
        expr = build_address (expr);
@@ -366,19 +369,18 @@ build_base_path (enum tree_code code,
          t = TREE_TYPE (TYPE_VFIELD (current_class_type));
          t = build_pointer_type (t);
          v_offset = convert (t, current_vtt_parm);
-         v_offset = cp_build_indirect_ref (v_offset, RO_NULL, 
-                                            tf_warning_or_error);
+         v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain);
        }
       else
        v_offset = build_vfield_ref (cp_build_indirect_ref (expr, RO_NULL,
-                                                            tf_warning_or_error),
+                                                            complain),
                                     TREE_TYPE (TREE_TYPE (expr)));
 
       v_offset = fold_build_pointer_plus (v_offset, BINFO_VPTR_FIELD (v_binfo));
       v_offset = build1 (NOP_EXPR,
                         build_pointer_type (ptrdiff_type_node),
                         v_offset);
-      v_offset = cp_build_indirect_ref (v_offset, RO_NULL, tf_warning_or_error);
+      v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain);
       TREE_CONSTANT (v_offset) = 1;
 
       offset = convert_to_integer (ptrdiff_type_node,
@@ -418,7 +420,7 @@ build_base_path (enum tree_code code,
     null_test = NULL;
 
   if (!want_pointer)
-    expr = cp_build_indirect_ref (expr, RO_NULL, tf_warning_or_error);
+    expr = cp_build_indirect_ref (expr, RO_NULL, complain);
 
  out:
   if (null_test)
@@ -523,7 +525,7 @@ convert_to_base (tree object, tree type, bool check_access, bool nonnull,
   if (!binfo || binfo == error_mark_node)
     return error_mark_node;
 
-  return build_base_path (PLUS_EXPR, object, binfo, nonnull);
+  return build_base_path (PLUS_EXPR, object, binfo, nonnull, complain);
 }
 
 /* EXPR is an expression with unqualified class type.  BASE is a base
index 573c166a08b42336c16bf741d4af0dbbd139ef88..f2c921192beb372ccef7775291288c4791d5fa3b 100644 (file)
@@ -4790,7 +4790,7 @@ extern void validate_conversion_obstack           (void);
 /* in class.c */
 extern tree build_vfield_ref                   (tree, tree);
 extern tree build_base_path                    (enum tree_code, tree,
-                                                tree, int);
+                                                tree, int, tsubst_flags_t);
 extern tree convert_to_base                    (tree, tree, bool, bool,
                                                 tsubst_flags_t);
 extern tree convert_to_base_statically         (tree, tree);
index 8a23d5199f67d9f0385f811567892af00cfb3552..3e618d320adc4042a28d492182b4cc558f4b31c6 100644 (file)
@@ -1,7 +1,7 @@
 /* Language-level data type conversion for GNU C++.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -157,7 +157,8 @@ cp_convert_to_pointer (tree type, tree expr)
          if (binfo || same_p)
            {
              if (binfo)
-               expr = build_base_path (code, expr, binfo, 0);
+               expr = build_base_path (code, expr, binfo, 0,
+                                       tf_warning_or_error);
              /* Add any qualifier conversions.  */
              return build_nop (type, expr);
            }
@@ -275,7 +276,8 @@ convert_to_pointer_force (tree type, tree expr)
            return error_mark_node;
          if (binfo)
            {
-             expr = build_base_path (code, expr, binfo, 0);
+             expr = build_base_path (code, expr, binfo, 0,
+                                     tf_warning_or_error);
              if (expr == error_mark_node)
                 return error_mark_node;
              /* Add any qualifier conversions.  */
@@ -341,7 +343,8 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
        return error_mark_node;
       if (binfo == NULL_TREE)
        return error_not_base_type (target_type, argtype);
-      rval = build_base_path (PLUS_EXPR, rval, binfo, 1);
+      rval = build_base_path (PLUS_EXPR, rval, binfo, 1,
+                             tf_warning_or_error);
     }
   else
     rval
index 68d4e6812140851b9d79a449ac5be482ea9fe1ac..ac3221e30d0b74d7af365e1b81a11e274e0d193b 100644 (file)
@@ -100,7 +100,8 @@ dfs_initialize_vtbl_ptrs (tree binfo, void *data)
     {
       tree base_ptr = TREE_VALUE ((tree) data);
 
-      base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1);
+      base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1,
+                                 tf_warning_or_error);
 
       expand_virtual_init (binfo, base_ptr);
     }
@@ -963,7 +964,7 @@ emit_mem_initializers (tree mem_inits)
          tree base_addr;
 
          base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
-                                      subobject, 1);
+                                      subobject, 1, tf_warning_or_error);
          expand_aggr_init_1 (subobject, NULL_TREE,
                              cp_build_indirect_ref (base_addr, RO_NULL,
                                                      tf_warning_or_error),
index 757e711dd2c6bcd035807da4cb28c28dc43b7b3d..88bb2a9ef21cffb561ca60c6bc10369b45ee0e34 100644 (file)
@@ -516,7 +516,8 @@ do_build_copy_constructor (tree fndecl)
       for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
           VEC_iterate (tree, vbases, i, binfo); i++)
        {
-         init = build_base_path (PLUS_EXPR, parm, binfo, 1);
+         init = build_base_path (PLUS_EXPR, parm, binfo, 1,
+                                 tf_warning_or_error);
          if (move_p)
            init = move (init);
          member_init_list
@@ -531,7 +532,8 @@ do_build_copy_constructor (tree fndecl)
          if (BINFO_VIRTUAL_P (base_binfo))
            continue;
 
-         init = build_base_path (PLUS_EXPR, parm, base_binfo, 1);
+         init = build_base_path (PLUS_EXPR, parm, base_binfo, 1,
+                                 tf_warning_or_error);
          if (move_p)
            init = move (init);
          member_init_list
@@ -624,7 +626,8 @@ do_build_copy_assign (tree fndecl)
 
          /* We must convert PARM directly to the base class
             explicitly since the base class may be ambiguous.  */
-         converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1);
+         converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1,
+                                           tf_warning_or_error);
          if (move_p)
            converted_parm = move (converted_parm);
          /* Call the base class assignment operator.  */
index 434b7725ba86c7b568b3809a659a50c577bd9daf..818b8d0eee4ca30b289d5ce3135548fb19fadf31 100644 (file)
@@ -1,6 +1,6 @@
 /* RunTime Type Identification
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009, 2010
+   2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Mostly written by Jason Merrill (jason@cygnus.com).
 
@@ -616,7 +616,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
     if (binfo)
       {
        expr = build_base_path (PLUS_EXPR, convert_from_reference (expr),
-                               binfo, 0);
+                               binfo, 0, complain);
        if (TREE_CODE (exprtype) == POINTER_TYPE)
          expr = rvalue (expr);
        return expr;
index ed52f3c4f3f6837496716a637c3ccfa2346f8a92..955e37a28893d596c9e05defa8b252ac3ab7234a 100644 (file)
@@ -2221,7 +2221,7 @@ build_class_member_access_expr (tree object, tree member,
 
          /* Convert to the base.  */
          object = build_base_path (PLUS_EXPR, object, binfo,
-                                   /*nonnull=*/1);
+                                   /*nonnull=*/1, complain);
          /* If we found the base successfully then we should be able
             to convert to it successfully.  */
          gcc_assert (object != error_mark_node);
@@ -3073,7 +3073,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
          basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
                                  basetype, ba_check, NULL);
          instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype,
-                                         1);
+                                         1, tf_warning_or_error);
          if (instance_ptr == error_mark_node)
            return error_mark_node;
        }
@@ -5772,7 +5772,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
       /* 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);
+                             base, /*nonnull=*/false, complain);
       /* Convert the pointer to a reference -- but then remember that
         there are no expressions with reference type in C++.
 
@@ -5874,7 +5874,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
       base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
                          c_cast_p ? ba_unique : ba_check,
                          NULL);
-      expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
+      expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false,
+                             complain);
       return cp_fold_convert(type, expr);
     }
 
index 1c0bb38a8b8774ba48e3a874673b8552727981ee..96b95c2b5cebd395ccd37b3890229ed273ace4b5 100644 (file)
@@ -1398,7 +1398,8 @@ build_scoped_ref (tree datum, tree basetype, tree* binfo_p)
     }
 
   *binfo_p = binfo;
-  return build_base_path (PLUS_EXPR, datum, binfo, 1);
+  return build_base_path (PLUS_EXPR, datum, binfo, 1,
+                         tf_warning_or_error);
 }
 
 /* Build a reference to an object specified by the C++ `->' operator.
@@ -1565,7 +1566,8 @@ build_m_component_ref (tree datum, tree component)
 
       /* Convert object to the correct base.  */
       if (binfo)
-       datum = build_base_path (PLUS_EXPR, datum, binfo, 1);
+       datum = build_base_path (PLUS_EXPR, datum, binfo, 1,
+                                tf_warning_or_error);
 
       /* Build an expression for "object + offset" where offset is the
         value stored in the pointer-to-data-member.  */
index 4f0cebca6e8c0ec6e1d526fae0d350bf800fdbee..c5175faf4bc47779aa710df073f73e491ca058d2 100644 (file)
@@ -1,3 +1,8 @@
+2011-09-24  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/44267
+       * g++.dg/template/sfinae28.C: New.
+
 2011-09-23  Ian Lance Taylor  <iant@google.com>
 
        * go.test/go-test.exp (errchk): Handle more cases of getting
diff --git a/gcc/testsuite/g++.dg/template/sfinae28.C b/gcc/testsuite/g++.dg/template/sfinae28.C
new file mode 100644 (file)
index 0000000..1bd9c2c
--- /dev/null
@@ -0,0 +1,24 @@
+// Origin: PR c++/44267
+
+struct B {};
+struct D : B {};
+struct VD : virtual B {};
+
+template <class T> T create();
+
+typedef char one[1];
+typedef char two[2];
+
+template <class D, class B>
+one& f(char (*)[sizeof(static_cast<D>(create<B>()))]);
+
+template <class D, class B>
+two& f(...);
+
+int main()
+{
+   f<D*, int>(0);
+   f<D*, B*>(0);
+   f<VD*, B*>(0);
+   return 0;
+}