From patchwork Sun Feb 20 23:15:00 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: C++ PATCH for c++/46472 (rejects-valid with constexpr constructor template and implicitly declared constructor) Date: Sun, 20 Feb 2011 13:15:00 -0000 From: Jason Merrill X-Patchwork-Id: 83768 Message-Id: <4D61A074.4060002@redhat.com> To: gcc-patches List In this testcase, we were trusting the declaration of the constructor template and therefore decided that the B() constructor was constexpr; but then when we instantiate the A constructor we see that it isn't actually constexpr for int, so we complain about using it in constexpr B(). Oops. The fix is to require A() to be instantiated before we use its constexprness in determining the constexprness of B(). Tested x86_64-pc-linux-gnu, applied to trunk. commit 5bed32784ef8e874786de97c3c31b4bb94891b3e Author: Jason Merrill Date: Sun Feb 20 17:13:49 2011 -0500 PR c++/46472 * method.c (process_subob_fn): Instantiate constexpr templates. * optimize.c (maybe_clone_body): Propagate DECL_DECLARED_CONSTEXPR_P. diff --git a/gcc/cp/method.c b/gcc/cp/method.c index bfe8a06..47f1808 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -941,8 +941,17 @@ process_subob_fn (tree fn, bool move_p, tree *spec_p, bool *trivial_p, goto bad; } - if (constexpr_p && !DECL_DECLARED_CONSTEXPR_P (fn)) - *constexpr_p = false; + if (constexpr_p) + { + /* If this is a specialization of a constexpr template, we need to + force the instantiation now so that we know whether or not it's + really constexpr. */ + if (DECL_DECLARED_CONSTEXPR_P (fn) && DECL_TEMPLATE_INSTANTIATION (fn) + && !DECL_TEMPLATE_INSTANTIATED (fn)) + instantiate_decl (fn, /*defer_ok*/false, /*expl_class*/false); + if (!DECL_DECLARED_CONSTEXPR_P (fn)) + *constexpr_p = false; + } return; diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index b00bc28..ed59f91 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -256,6 +256,7 @@ maybe_clone_body (tree fn) /* Update CLONE's source position information to match FN's. */ DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn); DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn); + DECL_DECLARED_CONSTEXPR_P (clone) = DECL_DECLARED_CONSTEXPR_P (fn); DECL_COMDAT (clone) = DECL_COMDAT (fn); DECL_WEAK (clone) = DECL_WEAK (fn); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-synth1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-synth1.C new file mode 100644 index 0000000..9830939 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-synth1.C @@ -0,0 +1,14 @@ +// PR c++/46472 +// { dg-options -std=c++0x } + +template struct A { + T t; + constexpr A(){} +}; + +struct B +{ + A a; +}; + +B b;