This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PR c++/81124] inline namespace checking


This fixes 81124, where we used ovl_iterate to iterate over a lookup result. We should always use lkp_iterate in those circumstances.

However, regular lookup is not what we want here. We don't want to follow using directives -- just look in the local inline hierarchy. Plus also ignore decls found by using declarations.

Finally, I could also fix 79766, by moving the excessive-qualification check to after finding the decl. '::foo' is perfectly fine to discover foo in an inline child namespace.

nathan
--
Nathan Sidwell
2017-06-19  Nathan Sidwell  <nathan@acm.org>

	PR c++/81124
	PR c++/79766
	* name-lookup.c (set_decl_namespace): Don't follow using
	directives and ignore using decls.  Only check overly-explicit
	scope after discovering decl.

	* g++.dg/lookup/pr79766.C: New.
	* g++.dg/lookup/pr81124.C: New.
	* g++.dg/template/explicit6.C: Adjust.
	* g++.old-deja/g++.other/decl5.C: Adjust.

Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 249369)
+++ cp/name-lookup.c	(working copy)
@@ -4266,8 +4266,6 @@ set_global_binding (tree name, tree val)
 void
 set_decl_namespace (tree decl, tree scope, bool friendp)
 {
-  tree old;
-
   /* Get rid of namespace aliases.  */
   scope = ORIGINAL_NAMESPACE (scope);
 
@@ -4277,41 +4275,49 @@ set_decl_namespace (tree decl, tree scop
 	   decl, scope);
   DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
 
-  /* Writing "int N::i" to declare a variable within "N" is invalid.  */
-  if (scope == current_namespace)
-    {
-      if (at_namespace_scope_p ())
-	error ("explicit qualification in declaration of %qD",
-	       decl);
-      return;
-    }
+  /* See whether this has been declared in the namespace or inline
+     children.  */
+  tree old = NULL_TREE;
+  {
+    name_lookup lookup (DECL_NAME (decl), LOOKUP_HIDDEN);
+    if (!lookup.search_qualified (scope, /*usings=*/false))
+      /* No old declaration at all.  */
+      goto not_found;
+    old = lookup.value;
+  }
 
-  /* See whether this has been declared in the namespace.  */
-  old = lookup_qualified_name (scope, DECL_NAME (decl), /*type*/false,
-			       /*complain*/true, /*hidden*/true);
-  if (old == error_mark_node)
-    /* No old declaration at all.  */
-    goto complain;
   /* If it's a TREE_LIST, the result of the lookup was ambiguous.  */
   if (TREE_CODE (old) == TREE_LIST)
     {
+    ambiguous:
+      DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
       error ("reference to %qD is ambiguous", decl);
       print_candidates (old);
       return;
     }
-  if (!OVL_P (decl))
+
+  if (!DECL_DECLARES_FUNCTION_P (decl))
     {
-      /* We might have found OLD in an inline namespace inside SCOPE.  */
-      if (TREE_CODE (decl) == TREE_CODE (old))
-	DECL_CONTEXT (decl) = DECL_CONTEXT (old);
       /* Don't compare non-function decls with decls_match here, since
 	 it can't check for the correct constness at this
-	 point. pushdecl will find those errors later.  */
+	 point.  pushdecl will find those errors later.  */
+
+      /* We might have found it in an inline namespace child of SCOPE.  */
+      if (TREE_CODE (decl) == TREE_CODE (old))
+	DECL_CONTEXT (decl) = DECL_CONTEXT (old);
+
+    found:
+      /* Writing "N::i" to declare something directly in "N" is invalid.  */
+      if (CP_DECL_CONTEXT (decl) == current_namespace
+	  && at_namespace_scope_p ())
+	error ("explicit qualification in declaration of %qD", decl);
       return;
     }
+
   /* Since decl is a function, old should contain a function decl.  */
   if (!OVL_P (old))
-    goto complain;
+    goto not_found;
+
   /* We handle these in check_explicit_instantiation_namespace.  */
   if (processing_explicit_instantiation)
     return;
@@ -4325,53 +4331,48 @@ set_decl_namespace (tree decl, tree scop
      friends in any namespace.  */
   if (friendp && DECL_USE_TEMPLATE (decl))
     return;
-  if (OVL_P (old))
+
+  tree found;
+  found = NULL_TREE;
+
+  for (lkp_iterator iter (old); iter; ++iter)
     {
-      tree found = NULL_TREE;
+      if (iter.using_p ())
+	continue;
 
-      for (ovl_iterator iter (old); iter; ++iter)
-	{
-	  tree ofn = *iter;
-	  /* Adjust DECL_CONTEXT first so decls_match will return true
-	     if DECL will match a declaration in an inline namespace.  */
-	  DECL_CONTEXT (decl) = DECL_CONTEXT (ofn);
-	  if (decls_match (decl, ofn))
-	    {
-	      if (found && !decls_match (found, ofn))
-		{
-		  DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
-		  error ("reference to %qD is ambiguous", decl);
-		  print_candidates (old);
-		  return;
-		}
-	      found = ofn;
-	    }
-	}
-      if (found)
+      tree ofn = *iter;
+
+      /* Adjust DECL_CONTEXT first so decls_match will return true
+	 if DECL will match a declaration in an inline namespace.  */
+      DECL_CONTEXT (decl) = DECL_CONTEXT (ofn);
+      if (decls_match (decl, ofn))
 	{
-	  if (!is_nested_namespace (scope, CP_DECL_CONTEXT (found), true))
-	    goto complain;
-	  if (DECL_HIDDEN_FRIEND_P (found))
+	  if (found)
 	    {
-	      pedwarn (DECL_SOURCE_LOCATION (decl), 0,
-		       "%qD has not been declared within %qD", decl, scope);
-	      inform (DECL_SOURCE_LOCATION (found),
-		      "only here as a %<friend%>");
+	      /* We found more than one matching declaration.  */
+	      DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
+	      goto ambiguous;
 	    }
-	  DECL_CONTEXT (decl) = DECL_CONTEXT (found);
-	  return;
+	  found = ofn;
 	}
     }
-  else
+
+  if (found)
     {
-      DECL_CONTEXT (decl) = DECL_CONTEXT (old);
-      if (decls_match (decl, old))
-	return;
+      if (DECL_HIDDEN_FRIEND_P (found))
+	{
+	  pedwarn (DECL_SOURCE_LOCATION (decl), 0,
+		   "%qD has not been declared within %qD", decl, scope);
+	  inform (DECL_SOURCE_LOCATION (found),
+		  "only here as a %<friend%>");
+	}
+      DECL_CONTEXT (decl) = DECL_CONTEXT (found);
+      goto found;
     }
 
+ not_found:
   /* It didn't work, go back to the explicit scope.  */
   DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
- complain:
   error ("%qD should have been declared inside %qD", decl, scope);
 }
 
Index: testsuite/g++.dg/lookup/pr79766.C
===================================================================
--- testsuite/g++.dg/lookup/pr79766.C	(nonexistent)
+++ testsuite/g++.dg/lookup/pr79766.C	(working copy)
@@ -0,0 +1,29 @@
+// { dg-do compile { target c++11 } }
+// PR 79766 qualified name to find inline namespace is ok
+
+namespace Y 
+{
+  inline namespace X
+  {
+    void Q ();
+  }
+}
+
+void Y::Q () // OK -> Y::X::Q
+{
+}
+
+inline namespace Z
+{
+  void R ();
+}
+
+void ::R () // OK -> Z::R
+{
+}
+
+void S ();
+
+void ::S () // { dg-error "explicit qualification" }
+{
+}
Index: testsuite/g++.dg/lookup/pr81124.C
===================================================================
--- testsuite/g++.dg/lookup/pr81124.C	(nonexistent)
+++ testsuite/g++.dg/lookup/pr81124.C	(working copy)
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+// c++/81124 ICE with inline namespace
+
+namespace std {
+inline namespace {
+int to_string();
+void to_string(int);
+}
+void to_string();
+}
+int std::to_string();
Index: testsuite/g++.dg/template/explicit6.C
===================================================================
--- testsuite/g++.dg/template/explicit6.C	(revision 249364)
+++ testsuite/g++.dg/template/explicit6.C	(working copy)
@@ -5,4 +5,4 @@
 // Bug 19895: ICE on invalid
 
 struct A;
-template A<>::A(); // { dg-error "(not a template)|(explicit qualification)" }
+template A<>::A(); // { dg-error "(should have been)|(not a template)" }
Index: testsuite/g++.old-deja/g++.other/decl5.C
===================================================================
--- testsuite/g++.old-deja/g++.other/decl5.C	(revision 249364)
+++ testsuite/g++.old-deja/g++.other/decl5.C	(working copy)
@@ -53,8 +53,8 @@ namespace N {
 
 namespace NMS
 {
-  void NMS::fn();     // { dg-error "explicit qual" }
-  int NMS::i;         // { dg-error "explicit qual" }
+  void NMS::fn();     // { dg-error "should have been" }
+  int NMS::i;         // { dg-error "should have been" }
   struct NMS::D {     // { dg-error "does not name a class" }
     int i;
   };

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]