Index: testsuite/g++.dg/template/sfinae28.C
===================================================================
--- testsuite/g++.dg/template/sfinae28.C	(revision 0)
+++ testsuite/g++.dg/template/sfinae28.C	(revision 0)
@@ -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;
+}
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 179128)
+++ cp/typeck.c	(working copy)
@@ -2221,7 +2221,7 @@ build_class_member_access_expr (tree object, tree
 
 	  /* 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_p
 	  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_
       /* 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_
       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: cp/init.c
===================================================================
--- cp/init.c	(revision 179128)
+++ cp/init.c	(working copy)
@@ -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: cp/class.c
===================================================================
--- cp/class.c	(revision 179128)
+++ cp/class.c	(working copy)
@@ -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 chec
   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: cp/method.c
===================================================================
--- cp/method.c	(revision 179128)
+++ cp/method.c	(working copy)
@@ -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: cp/rtti.c
===================================================================
--- cp/rtti.c	(revision 179128)
+++ cp/rtti.c	(working copy)
@@ -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
     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: cp/typeck2.c
===================================================================
--- cp/typeck2.c	(revision 179128)
+++ cp/typeck2.c	(working copy)
@@ -1398,7 +1398,8 @@ build_scoped_ref (tree datum, tree basetype, tree*
     }
 
   *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: cp/call.c
===================================================================
--- cp/call.c	(revision 179128)
+++ cp/call.c	(working copy)
@@ -6449,7 +6449,7 @@ build_over_call (struct z_candidate *cand, int fla
       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 fla
       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 fla
       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 nam
 	    /* 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: cp/cvt.c
===================================================================
--- cp/cvt.c	(revision 179128)
+++ cp/cvt.c	(working copy)
@@ -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
 	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: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 179128)
+++ cp/cp-tree.h	(working copy)
@@ -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);
