Patchwork [C++] PR 54191

login
register
mail settings
Submitter Paolo Carlini
Date Aug. 8, 2012, 8:40 p.m.
Message ID <5022CEBF.1060602@oracle.com>
Download mbox | patch
Permalink /patch/175955/
State New
Headers show

Comments

Paolo Carlini - Aug. 8, 2012, 8:40 p.m.
Hi,

this is a booted and tested patch which handles all the tests submitted 
as part of the PR besides the first 4, which require 
finish_decltype_type to use an instantiation_dependent_p along the lines 
of the work done as part of c++/51222. As I mentioned, I already 
verified that the latter work is enough to fix those 4 tests, thus my 
idea would be resolving asap this PR and then adding the 4 tests to 
c++/51222 or opening a separate PR only for those, blocked by c++/51222, 
whichever option you like.

Otherwise, as I already described, I'm simply adding a tsubst_flags_t 
parameter to lookup_base, and the rest is straightforward.

Thanks,
Paolo.

////////////////////////////////
/cp
2012-08-08  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54191
	* search.c (lookup_base): Add tsubst_flags_t parameter.
	(adjust_result_of_qualified_name_lookup, check_final_overrider):
	Adjust.
	* name-lookup.c (do_class_using_decl): Likewise.
	* typeck.c (build_class_member_access_expr,
	finish_class_member_access_expr, get_member_function_from_ptrfunc,
	build_static_cast_1, get_delta_difference_1): Likewise.
	* class.c (build_base_path, convert_to_base, build_vtbl_ref_1,
	warn_about_ambiguous_bases): Likewise.
	* rtti.c (build_dynamic_cast_1): Likewise.
	* tree.c (maybe_dummy_object): Likewise.
	* typeck2.c (error_not_base_type, build_scoped_ref,
	build_m_component_ref): Likewise.
	* cvt.c (cp_convert_to_pointer, convert_to_pointer_force,
	build_up_reference): Likewise.
	* call.c (build_over_call): Likewise.
	(build_conditional_expr_1): Check arg2 and arg3 for error_mark_node
	before the valid_operands label.
	* cp-tree.h: Update.

/testsuite
2012-08-08  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54191
	* g++.dg/cpp0x/sfinae39.C: New.
Jason Merrill - Aug. 27, 2012, 4:28 p.m.
Let's do away with ba_quiet entirely and instead pass tf_none in cases 
where we would have set ba_quiet.

>  #define DERIVED_FROM_P(PARENT, TYPE) \
> -  (lookup_base ((TYPE), (PARENT), ba_any, NULL) != NULL_TREE)
> +  (lookup_base ((TYPE), (PARENT), ba_any, NULL, tf_warning_or_error) \
> +   != NULL_TREE)
>  /* Nonzero iff TYPE is uniquely derived from PARENT. Ignores
>     accessibility.  */
>  #define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) \
> -  (lookup_base ((TYPE), (PARENT), ba_unique | ba_quiet, NULL) != NULL_TREE)
> +  (lookup_base ((TYPE), (PARENT), ba_unique | ba_quiet, NULL, \
> +		tf_warning_or_error) != NULL_TREE)
>  /* Nonzero iff TYPE is publicly & uniquely derived from PARENT.  */
>  #define PUBLICLY_UNIQUELY_DERIVED_P(PARENT, TYPE) \
>    (lookup_base ((TYPE), (PARENT), ba_ignore_scope | ba_check | ba_quiet, \
> -		NULL) != NULL_TREE)
> +		NULL, tf_warning_or_error) != NULL_TREE)

I think anything that's just checking whether a base is there/usable 
should use tf_none.

