Patchwork [C++] PR 56970

login
register
mail settings
Submitter Paolo Carlini
Date April 24, 2013, 11:49 a.m.
Message ID <5177C6CF.90807@oracle.com>
Download mbox | patch
Permalink /patch/239170/
State New
Headers show

Comments

Paolo Carlini - April 24, 2013, 11:49 a.m.
Hi,

one of those cases where we error out in a SFINAE context because the 
tsubst_flags_t isn't propagated far enough. The straightforward patch 
works fine mainline and 4_8-branch.

Tested x86_64-linux.

Thanks,
Paolo.

////////////////////////
/cp
2013-04-24  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/56970
	* init.c (build_offset_ref): Add tsubst_flags_t parameter.
	* semantics.c (finish_qualified_id_expr): Likewise.
	(finish_id_expression): Update.
	* typeck.c (cp_build_addr_expr_1): Likewise.
	* pt.c (tsubst_qualified_id, resolve_nondeduced_context): Likewise.
	* cp-tree.h: Update declarations.

/testsuite
2013-04-24  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/56970
	* g++.dg/cpp0x/sfinae45.C: New.
Jason Merrill - April 24, 2013, 1:03 p.m.
OK.

Jason

Patch

Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 198220)
+++ cp/cp-tree.h	(working copy)
@@ -5351,7 +5351,8 @@  extern tree get_type_value			(tree);
 extern tree build_zero_init			(tree, tree, bool);
 extern tree build_value_init			(tree, tsubst_flags_t);
 extern tree build_value_init_noctor		(tree, tsubst_flags_t);
-extern tree build_offset_ref			(tree, tree, bool);
+extern tree build_offset_ref			(tree, tree, bool,
+						 tsubst_flags_t);
 extern tree build_new				(vec<tree, va_gc> **, tree, tree,
 						 vec<tree, va_gc> **, int,
                                                  tsubst_flags_t);
@@ -5748,7 +5749,7 @@  extern void add_typedef_to_current_template_for_ac
 							      location_t);
 extern void check_accessibility_of_qualified_id (tree, tree, tree);
 extern tree finish_qualified_id_expr		(tree, tree, bool, bool,
-						 bool, bool);
+						 bool, bool, tsubst_flags_t);
 extern void simplify_aggr_init_expr		(tree *);
 extern void finalize_nrv			(tree *, tree, tree);
 extern void note_decl_for_pch			(tree);
Index: cp/init.c
===================================================================
--- cp/init.c	(revision 198220)
+++ cp/init.c	(working copy)
@@ -1817,7 +1817,8 @@  get_type_value (tree name)
    @@ This function should be rewritten and placed in search.c.  */
 
 tree
-build_offset_ref (tree type, tree member, bool address_p)
+build_offset_ref (tree type, tree member, bool address_p,
+		  tsubst_flags_t complain)
 {
   tree decl;
   tree basebinfo = NULL_TREE;
@@ -1841,7 +1842,8 @@  tree
   type = TYPE_MAIN_VARIANT (type);
   if (!COMPLETE_OR_OPEN_TYPE_P (complete_type (type)))
     {
-      error ("incomplete type %qT does not have member %qD", type, member);
+      if (complain & tf_error)
+	error ("incomplete type %qT does not have member %qD", type, member);
       return error_mark_node;
     }
 
@@ -1854,7 +1856,8 @@  tree
 
   if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member))
     {
-      error ("invalid pointer to bit-field %qD", member);
+      if (complain & tf_error)
+	error ("invalid pointer to bit-field %qD", member);
       return error_mark_node;
     }
 
@@ -1883,10 +1886,10 @@  tree
 	  if (address_p && DECL_P (t)
 	      && DECL_NONSTATIC_MEMBER_P (t))
 	    perform_or_defer_access_check (TYPE_BINFO (type), t, t,
-					   tf_warning_or_error);
+					   complain);
 	  else
 	    perform_or_defer_access_check (basebinfo, t, t,
-					   tf_warning_or_error);
+					   complain);
 
 	  if (DECL_STATIC_FUNCTION_P (t))
 	    return t;
