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