1 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s |
2 | |
3 | namespace basic { |
4 | // Ensuring that __bos can be used in constexpr functions without anything |
5 | // sketchy going on... |
6 | constexpr int bos0() { |
7 | int k = 5; |
8 | char cs[10] = {}; |
9 | return __builtin_object_size(&cs[k], 0); |
10 | } |
11 | |
12 | constexpr int bos1() { |
13 | int k = 5; |
14 | char cs[10] = {}; |
15 | return __builtin_object_size(&cs[k], 1); |
16 | } |
17 | |
18 | constexpr int bos2() { |
19 | int k = 5; |
20 | char cs[10] = {}; |
21 | return __builtin_object_size(&cs[k], 2); |
22 | } |
23 | |
24 | constexpr int bos3() { |
25 | int k = 5; |
26 | char cs[10] = {}; |
27 | return __builtin_object_size(&cs[k], 3); |
28 | } |
29 | |
30 | static_assert(bos0() == sizeof(char) * 5, ""); |
31 | static_assert(bos1() == sizeof(char) * 5, ""); |
32 | static_assert(bos2() == sizeof(char) * 5, ""); |
33 | static_assert(bos3() == sizeof(char) * 5, ""); |
34 | } |
35 | |
36 | namespace in_enable_if { |
37 | // The code that prompted these changes was __bos in enable_if |
38 | |
39 | void 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... |
46 | void 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 | |
51 | struct LargeStruct { |
52 | int pad; |
53 | char buf[6]; |
54 | int pad2; |
55 | }; |
56 | |
57 | struct SmallStruct { |
58 | int pad; |
59 | char buf[5]; |
60 | int pad2; |
61 | }; |
62 | |
63 | void noWriteToBuf() { |
64 | char buf[6]; |
65 | copy5CharsInto(buf); |
66 | |
67 | LargeStruct large; |
68 | copy5CharsIntoStrict(large.buf); |
69 | } |
70 | |
71 | void initTheBuf() { |
72 | char buf[6] = {}; |
73 | copy5CharsInto(buf); |
74 | |
75 | LargeStruct large = {0, {}, 0}; |
76 | copy5CharsIntoStrict(large.buf); |
77 | } |
78 | |
79 | int getI(); |
80 | void 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 | |
92 | void 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 | |