public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* PATCH: PR c++/31749
@ 2007-08-07 19:14 Ollie Wild
  2007-08-10 18:19 ` Ollie Wild
  2007-08-17 21:14 ` Jason Merrill
  0 siblings, 2 replies; 3+ messages in thread
From: Ollie Wild @ 2007-08-07 19:14 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 1167 bytes --]

According to section 7.3.3, paragraph 10 of the C++ standard:

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.

Currently, GCC does not properly handle duplicate declarations
stemming from a using declaration.  In some cases (as indicated in the
initial bug report), it generates an ICE.  In other cases, it just
gives an erroneous "is already declared in this scope" error.  This
patch resolves both problems by differentiating implicit type
declarations inside do_nonmember_using_decl.

The patch must be applied on top of the previously submitted patch at
http://gcc.gnu.org/ml/gcc-patches/2007-08/msg00412.html.

Ollie

:ADDPATCH c++:


2007-08-07  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-07  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.

[-- Attachment #2: duplicate_name.patch --]
[-- Type: text/x-patch, Size: 8486 bytes --]

diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 48b387a..5f7e718 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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.  */
diff --git a/gcc/testsuite/g++.dg/lookup/builtin3.C b/gcc/testsuite/g++.dg/lookup/builtin3.C
new file mode 100644
index 0000000..3a29d87
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/builtin3.C
@@ -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
index 0000000..b1785dc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/builtin4.C
@@ -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
index 0000000..973998b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using19.C
@@ -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;

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: PATCH: PR c++/31749
  2007-08-07 19:14 PATCH: PR c++/31749 Ollie Wild
@ 2007-08-10 18:19 ` Ollie Wild
  2007-08-17 21:14 ` Jason Merrill
  1 sibling, 0 replies; 3+ messages in thread
From: Ollie Wild @ 2007-08-10 18:19 UTC (permalink / raw)
  To: GCC Patches

On 8/7/07, Ollie Wild <aaw@google.com> wrote:
> The patch must be applied on top of the previously submitted patch at
> http://gcc.gnu.org/ml/gcc-patches/2007-08/msg00412.html.

FYI, the precursor patch has been approved and committed.

Ollie

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re:PATCH: PR c++/31749
  2007-08-07 19:14 PATCH: PR c++/31749 Ollie Wild
  2007-08-10 18:19 ` Ollie Wild
@ 2007-08-17 21:14 ` Jason Merrill
  1 sibling, 0 replies; 3+ messages in thread
From: Jason Merrill @ 2007-08-17 21:14 UTC (permalink / raw)
  To: aaw, gcc-patches List

This is OK.

Jason

:REVIEWURL http://gcc.gnu.org/ml/gcc-patches/2007-08/msg00452.html:

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2007-08-17 21:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-08-07 19:14 PATCH: PR c++/31749 Ollie Wild
2007-08-10 18:19 ` Ollie Wild
2007-08-17 21:14 ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).