re PR c++/81124 (internal compiler error: in operator*, at cp/cp-tree.h:726)
authorNathan Sidwell <nathan@acm.org>
Mon, 19 Jun 2017 19:11:31 +0000 (19:11 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 19 Jun 2017 19:11:31 +0000 (19:11 +0000)
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.

From-SVN: r249385

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/pr79766.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/pr81124.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/explicit6.C
gcc/testsuite/g++.old-deja/g++.other/decl5.C

index 55ba486d9f226fde6ee277b027e4efc0eeab5fbd..b80d3738319c48cb8488b82856f636774fe68871 100644 (file)
@@ -1,3 +1,11 @@
+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.
+
 2017-06-19  Jason Merrill  <jason@redhat.com>
 
        PR c++/81073 - constexpr and static var in statement-expression.
index a337942d6ae118a202bd33b48eaa5292d7cc4e95..e91b89cf15b29e0fe68ed9f486973440346aa323 100644 (file)
@@ -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 scope, bool friendp)
           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 scope, bool friendp)
      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 80ebf57cd902c9bb517f309bd2c68a8c12bc55e5..3c17355f3f57520092758a9314fae90e08ff16f4 100644 (file)
@@ -1,3 +1,12 @@
+2017-06-19  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/81124
+       PR c++/79766
+       * 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.
+
 2017-06-19  Christophe Lyon  <christophe.lyon@linaro.org>
 
        * g++.old-deja/g++.eh/badalloc1.C: Remove code path for
diff --git a/gcc/testsuite/g++.dg/lookup/pr79766.C b/gcc/testsuite/g++.dg/lookup/pr79766.C
new file mode 100644 (file)
index 0000000..de9bbb5
--- /dev/null
@@ -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" }
+{
+}
diff --git a/gcc/testsuite/g++.dg/lookup/pr81124.C b/gcc/testsuite/g++.dg/lookup/pr81124.C
new file mode 100644 (file)
index 0000000..d80d88a
--- /dev/null
@@ -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 a28fd9e66a39860650fdc80d867465a5cbd2f93c..24fa50df209ec97dfd0606cdfe3cd97d99f8ce7c 100644 (file)
@@ -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 9167061c6b1f5554955432412ce1375748634cfc..3ac91379e762688eddef90324e72474716927202 100644 (file)
@@ -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;
   };