builtin-object-size-cxx14.cpp 2.7 KB

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