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: PR 14360, 14361, 14359


This patch fixes three more C++ regressions:

PR 14360 is an issue with Koenig lookup.  The key question is "when
normal lookup finds a non-function (a variable, for example), is
argument-dependent lookup still performed?"  The standard isn't clear,
and DR 218 has been open for several years to clarify that question
and several others.  The committee seems to agree that the answer to
the question should be "no, argument-dependent lookup should not be
performed" which agrees with the submitter of the bug report and with
previous versions of G++, so I've changed the compiler to implement
that behavior.

PR 14361 is a silly parsing problem: when reparsing a saved default
argument, we silently ignored extra junk at the end of the default
argument.

PR 14359 is a problem with templates and friends that I fixed on the
mainline, but failed to backport to the branch.

Tested on i686-pc-linux-gnu, applied on the mainline, and (except for
14359) on the branch.

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

2004-03-01  Mark Mitchell  <mark@codesourcery.com>

	PR c++/14360
	* parser.c (cp_parser_postfix_expression): Do not perform Koenig
	lookup if ordinary name-lookup finds a non-function.
	* pt.c (tsubst_copy_and_build): Likewise.

	PR c++/14361
	* parser.c (cp_parser_late_parsing_default_args): Check that there
	are no extra tokens after the end of the default-argument
	expression.
	
	Backport 2004-02-12  Mark Mitchell  <mark@codesourcery.com>
	* decl.c (redeclaration_error_message): Correct handling of
	templates.
	* pt.c (tsubst_friend_declaration): Adjust code to determine
	whether or not a friend template is a definition.
	(tsubst_decl): Clear DECL_INITIAL for new FUNCTION_DECLs.

2004-03-01  Mark Mitchell  <mark@codesourcery.com>

	PR c++/14360
	* g++.old-deja/g++.ns/koenig5.C: Remove some error markers.
	
	PR c++/14361
	* g++.dg/parse/defarg7.C: New test.

	PR c++/14359
	* g++.dg/template/friend26.C: New test.

Index: cp/ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/ChangeLog,v
retrieving revision 1.3892.2.64
diff -c -5 -p -r1.3892.2.64 ChangeLog
*** cp/ChangeLog	1 Mar 2004 06:21:37 -0000	1.3892.2.64
--- cp/ChangeLog	2 Mar 2004 01:58:07 -0000
***************
*** 1,5 ****
--- 1,24 ----
+ 2004-03-01  Mark Mitchell  <mark@codesourcery.com>
+ 
+ 	PR c++/14360
+ 	* parser.c (cp_parser_postfix_expression): Do not perform Koenig
+ 	lookup if ordinary name-lookup finds a non-function.
+ 	* pt.c (tsubst_copy_and_build): Likewise.
+ 
+ 	PR c++/14361
+ 	* parser.c (cp_parser_late_parsing_default_args): Check that there
+ 	are no extra tokens after the end of the default-argument
+ 	expression.
+ 	
+ 	Backport 2004-02-12  Mark Mitchell  <mark@codesourcery.com>
+ 	* decl.c (redeclaration_error_message): Correct handling of
+ 	templates.
+ 	* pt.c (tsubst_friend_declaration): Adjust code to determine
+ 	whether or not a friend template is a definition.
+ 	(tsubst_decl): Clear DECL_INITIAL for new FUNCTION_DECLs.
+ 
  2004-02-29  Mark Mitchell  <mark@codesourcery.com>
  
  	PR c++/14138
  	* name-lookup.h (push_scope): Change prototype.
  	* name-lookup.c (push_scope): Do not reenter the current class
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1174.2.10
diff -c -5 -p -r1.1174.2.10 decl.c
*** cp/decl.c	1 Mar 2004 06:21:38 -0000	1.1174.2.10
--- cp/decl.c	2 Mar 2004 01:58:09 -0000
*************** redeclaration_error_message (tree newdec
*** 2026,2045 ****
  	}
        return 0;
      }
    else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
      {
!       if ((TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
! 	   && (DECL_TEMPLATE_RESULT (newdecl)
! 	       != DECL_TEMPLATE_RESULT (olddecl))
! 	   && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl))
! 	   && DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)))
! 	  || (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL
! 	      && COMPLETE_TYPE_P (TREE_TYPE (newdecl))
! 	      && COMPLETE_TYPE_P (TREE_TYPE (olddecl))))
  	return "redefinition of `%#D'";
