llvm-capstone/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp
Nathan Sidwell 444ec0957c [clang] p0388 array list initialization overloads
This is the second part of p0388, dealing with overloads of list
initialization to incomplete array types.  It extends the handling
added in D103088 to permit incomplete arrays.  We have to record that
the conversion involved an incomplete array, and so (re-add) a bit flag
into the standard conversion sequence object.  Comparing such
conversion sequences requires knowing (a) the number of array elements
initialized and (b) whether the initialization is of an incomplete array.

This also updates the web page to indicate p0388 is implemented (there
is no feature macro).

Differential Revision: https://reviews.llvm.org/D103908
2021-10-12 07:35:21 -07:00

174 lines
3.7 KiB
C++

// RUN: %clang_cc1 -std=c++20 -verify %s
// RUN: %clang_cc1 -std=c++17 -verify %s
// p0388 conversions to unbounded array
// dcl.init.list/3
namespace One {
int ga[1];
auto &frob1() {
int(&r1)[] = ga;
#if __cplusplus < 202002
// expected-error@-2{{cannot bind to a value of unrelated type}}
#endif
return r1;
}
auto &frob2(int (&arp)[1]) {
int(&r2)[] = arp;
#if __cplusplus < 202002
// expected-error@-2{{cannot bind to a value of unrelated type}}
#endif
return r2;
}
} // namespace One
namespace Two {
int ga[1];
auto *frob1() {
int(*r1)[] = &ga;
#if __cplusplus < 202002
// expected-error@-2{{with an rvalue of type}}
#endif
return r1;
}
auto *frob2(int (*arp)[1]) {
int(*r2)[] = arp;
#if __cplusplus < 202002
// expected-error@-2{{with an lvalue of type}}
#endif
return r2;
}
} // namespace Two
namespace Four {
using Inc = int[2];
using Mat = Inc[1];
Mat *ga[2];
auto *frob1() {
Inc(*const(*r1)[])[] = &ga;
#if __cplusplus < 202002
// expected-error@-2{{with an rvalue of type}}
#else
// missing a required 'const'
Inc(*(*r2)[])[] = &ga; // expected-error{{cannot initialize}}
#endif
return r1;
}
auto *frob2(Mat *(*arp)[1]) {
Inc(*const(*r2)[])[] = arp;
#if __cplusplus < 202002
// expected-error@-2{{with an lvalue of type}}
#else
Inc(*(*r3)[])[] = arp; // expected-error{{cannot initialize}}
#endif
return r2;
}
} // namespace Four
namespace Five {
// from the paper
char (&b(int(&&)[]))[1]; // #1
char (&b(long(&&)[]))[2]; // #2
char (&b(int(&&)[1]))[3]; // #3
char (&b(long(&&)[1]))[4]; // #4
char (&b(int(&&)[2]))[5]; // #5
#if __cplusplus < 202002
// expected-note@-6{{cannot convert initializer}}
// expected-note@-6{{cannot convert initializer}}
// expected-note@-6{{too many initializers}}
// expected-note@-6{{too many initializers}}
// expected-note@-6{{too many initializers}}
#endif
void f() {
static_assert(sizeof(b({1})) == 3);
static_assert(sizeof(b({1, 2})) == 5);
static_assert(sizeof(b({1, 2, 3})) == 1);
#if __cplusplus < 202002
// expected-error@-2{{no matching function}}
#endif
}
} // namespace Five
#if __cplusplus >= 202002
namespace Six {
// from over.ics.rank 3.1
char (&f(int(&&)[]))[1]; // #1
char (&f(double(&&)[]))[2]; // #2
char (&f(int(&&)[2]))[3]; // #3
void toto() {
// Calls #1: Better than #2 due to conversion, better than #3 due to bounds
static_assert(sizeof(f({1})) == 1);
// Calls #2: Identity conversion is better than floating-integral conversion
static_assert(sizeof(f({1.0})) == 2);
// Calls #2: Identity conversion is better than floating-integral conversion
static_assert(sizeof(f({1.0, 2.0})) == 2);
// Calls #3: Converting to array of known bound is better than to unknown
// bound, and an identity conversion is better than
// floating-integral conversion
static_assert(sizeof(f({1, 2})) == 3);
}
} // namespace Six
namespace Seven {
char (&f(int(&&)[]))[1]; // #1
char (&f(double(&&)[1]))[2]; // #2
void quux() {
// Calls #2, float-integral conversion rather than create zero-sized array
static_assert(sizeof(f({})) == 2);
}
} // namespace Seven
namespace Eight {
// brace-elision is not a thing here:
struct A {
int x, y;
};
char (&f1(int(&&)[]))[1]; // #1
char (&f1(A(&&)[]))[2]; // #2
void g1() {
// pick #1, even though that is more elements than #2
// 6 ints, as opposed to 3 As
static_assert(sizeof(f1({1, 2, 3, 4, 5, 6})) == 1);
}
void f2(A(&&)[]); // expected-note{{candidate function not viable}}
void g2() {
f2({1, 2, 3, 4, 5, 6}); // expected-error{{no matching function}}
}
void f3(A(&&)[]);
void g3() {
auto &f = f3;
f({1, 2, 3, 4, 5, 6}); // OK! We're coercing to an already-selected function
}
} // namespace Eight
#endif