[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