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] Fix 21280


this patch fixes a regression with synthesized functions and #pragma interface. We were mistakingly thinking a synthesized function's interface status was determined by where the function was first needed.

This fixes things so that we set the function's location correctly (as the class definition location). I also preserved the existing behaviour of using the location of first use to clue the user as to why the function was needed. However, I improved this by giving a separate error after any errors synthesization created.

built & tested on i686-pc-linux-gnu, installed 4.0 and HEAD

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2005-06-02  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/21280
	* Make-lang.in (method.o): Add diagnostic.h
	* decl.c (start_preparsed_function): Use decl's location for file
	info.
	* decl2.c (cp_finish_file): Set input_location before synthesizing
	a function.
	(mark_used): When deferring a synthesized function, save current
	location.  Do not set function's location when actually
	synthesizing it.
	* method.c: #include diagnostic.h.
	(synthesize_method): Set the functions source location.  Show
	needed location if errors are emitted.

2005-06-02  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/21280
	* g++.dg/opt/interface2.h: New.
	* g++.dg/opt/interface2.C: New.
	* g++.dg/init/ctor4.C: Adjust error lines.
	* g++.old-deja/g++.bob/inherit2.C: Likewise.
	* g++.old-deja/g++.bugs/900205_04.C: Likewise.
	* g++.old-deja/g++.jason/opeq3.C: Likewise.
	* g++.old-deja/g++.pt/assign1.C: Likewise.
	* g++.old-deja/g++.pt/crash20.C: Likewise.

Index: cp/Make-lang.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/Make-lang.in,v
retrieving revision 1.200.8.1
diff -c -3 -p -r1.200.8.1 Make-lang.in
*** cp/Make-lang.in	24 Apr 2005 12:46:31 -0000	1.200.8.1
--- cp/Make-lang.in	2 Jun 2005 14:04:22 -0000
*************** cp/friend.o: cp/friend.c $(CXX_TREE_H) $
*** 251,257 ****
  cp/init.o: cp/init.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
    except.h $(TARGET_H)
  cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(RTL_H) $(EXPR_H) \
!   $(TM_P_H) $(TARGET_H) gt-cp-method.h
  cp/cvt.o: cp/cvt.c $(CXX_TREE_H) $(TM_H) cp/decl.h flags.h toplev.h convert.h
  cp/search.o: cp/search.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H)
  cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) \
--- 251,257 ----
  cp/init.o: cp/init.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
    except.h $(TARGET_H)
  cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(RTL_H) $(EXPR_H) \
!   $(TM_P_H) $(TARGET_H) diagnostic.h gt-cp-method.h
  cp/cvt.o: cp/cvt.c $(CXX_TREE_H) $(TM_H) cp/decl.h flags.h toplev.h convert.h
  cp/search.o: cp/search.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H)
  cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) \
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1371.2.12
diff -c -3 -p -r1.1371.2.12 decl.c
*** cp/decl.c	1 Jun 2005 14:46:58 -0000	1.1371.2.12
--- cp/decl.c	2 Jun 2005 14:04:58 -0000
*************** start_preparsed_function (tree decl1, tr
*** 9857,9863 ****
    int doing_friend = 0;
    struct cp_binding_level *bl;
    tree current_function_parms;
!   struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename));
  
    /* Sanity check.  */
    gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE);
--- 9857,9864 ----
    int doing_friend = 0;
    struct cp_binding_level *bl;
    tree current_function_parms;
!   struct c_fileinfo *finfo
!     = get_fileinfo (lbasename (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1))));
  
    /* Sanity check.  */
    gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE);
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.770.2.1
diff -c -3 -p -r1.770.2.1 decl2.c
*** cp/decl2.c	5 Apr 2005 15:38:09 -0000	1.770.2.1
--- cp/decl2.c	2 Jun 2005 14:05:07 -0000
*************** cp_finish_file (void)
*** 2908,2913 ****
--- 2908,2917 ----
  		 finish_function doesn't clean things up, and we end
  		 up with CURRENT_FUNCTION_DECL set.  */
  	      push_to_top_level ();
+ 	      /* The decl's location will mark where it was first
+ 	         needed.  Save that so synthesize method can indicate
+ 	         where it was needed from, in case of error  */
+ 	      input_location = DECL_SOURCE_LOCATION (decl);
  	      synthesize_method (decl);
  	      pop_from_top_level ();
  	      reconsider = true;
