<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Aug 18, 2014 at 8:59 AM, Jim Porter <span dir="ltr"><<a href="mailto:jvp4846@g.rit.edu" target="_blank">jvp4846@g.rit.edu</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">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.<br>


<br>
--------------------<br>
<br>
First, I think clang is incorrectly failing on the explicit default constructor in this sample:<br>
<br>
  struct foo {<br>
    explicit foo() {}<br>
  };<br>
<br>
  foo make_foo() {<br>
    return {};<br>
  }<br>
<br>
  int main() {<br>
    auto f = make_foo();<br>
    return 0;<br>
  }<br>
<br>
clang tells me "chosen constructor is explicit in copy-initialization", but according to 8.5.4p3, make_foo should be value-initializing foo:<br>
<br>
  If the initializer list has no elements and T is a class type with a<br>
  default constructor, the object is value-initialized.<br></blockquote><div><br></div><div>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:</div>

<div><br></div><div>"When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor in two phases:</div><div> -- [choose from initializer-list constructors]</div>

<div> -- [try all constructors]</div><div><div>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."</div>

</div><div><br></div><div>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.</div>

<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
--------------------<br>
<br>
Second, the following seems to be trying to invoke a copy-constructor when it shouldn't:<br>
<br>
  struct foo {<br>
    foo() {}<br>
    foo(const foo &) = delete;<br>
    foo & operator =(const foo &) = delete;<br>
  };<br>
<br>
  template<typename T><br>
  foo make() {<br>
    return {};<br>
  }<br>
<br>
  int main() {<br>
    auto &&f = make<foo>();<br>
    return 0;<br>
  }<br>
<br>
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?<br>

</blockquote><div><br></div><div>This was a bug. Fixed in r216224; thanks for the report.</div></div></div></div>