Jason
Paolo Carlini - Aug. 27, 2012, 5:36 p.m.
On 08/27/2012 06:28 PM, Jason Merrill wrote:
> Let's do away with ba_quiet entirely and instead pass tf_none in cases 
> where we would have set ba_quiet.
Thanks for the feedback. Indeed, as I tried to explain in an older 
message, that was also my understanding. The practical difficulty with 
the mapping (which you can also guess from the current structure of 
get_delta_difference_1, the if (kind == bk_inaccessible || kind == 
bk_ambig) check) is that ba_quiet, as used by lookup_base, doesn't just 
control the error calls - like normally tf_error does - it *also* 
changes the return value, error_mark_node or NULL_TREE. I'm still not 
sure about the correct (and concise! see get_delta_difference_1, again) 
way to handle this...

Paolo.
Jason Merrill - Aug. 27, 2012, 6:04 p.m.
On 08/27/2012 01:36 PM, Paolo Carlini wrote:
> Thanks for the feedback. Indeed, as I tried to explain in an older
> message, that was also my understanding. The practical difficulty with
> the mapping (which you can also guess from the current structure of
> get_delta_difference_1, the if (kind == bk_inaccessible || kind ==
> bk_ambig) check) is that ba_quiet, as used by lookup_base, doesn't just
> control the error calls - like normally tf_error does - it *also*
> changes the return value, error_mark_node or NULL_TREE. I'm still not
> sure about the correct (and concise! see get_delta_difference_1, again)
> way to handle this...

I think the right way is to adjust the callers to handle error_mark_node 
return properly.  Macros may need to become functions.

Jason

Patch

Index: testsuite/g++.dg/cpp0x/sfinae39.C
===================================================================
--- testsuite/g++.dg/cpp0x/sfinae39.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/sfinae39.C	(revision 0)
@@ -0,0 +1,98 @@ 
+// PR c++/54191
+// { dg-do compile { target c++11 } }
+
+struct B
+{};
+
+struct D
+  : private B
+{};
+
+template<typename T>
+T &&declval();
+
+
+template<typename From, typename To,
+         typename = decltype(static_cast<To>(declval<From>()))>
+constexpr bool test_static_cast(int)
+{ return true; }
+
+template<typename, typename>
+constexpr bool test_static_cast(bool)
+{ return false; }
+
+static_assert(!test_static_cast<B &, D &>(0), "");
+static_assert(!test_static_cast<B *, D *>(0), "");
+
+
+template<typename From, typename To,
+         typename = decltype(dynamic_cast<To>(declval<From>()))>
+constexpr bool test_dynamic_cast(int)
+{ return true; }
+
+template<typename, typename>
+constexpr bool test_dynamic_cast(bool)
+{ return false; }
+
+static_assert(!test_dynamic_cast<D &, B &>(0), "");
+static_assert(!test_dynamic_cast<D *, B *>(0), "");
+
+
+int B::*pm = 0;
+
+template<typename T, typename = decltype(declval<T>().*pm)>
+constexpr bool test_member_ptr_dot(int)
+{ return true; }
+
+template<typename>
+constexpr bool test_member_ptr_dot(bool)
+{ return false; }
+
+static_assert(!test_member_ptr_dot<D>(0), "");
+
+
+template<typename T, typename = decltype(declval<T>()->*pm)>
+constexpr bool test_member_ptr_arrow(int)
+{ return true; }
+
+template<typename>
+constexpr bool test_member_ptr_arrow(bool)
+{ return false; }
+
+static_assert(!test_member_ptr_arrow<D *>(0), "");
+
+
+template<typename T, typename U,
+         typename = decltype(declval<T>() < declval<U>())>
+constexpr bool test_rel_op(int)
+{ return true; }
+
+template<typename, typename>
+constexpr bool test_rel_op(bool)
+{ return false; }
+
+static_assert(!test_rel_op<D *, B *>(0), "");
+
+
+template<typename T, typename U,
+         typename = decltype(declval<T>() == declval<U>())>
+constexpr bool test_eq(int)
+{ return true; }
+
+template<typename, typename>
+constexpr bool test_eq(bool)
+{ return false; }
+
+static_assert(!test_eq<D *, B *>(0), "");
+
+
+template<typename T, typename U,
+         typename = decltype(false ? declval<T>() : declval<U>())>
+constexpr bool test_cond_op(int)
+{ return true; }
+
+template<typename, typename>
+constexpr bool test_cond_op(bool)
+{ return false; }
+
+static_assert(!test_cond_op<B *, D *>(0), "");
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 190231)
+++ cp/typeck.c	(working copy)
@@ -2247,7 +2247,7 @@  build_class_member_access_expr (tree object, tree
 	  base_kind kind;
 
 	  binfo = lookup_base (access_path ? access_path : object_type,
-			       member_scope, ba_unique,  &kind);
+			       member_scope, ba_unique, &kind, complain);
 	  if (binfo == error_mark_node)
 	    return error_mark_node;
 
