aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-07-10 15:29:59 -0400
committerJason Merrill <jason@gcc.gnu.org>2014-07-10 15:29:59 -0400
commitc0221884ecbda8d99a43aa0f5e306638c71533d6 (patch)
tree7cef2e435d85f003b0320c564b270b29bbcc9dca /gcc
parent7757d79bfcce1f13facc96a420eea4bcd542a3e2 (diff)
downloadgcc-c0221884ecbda8d99a43aa0f5e306638c71533d6.zip
gcc-c0221884ecbda8d99a43aa0f5e306638c71533d6.tar.gz
gcc-c0221884ecbda8d99a43aa0f5e306638c71533d6.tar.bz2
re PR ipa/61659 (Extra undefined symbol because of devirtualization)
PR c++/61659 PR c++/61687 gcc/c-family/ * c.opt (-fuse-all-virtuals): New. gcc/cp/ * decl2.c (mark_all_virtuals): New variable. (maybe_emit_vtables): Check it instead of flag_devirtualize. (cp_write_global_declarations): Set it and give helpful diagnostic if it introduces errors. * class.c (finish_struct_1): Check it. * decl.c (grokdeclarator): Clear virtualp after 'virtual auto' error. From-SVN: r212436
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/class.c2
-rw-r--r--gcc/cp/decl.c7
-rw-r--r--gcc/cp/decl2.c30
-rw-r--r--gcc/testsuite/g++.dg/template/dtor9.C1
-rw-r--r--gcc/testsuite/g++.dg/template/dtor9a.C13
8 files changed, 70 insertions, 4 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 2445597..23c5c82 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2014-07-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/61659
+ PR c++/61687
+ * c.opt (-fuse-all-virtuals): New.
+
2014-07-09 Richard Biener <rguenther@suse.de>
PR c-family/61741
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index faef774..3a2084f 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1268,6 +1268,10 @@ funsigned-char
C ObjC C++ ObjC++ LTO Var(flag_signed_char, 0)
Make \"char\" unsigned by default
+fuse-all-virtuals
+C++ ObjC++ Var(flag_use_all_virtuals) Init(1)
+Treat all virtual functions as odr-used
+
fuse-cxa-atexit
C++ ObjC++ Var(flag_use_cxa_atexit) Init(DEFAULT_USE_CXA_ATEXIT)
Use __cxa_atexit to register destructors
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5827bbd..a184a40 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+2014-07-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/61659
+ PR c++/61687
+ * decl2.c (mark_all_virtuals): New variable.
+ (maybe_emit_vtables): Check it instead of flag_devirtualize.
+ (cp_write_global_declarations): Set it and give helpful diagnostic
+ if it introduces errors.
+ * class.c (finish_struct_1): Check it.
+ * decl.c (grokdeclarator): Clear virtualp after 'virtual auto' error.
+
2014-07-09 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/60686
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 3a44dba..d0eb103 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6408,7 +6408,7 @@ finish_struct_1 (tree t)
in every translation unit where the class definition appears. If
we're devirtualizing, we can look into the vtable even if we
aren't emitting it. */
- if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE || flag_devirtualize)
+ if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE || flag_use_all_virtuals)
keyed_classes = tree_cons (NULL_TREE, t, keyed_classes);
}
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1ade586..01d74e3 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -9631,8 +9631,11 @@ grokdeclarator (const cp_declarator *declarator,
"-std=gnu++1y");
}
else if (virtualp)
- error ("virtual function cannot "
- "have deduced return type");
+ {
+ error ("virtual function cannot "
+ "have deduced return type");
+ virtualp = false;
+ }
}
else if (!is_auto (type))
{
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 98897f4..0926dbc 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -106,6 +106,11 @@ static GTY(()) vec<tree, va_gc> *no_linkage_decls;
/* Nonzero if we're done parsing and into end-of-file activities. */
int at_eof;
+
+/* Nonzero if we've instantiated everything used directly, and now want to
+ mark all virtual functions as used so that they are available for
+ devirtualization. */
+static int mark_all_virtuals;
/* Return a member function type (a METHOD_TYPE), given FNTYPE (a
@@ -2009,7 +2014,7 @@ maybe_emit_vtables (tree ctype)
if (DECL_COMDAT (primary_vtbl)
&& CLASSTYPE_DEBUG_REQUESTED (ctype))
note_debug_info_needed (ctype);
- if (flag_devirtualize)
+ if (mark_all_virtuals)
/* Make sure virtual functions get instantiated/synthesized so that
they can be inlined after devirtualization even if the vtable is
never emitted. */
@@ -4340,6 +4345,8 @@ cp_write_global_declarations (void)
instantiated, etc., etc. */
emit_support_tinfos ();
+ int errs = errorcount + sorrycount;
+ bool explained_devirt = false;
do
{
@@ -4572,6 +4579,27 @@ cp_write_global_declarations (void)
pending_statics->length ()))
reconsider = true;
+ if (flag_use_all_virtuals)
+ {
+ if (!reconsider && !mark_all_virtuals)
+ {
+ mark_all_virtuals = true;
+ reconsider = true;
+ errs = errorcount + sorrycount;
+ }
+ else if (mark_all_virtuals
+ && !explained_devirt
+ && (errorcount + sorrycount > errs))
+ {
+ inform (global_dc->last_location, "this error is seen due to "
+ "instantiation of all virtual functions, which the C++ "
+ "standard says are always considered used; this is done "
+ "to support devirtualization optimizations, but can be "
+ "disabled with -fno-use-all-virtuals");
+ explained_devirt = true;
+ }
+ }
+
retries++;
}
while (reconsider);
diff --git a/gcc/testsuite/g++.dg/template/dtor9.C b/gcc/testsuite/g++.dg/template/dtor9.C
index fd71389..006a754 100644
--- a/gcc/testsuite/g++.dg/template/dtor9.C
+++ b/gcc/testsuite/g++.dg/template/dtor9.C
@@ -1,4 +1,5 @@
// PR c++/60347
+// { dg-options "-fno-use-all-virtuals" }
struct A;
diff --git a/gcc/testsuite/g++.dg/template/dtor9a.C b/gcc/testsuite/g++.dg/template/dtor9a.C
new file mode 100644
index 0000000..aaae8b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dtor9a.C
@@ -0,0 +1,13 @@
+// PR c++/60347
+// { dg-options "-fuse-all-virtuals" }
+
+struct A;
+
+template <class T>
+struct B
+{
+ T* p;
+ virtual ~B() { p->~T(); } // { dg-error "incomplete" }
+};
+
+struct C: B<A> { };