re PR c++/31749 (ICE with invalid redeclaration of builtin)
authorOllie Wild <aaw@google.com>
Fri, 17 Aug 2007 21:42:38 +0000 (21:42 +0000)
committerOllie Wild <aaw@gcc.gnu.org>
Fri, 17 Aug 2007 21:42:38 +0000 (21:42 +0000)
PR c++/31749

gcc/cp/
* name-lookup.c (do_nonmember_using_decl): Shift implicit type
declarations into appropriate slots for comparison.  Fix type
comparison.

gcc/testsuite/
* g++.dg/lookup/builtin3.C: New test.
* g++.dg/lookup/builtin4.C: New test.
* g++.dg/lookup/using19.C: New test.

From-SVN: r127600

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/builtin3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/builtin4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/using19.C [new file with mode: 0644]

index f01075d..9556496 100644 (file)
@@ -1,3 +1,10 @@
+2007-08-17  Ollie Wild  <aaw@google.com>
+
+       PR c++/31749
+       * name-lookup.c (do_nonmember_using_decl): Shift implicit type
+       declarations into appropriate slots for comparison.  Fix type
+       comparison.
+
 2007-08-17  Paolo Carlini  <pcarlini@suse.de>
 
        PR c++/32112
index 48b387a..5f7e718 100644 (file)
@@ -2099,6 +2099,20 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
       return;
     }
 
+  /* Shift the old and new bindings around so we're comparing class and
+     enumeration names to each other.  */
+  if (oldval && DECL_IMPLICIT_TYPEDEF_P (oldval))
+    {
+      oldtype = oldval;
+      oldval = NULL_TREE;
+    }
+
+  if (decls.value && DECL_IMPLICIT_TYPEDEF_P (decls.value))
+    {
+      decls.type = decls.value;
+      decls.value = NULL_TREE;
+    }
+
   /* It is impossible to overload a built-in function; any explicit
      declaration eliminates the built-in declaration.  So, if OLDVAL
      is a built-in, then we can just pretend it isn't there.  */
@@ -2108,87 +2122,91 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
       && !DECL_HIDDEN_FRIEND_P (oldval))
     oldval = NULL_TREE;
 
-  /* Check for using functions.  */
-  if (decls.value && is_overloaded_fn (decls.value))
+  if (decls.value)
     {
-      tree tmp, tmp1;
-
-      if (oldval && !is_overloaded_fn (oldval))
-       {
-         if (!DECL_IMPLICIT_TYPEDEF_P (oldval))
-           error ("%qD is already declared in this scope", name);
-         oldval = NULL_TREE;
-       }
-
-      *newval = oldval;
-      for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
+      /* Check for using functions.  */
+      if (is_overloaded_fn (decls.value))
        {
-         tree new_fn = OVL_CURRENT (tmp);
+         tree tmp, tmp1;
 
-         /* [namespace.udecl]
+         if (oldval && !is_overloaded_fn (oldval))
+           {
+             error ("%qD is already declared in this scope", name);
+             oldval = NULL_TREE;
+           }
 
-            If a function declaration in namespace scope or block
-            scope has the same name and the same parameter types as a
-            function introduced by a using declaration the program is
-            ill-formed.  */
-         for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
+         *newval = oldval;
+         for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
            {
-             tree old_fn = OVL_CURRENT (tmp1);
-
-             if (new_fn == old_fn)
-               /* The function already exists in the current namespace.  */
-               break;
-             else if (OVL_USED (tmp1))
-               continue; /* this is a using decl */
-             else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
-                                 TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
+             tree new_fn = OVL_CURRENT (tmp);
+
+             /* [namespace.udecl]
+
+                If a function declaration in namespace scope or block
+                scope has the same name and the same parameter types as a
+                function introduced by a using declaration the program is
+                ill-formed.  */
+             for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
                {
-                 gcc_assert (!DECL_ANTICIPATED (old_fn)
-                             || DECL_HIDDEN_FRIEND_P (old_fn));
+                 tree old_fn = OVL_CURRENT (tmp1);
 
-                 /* There was already a non-using declaration in
-                    this scope with the same parameter types. If both
-                    are the same extern "C" functions, that's ok.  */
-                 if (decls_match (new_fn, old_fn))
+                 if (new_fn == old_fn)
+                   /* The function already exists in the current namespace.  */
                    break;
-                 else
+                 else if (OVL_USED (tmp1))
+                   continue; /* this is a using decl */
+                 else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
+                                     TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
                    {
-                     error ("%qD is already declared in this scope", name);
-                     break;
+                     gcc_assert (!DECL_ANTICIPATED (old_fn)
+                                 || DECL_HIDDEN_FRIEND_P (old_fn));
+
+                     /* There was already a non-using declaration in
+                        this scope with the same parameter types. If both
+                        are the same extern "C" functions, that's ok.  */
+                     if (decls_match (new_fn, old_fn))
+                       break;
+                     else
+                       {
+                         error ("%qD is already declared in this scope", name);
+                         break;
+                       }
                    }
                }
-           }
-
-         /* If we broke out of the loop, there's no reason to add
-            this function to the using declarations for this
-            scope.  */
-         if (tmp1)
-           continue;
 
-         /* If we are adding to an existing OVERLOAD, then we no
-            longer know the type of the set of functions.  */
-         if (*newval && TREE_CODE (*newval) == OVERLOAD)
-           TREE_TYPE (*newval) = unknown_type_node;
-         /* Add this new function to the set.  */
-         *newval = build_overload (OVL_CURRENT (tmp), *newval);
-         /* If there is only one function, then we use its type.  (A
-            using-declaration naming a single function can be used in
-            contexts where overload resolution cannot be
-            performed.)  */
-         if (TREE_CODE (*newval) != OVERLOAD)
-           {
-             *newval = ovl_cons (*newval, NULL_TREE);
-             TREE_TYPE (*newval) = TREE_TYPE (OVL_CURRENT (tmp));
+             /* If we broke out of the loop, there's no reason to add
+                this function to the using declarations for this
+                scope.  */
+             if (tmp1)
+               continue;
+
+             /* If we are adding to an existing OVERLOAD, then we no
+                longer know the type of the set of functions.  */
+             if (*newval && TREE_CODE (*newval) == OVERLOAD)
+               TREE_TYPE (*newval) = unknown_type_node;
+             /* Add this new function to the set.  */
+             *newval = build_overload (OVL_CURRENT (tmp), *newval);
+             /* If there is only one function, then we use its type.  (A
+                using-declaration naming a single function can be used in
+                contexts where overload resolution cannot be
+                performed.)  */
+             if (TREE_CODE (*newval) != OVERLOAD)
+               {
+                 *newval = ovl_cons (*newval, NULL_TREE);
+                 TREE_TYPE (*newval) = TREE_TYPE (OVL_CURRENT (tmp));
+               }
+             OVL_USED (*newval) = 1;
            }
-         OVL_USED (*newval) = 1;
+       }
+      else
+       {
+         *newval = decls.value;
+         if (oldval && !decls_match (*newval, oldval))
+           error ("%qD is already declared in this scope", name);
        }
     }
   else
