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