!       return 0;
      }
    else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
      {
        /* Objects declared at top level:  */
        /* If at least one is a reference, it's ok.  */
--- 2026,2060 ----
  	}
        return 0;
      }
    else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
      {
!       tree nt, ot;
! 
!       if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
! 	{
! 	  if (COMPLETE_TYPE_P (TREE_TYPE (newdecl))
! 	      && COMPLETE_TYPE_P (TREE_TYPE (olddecl)))
! 	    return "redefinition of `%#D'";
! 	  return NULL;
! 	}
! 
!       if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != FUNCTION_DECL
! 	  || (DECL_TEMPLATE_RESULT (newdecl) 
! 	      == DECL_TEMPLATE_RESULT (olddecl)))
! 	return NULL;
! 
!       nt = DECL_TEMPLATE_RESULT (newdecl);
!       if (DECL_TEMPLATE_INFO (nt))
! 	nt = DECL_TEMPLATE_RESULT (template_for_substitution (nt));
!       ot = DECL_TEMPLATE_RESULT (olddecl);
!       if (DECL_TEMPLATE_INFO (ot))
! 	ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot));
!       if (DECL_INITIAL (nt) && DECL_INITIAL (ot))
  	return "redefinition of `%#D'";
! 
!       return NULL;
      }
    else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
      {
        /* Objects declared at top level:  */
        /* If at least one is a reference, it's ok.  */
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.157.2.17
diff -c -5 -p -r1.157.2.17 parser.c
*** cp/parser.c	1 Mar 2004 20:39:10 -0000	1.157.2.17
--- cp/parser.c	2 Mar 2004 01:58:10 -0000
*************** cp_parser_postfix_expression (cp_parser 
*** 3734,3746 ****
  	      }
  
  	    koenig_p = false;
  	    if (idk == CP_ID_KIND_UNQUALIFIED)
  	      {
  		if (args
  		    && (is_overloaded_fn (postfix_expression)
- 			|| DECL_P (postfix_expression)
  			|| TREE_CODE (postfix_expression) == IDENTIFIER_NODE))
  		  {
  		    koenig_p = true;
  		    postfix_expression 
  		      = perform_koenig_lookup (postfix_expression, args);
--- 3734,3748 ----
  	      }
  
  	    koenig_p = false;
  	    if (idk == CP_ID_KIND_UNQUALIFIED)
  	      {
+ 		/* We do not perform argument-dependent lookup if
+ 		   normal lookup finds a non-function, in accordance
+ 		   with the expected resolution of DR 218.  */
  		if (args
  		    && (is_overloaded_fn (postfix_expression)
  			|| TREE_CODE (postfix_expression) == IDENTIFIER_NODE))
  		  {
  		    koenig_p = true;
  		    postfix_expression 
  		      = perform_koenig_lookup (postfix_expression, args);
*************** cp_parser_late_parsing_default_args (cp_
*** 14659,14668 ****
--- 14661,14676 ----
        if (DECL_CLASS_SCOPE_P (fn))
  	push_nested_class (DECL_CONTEXT (fn));
        TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
        if (DECL_CLASS_SCOPE_P (fn))
  	pop_nested_class ();
+ 
+       /* If the token stream has not been completely used up, then
+ 	 there was extra junk after the end of the default
+ 	 argument.  */
+       if (!cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ 	cp_parser_error (parser, "expected `,'");
  
         /* Restore saved state.  */
        parser->lexer = saved_lexer;
        parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
      }
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.816.2.15
diff -c -5 -p -r1.816.2.15 pt.c
*** cp/pt.c	1 Mar 2004 20:39:11 -0000	1.816.2.15
--- cp/pt.c	2 Mar 2004 01:58:11 -0000
*************** tsubst_friend_function (tree decl, tree 
*** 5014,5038 ****
  
        /* We must save some information from NEW_FRIEND before calling
  	 duplicate decls since that function will free NEW_FRIEND if
  	 possible.  */
        new_friend_template_info = DECL_TEMPLATE_INFO (new_friend);
        if (TREE_CODE (new_friend) == TEMPLATE_DECL)
  	{
  	  /* This declaration is a `primary' template.  */
  	  DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
  	  
- 	  new_friend_is_defn 
- 	    = DECL_INITIAL (DECL_TEMPLATE_RESULT (new_friend)) != NULL_TREE;
  	  new_friend_result_template_info
  	    = DECL_TEMPLATE_INFO (DECL_TEMPLATE_RESULT (new_friend));
  	}
        else
! 	{
! 	  new_friend_is_defn = DECL_INITIAL (new_friend) != NULL_TREE;
! 	  new_friend_result_template_info = NULL_TREE;
! 	}
  
        /* Inside pushdecl_namespace_level, we will push into the
  	 current namespace. However, the friend function should go
  	 into the namespace of the template.  */
        ns = decl_namespace_context (new_friend);
--- 5014,5037 ----
  
        /* We must save some information from NEW_FRIEND before calling
  	 duplicate decls since that function will free NEW_FRIEND if
  	 possible.  */
        new_friend_template_info = DECL_TEMPLATE_INFO (new_friend);
+       new_friend_is_defn =
+ 	    (DECL_INITIAL (DECL_TEMPLATE_RESULT 
+ 			   (template_for_substitution (new_friend)))
+ 	     != NULL_TREE);
        if (TREE_CODE (new_friend) == TEMPLATE_DECL)
  	{
  	  /* This declaration is a `primary' template.  */
  	  DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
  	  
  	  new_friend_result_template_info
  	    = DECL_TEMPLATE_INFO (DECL_TEMPLATE_RESULT (new_friend));
  	}
        else
! 	new_friend_result_template_info = NULL_TREE;
  
        /* Inside pushdecl_namespace_level, we will push into the
  	 current namespace. However, the friend function should go
  	 into the namespace of the template.  */
        ns = decl_namespace_context (new_friend);
*************** tsubst_decl (tree t, tree args, tree typ
*** 6170,6180 ****
  	DECL_USE_TEMPLATE (r) = 0;
  	TREE_TYPE (r) = type;
  	/* Clear out the mangled name and RTL for the instantiation.  */
  	SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
  	SET_DECL_RTL (r, NULL_RTX);
! 
  	DECL_CONTEXT (r) = ctx;
  
  	if (member && DECL_CONV_FN_P (r)) 
  	  /* Type-conversion operator.  Reconstruct the name, in
  	     case it's the name of one of the template's parameters.  */
--- 6169,6179 ----
  	DECL_USE_TEMPLATE (r) = 0;
  	TREE_TYPE (r) = type;
  	/* Clear out the mangled name and RTL for the instantiation.  */
  	SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
  	SET_DECL_RTL (r, NULL_RTX);
! 	DECL_INITIAL (r) = NULL_TREE;
  	DECL_CONTEXT (r) = ctx;
  
  	if (member && DECL_CONV_FN_P (r)) 
  	  /* Type-conversion operator.  Reconstruct the name, in
  	     case it's the name of one of the template's parameters.  */
*************** tsubst_copy_and_build (tree t, 
*** 8357,8370 ****
  	    if (BASELINK_P (function))
  	      qualified_p = true;
  	  }
  
  	call_args = RECUR (TREE_OPERAND (t, 1));
! 	  
  	if (koenig_p
  	    && (is_overloaded_fn (function)
- 		|| DECL_P (function)
  		|| TREE_CODE (function) == IDENTIFIER_NODE))
  	  function = perform_koenig_lookup (function, call_args);
  
  	if (TREE_CODE (function) == IDENTIFIER_NODE)
  	  {
--- 8356,8371 ----
  	    if (BASELINK_P (function))
  	      qualified_p = true;
  	  }
  
  	call_args = RECUR (TREE_OPERAND (t, 1));
! 
! 	/* We do not perform argument-dependent lookup if normal
! 	   lookup finds a non-function, in accordance with the
! 	   expected resolution of DR 218.  */
  	if (koenig_p
  	    && (is_overloaded_fn (function)
  		|| TREE_CODE (function) == IDENTIFIER_NODE))
  	  function = perform_koenig_lookup (function, call_args);
  
  	if (TREE_CODE (function) == IDENTIFIER_NODE)
  	  {
Index: testsuite/ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/ChangeLog,v
retrieving revision 1.3389.2.115
diff -c -5 -p -r1.3389.2.115 ChangeLog
*** testsuite/ChangeLog	1 Mar 2004 20:39:12 -0000	1.3389.2.115
--- testsuite/ChangeLog	2 Mar 2004 01:58:12 -0000
***************
*** 1,7 ****
--- 1,16 ----
  2004-03-01  Mark Mitchell  <mark@codesourcery.com>
  
+ 	PR c++/14360
+ 	* g++.old-deja/g++.ns/koenig5.C: Remove some error markers.
+ 	
+ 	PR c++/14361
+ 	* g++.dg/parse/defarg7.C: New test.
+ 
+ 	PR c++/14359
+ 	* g++.dg/template/friend26.C: New test.
+ 
  	PR c++/14324
  	* g++.dg/abi/mangle21.C: New test.
  
  	PR c++/14260
  	* g++.dg/parse/constructor2.C: New test.
Index: testsuite/g++.dg/parse/defarg7.C
===================================================================
RCS file: testsuite/g++.dg/parse/defarg7.C
diff -N testsuite/g++.dg/parse/defarg7.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/defarg7.C	2 Mar 2004 01:58:13 -0000
***************
*** 0 ****
--- 1,5 ----
+ // PR c++/14361
+ 
+ class A {
+   A ( int n=0 int n ); // { dg-error "" }
+ };
Index: testsuite/g++.dg/template/friend26.C
===================================================================
RCS file: testsuite/g++.dg/template/friend26.C
diff -N testsuite/g++.dg/template/friend26.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/friend26.C	2 Mar 2004 01:58:13 -0000
***************
*** 0 ****
--- 1,15 ----
+ // PR c++/14359
+ 
+ template<typename> struct A {};
+ 
+ template<typename> struct B
+ {
+     template<typename T> friend void foo(const A<T>& a, const B&) { a; }
+ };
+ 
+ void bar()
+ {
+     A<void> a;
+     B<void> b;
+     foo(a,b);
+ }
Index: testsuite/g++.old-deja/g++.ns/koenig5.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.ns/koenig5.C,v
retrieving revision 1.3
diff -c -5 -p -r1.3 koenig5.C
*** testsuite/g++.old-deja/g++.ns/koenig5.C	1 May 2003 02:02:47 -0000	1.3
--- testsuite/g++.old-deja/g++.ns/koenig5.C	2 Mar 2004 01:58:13 -0000
***************
*** 1,16 ****
  // { dg-do assemble  }
  // To find function pointers in Koenig lookup is ok as long as we only find one.
  namespace A{
!   void foo();             // { dg-error "" } 
    struct X{};
    void (*bar)(X*)=0;
  }
  using A::X;
  
! void (*foo)(X*)=0;        // { dg-error "" } 
  
  void g()
  {
!   foo(new X);            // { dg-error "" } both objects and functions found
    bar(new X);            // ok
  }
--- 1,18 ----
  // { dg-do assemble  }
  // To find function pointers in Koenig lookup is ok as long as we only find one.
  namespace A{
!   void foo();             
    struct X{};
    void (*bar)(X*)=0;
  }
  using A::X;
  
! void (*foo)(X*)=0;        
  
  void g()
  {
!   foo(new X);            // ok -- DR 218 says that we find the global
! 			 // foo variable first, and therefore do not
! 			 // perform argument-dependent lookup.
    bar(new X);            // ok
  }


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