@@ -2630,7 +2630,8 @@  finish_class_member_access_expr (tree object, tree
 	    }
 
 	  /* Find the base of OBJECT_TYPE corresponding to SCOPE.  */
-	  access_path = lookup_base (object_type, scope, ba_check, NULL);
+	  access_path = lookup_base (object_type, scope, ba_check,
+				     NULL, complain);
 	  if (access_path == error_mark_node)
 	    return error_mark_node;
 	  if (!access_path)
@@ -3151,7 +3152,7 @@  get_member_function_from_ptrfunc (tree *instance_p
 	  (basetype, TREE_TYPE (TREE_TYPE (instance_ptr))))
 	{
 	  basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
-				  basetype, ba_check, NULL);
+				  basetype, ba_check, NULL, complain);
 	  instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype,
 					  1, complain);
 	  if (instance_ptr == error_mark_node)
@@ -5997,7 +5998,7 @@  build_static_cast_1 (tree type, tree expr, bool c_
 	 not considered.  */
       base = lookup_base (TREE_TYPE (type), intype,
 			  c_cast_p ? ba_unique : ba_check,
-			  NULL);
+			  NULL, complain);
 
       /* Convert from "B*" to "D*".  This function will check that "B"
 	 is not a virtual base of "D".  */
@@ -6121,7 +6122,7 @@  build_static_cast_1 (tree type, tree expr, bool c_
 	return error_mark_node;
       base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
 			  c_cast_p ? ba_unique : ba_check,
-			  NULL);
+			  NULL, complain);
       expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false,
 			      complain);
       return cp_fold_convert(type, expr);
