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