@@ -1900,7 +1903,7 @@  tree
        check_accessibility_of_qualified_id in case it is
        a pointer to non-static member.  */
     perform_or_defer_access_check (TYPE_BINFO (type), member, member,
-				   tf_warning_or_error);
+				   complain);
 
   if (!address_p)
     {
@@ -1932,15 +1935,17 @@  tree
 	  if (flag_ms_extensions)
 	    {
 	      PTRMEM_OK_P (member) = 1;
-	      return cp_build_addr_expr (member, tf_warning_or_error);
+	      return cp_build_addr_expr (member, complain);
 	    }
-	  error ("invalid use of non-static member function %qD",
-		 TREE_OPERAND (member, 1));
+	  if (complain & tf_error)
+	    error ("invalid use of non-static member function %qD",
+		   TREE_OPERAND (member, 1));
 	  return error_mark_node;
 	}
       else if (TREE_CODE (member) == FIELD_DECL)
 	{
-	  error ("invalid use of non-static data member %qD", member);
+	  if (complain & tf_error)
+	    error ("invalid use of non-static data member %qD", member);
 	  return error_mark_node;
 	}
       return member;
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 198220)
+++ cp/pt.c	(working copy)
@@ -12053,7 +12053,7 @@  tsubst_qualified_id (tree qualified_id, tree args,
       expr = (finish_qualified_id_expr
 	      (scope, expr, done, address_p && PTRMEM_OK_P (qualified_id),
 	       QUALIFIED_NAME_IS_TEMPLATE (qualified_id),
-	       /*template_arg_p=*/false));
+	       /*template_arg_p=*/false, complain));
     }
 
   /* Expressions do not generally have reference type.  */
@@ -16040,7 +16040,7 @@  resolve_nondeduced_context (tree orig_expr)
 	    {
 	      tree base
 		= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (offset, 0)));
-	      expr = build_offset_ref (base, expr, addr);
+	      expr = build_offset_ref (base, expr, addr, tf_warning_or_error);
 	    }
 	  if (addr)
 	    expr = cp_build_addr_expr (expr, tf_warning_or_error);
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 198220)
+++ cp/semantics.c	(working copy)
@@ -1772,7 +1772,8 @@  finish_qualified_id_expr (tree qualifying_class,
 			  bool done,
 			  bool address_p,
 			  bool template_p,
-			  bool template_arg_p)
+			  bool template_arg_p,
+			  tsubst_flags_t complain)
 {
   gcc_assert (TYPE_P (qualifying_class));
 
@@ -1792,7 +1793,7 @@  finish_qualified_id_expr (tree qualifying_class,
       if (TREE_CODE (expr) == SCOPE_REF)
 	expr = TREE_OPERAND (expr, 1);
       expr = build_offset_ref (qualifying_class, expr,
-			       /*address_p=*/true);
+			       /*address_p=*/true, complain);
       return expr;
     }
 
@@ -1826,11 +1827,12 @@  finish_qualified_id_expr (tree qualifying_class,
 		 expr,
 		 BASELINK_ACCESS_BINFO (expr),
 		 /*preserve_reference=*/false,
-		 tf_warning_or_error));
+		 complain));
       else if (done)
 	/* The expression is a qualified name whose address is not
 	   being taken.  */
-	expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false);
+	expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false,
+				 complain);
     }
   else if (BASELINK_P (expr))
     ;
@@ -3278,7 +3280,8 @@  finish_id_expression (tree id_expression,
 		    decl = finish_qualified_id_expr (scope, decl,
 						     done, address_p,
 						     template_p,
-						     template_arg_p);
+						     template_arg_p,
+						     tf_warning_or_error);
 		  else
 		    {
 		      tree type = NULL_TREE;
@@ -3394,7 +3397,8 @@  finish_id_expression (tree id_expression,
 					     done,
 					     address_p,
 					     template_p,
-					     template_arg_p);
+					     template_arg_p,
+					     tf_warning_or_error);
 	  else
 	    decl = convert_from_reference (decl);
 	}
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 198220)
+++ cp/typeck.c	(working copy)
@@ -5164,7 +5164,7 @@  cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 		       "  Say %<&%T::%D%>",
 		       base, name);
 	}
-      arg = build_offset_ref (base, fn, /*address_p=*/true);
+      arg = build_offset_ref (base, fn, /*address_p=*/true, complain);
     }
 
   /* Uninstantiated types are all functions.  Taking the
Index: testsuite/g++.dg/cpp0x/sfinae45.C
===================================================================
--- testsuite/g++.dg/cpp0x/sfinae45.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/sfinae45.C	(working copy)
@@ -0,0 +1,35 @@ 
+// PR c++/56970
+// { dg-do compile { target c++11 } }
+
+template <typename T>
+struct has
+{
+  template <typename>
+  constexpr static int test(...) {
+    return 0;
+  }
+  
+  template <typename C>
+  constexpr static int test(decltype(sizeof(C::x))) {  // Doesn't compile.
+    return 1;   // Is a member variable.
+  }
+  
+  template <typename C, int c = sizeof(decltype(((C*)nullptr)->x()))>
+  constexpr static int test(int) {
+    return 2;   // Is a member function.
+  }
+
+  static const int value = test<T>(0);
+};
+
+struct foo {
+  int x;
+};
+
+struct bar {
+  int x();
+};
+
+static_assert(has<int>::value == 0, "");
+static_assert(has<foo>::value == 1, "");
+static_assert(has<bar>::value == 2, "");