diff mbox

Fix for PR c++/46170

Message ID m3aalyrhol.fsf@tutu.torimasen.com
State New
Headers show

Commit Message

Dodji Seketeli Oct. 28, 2010, 5:48 a.m. UTC
Hello,

In the example of the patch below, a tentative substitution failure is
reported as an error. While instantiating set_member_constant<bool,
&cflat_options::show_precharges, true>, check_valid_ptrmem_cst_expr
indirectly called during type unification emits an error diagnostic.

The current patch adds a COMPLAIN parameter to
check_valid_ptrmem_cst_expr to make avoid emitting an error in a SFINAE
context.


Tested on x86_64-unknown-linux-gnu against trunk.

Comments

Jason Merrill Oct. 28, 2010, 12:30 p.m. UTC | #1
OK.

Jason
diff mbox

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 85a5ea5..a5c95c5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -4904,14 +4904,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;
 }
 
@@ -5283,7 +5287,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
@@ -5315,7 +5319,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/g++.dg/template/sfinae26.C b/gcc/testsuite/g++.dg/template/sfinae26.C
new file mode 100644
index 0000000..41673fb
--- /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");