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