mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 13:50:11 +00:00
444ec0957c
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
174 lines
3.7 KiB
C++
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
|