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]

C++ PATCH: PRs 19395, 19367


PR 19395 reports that we were allowing qualified names in typedef
declarators at class scope.  We already had code to issue appropriate
errors in non-class scopes; this was simply an oversight.

PR 19367 was a case where we got rather confused about
using-declarations when there was already a builtin declaration in the
namespace in which the using-declaration occurred.  In particular, we
tried to overload the built-in with the new declaration, which is
incorrect; the using-declaration should supplant the built-in.
(Parenthetically, the way I think builtins ought to work is that when
name-lookup fails to find a name in a namespace scope, then we ought
to check if the name is a built-in, and create the built-in at that
time.  That would entirely avoid DECL_ANTICIPATED and the myriad
complexities that come with it.)

Tested on x86_64-unknown-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2005-01-30  Mark Mitchell  <mark@codesourcery.com>

	PR c++/19395
	* decl.c (grokdeclarator): Refactor code so that qualified names
	are never allowed as the declarator in a typedef.

	PR c++/19367
	* name-lookup.c (do_nonmember_using_decl): Avoid overloading
	builtin declarations.

2005-01-30  Mark Mitchell  <mark@codesourcery.com>

	PR c++/19395
	* g++.dg/parse/error24.C: New test. 

	PR c++/19367
	* g++.dg/lookup/builtin1.C: New test.

Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1355
diff -c -5 -p -r1.1355 decl.c
*** cp/decl.c	27 Jan 2005 07:32:20 -0000	1.1355
--- cp/decl.c	31 Jan 2005 03:56:03 -0000
*************** grokdeclarator (const cp_declarator *dec
*** 7522,7543 ****
  	 in typenames, fields or parameters.  */
        if (current_lang_name == lang_name_java)
  	TYPE_FOR_JAVA (type) = 1;
  
        if (decl_context == FIELD)
! 	{
! 	  if (constructor_name_p (unqualified_id, current_class_type))
! 	    pedwarn ("ISO C++ forbids nested type %qD with same name "
!                      "as enclosing class",
! 		     unqualified_id);
! 	  decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
! 	}
        else
  	{
- 	  decl = build_decl (TYPE_DECL, unqualified_id, type);
- 	  if (in_namespace || ctype)
- 	    error ("%Jtypedef name may not be a nested-name-specifier", decl);
  	  if (!current_function_decl)
  	    DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
  	  else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (current_function_decl)
  		   || (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P 
  		       (current_function_decl)))
--- 7522,7539 ----
  	 in typenames, fields or parameters.  */
        if (current_lang_name == lang_name_java)
  	TYPE_FOR_JAVA (type) = 1;
  
        if (decl_context == FIELD)
! 	decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
        else
+ 	decl = build_decl (TYPE_DECL, unqualified_id, type);
+       if (id_declarator && declarator->u.id.qualifying_scope)
+ 	error ("%Jtypedef name may not be a nested-name-specifier", decl);
+ 
+       if (decl_context != FIELD)
  	{
  	  if (!current_function_decl)
  	    DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
  	  else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (current_function_decl)
  		   || (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P 
  		       (current_function_decl)))
*************** grokdeclarator (const cp_declarator *dec
*** 7545,7554 ****
--- 7541,7554 ----
  	       clones of this constructor/destructor, and there will
  	       be copies of this TYPE_DECL generated in those
  	       clones.  */
  	    DECL_ABSTRACT (decl) = 1;
  	}
+       else if (constructor_name_p (unqualified_id, current_class_type))
+ 	pedwarn ("ISO C++ forbids nested type %qD with same name "
+ 		 "as enclosing class",
+ 		 unqualified_id);
  
        /* If the user declares "typedef struct {...} foo" then the
  	 struct will have an anonymous name.  Fill that name in now.
  	 Nothing can refer to it, so nothing needs know about the name
  	 change.  */
Index: cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.107
diff -c -5 -p -r1.107 name-lookup.c
*** cp/name-lookup.c	31 Jan 2005 01:16:59 -0000	1.107
--- cp/name-lookup.c	31 Jan 2005 03:56:05 -0000
*************** do_nonmember_using_decl (tree scope, tre
*** 2034,2043 ****
--- 2034,2052 ----
  	  if (!DECL_IMPLICIT_TYPEDEF_P (oldval))
  	    error ("%qD is already declared in this scope", name);
  	  oldval = 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.  */
+       if (oldval 
+ 	  && TREE_CODE (oldval) == FUNCTION_DECL
+ 	  && DECL_ANTICIPATED (oldval))
+ 	oldval = NULL_TREE;
+ 
        *newval = oldval;
        for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
  	{
  	  tree new_fn = OVL_CURRENT (tmp);
  
*************** do_nonmember_using_decl (tree scope, tre
*** 2057,2093 ****
  	      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))))
  		{
  	          /* 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 the OLD_FN was a builtin, we've seen a real 
! 			 declaration in another namespace.  Use it instead.
! 			 Set tmp1 to NULL so we can use the existing
! 			 OVERLOAD logic at the end of this inner loop.
! 		      */
! 		      if (DECL_ANTICIPATED (old_fn))
! 			{
! 			  gcc_assert (! DECL_ANTICIPATED (new_fn));
! 			  tmp1 = NULL;
! 			}
! 		      break;
! 		    }
! 		  else if (!DECL_ANTICIPATED (old_fn))
! 		    {
! 		      /* If the OLD_FN was really declared, the
! 			 declarations don't match.  */
  		      error ("%qD is already declared in this scope", name);
  		      break;
  		    }
- 
- 		  /* If the OLD_FN was not really there, just ignore
- 		     it and keep going.  */
  		}
  	    }
  
  	  /* If we broke out of the loop, there's no reason to add
  	     this function to the using declarations for this
--- 2066,2087 ----
  	      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))))
  		{
+ 		  gcc_assert (!DECL_ANTICIPATED (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
Index: testsuite/g++.dg/lookup/builtin1.C
===================================================================
RCS file: testsuite/g++.dg/lookup/builtin1.C
diff -N testsuite/g++.dg/lookup/builtin1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/lookup/builtin1.C	31 Jan 2005 03:56:05 -0000
***************
*** 0 ****
--- 1,12 ----
+ // PR c++/19367
+ // { dg-do link } 
+ 
+ void abort (void) { throw 3; }
+ 
+ namespace std { using ::abort; }
+ 
+ int main ()
+ {
+   using std::abort;
+   abort();
+ }
Index: testsuite/g++.dg/parse/error24.C
===================================================================
RCS file: testsuite/g++.dg/parse/error24.C
diff -N testsuite/g++.dg/parse/error24.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/error24.C	31 Jan 2005 03:56:05 -0000
***************
*** 0 ****
--- 1,7 ----
+ // PR c++/19395
+ 
+ struct A {
+   typedef int ::X; // { dg-error "" }
+ };
+ 
+ 


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