From 6c74ff23008028116fa0ee942d2905e56a55fbab Mon Sep 17 00:00:00 2001
From: Jason Merrill <jason@redhat.com>
Date: Tue, 26 Mar 2013 23:01:41 -0400
Subject: [PATCH] re PR c++/52597 ([C++11] confusing diagnostics for invalid
 use of non-static member function in decltype)

	PR c++/52597
	* typeck.c (invalid_nonstatic_memfn_p): Use get_first_fn.  Take tree.
	* semantics.c (finish_decltype_type): Check it before type_unknown_p.
	* cp-tree.h: Adjust prototype.

From-SVN: r197131
---
 gcc/cp/ChangeLog                             |  5 +++++
 gcc/cp/cp-tree.h                             |  2 +-
 gcc/cp/semantics.c                           |  6 +++---
 gcc/cp/typeck.c                              | 11 +++++++++--
 gcc/testsuite/g++.dg/cpp0x/decltype50.C      | 18 ++++++++++++++++++
 gcc/testsuite/g++.dg/template/overload6.C    |  5 ++---
 gcc/testsuite/g++.dg/template/ptrmem4.C      |  4 ++--
 gcc/testsuite/g++.old-deja/g++.mike/p11110.C |  5 ++---
 8 files changed, 42 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype50.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0c5bcee6ebe3..3fe07d9711b7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
 2013-03-26  Jason Merrill  <jason@redhat.com>
 
+	PR c++/52597
+	* typeck.c (invalid_nonstatic_memfn_p): Use get_first_fn.  Take tree.
+	* semantics.c (finish_decltype_type): Check it before type_unknown_p.
+	* cp-tree.h: Adjust prototype.
+
 	PR c++/45282
 	* typeck2.c (build_m_component_ref): Handle prvalue object.
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 401868549cda..36671d5c3a3f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5988,7 +5988,7 @@ extern tree build_typed_address			(tree, tree);
 extern tree build_nop				(tree, tree);
 extern tree non_reference			(tree);
 extern tree lookup_anon_field			(tree, tree);
-extern bool invalid_nonstatic_memfn_p		(const_tree, tsubst_flags_t);
+extern bool invalid_nonstatic_memfn_p		(tree, tsubst_flags_t);
 extern tree convert_member_func_to_ptr		(tree, tree, tsubst_flags_t);
 extern tree convert_ptrmem			(tree, tree, bool, bool,
 						 tsubst_flags_t);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 333980e88e7a..e8fc778dd2ec 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5275,6 +5275,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
 
   expr = resolve_nondeduced_context (expr);
 
+  if (invalid_nonstatic_memfn_p (expr, complain))
+    return error_mark_node;
+
   if (type_unknown_p (expr))
     {
       if (complain & tf_error)
@@ -5282,9 +5285,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
       return error_mark_node;
     }
 
-  if (invalid_nonstatic_memfn_p (expr, complain))
-    return error_mark_node;
-
   /* To get the size of a static data member declared as an array of
      unknown bound, we need to instantiate it.  */
   if (TREE_CODE (expr) == VAR_DECL
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 4e42a9d3d7b6..8778b2cf7b91 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1766,9 +1766,16 @@ cxx_alignas_expr (tree e)
    violates these rules.  */
 
 bool
-invalid_nonstatic_memfn_p (const_tree expr, tsubst_flags_t complain)
+invalid_nonstatic_memfn_p (tree expr, tsubst_flags_t complain)
 {
-  if (expr && DECL_NONSTATIC_MEMBER_FUNCTION_P (expr))
+  if (expr == NULL_TREE)
+    return false;
+  /* Don't enforce this in MS mode.  */
+  if (flag_ms_extensions)
+    return false;
+  if (is_overloaded_fn (expr) && !really_overloaded_fn (expr))
+    expr = get_first_fn (expr);
+  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (expr))
     {
       if (complain & tf_error)
         error ("invalid use of non-static member function");
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype50.C b/gcc/testsuite/g++.dg/cpp0x/decltype50.C
new file mode 100644
index 000000000000..dc3332ac5253
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype50.C
@@ -0,0 +1,18 @@
+// PR c++/52597
+// { dg-require-effective-target c++11 }
+
+struct A {
+   int zip();
+
+   decltype(zip) bar0; // { dg-error "invalid use of non-static member function" }
+   void bar1() {
+     typedef decltype(this->A::zip) x; // { dg-error "invalid use of non-static member function" }
+   }
+   void bar2() {
+     typedef decltype(A::zip) x; // { dg-error "invalid use of non-static member function" }
+   }
+};
+
+typedef decltype(A().zip) x; // { dg-error "invalid use of non-static member function" }
+
+// { dg-prune-output "invalid type in declaration" }
diff --git a/gcc/testsuite/g++.dg/template/overload6.C b/gcc/testsuite/g++.dg/template/overload6.C
index 5e26c448b18a..8d574e73087b 100644
--- a/gcc/testsuite/g++.dg/template/overload6.C
+++ b/gcc/testsuite/g++.dg/template/overload6.C
@@ -4,7 +4,7 @@
 // PR 21592:ICE
 // Origin:  Volker Reichelt <reichelt@gcc.gnu.org>
 
-template<typename T> void unique(T,T); // { dg-message "note" }
+template<typename T> void unique(T,T);
 
 struct A
 {
@@ -13,6 +13,5 @@ struct A
 
 template<int> void foo()
 {
-  unique(A().begin); // { dg-error "no matching function" "" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 16 }
+  unique(A().begin); // { dg-error "invalid use of non-static member function" }
 }
diff --git a/gcc/testsuite/g++.dg/template/ptrmem4.C b/gcc/testsuite/g++.dg/template/ptrmem4.C
index 14f36d4e386f..076503202c01 100644
--- a/gcc/testsuite/g++.dg/template/ptrmem4.C
+++ b/gcc/testsuite/g++.dg/template/ptrmem4.C
@@ -6,7 +6,7 @@
 // Pointer to member function template argument deduction ICE.
 
 
-template <class CONT> void queryAliases(CONT& fill_me); // { dg-message "queryAliases|no known conversion" }
+template <class CONT> void queryAliases(CONT& fill_me);
 
 struct SpyExample
 {
@@ -16,5 +16,5 @@ struct SpyExample
 
 void SpyExample::ready()
 {
-  queryAliases(inputs); // { dg-error "matching|unresolved" }
+  queryAliases(inputs); // { dg-error "invalid" }
 }
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p11110.C b/gcc/testsuite/g++.old-deja/g++.mike/p11110.C
index 7e3a1ffa3353..714f628f5efb 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p11110.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p11110.C
@@ -6,7 +6,7 @@ class data;
 class conatiner {
 public:
   virtual void* first    ();
-  virtual data* contents (void* i);     // { dg-message "conatiner::contents|no known conversion" }
+  virtual data* contents (void* i);
 };
 
 class user {
@@ -17,6 +17,5 @@ private:
 };
 
 data* user::data1() const {
-  return (_c.contents (_c.first));	// { dg-error "match" } 
-  // { dg-message "candidate" "candidate note" { target *-*-* } 20 }
+  return (_c.contents (_c.first)); // { dg-error "invalid use of non-static member function" }
 }
-- 
GitLab