rsmith added inline comments.

================
Comment at: clang/test/CXX/drs/dr14xx.cpp:411-414
+  void f(const char[4]);
+  void f(const wchar_t[4]);
+  void f(const char16_t[4]);
+  void f(const char32_t[4]);
----------------
Mordante wrote:
> rsmith wrote:
> > These should presumably be references to arrays, rather than arrays, or the 
> > parameter type is as if you wrote (for example) `void f(const char *)`, 
> > which shouldn't get the special treatment here.
> > 
> > [over.ics.list]p4 mentions this in its footnote:
> > 
> > "Otherwise, if the parameter type is a character array [Footnote: Since 
> > there are no parameters of array type, this will only occur as the 
> > referenced type of a reference parameter.] and the initializer list has a 
> > single element that is an appropriately-typed string-literal (9.4.3), the 
> > implicit conversion sequence is the identity conversion."
> Ah I missed that footnote. I reread the standard and can you confirm some 
> cases?
> ```
> namespace A { 
>   void f(const char(&)[4]);
>   void g() { f({"abc"}); }
> }
> namespace B { 
>   void f(const char(&&)[4]);
>   void g() { f({"abc"}); }
> } 
> ```
> both should work and with P0388 the array without bounds will also work.
> 
> I ask since this is my interpretation of the standard, but it seems there's a 
> difference between implementations and `void f(const char(&&)[4]);` fails for 
> "abc" but works for "ab".
> It seems ICC and consider "abc" an lvalue in this case and not when using 
> "ab".
> 
> Here's a gotbolt link with the examples https://godbolt.org/z/r1TKfx
That's a really interesting example :)

The initializer is a list containing an lvalue of type `const char[4]`. Per 
[dcl.init.list]/3.9 and /3.10, the behavior depends on whether the referenced 
type is reference-related to `const char[4]` -- if so, then the reference can 
only bind directly and a `&&` reference will be invalid, because it's binding 
an rvalue reference to an lvalue, and if not, then we create an array temporary 
and the `&&` binding is fine.

Per [dcl.init.ref]/4, `const char[???]` is reference-related to `const char[4]` 
if they are similar types, and per [conv.qual]/2, the types are similar if 
`???` is omitted or `4`, and not similar otherwise.

So:
* `const char (&&r)[4] = {"abc"}` is ill-formed (types are the same, binds 
rvalue reference to lvalue)
* `const char (&&)[] = {"abc"}` is ill-formed (types are similar, binds rvalue 
reference to lvalue)
* `const char (&&r)[5] = {"abc"}` is OK (types are not similar, creates 
temporary)

That seems like a very surprising outcome to me. Perhaps we should probably 
ignore array bounds entirely when determining whether two types are 
reference-related. I'll take this to CWG for discussion.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87561/new/

https://reviews.llvm.org/D87561

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to