From 574e2ba2eec1097f3decd0ade984097e425a4d7f Mon Sep 17 00:00:00 2001
From: Dodji Seketeli <dodji@redhat.com>
Date: Tue, 2 Nov 2010 12:58:48 +0000
Subject: [PATCH] Fix PR c++/46170, c++/46162

gcc/cp/ChangeLog:
	PR c++/46170
	PR c++/46162
	* pt.c (check_valid_ptrmem_cst_expr): Add a complain parameter to
	control diagnostic.
	(convert_nontype_argument, convert_nontype_argument): Pass the
	complain parameter down to check_valid_ptrmem_cst_expr.

gcc/testsuite/ChangeLog:
	PR c++/46170
	PR c++/46162
	* g++.dg/template/sfinae26.C: New test.
	* g++.dg/template/sfinae27.C: Likewise.

From-SVN: r166181
---
 gcc/cp/ChangeLog                         |  8 ++++++
 gcc/cp/pt.c                              | 16 ++++++-----
 gcc/testsuite/ChangeLog                  |  7 +++++
 gcc/testsuite/g++.dg/template/sfinae26.C | 34 ++++++++++++++++++++++++
 gcc/testsuite/g++.dg/template/sfinae27.C | 33 +++++++++++++++++++++++
 5 files changed, 92 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/sfinae26.C
 create mode 100644 gcc/testsuite/g++.dg/template/sfinae27.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1ab6854ea8a8..66b6671defd4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,13 @@
 2010-11-02  Dodji Seketeli  <dodji@redhat.com>
 
+	PR c++/46170
+	PR c++/46162
+	* pt.c (check_valid_ptrmem_cst_expr): Add a complain parameter to
+	 control diagnostic.
+	(convert_nontype_argument, convert_nontype_argument): Pass the
+	complain parameter down to check_valid_ptrmem_cst_expr.
+
+2010-11-02  Dodji Seketeli  <dodji@redhat.com>
 	PR c++/45606
 	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
 	(struct template_parm_index_s)<num_siblings>: New field.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e4975c6a1120..21366d962e94 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5224,14 +5224,18 @@ convert_nontype_argument_function (tree type, tree expr)
    Emit an error otherwise.  */
 
 static bool
-check_valid_ptrmem_cst_expr (tree type, tree expr)
+check_valid_ptrmem_cst_expr (tree type, tree expr,
+			     tsubst_flags_t complain)
 {
   STRIP_NOPS (expr);
   if (expr && (null_ptr_cst_p (expr) || TREE_CODE (expr) == PTRMEM_CST))
     return true;
-  error ("%qE is not a valid template argument for type %qT",
-	 expr, type);
-  error ("it must be a pointer-to-member of the form `&X::Y'");
+  if (complain & tf_error)
+    {
+      error ("%qE is not a valid template argument for type %qT",
+	     expr, type);
+      error ("it must be a pointer-to-member of the form `&X::Y'");
+    }
   return false;
 }
 
@@ -5600,7 +5604,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 
       /* [temp.arg.nontype] bullet 1 says the pointer to member
          expression must be a pointer-to-member constant.  */
-      if (!check_valid_ptrmem_cst_expr (type, expr))
+      if (!check_valid_ptrmem_cst_expr (type, expr, complain))
 	return error_mark_node;
 
       /* There is no way to disable standard conversions in
@@ -5632,7 +5636,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
     {
       /* [temp.arg.nontype] bullet 1 says the pointer to member
          expression must be a pointer-to-member constant.  */
-      if (!check_valid_ptrmem_cst_expr (type, expr))
+      if (!check_valid_ptrmem_cst_expr (type, expr, complain))
 	return error_mark_node;
 
       expr = perform_qualification_conversions (type, expr);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b784b1cad8d3..9e657754de5c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2010-11-02  Dodji Seketeli  <dodji@redhat.com>
+
+	PR c++/46170
+    	PR c++/46162
+	* g++.dg/template/sfinae26.C: New test.
+	* g++.dg/template/sfinae27.C: Likewise.
+
 2010-11-02  Dodji Seketeli  <dodji@redhat.com>
 
 	PR c++/45606
diff --git a/gcc/testsuite/g++.dg/template/sfinae26.C b/gcc/testsuite/g++.dg/template/sfinae26.C
new file mode 100644
index 000000000000..41673fb48d92
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/sfinae26.C
@@ -0,0 +1,34 @@
+// Origin: PR c++/46170
+// { dg-do "compile" }
+
+namespace util {
+  struct option_value {
+  };
+  template <class T> struct options_map_impl {
+    typedef T options_struct_type;
+    typedef bool (*opt_func)(const option_value&, options_struct_type&);
+    template <class V, V K>  static  bool  set_member_constant(const option_value&,
+							       options_struct_type&, V options_struct_type::*);
+    template <class V, V options_struct_type::*mem, V K>  static  bool 
+    set_member_constant(const option_value& opt, options_struct_type& t) {
+      return set_member_constant<V,K>(opt, t, mem);
+    }
+  };
+}
+struct cflat_options {
+  bool show_precharges;
+};
+typedef util::options_map_impl<cflat_options> options_map_impl_type;
+class register_options_modifier {
+  typedef options_map_impl_type::opt_func modifier_type;
+public:  register_options_modifier();
+  register_options_modifier(const char* Mode,    const modifier_type COM,   
+			    const char* h);
+};
+static const register_options_modifier
+cflat_opt_mod_show_precharges("precharges",
+			      &options_map_impl_type::set_member_constant<bool,
+									  &cflat_options::show_precharges, true>, "show precharge expressions"),
+  cflat_opt_mod_no_show_precharges("no-" "precharges",
+				   &options_map_impl_type::set_member_constant<bool,
+									       &cflat_options::show_precharges, false>, "hide precharge expressions");
diff --git a/gcc/testsuite/g++.dg/template/sfinae27.C b/gcc/testsuite/g++.dg/template/sfinae27.C
new file mode 100644
index 000000000000..0ecd1700dec8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/sfinae27.C
@@ -0,0 +1,33 @@
+// Origin: PR c++/46162
+
+struct small_type { char dummy; };
+struct large_type { char dummy[2]; };
+
+template<class T>
+struct has_foo_member_variable
+{
+  template<int T::*> struct tester;
+  template<class U> static small_type has_foo(tester<&U::foo> *);
+  template<class U> static large_type has_foo(...);
+  static const bool value = (sizeof(has_foo<T>(0)) == sizeof(small_type));
+};
+
+struct A
+{
+  static int foo()
+  {
+    return 0;
+  }
+};
+
+struct B
+{
+  static int foo;
+};
+
+void
+bar()
+{
+  bool b = has_foo_member_variable<A>::value;
+}
+
-- 
GitLab