*************** mark_used (tree decl)
*** 3178,3183 ****
--- 3182,3195 ----
      {
        if (DECL_DEFERRED_FN (decl))
  	return;
+       
+       /* Remember the current location for a function we will end up
+          synthesizing.  Then we can inform the user where it was
+          required in the case of error.  */
+       if (DECL_ARTIFICIAL (decl) && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
+ 	  && !DECL_THUNK_P (decl))
+ 	DECL_SOURCE_LOCATION (decl) = input_location;
+       
        note_vague_linkage_fn (decl);
      }
    
*************** mark_used (tree decl)
*** 3195,3208 ****
  	 pointing to the class location.  */
        && current_function_decl)
      {
-       /* Put the function definition at the position where it is needed,
- 	 rather than within the body of the class.  That way, an error
- 	 during the generation of the implicit body points at the place
- 	 where the attempt to generate the function occurs, giving the
- 	 user a hint as to why we are attempting to generate the
- 	 function.  */
-       DECL_SOURCE_LOCATION (decl) = input_location;
- 
        synthesize_method (decl);
        /* If we've already synthesized the method we don't need to
  	 instantiate it, so we can return right away.  */
--- 3207,3212 ----
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.322.4.2
diff -c -3 -p -r1.322.4.2 method.c
*** cp/method.c	29 May 2005 00:17:27 -0000	1.322.4.2
--- cp/method.c	2 Jun 2005 14:05:14 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 36,41 ****
--- 36,42 ----
  #include "toplev.h"
  #include "tm_p.h"
  #include "target.h"
+ #include "diagnostic.h"
  
  /* Various flags to control the mangling process.  */
  
*************** do_build_assign_ref (tree fndecl)
*** 702,707 ****
--- 703,710 ----
    finish_compound_stmt (compound_stmt);
  }
  
+ /* Synthesize FNDECL, a non-static member function.   */
+ 
  void
  synthesize_method (tree fndecl)
  {
*************** synthesize_method (tree fndecl)
*** 710,726 ****
    bool need_body = true;
    tree stmt;
    location_t save_input_location = input_location;
  
    /* If we've been asked to synthesize a clone, just synthesize the
       cloned function instead.  Doing so will automatically fill in the
       body for the clone.  */
    if (DECL_CLONED_FUNCTION_P (fndecl))
!     {
!       DECL_SOURCE_LOCATION (DECL_CLONED_FUNCTION (fndecl)) =
! 	DECL_SOURCE_LOCATION (fndecl);
!       synthesize_method (DECL_CLONED_FUNCTION (fndecl));
!       return;
!     }
  
    /* We may be in the middle of deferred access check.  Disable
       it now.  */
--- 713,731 ----
    bool need_body = true;
    tree stmt;
    location_t save_input_location = input_location;
+   int error_count = errorcount;
+   int warning_count = warningcount;
  
+   /* Reset the source location, we might have been previously
+      deferred, and thus have saved where we were first needed.  */
+   DECL_SOURCE_LOCATION (fndecl)
+     = DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (fndecl)));
+   
    /* If we've been asked to synthesize a clone, just synthesize the
       cloned function instead.  Doing so will automatically fill in the
       body for the clone.  */
    if (DECL_CLONED_FUNCTION_P (fndecl))
!     fndecl = DECL_CLONED_FUNCTION (fndecl);
  
    /* We may be in the middle of deferred access check.  Disable
       it now.  */
*************** synthesize_method (tree fndecl)
*** 770,775 ****
--- 775,784 ----
      pop_function_context_from (context);
  
    pop_deferring_access_checks ();
