This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix 21280
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 02 Jun 2005 18:36:51 +0100
- Subject: [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 }