It's perfectly OK to initialize a base class of abstract type; it's only
an error to create a full object of such a type. So this patch moves
the check from more generic initialization code out into a function
that's definitely creating a new object.
Tested x86_64-pc-linux-gnu, applying to trunk and 4.7.
commit 6fb305c7c88b07c429e8a39fbd514a417c5b6127
Author: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Fri Dec 7 04:54:27 2012 +0000
PR c++/54325
* tree.c (build_aggr_init_expr): Don't check for abstract class.
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 28ff0f2..ca82f75 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -407,18 +407,13 @@ build_aggr_init_array (tree return_type, tree fn, tree slot, int nargs,
callable. */
tree
-build_aggr_init_expr (tree type, tree init, tsubst_flags_t complain)
+build_aggr_init_expr (tree type, tree init, tsubst_flags_t /*complain*/)
{
tree fn;
tree slot;
tree rval;
int is_ctor;
- /* Make sure that we're not trying to create an instance of an
- abstract class. */
- if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain))
- return error_mark_node;
-
if (TREE_CODE (init) == CALL_EXPR)
fn = CALL_EXPR_FN (init);
else if (TREE_CODE (init) == AGGR_INIT_EXPR)
@@ -477,6 +472,11 @@ build_cplus_new (tree type, tree init, tsubst_flags_t complain)
tree rval = build_aggr_init_expr (type, init, complain);
tree slot;
+ /* Make sure that we're not trying to create an instance of an
+ abstract class. */
+ if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain))
+ return error_mark_node;
+
if (TREE_CODE (rval) == AGGR_INIT_EXPR)
slot = AGGR_INIT_EXPR_SLOT (rval);
else if (TREE_CODE (rval) == CALL_EXPR
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-pure.C b/gcc/testsuite/g++.dg/cpp0x/initlist-pure.C
new file mode 100644
index 0000000..63c341c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-pure.C
@@ -0,0 +1,25 @@
+// PR c++/54325
+// { dg-options -std=c++11 }
+
+class Base {
+public:
+ Base() {};
+ virtual ~Base() {};
+
+ virtual void do_stuff() = 0;
+};
+
+class Derived: public Base {
+public:
+ Derived() : Base{} {};
+ virtual ~Derived() {};
+
+ virtual void do_stuff() {};
+};
+
+int
+main() {
+ Derived d;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/other/abstract3.C b/gcc/testsuite/g++.dg/other/abstract3.C
index 528b7d7..95e293e 100644
--- a/gcc/testsuite/g++.dg/other/abstract3.C
+++ b/gcc/testsuite/g++.dg/other/abstract3.C
@@ -8,5 +8,5 @@ struct A // { dg-message "note" }
struct B
{
A a; // { dg-error "abstract" }
- B() : a() {} // { dg-error "abstract" }
+ B() : a() {}
};