diff mbox series

[PR,c++/82710] false positive paren warning

Message ID 39398177-ddf0-51de-78d1-7129062ab448@acm.org
State New
Headers show
Series [PR,c++/82710] false positive paren warning | expand

Commit Message

Nathan Sidwell Nov. 2, 2017, 6:24 p.m. UTC
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.

nathan

Comments

Nathan Sidwell Nov. 3, 2017, 1:14 p.m. UTC | #1
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
diff mbox series

Patch

2017-11-02  Nathan Sidwell  <nathan@acm.org>

	PR c++/82710
	* decl.c (grokdeclarator): Don't warn when parens protect a return
	type from a qualified name.

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

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 254344)
+++ cp/decl.c	(working copy)
@@ -10788,18 +10788,25 @@  grokdeclarator (const cp_declarator *dec
 					    attr_flags);
 	}
 
+      inner_declarator = declarator->declarator;
+
       /* We don't want to warn in parmeter context because we don't
 	 yet know if the parse will succeed, and this might turn out
 	 to be a constructor call.  */
       if (decl_context != PARM
-	  && declarator->parenthesized != UNKNOWN_LOCATION)
+	  && 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
+	       && inner_declarator->kind == cdk_id
+	       && inner_declarator->u.id.qualifying_scope))
 	warning_at (declarator->parenthesized, OPT_Wparentheses,
 		    "unnecessary parentheses in declaration of %qs", name);
       if (declarator->kind == cdk_id || declarator->kind == cdk_decomp)
 	break;
 
-      inner_declarator = declarator->declarator;
-
       switch (declarator->kind)
 	{
 	case cdk_array:
Index: testsuite/g++.dg/warn/pr82710.C
===================================================================
--- testsuite/g++.dg/warn/pr82710.C	(revision 0)
+++ testsuite/g++.dg/warn/pr82710.C	(working copy)
@@ -0,0 +1,32 @@ 
+// { dg-additional-options -Wparentheses }
+
+// the MVP warning triggered on a friend decl.  */
+class X;
+
+namespace here 
+{
+  // these friends
+  X friendFunc1();
+  X *friendFunc2 ();
+  int friendFunc3 ();
+}
+
+namespace nm
+{
+  namespace here 
+  {
+    // Not these friends
+    void friendFunc1 ();
+    void friendFunc2 ();
+    void friendFunc3 ();
+  }
+
+  class TestClass
+  {
+    friend X (::here::friendFunc1 ()); // parens are needed
+    friend X *(::here::friendFunc2 ()); // { dg-warning "" }
+    friend X *::here::friendFunc2 ();
+    friend int (::here::friendFunc3 ()); // { dg-warning "" }
+  };
+}
+