1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s
2*67e74705SXin Li
3*67e74705SXin Li namespace basic {
4*67e74705SXin Li // Ensuring that __bos can be used in constexpr functions without anything
5*67e74705SXin Li // sketchy going on...
bos0()6*67e74705SXin Li constexpr int bos0() {
7*67e74705SXin Li int k = 5;
8*67e74705SXin Li char cs[10] = {};
9*67e74705SXin Li return __builtin_object_size(&cs[k], 0);
10*67e74705SXin Li }
11*67e74705SXin Li
bos1()12*67e74705SXin Li constexpr int bos1() {
13*67e74705SXin Li int k = 5;
14*67e74705SXin Li char cs[10] = {};
15*67e74705SXin Li return __builtin_object_size(&cs[k], 1);
16*67e74705SXin Li }
17*67e74705SXin Li
bos2()18*67e74705SXin Li constexpr int bos2() {
19*67e74705SXin Li int k = 5;
20*67e74705SXin Li char cs[10] = {};
21*67e74705SXin Li return __builtin_object_size(&cs[k], 2);
22*67e74705SXin Li }
23*67e74705SXin Li
bos3()24*67e74705SXin Li constexpr int bos3() {
25*67e74705SXin Li int k = 5;
26*67e74705SXin Li char cs[10] = {};
27*67e74705SXin Li return __builtin_object_size(&cs[k], 3);
28*67e74705SXin Li }
29*67e74705SXin Li
30*67e74705SXin Li static_assert(bos0() == sizeof(char) * 5, "");
31*67e74705SXin Li static_assert(bos1() == sizeof(char) * 5, "");
32*67e74705SXin Li static_assert(bos2() == sizeof(char) * 5, "");
33*67e74705SXin Li static_assert(bos3() == sizeof(char) * 5, "");
34*67e74705SXin Li }
35*67e74705SXin Li
36*67e74705SXin Li namespace in_enable_if {
37*67e74705SXin Li // The code that prompted these changes was __bos in enable_if
38*67e74705SXin Li
39*67e74705SXin Li void copy5CharsInto(char *buf) // expected-note{{candidate}}
40*67e74705SXin Li __attribute__((enable_if(__builtin_object_size(buf, 0) != -1 &&
41*67e74705SXin Li __builtin_object_size(buf, 0) > 5,
42*67e74705SXin Li "")));
43*67e74705SXin Li
44*67e74705SXin Li // We use different EvalModes for __bos with type 0 versus 1. Ensure 1 works,
45*67e74705SXin Li // too...
46*67e74705SXin Li void copy5CharsIntoStrict(char *buf) // expected-note{{candidate}}
47*67e74705SXin Li __attribute__((enable_if(__builtin_object_size(buf, 1) != -1 &&
48*67e74705SXin Li __builtin_object_size(buf, 1) > 5,
49*67e74705SXin Li "")));
50*67e74705SXin Li
51*67e74705SXin Li struct LargeStruct {
52*67e74705SXin Li int pad;
53*67e74705SXin Li char buf[6];
54*67e74705SXin Li int pad2;
55*67e74705SXin Li };
56*67e74705SXin Li
57*67e74705SXin Li struct SmallStruct {
58*67e74705SXin Li int pad;
59*67e74705SXin Li char buf[5];
60*67e74705SXin Li int pad2;
61*67e74705SXin Li };
62*67e74705SXin Li
noWriteToBuf()63*67e74705SXin Li void noWriteToBuf() {
64*67e74705SXin Li char buf[6];
65*67e74705SXin Li copy5CharsInto(buf);
66*67e74705SXin Li
67*67e74705SXin Li LargeStruct large;
68*67e74705SXin Li copy5CharsIntoStrict(large.buf);
69*67e74705SXin Li }
70*67e74705SXin Li
initTheBuf()71*67e74705SXin Li void initTheBuf() {
72*67e74705SXin Li char buf[6] = {};
73*67e74705SXin Li copy5CharsInto(buf);
74*67e74705SXin Li
75*67e74705SXin Li LargeStruct large = {0, {}, 0};
76*67e74705SXin Li copy5CharsIntoStrict(large.buf);
77*67e74705SXin Li }
78*67e74705SXin Li
79*67e74705SXin Li int getI();
initTheBufWithALoop()80*67e74705SXin Li void initTheBufWithALoop() {
81*67e74705SXin Li char buf[6] = {};
82*67e74705SXin Li for (unsigned I = getI(); I != sizeof(buf); ++I)
83*67e74705SXin Li buf[I] = I;
84*67e74705SXin Li copy5CharsInto(buf);
85*67e74705SXin Li
86*67e74705SXin Li LargeStruct large;
87*67e74705SXin Li for (unsigned I = getI(); I != sizeof(buf); ++I)
88*67e74705SXin Li large.buf[I] = I;
89*67e74705SXin Li copy5CharsIntoStrict(large.buf);
90*67e74705SXin Li }
91*67e74705SXin Li
tooSmallBuf()92*67e74705SXin Li void tooSmallBuf() {
93*67e74705SXin Li char buf[5];
94*67e74705SXin Li copy5CharsInto(buf); // expected-error{{no matching function for call}}
95*67e74705SXin Li
96*67e74705SXin Li SmallStruct small;
97*67e74705SXin Li copy5CharsIntoStrict(small.buf); // expected-error{{no matching function for call}}
98*67e74705SXin Li }
99*67e74705SXin Li }
100