On 11/02/2017 02:24 PM, Nathan Sidwell wrote:
This patch fixes pr82710, were we erroneously warn on something like:
    friend class_X (::other::name (...));
the parens are needed, otherwise the '::other' is taken to be a qualified lookup inside the class_X.

Unfortunately, at the point we can check, we've lost information that '::' was used.  So I back off when we see a qualified name there.

I realized CLASS_TYPE_P was overly restrictive. There are other class-like entities that also need protection (typename_types etc). Fixed with this patch that uses MAYBE_CLASS_TYPE and ENUMERAL_TYPE. I pushed this test to the end, as it is more complicated, so we'll only get to it after we know we have a qualified name.

nathan

--
Nathan Sidwell
2017-11-03  Nathan Sidwell  <nat...@acm.org>

	PR c++/82710
	* decl.c (grokdeclarator): Protect MAYBE_CLASS things from paren
	warning too.

	PR c++/82710
	* g++.dg/warn/pr82710.C: More cases.

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 254350)
+++ cp/decl.c	(working copy)
@@ -10795,13 +10795,15 @@ grokdeclarator (const cp_declarator *dec
 	 to be a constructor call.  */
       if (decl_context != PARM
 	  && declarator->parenthesized != UNKNOWN_LOCATION
-	  /* If the type is a class and the inner name used a global
-	     namespace qualifier, we need the parens.  Unfortunately
-	     all we can tell is that a qualified name was used.  */
-	  && !(CLASS_TYPE_P (type)
-	       && inner_declarator
+	  /* If the type is class-like and the inner name used a
+	     global namespace qualifier, we need the parens.
+	     Unfortunately all we can tell is whether a qualified name
+	     was used or not.  */
+	  && !(inner_declarator
 	       && inner_declarator->kind == cdk_id
-	       && inner_declarator->u.id.qualifying_scope))
+	       && inner_declarator->u.id.qualifying_scope
+	       && (MAYBE_CLASS_TYPE_P (type)
+		   || TREE_CODE (type) == ENUMERAL_TYPE)))
 	warning_at (declarator->parenthesized, OPT_Wparentheses,
 		    "unnecessary parentheses in declaration of %qs", name);
       if (declarator->kind == cdk_id || declarator->kind == cdk_decomp)
Index: testsuite/g++.dg/warn/pr82710.C
===================================================================
--- testsuite/g++.dg/warn/pr82710.C	(revision 254349)
+++ testsuite/g++.dg/warn/pr82710.C	(working copy)
@@ -1,7 +1,10 @@
-// { dg-additional-options -Wparentheses }
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wparentheses -Wno-non-template-friend" }
 
 // the MVP warning triggered on a friend decl.  */
 class X;
+enum class Q {}; // C++ 11ness
+enum R {};
 
 namespace here 
 {
@@ -9,6 +12,9 @@ namespace here
   X friendFunc1();
   X *friendFunc2 ();
   int friendFunc3 ();
+  int bob ();
+  Q bill ();
+  R ben ();
 }
 
 namespace nm
@@ -19,6 +25,9 @@ namespace nm
     void friendFunc1 ();
     void friendFunc2 ();
     void friendFunc3 ();
+    int bob ();
+    Q bill ();
+    R ben ();
   }
 
   class TestClass
@@ -28,5 +37,12 @@ namespace nm
     friend X *::here::friendFunc2 ();
     friend int (::here::friendFunc3 ()); // { dg-warning "" }
   };
+
+  template <typename T> class X
+  {
+    friend typename T::frob (::here::bob ());
+    friend Q (::here::bill ());
+    friend R (::here::ben ());
+  };
 }
 

Reply via email to