@@ -7181,16 +7182,11 @@  get_delta_difference_1 (tree from, tree to, bool c
 {
   tree binfo;
   base_kind kind;
-  base_access access = c_cast_p ? ba_unique : ba_check;
 
-  /* Note: ba_quiet does not distinguish between access control and
-     ambiguity.  */
-  if (!(complain & tf_error))
-    access |= ba_quiet;
+  binfo = lookup_base (to, from, c_cast_p ? ba_unique : ba_check,
+		       &kind, complain);
 
-  binfo = lookup_base (to, from, access, &kind);
-
-  if (kind == bk_inaccessible || kind == bk_ambig)
+  if (binfo == error_mark_node)
     {
       if (!(complain & tf_error))
 	return error_mark_node;
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 190231)
+++ cp/class.c	(working copy)
@@ -275,7 +275,7 @@  build_base_path (enum tree_code code,
       if (complain & tf_error)
 	{
 	  tree base = lookup_base (probe, BINFO_TYPE (d_binfo),
-				   ba_unique, NULL);
+				   ba_unique, NULL, complain);
 	  gcc_assert (base == error_mark_node);
 	}
       return error_mark_node;
@@ -557,9 +557,7 @@  convert_to_base (tree object, tree type, bool chec
   access = check_access ? ba_check : ba_unique;
   if (!(complain & tf_error))
     access |= ba_quiet;
-  binfo = lookup_base (object_type, type,
-		       access,
-		       NULL);
+  binfo = lookup_base (object_type, type, access, NULL, complain);
   if (!binfo || binfo == error_mark_node)
     return error_mark_node;
 
@@ -652,7 +650,8 @@  build_vtbl_ref_1 (tree instance, tree idx)
   if (fixed_type && !cdtorp)
     {
       tree binfo = lookup_base (fixed_type, basetype,
-				ba_unique | ba_quiet, NULL);
+				ba_unique | ba_quiet,
+				NULL, tf_warning_or_error);
       if (binfo)
 	vtbl = unshare_expr (BINFO_VTABLE (binfo));
     }
@@ -5483,7 +5482,8 @@  warn_about_ambiguous_bases (tree t)
     {
       basetype = BINFO_TYPE (base_binfo);
 
-      if (!lookup_base (t, basetype, ba_unique | ba_quiet, NULL))
+      if (!lookup_base (t, basetype, ba_unique | ba_quiet,
+			NULL, tf_warning_or_error))
 	warning (0, "direct base %qT inaccessible in %qT due to ambiguity",
 		 basetype, t);
     }
@@ -5495,9 +5495,10 @@  warn_about_ambiguous_bases (tree t)
       {
 	basetype = BINFO_TYPE (binfo);
 
-	if (!lookup_base (t, basetype, ba_unique | ba_quiet, NULL))
-	  warning (OPT_Wextra, "virtual base %qT inaccessible in %qT due to ambiguity",
-		   basetype, t);
+	if (!lookup_base (t, basetype, ba_unique | ba_quiet,
+			  NULL, tf_warning_or_error))
+	  warning (OPT_Wextra, "virtual base %qT inaccessible in %qT due "
+		   "to ambiguity", basetype, t);
       }
 }
 
Index: cp/rtti.c
===================================================================
--- cp/rtti.c	(revision 190231)
+++ cp/rtti.c	(working copy)
@@ -615,7 +615,7 @@  build_dynamic_cast_1 (tree type, tree expr, tsubst
     tree binfo;
 
     binfo = lookup_base (TREE_TYPE (exprtype), TREE_TYPE (type),
-			 ba_check, NULL);
+			 ba_check, NULL, complain);
 
     if (binfo)
       {
Index: cp/tree.c
===================================================================
--- cp/tree.c	(revision 190231)
+++ cp/tree.c	(working copy)
@@ -2772,7 +2772,8 @@  maybe_dummy_object (tree type, tree* binfop)
   tree current = current_nonlambda_class_type ();
 
   if (current
-      && (binfo = lookup_base (current, type, ba_any, NULL)))
+      && (binfo = lookup_base (current, type, ba_any,
+			       NULL, tf_warning_or_error)))
     context = current;
   else
     {
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c	(revision 190231)
+++ cp/typeck2.c	(working copy)
@@ -57,7 +57,8 @@  error_not_base_type (tree basetype, tree type)
 tree
 binfo_or_else (tree base, tree type)
 {
-  tree binfo = lookup_base (type, base, ba_unique, NULL);
+  tree binfo = lookup_base (type, base, ba_unique,
+			    NULL, tf_warning_or_error);
 
   if (binfo == error_mark_node)
     return NULL_TREE;
@@ -1447,7 +1448,8 @@  build_scoped_ref (tree datum, tree basetype, tree*
   if (*binfo_p)
     binfo = *binfo_p;
   else
-    binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
+    binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check,
+			 NULL, tf_warning_or_error);
 
   if (!binfo || binfo == error_mark_node)
     {
@@ -1600,7 +1602,7 @@  build_m_component_ref (tree datum, tree component,
     }
   else
     {
-      binfo = lookup_base (objtype, ctype, ba_check, NULL);
+      binfo = lookup_base (objtype, ctype, ba_check, NULL, complain);
 
       if (!binfo)
 	{
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 190231)
+++ cp/call.c	(working copy)
@@ -4767,6 +4767,9 @@  build_conditional_expr_1 (tree arg1, tree arg2, tr
       return error_mark_node;
     }
 
+  if (arg2 == error_mark_node || arg3 == error_mark_node)
+    return error_mark_node;
+
  valid_operands:
   result = build3 (COND_EXPR, result_type, arg1, arg2, arg3);
   if (!cp_unevaluated_operand)
@@ -6617,7 +6620,8 @@  build_over_call (struct z_candidate *cand, int fla
 	 will be to the derived class, not the base declaring fn. We
 	 must convert from derived to base.  */
       base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)),
-				TREE_TYPE (parmtype), ba_unique, NULL);
+				TREE_TYPE (parmtype), ba_unique,
+				NULL, complain);
       converted_arg = build_base_path (PLUS_EXPR, converted_arg,
 				       base_binfo, 1, complain);
 
@@ -6861,7 +6865,7 @@  build_over_call (struct z_candidate *cand, int fla
       tree t;
       tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (argarray[0])),
 				DECL_CONTEXT (fn),
-				ba_any, NULL);
+				ba_any, NULL, complain);
       gcc_assert (binfo && binfo != error_mark_node);
 
       /* Warn about deprecated virtual functions now, since we're about
Index: cp/cvt.c
===================================================================
--- cp/cvt.c	(revision 190231)
+++ cp/cvt.c	(working copy)
@@ -149,11 +149,13 @@  cp_convert_to_pointer (tree type, tree expr, tsubs
 	  binfo = NULL_TREE;
 	  /* Try derived to base conversion.  */
 	  if (!same_p)
