[cfe-dev] [bug?] list-initialization failures in a return statement
Richard Smith
richard at metafoo.co.uk
Thu Aug 21 14:00:58 PDT 2014
On Mon, Aug 18, 2014 at 8:59 AM, Jim Porter <jvp4846 at g.rit.edu> wrote:
> I've found what I think are a couple of bugs in how clang (3.4)
> list-initializes objects in a return statement. It probably applies to any
> copy-list-initialization context, but I haven't tested all the
> possibilities. I'm posting this here instead of just filing a bug because I
> wanted to get some feedback on whether I'm correct about this or not.
>
> --------------------
>
> First, I think clang is incorrectly failing on the explicit default
> constructor in this sample:
>
> struct foo {
> explicit foo() {}
> };
>
> foo make_foo() {
> return {};
> }
>
> int main() {
> auto f = make_foo();
> return 0;
> }
>
> clang tells me "chosen constructor is explicit in copy-initialization",
> but according to 8.5.4p3, make_foo should be value-initializing foo:
>
> If the initializer list has no elements and T is a class type with a
> default constructor, the object is value-initialized.
>
OK, but value-initialization defers to default-initialization here, and
default-initialization performs overload resolution to select the default
constructor. This -- presumably -- uses 13.3.1.7 to select the constructor:
"When objects of non-aggregate class type T are list-initialized (8.5.4),
overload resolution selects the constructor in two phases:
-- [choose from initializer-list constructors]
-- [try all constructors]
If the initializer list has no elements and T has a default constructor,
the first phase is omitted. In copy-list-initialization, if an explicit
constructor is chosen, the initialization is ill-formed."
Since we're in copy-list-initialization, T has a default constructor, and
the list has no elements, we try all constructors. Since we pick an
explicit constructor, the program is ill-formed.
--------------------
>
> Second, the following seems to be trying to invoke a copy-constructor when
> it shouldn't:
>
> struct foo {
> foo() {}
> foo(const foo &) = delete;
> foo & operator =(const foo &) = delete;
> };
>
> template<typename T>
> foo make() {
> return {};
> }
>
> int main() {
> auto &&f = make<foo>();
> return 0;
> }
>
> clang reports "call to deleted constructor of 'foo'". However, if I remove
> the default constructor and let clang create its own, or if I change the
> signature of make() to `template<typename T> T make()`, it compiles without
> error. It seems like clang is assuming that T is not the same as foo, and
> so tries to invoke the deleted copy constructor. However, if T is foo, that
> shouldn't matter, right?
>
This was a bug. Fixed in r216224; thanks for the report.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140821/58c1c158/attachment.html>
More information about the cfe-dev
mailing list