+ 
+   if (error_count != errorcount || warning_count != warningcount)
+     error ("%Hsynthesized method %qD first required here ",
+ 	   &input_location, fndecl);
  }
  
  /* Use EXTRACTOR to locate the relevant function called for each base &
Index: testsuite/g++.dg/opt/interface2.C
===================================================================
RCS file: testsuite/g++.dg/opt/interface2.C
diff -N testsuite/g++.dg/opt/interface2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/opt/interface2.C	2 Jun 2005 14:15:04 -0000
***************
*** 0 ****
--- 1,19 ----
+ // Copyright (C) 2005 Free Software Foundation, Inc.
+ // Contributed by Nathan Sidwell 2 Jun 2005 <nathan@codesourcery.com>
+ 
+ // PR 21280
+ // Origin: Jens Maurer <jens.maurer@gmx.net>
+ 
+ #include "interface2.h"
+ 
+ struct A
+ {
+   A() { }
+   virtual ~A() { }
+ };
+ 
+ int main()
+ {
+   A a;
+   C<A> c(a);
+ }
Index: testsuite/g++.dg/opt/interface2.h
===================================================================
RCS file: testsuite/g++.dg/opt/interface2.h
diff -N testsuite/g++.dg/opt/interface2.h
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/opt/interface2.h	2 Jun 2005 14:15:04 -0000
***************
*** 0 ****
--- 1,11 ----
+ #pragma interface
+ 
+ template<class T>
+ struct C
+ {
+   explicit C(const T& t) : a(t) { }
+   virtual ~C() { }
+   T a;
+ };
+ 
+ 
Index: testsuite/g++.dg/init/ctor4.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/init/ctor4.C,v
retrieving revision 1.1
diff -c -3 -p -r1.1 ctor4.C
*** testsuite/g++.dg/init/ctor4.C	15 Feb 2005 19:39:30 -0000	1.1
--- testsuite/g++.dg/init/ctor4.C	2 Jun 2005 14:05:48 -0000
*************** public:
*** 6,12 ****
    foo();
  };
  
! class bar: public foo {
  private:
    int &a;
  };
--- 6,12 ----
    foo();
  };
  
! class bar: public foo {// { dg-error "uninitialized" }
  private:
    int &a;
  };
*************** foo::foo() {
*** 16,20 ****
  
  int main(int argc, char **argv)
  {
!   bar x; // { dg-error "uninitialized" }
  }
--- 16,20 ----
  
  int main(int argc, char **argv)
  {
!   bar x; // { dg-error "synthesized" }
  }
Index: testsuite/g++.old-deja/g++.bob/inherit2.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C,v
retrieving revision 1.6
diff -c -3 -p -r1.6 inherit2.C
*** testsuite/g++.old-deja/g++.bob/inherit2.C	1 May 2003 02:02:34 -0000	1.6
--- testsuite/g++.old-deja/g++.bob/inherit2.C	2 Jun 2005 14:05:54 -0000
*************** public:
*** 6,16 ****
    void z();
    A(void) {}
  private:
!   A(const A &) { abort(); } // { dg-error "" } 
    const A& operator =(const A &) { abort(); }
  };
  
! class B : public A {
  public:
    B(void) {}
  };
--- 6,16 ----
    void z();
    A(void) {}
  private:
!   A(const A &) { abort(); } // { dg-error "private" } 
    const A& operator =(const A &) { abort(); }
  };
  
! class B : public A { // { dg-error "within" }
  public:
    B(void) {}
  };
*************** void f(B b) {
*** 20,24 ****
  
  void g() {
    B h;
!   f(h); // { dg-error "" } 
  }
--- 20,24 ----
  
  void g() {
    B h;
!   f(h); // { dg-error "synthesized|argument" } 
  }
Index: testsuite/g++.old-deja/g++.bugs/900205_04.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.bugs/900205_04.C,v
retrieving revision 1.5
diff -c -3 -p -r1.5 900205_04.C
*** testsuite/g++.old-deja/g++.bugs/900205_04.C	15 Feb 2005 19:39:31 -0000	1.5
--- testsuite/g++.old-deja/g++.bugs/900205_04.C	2 Jun 2005 14:05:55 -0000
*************** struct0::struct0 (int, void *) // { dg-e
*** 23,31 ****
  {
  }
  
! struct struct0_derived_struct_0 : public struct0 { // { dg-error "" }
  };
  
! struct0_derived_struct_0 object;
  
  int main () { return 0; }
--- 23,31 ----
  {
  }
  
! struct struct0_derived_struct_0 : public struct0 { // { dg-error "no matching" }
  };
  
! struct0_derived_struct_0 object; // { dg-error "synthesized" }
  
  int main () { return 0; }
Index: testsuite/g++.old-deja/g++.jason/opeq3.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.jason/opeq3.C,v
retrieving revision 1.4
diff -c -3 -p -r1.4 opeq3.C
*** testsuite/g++.old-deja/g++.jason/opeq3.C	1 May 2003 02:02:40 -0000	1.4
--- testsuite/g++.old-deja/g++.jason/opeq3.C	2 Jun 2005 14:05:57 -0000
***************
*** 1,7 ****
  // { dg-do assemble  }
  // Bug: g++ generates code for assignment in invalid situations.
  
! class X {
    int& a;
  public:
    X(int& i): a(i) { };
--- 1,7 ----
  // { dg-do assemble  }
  // Bug: g++ generates code for assignment in invalid situations.
  
! class X { // { dg-error "assignment" }
    int& a;
  public:
    X(int& i): a(i) { };
*************** void foo ()
*** 11,15 ****
  {
    int one=1, two=2;
    X a(one), b(two);
!   a = b;			// { dg-error "" } no assignment semantics defined
  }
--- 11,15 ----
  {
    int one=1, two=2;
    X a(one), b(two);
!   a = b;			// { dg-error "synthesized" }
  }
Index: testsuite/g++.old-deja/g++.pt/assign1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.pt/assign1.C,v
retrieving revision 1.3
diff -c -3 -p -r1.3 assign1.C
*** testsuite/g++.old-deja/g++.pt/assign1.C	1 May 2003 02:02:53 -0000	1.3
--- testsuite/g++.old-deja/g++.pt/assign1.C	2 Jun 2005 14:06:05 -0000
***************
*** 1,8 ****
! // { dg-do assemble  }
  // Origin: Mark Mitchell <mark@codesourcery.com>
  
  template <class T>
! struct S {
    S();
    T t;
  };
--- 1,8 ----
! // { dg-do compile  }
  // Origin: Mark Mitchell <mark@codesourcery.com>
  
  template <class T>
! struct S { // { dg-error "assignment" }
    S();
    T t;
  };
*************** struct S {
*** 10,14 ****
  void f()
  {
    S<const int> s;
!   s = s; // { dg-error "" } generated assignment operator is illegal
  }
--- 10,14 ----
  void f()
  {
    S<const int> s;
!   s = s; // { dg-error "synthesized" }
  }
Index: testsuite/g++.old-deja/g++.pt/crash20.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.pt/crash20.C,v
retrieving revision 1.4
diff -c -3 -p -r1.4 crash20.C
*** testsuite/g++.old-deja/g++.pt/crash20.C	1 May 2003 02:02:53 -0000	1.4
--- testsuite/g++.old-deja/g++.pt/crash20.C	2 Jun 2005 14:06:05 -0000
***************
*** 1,9 ****
! // { dg-do assemble  }
  
  template <class T = int>
! struct A { const T x; A() : x(0) { } A(T x) : x(x) { } }; 
  
  template <class B>
! void func () { B y; y = B(); } // { dg-error "" } can't use default assignment
  
  int main (void) { func< A<> >(); }
--- 1,16 ----
! // { dg-do compile  }
  
  template <class T = int>
! struct A { // { dg-error "assignment" }
!   const T x;
!   A() : x(0) { } A(T x) : x(x) { }
! }; 
  
  template <class B>
! void func ()
! {
!   B y; 
!   y = B();  // { dg-error "synthesized" }
! }
  
  int main (void) { func< A<> >(); }
2005-06-02  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/21280
	* testsuite/27_io/ios_base/cons/assign_neg.cc: Adjust expected errors.
	* testsuite/27_io/ios_base/cons/copy_neg.cc: Likewise.

Index: testsuite/27_io/ios_base/cons/assign_neg.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc,v
retrieving revision 1.11
diff -c -3 -p -r1.11 assign_neg.cc
*** testsuite/27_io/ios_base/cons/assign_neg.cc	2 Nov 2004 19:00:18 -0000	1.11
--- testsuite/27_io/ios_base/cons/assign_neg.cc	2 Jun 2005 17:05:37 -0000
*************** void test01()
*** 40,45 ****
    test_base io2;
    io1 = io2;
  }
! // { dg-error "within this context" "" { target *-*-* } 41 } 
  // { dg-error "is private" "" { target *-*-* } 782 } 
  // { dg-error "operator=" "" { target *-*-* } 0 } 
--- 40,46 ----
    test_base io2;
    io1 = io2;
  }
! // { dg-error "synthesized" "" { target *-*-* } 41 } 
! // { dg-error "within this context" "" { target *-*-* } 34 } 
  // { dg-error "is private" "" { target *-*-* } 782 } 
  // { dg-error "operator=" "" { target *-*-* } 0 } 
Index: testsuite/27_io/ios_base/cons/copy_neg.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc,v
retrieving revision 1.11
diff -c -3 -p -r1.11 copy_neg.cc
*** testsuite/27_io/ios_base/cons/copy_neg.cc	2 Nov 2004 19:00:18 -0000	1.11
--- testsuite/27_io/ios_base/cons/copy_neg.cc	2 Jun 2005 17:05:37 -0000
*************** void test02()
*** 40,45 ****
    test_base io1;
    test_base io2 = io1; 
  }
! // { dg-error "within this context" "" { target *-*-* } 41 } 
  // { dg-error "is private" "" { target *-*-* } 779 } 
  // { dg-error "copy constructor" "" { target *-*-* } 0 } 
--- 40,46 ----
    test_base io1;
    test_base io2 = io1; 
  }
! // { dg-error "within this context" "" { target *-*-* } 35 } 
! // { dg-error "synthesized" "" { target *-*-* } 41 } 
  // { dg-error "is private" "" { target *-*-* } 779 } 
  // { dg-error "copy constructor" "" { target *-*-* } 0 } 

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