-	    binfo = lookup_base (intype_class, type_class, ba_check, NULL);
+	    binfo = lookup_base (intype_class, type_class, ba_check,
+				 NULL, complain);
 	  if (!same_p && !binfo)
 	    {
 	      /* Try base to derived conversion.  */
-	      binfo = lookup_base (type_class, intype_class, ba_check, NULL);
+	      binfo = lookup_base (type_class, intype_class, ba_check,
+				   NULL, complain);
 	      code = MINUS_EXPR;
 	    }
 	  if (binfo == error_mark_node)
@@ -279,11 +281,11 @@  convert_to_pointer_force (tree type, tree expr, ts
 	  tree binfo;
 
 	  binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type),
-			       ba_unique, NULL);
+			       ba_unique, NULL, complain);
 	  if (!binfo)
 	    {
 	      binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
-				   ba_unique, NULL);
+				   ba_unique, NULL, complain);
 	      code = MINUS_EXPR;
 	    }
 	  if (binfo == error_mark_node)
@@ -352,7 +354,8 @@  build_up_reference (tree type, tree arg, int flags
       && MAYBE_CLASS_TYPE_P (target_type))
     {
       /* We go through lookup_base for the access control.  */
-      tree binfo = lookup_base (argtype, target_type, ba_check, NULL);
+      tree binfo = lookup_base (argtype, target_type, ba_check,
+				NULL, complain);
       if (binfo == error_mark_node)
 	return error_mark_node;
       if (binfo == NULL_TREE)
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 190231)
+++ cp/cp-tree.h	(working copy)
@@ -1278,15 +1278,17 @@  enum languages { lang_c, lang_cplusplus, lang_java
 /* Nonzero iff TYPE is derived from PARENT. Ignores accessibility and
    ambiguity issues.  */
 #define DERIVED_FROM_P(PARENT, TYPE) \
-  (lookup_base ((TYPE), (PARENT), ba_any, NULL) != NULL_TREE)
+  (lookup_base ((TYPE), (PARENT), ba_any, NULL, tf_warning_or_error) \
+   != NULL_TREE)
 /* Nonzero iff TYPE is uniquely derived from PARENT. Ignores
    accessibility.  */
 #define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) \
-  (lookup_base ((TYPE), (PARENT), ba_unique | ba_quiet, NULL) != NULL_TREE)
+  (lookup_base ((TYPE), (PARENT), ba_unique | ba_quiet, NULL, \
+		tf_warning_or_error) != NULL_TREE)
 /* Nonzero iff TYPE is publicly & uniquely derived from PARENT.  */
 #define PUBLICLY_UNIQUELY_DERIVED_P(PARENT, TYPE) \
   (lookup_base ((TYPE), (PARENT), ba_ignore_scope | ba_check | ba_quiet, \
-		NULL) != NULL_TREE)
+		NULL, tf_warning_or_error) != NULL_TREE)
 
 /* Gives the visibility specification for a class type.  */
 #define CLASSTYPE_VISIBILITY(TYPE)		\