-    {
-      *newval = decls.value;
-      if (oldval && !decls_match (*newval, oldval))
-       error ("%qD is already declared in this scope", name);
-    }
+    *newval = oldval;
 
   if (decls.type && TREE_CODE (decls.type) == TREE_LIST)
     {
@@ -2198,13 +2216,16 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
   else
     {
       *newtype = decls.type;
-      if (oldtype && *newtype && !same_type_p (oldtype, *newtype))
-       {
-         error ("using declaration %qD introduced ambiguous type %qT",
-                name, oldtype);
-         return;
-       }
+      if (oldtype && *newtype && !decls_match (oldtype, *newtype))
+       error ("%qD is already declared in this scope", name);
     }
+
+    /* If *newval is empty, shift any class or enumeration name down.  */
+    if (!*newval)
+      {
+       *newval = *newtype;
+       *newtype = NULL_TREE;
+      }
 }
 
 /* Process a using-declaration at function scope.  */
index e08a327..2a637d5 100644 (file)
@@ -1,3 +1,10 @@
+2007-08-17  Ollie Wild  <aaw@google.com>
+
+       PR c++/31749
+       * g++.dg/lookup/builtin3.C: New test.
+       * g++.dg/lookup/builtin4.C: New test.
+       * g++.dg/lookup/using19.C: New test.
+
 2007-08-17  Paolo Carlini  <pcarlini@suse.de>
 
        PR c++/32190
diff --git a/gcc/testsuite/g++.dg/lookup/builtin3.C b/gcc/testsuite/g++.dg/lookup/builtin3.C
new file mode 100644 (file)
index 0000000..3a29d87
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright (C) 2007 Free Software Foundation
+// Contributed by Ollie Wild <aaw@google.com>
+// Origin: Volker Reichelt <reichelt@gcc.gnu.org>
+// { dg-do compile }
+
+// PR 31749: ICE with redeclaration of builtin
+
+namespace std
+{
+  union abort;
+}
+
+void abort();
+
+using std::abort;
diff --git a/gcc/testsuite/g++.dg/lookup/builtin4.C b/gcc/testsuite/g++.dg/lookup/builtin4.C
new file mode 100644 (file)
index 0000000..b1785dc
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright (C) 2007 Free Software Foundation
+// Contributed by Ollie Wild <aaw@google.com>
+// Origin: Volker Reichelt <reichelt@gcc.gnu.org>
+// { dg-do compile }
+
+// PR 31749: ICE with redeclaration of builtin
+
+namespace std
+{
+  union abort;
+}
+
+union abort;
+
+using std::abort; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/lookup/using19.C b/gcc/testsuite/g++.dg/lookup/using19.C
new file mode 100644 (file)
index 0000000..973998b
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright (C) 2007 Free Software Foundation
+// Contributed by Ollie Wild <aaw@google.com>
+// { dg-do compile }
+
+
+// C++ Standard, 7.3.3, clause 10:
+// "Since a using-declaration is a declaration, the restrictions on
+// declarations of the same name in the same declarative region (3.3) also
+// apply to using-declarations."
+
+namespace M
+{
+  union A;
+  void B();
+}
+
+void A();
+union B;
+
+using M::A;
+using M::B;