@@ -5439,8 +5441,8 @@  extern bool emit_tinfo_decl			(tree);
 
 /* in search.c */
 extern bool accessible_base_p			(tree, tree, bool);
-extern tree lookup_base				(tree, tree, base_access,
-						 base_kind *);
+extern tree lookup_base                         (tree, tree, base_access,
+						 base_kind *, tsubst_flags_t);
 extern tree dcast_base_hint			(tree, tree);
 extern int accessible_p				(tree, tree, bool);
 extern tree lookup_field_1			(tree, tree, bool);
Index: cp/search.c
===================================================================
--- cp/search.c	(revision 190231)
+++ cp/search.c	(working copy)
@@ -185,7 +185,8 @@  accessible_base_p (tree t, tree base, bool conside
    NULL_TREE is returned.  */
 
 tree
-lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
+lookup_base (tree t, tree base, base_access access,
+	     base_kind *kind_ptr, tsubst_flags_t complain)
 {
   tree binfo;
   tree t_binfo;
@@ -253,7 +254,8 @@  tree
       case bk_ambig:
 	if (!(access & ba_quiet))
 	  {
-	    error ("%qT is an ambiguous base of %qT", base, t);
+	    if (complain & tf_error)
+	      error ("%qT is an ambiguous base of %qT", base, t);
 	    binfo = error_mark_node;
 	  }
 	break;
@@ -271,7 +273,8 @@  tree
 	  {
 	    if (!(access & ba_quiet))
 	      {
-		error ("%qT is an inaccessible base of %qT", base, t);
+		if (complain & tf_error)
+		  error ("%qT is an inaccessible base of %qT", base, t);
 		binfo = error_mark_node;
 	      }
 	    else
@@ -1537,14 +1540,14 @@  adjust_result_of_qualified_name_lookup (tree decl,
 	 or ambiguity -- in either case, the choice of a static member
 	 function might make the usage valid.  */
       base = lookup_base (context_class, qualifying_scope,
-			  ba_unique | ba_quiet, NULL);
+			  ba_unique | ba_quiet, NULL, tf_warning_or_error);
       if (base)
 	{
 	  BASELINK_ACCESS_BINFO (decl) = base;
 	  BASELINK_BINFO (decl)
 	    = lookup_base (base, BINFO_TYPE (BASELINK_BINFO (decl)),
 			   ba_unique | ba_quiet,
-			   NULL);
+			   NULL, tf_warning_or_error);
 	}
     }
 
@@ -1875,10 +1878,12 @@  check_final_overrider (tree overrider, tree basefn
 	  /* Strictly speaking, the standard requires the return type to be
 	     complete even if it only differs in cv-quals, but that seems
 	     like a bug in the wording.  */
-	  if (!same_type_ignoring_top_level_qualifiers_p (base_return, over_return))
+	  if (!same_type_ignoring_top_level_qualifiers_p (base_return,
+							  over_return))
 	    {
 	      tree binfo = lookup_base (over_return, base_return,
-					ba_check | ba_quiet, NULL);
+					ba_check | ba_quiet,
+					NULL, tf_warning_or_error);
 
 	      if (!binfo)
 		fail = 1;
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 190231)
+++ cp/name-lookup.c	(working copy)
@@ -3256,7 +3256,8 @@  do_class_using_decl (tree scope, tree name)
   if (!scope_dependent_p)
     {
       base_kind b_kind;
-      binfo = lookup_base (current_class_type, scope, ba_any, &b_kind);
+      binfo = lookup_base (current_class_type, scope, ba_any, &b_kind,
+			   tf_warning_or_error);
       if (b_kind < bk_proper_base)
 	{
 	  if (!bases_dependent_p)