attr-require-constant-initialization.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. // RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++03 %s
  2. // RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++11 %s
  3. // RUN: %clang_cc1 -fsyntax-only -verify -DTEST_ONE -std=c++14 %s
  4. // RUN: %clang_cc1 -fsyntax-only -verify -DTEST_TWO \
  5. // RUN: -Wglobal-constructors -std=c++14 %s
  6. // RUN: %clang_cc1 -fsyntax-only -verify -DTEST_THREE -xc %s
  7. #define ATTR __attribute__((require_constant_initialization)) // expected-note 0+ {{expanded from macro}}
  8. int ReturnInt(); // expected-note 0+ {{declared here}}
  9. struct PODType { // expected-note 0+ {{declared here}}
  10. int value;
  11. int value2;
  12. };
  13. #if defined(__cplusplus)
  14. #if __cplusplus >= 201103L
  15. struct LitType {
  16. constexpr LitType() : value(0) {}
  17. constexpr LitType(int x) : value(x) {}
  18. LitType(void *) : value(-1) {} // expected-note 0+ {{declared here}}
  19. int value;
  20. };
  21. #endif
  22. struct NonLit { // expected-note 0+ {{declared here}}
  23. #if __cplusplus >= 201402L
  24. constexpr NonLit() : value(0) {}
  25. constexpr NonLit(int x) : value(x) {}
  26. #else
  27. NonLit() : value(0) {} // expected-note 0+ {{declared here}}
  28. NonLit(int x) : value(x) {}
  29. #endif
  30. NonLit(void *) : value(-1) {} // expected-note 0+ {{declared here}}
  31. ~NonLit() {}
  32. int value;
  33. };
  34. struct StoresNonLit {
  35. #if __cplusplus >= 201402L
  36. constexpr StoresNonLit() : obj() {}
  37. constexpr StoresNonLit(int x) : obj(x) {}
  38. #else
  39. StoresNonLit() : obj() {} // expected-note 0+ {{declared here}}
  40. StoresNonLit(int x) : obj(x) {}
  41. #endif
  42. StoresNonLit(void *p) : obj(p) {}
  43. NonLit obj;
  44. };
  45. #endif // __cplusplus
  46. #if defined(TEST_ONE) // Test semantics of attribute
  47. // Test diagnostics when attribute is applied to non-static declarations.
  48. void test_func_local(ATTR int param) { // expected-error {{only applies to global variables}}
  49. ATTR int x = 42; // expected-error {{only applies to}}
  50. ATTR extern int y;
  51. }
  52. struct ATTR class_mem { // expected-error {{only applies to}}
  53. ATTR int x; // expected-error {{only applies to}}
  54. };
  55. // [basic.start.static]p2.1
  56. // if each full-expression (including implicit conversions) that appears in
  57. // the initializer of a reference with static or thread storage duration is
  58. // a constant expression (5.20) and the reference is bound to a glvalue
  59. // designating an object with static storage duration, to a temporary object
  60. // (see 12.2) or subobject thereof, or to a function;
  61. // Test binding to a static glvalue
  62. const int glvalue_int = 42;
  63. const int glvalue_int2 = ReturnInt();
  64. ATTR const int &glvalue_ref ATTR = glvalue_int;
  65. ATTR const int &glvalue_ref2 ATTR = glvalue_int2;
  66. ATTR __thread const int &glvalue_ref_tl = glvalue_int;
  67. void test_basic_start_static_2_1() {
  68. const int non_global = 42;
  69. ATTR static const int &local_init = non_global; // expected-error {{variable does not have a constant initializer}}
  70. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  71. #if __cplusplus >= 201103L
  72. // expected-note@-3 {{reference to 'non_global' is not a constant expression}}
  73. // expected-note@-5 {{declared here}}
  74. #else
  75. // expected-note@-6 {{subexpression not valid in a constant expression}}
  76. #endif
  77. ATTR static const int &global_init = glvalue_int;
  78. ATTR static const int &temp_init = 42;
  79. }
  80. ATTR const int &temp_ref = 42;
  81. ATTR const int &temp_ref2 = ReturnInt(); // expected-error {{variable does not have a constant initializer}}
  82. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  83. #if __cplusplus >= 201103L
  84. // expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
  85. #else
  86. // expected-note@-5 {{subexpression not valid in a constant expression}}
  87. #endif
  88. ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not have a constant initializer}}
  89. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  90. #if __cplusplus >= 201103L
  91. // expected-note@-3 {{non-literal type 'const NonLit' cannot be used in a constant expression}}
  92. #else
  93. // expected-note@-5 {{subexpression not valid in a constant expression}}
  94. #endif
  95. #if __cplusplus >= 201103L
  96. ATTR const LitType &lit_temp_ref = 42;
  97. ATTR const int &subobj_ref = LitType{}.value;
  98. #endif
  99. ATTR const int &nl_subobj_ref = NonLit().value; // expected-error {{variable does not have a constant initializer}}
  100. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  101. #if __cplusplus >= 201103L
  102. // expected-note-re@-3 {{non-literal type '{{.*}}' cannot be used in a constant expression}}
  103. #else
  104. // expected-note@-5 {{subexpression not valid in a constant expression}}
  105. #endif
  106. struct TT1 {
  107. ATTR static const int &no_init;
  108. ATTR static const int &glvalue_init;
  109. ATTR static const int &temp_init;
  110. ATTR static const int &subobj_init;
  111. #if __cplusplus >= 201103L
  112. ATTR static thread_local const int &tl_glvalue_init;
  113. ATTR static thread_local const int &tl_temp_init; // expected-note {{required by 'require_constant_initialization' attribute here}}
  114. #endif
  115. };
  116. const int &TT1::glvalue_init = glvalue_int;
  117. const int &TT1::temp_init = 42;
  118. const int &TT1::subobj_init = PODType().value;
  119. #if __cplusplus >= 201103L
  120. thread_local const int &TT1::tl_glvalue_init = glvalue_int;
  121. thread_local const int &TT1::tl_temp_init = 42; // expected-error {{variable does not have a constant initializer}}
  122. // expected-note@-1 {{reference to temporary is not a constant expression}}
  123. // expected-note@-2 {{temporary created here}}
  124. #endif
  125. // [basic.start.static]p2.2
  126. // if an object with static or thread storage duration is initialized by a
  127. // constructor call, and if the initialization full-expression is a constant
  128. // initializer for the object;
  129. void test_basic_start_static_2_2() {
  130. #if __cplusplus < 201103L
  131. ATTR static PODType pod;
  132. #else
  133. ATTR static PODType pod; // expected-error {{variable does not have a constant initializer}}
  134. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  135. // expected-note@-2 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}}
  136. #endif
  137. ATTR static PODType pot2 = {ReturnInt()}; // expected-error {{variable does not have a constant initializer}}
  138. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  139. #if __cplusplus >= 201103L
  140. // expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
  141. #else
  142. // expected-note@-5 {{subexpression not valid in a constant expression}}
  143. #endif
  144. #if __cplusplus >= 201103L
  145. constexpr LitType l;
  146. ATTR static LitType static_lit = l;
  147. ATTR static LitType static_lit2 = (void *)0; // expected-error {{variable does not have a constant initializer}}
  148. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  149. // expected-note@-2 {{non-constexpr constructor 'LitType' cannot be used in a constant expression}}
  150. ATTR static LitType static_lit3 = ReturnInt(); // expected-error {{variable does not have a constant initializer}}
  151. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  152. // expected-note@-2 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
  153. ATTR thread_local LitType tls = 42;
  154. #endif
  155. }
  156. struct TT2 {
  157. ATTR static PODType pod_noinit;
  158. #if __cplusplus >= 201103L
  159. // expected-note@-2 {{required by 'require_constant_initialization' attribute here}}
  160. #endif
  161. ATTR static PODType pod_copy_init; // expected-note {{required by 'require_constant_initialization' attribute here}}
  162. #if __cplusplus >= 201402L
  163. ATTR static constexpr LitType lit = {};
  164. ATTR static const NonLit non_lit;
  165. ATTR static const NonLit non_lit_list_init;
  166. ATTR static const NonLit non_lit_copy_init; // expected-note {{required by 'require_constant_initialization' attribute here}}
  167. #endif
  168. };
  169. PODType TT2::pod_noinit; // expected-note 0+ {{declared here}}
  170. #if __cplusplus >= 201103L
  171. // expected-error@-2 {{variable does not have a constant initializer}}
  172. // expected-note@-3 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}}
  173. #endif
  174. PODType TT2::pod_copy_init(TT2::pod_noinit); // expected-error {{variable does not have a constant initializer}}
  175. #if __cplusplus >= 201103L
  176. // expected-note@-2 {{read of non-constexpr variable 'pod_noinit' is not allowed in a constant expression}}
  177. // expected-note@-3 {{in call to 'PODType(pod_noinit)'}}
  178. #else
  179. // expected-note@-5 {{subexpression not valid in a constant expression}}
  180. #endif
  181. #if __cplusplus >= 201402L
  182. const NonLit TT2::non_lit(42);
  183. const NonLit TT2::non_lit_list_init = {42};
  184. const NonLit TT2::non_lit_copy_init = 42; // expected-error {{variable does not have a constant initializer}}
  185. // expected-note@-1 {{subexpression not valid in a constant expression}}
  186. #endif
  187. #if __cplusplus >= 201103L
  188. ATTR LitType lit_ctor;
  189. ATTR LitType lit_ctor2{};
  190. ATTR LitType lit_ctor3 = {};
  191. ATTR __thread LitType lit_ctor_tl = {};
  192. #if __cplusplus >= 201402L
  193. ATTR NonLit nl_ctor;
  194. ATTR NonLit nl_ctor2{};
  195. ATTR NonLit nl_ctor3 = {};
  196. ATTR thread_local NonLit nl_ctor_tl = {};
  197. ATTR StoresNonLit snl;
  198. #else
  199. ATTR NonLit nl_ctor; // expected-error {{variable does not have a constant initializer}}
  200. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  201. // expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}}
  202. ATTR NonLit nl_ctor2{}; // expected-error {{variable does not have a constant initializer}}
  203. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  204. // expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}}
  205. ATTR NonLit nl_ctor3 = {}; // expected-error {{variable does not have a constant initializer}}
  206. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  207. // expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}}
  208. ATTR thread_local NonLit nl_ctor_tl = {}; // expected-error {{variable does not have a constant initializer}}
  209. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  210. // expected-note@-2 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}}
  211. ATTR StoresNonLit snl; // expected-error {{variable does not have a constant initializer}}
  212. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  213. // expected-note@-2 {{non-constexpr constructor 'StoresNonLit' cannot be used in a constant expression}}
  214. #endif
  215. // Non-literal types cannot appear in the initializer of a non-literal type.
  216. ATTR int nl_in_init = NonLit{42}.value; // expected-error {{variable does not have a constant initializer}}
  217. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  218. // expected-note@-2 {{non-literal type 'NonLit' cannot be used in a constant expression}}
  219. ATTR int lit_in_init = LitType{42}.value;
  220. #endif
  221. // [basic.start.static]p2.3
  222. // if an object with static or thread storage duration is not initialized by a
  223. // constructor call and if either the object is value-initialized or every
  224. // full-expression that appears in its initializer is a constant expression.
  225. void test_basic_start_static_2_3() {
  226. ATTR static int static_local = 42;
  227. ATTR static int static_local2; // zero-initialization takes place
  228. #if __cplusplus >= 201103L
  229. ATTR thread_local int tl_local = 42;
  230. #endif
  231. }
  232. ATTR int no_init; // zero initialization takes place
  233. ATTR int arg_init = 42;
  234. ATTR PODType pod_init = {};
  235. ATTR PODType pod_missing_init = {42 /* should have second arg */};
  236. ATTR PODType pod_full_init = {1, 2};
  237. ATTR PODType pod_non_constexpr_init = {1, ReturnInt()}; // expected-error {{variable does not have a constant initializer}}
  238. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  239. #if __cplusplus >= 201103L
  240. // expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
  241. #else
  242. // expected-note@-5 {{subexpression not valid in a constant expression}}
  243. #endif
  244. #if __cplusplus >= 201103L
  245. ATTR int val_init{};
  246. ATTR int brace_init = {};
  247. #endif
  248. ATTR __thread int tl_init = 0;
  249. typedef const char *StrType;
  250. #if __cplusplus >= 201103L
  251. // Test that the validity of the selected constructor is checked, not just the
  252. // initializer
  253. struct NotC {
  254. constexpr NotC(void *) {}
  255. NotC(int) {} // expected-note 0+ {{declared here}}
  256. };
  257. template <class T>
  258. struct TestCtor {
  259. constexpr TestCtor(int x) : value(x) {}
  260. // expected-note@-1 {{non-constexpr constructor 'NotC' cannot be used in a constant expression}}
  261. T value;
  262. };
  263. ATTR TestCtor<NotC> t(42); // expected-error {{variable does not have a constant initializer}}
  264. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  265. // expected-note@-2 {{in call to 'TestCtor(42)'}}
  266. #endif
  267. // Test various array types
  268. ATTR const char *foo[] = {"abc", "def"};
  269. ATTR PODType bar[] = {{}, {123, 456}};
  270. namespace AttrAddedTooLate {
  271. struct A {
  272. static const int n = 0; // expected-note {{here}}
  273. };
  274. ATTR const int A::n; // expected-warning {{added after initialization}}
  275. int m = 0; // expected-note {{here}}
  276. extern ATTR int m; // expected-warning {{added after initialization}}
  277. }
  278. #elif defined(TEST_TWO) // Test for duplicate warnings
  279. struct NotC {
  280. constexpr NotC(void *) {}
  281. NotC(int) {} // expected-note 2 {{declared here}}
  282. };
  283. template <class T>
  284. struct TestCtor {
  285. constexpr TestCtor(int x) : value(x) {} // expected-note 2 {{non-constexpr constructor}}
  286. T value;
  287. };
  288. ATTR LitType non_const_lit(nullptr); // expected-error {{variable does not have a constant initializer}}
  289. // expected-note@-1 {{required by 'require_constant_initialization' attribute here}}
  290. // expected-note@-2 {{non-constexpr constructor 'LitType' cannot be used in a constant expression}}
  291. ATTR NonLit non_const(nullptr); // expected-error {{variable does not have a constant initializer}}
  292. // expected-warning@-1 {{declaration requires a global destructor}}
  293. // expected-note@-2 {{required by 'require_constant_initialization' attribute here}}
  294. // expected-note@-3 {{non-constexpr constructor 'NonLit' cannot be used in a constant expression}}
  295. LitType const_init_lit(nullptr); // expected-warning {{declaration requires a global constructor}}
  296. NonLit const_init{42}; // expected-warning {{declaration requires a global destructor}}
  297. constexpr TestCtor<NotC> inval_constexpr(42); // expected-error {{must be initialized by a constant expression}}
  298. // expected-note@-1 {{in call to 'TestCtor(42)'}}
  299. ATTR constexpr TestCtor<NotC> inval_constexpr2(42); // expected-error {{must be initialized by a constant expression}}
  300. // expected-note@-1 {{in call to 'TestCtor(42)'}}
  301. #elif defined(TEST_THREE)
  302. #if defined(__cplusplus)
  303. #error This test requires C
  304. #endif
  305. // Test that using the attribute in C results in a diagnostic
  306. ATTR int x = 0; // expected-warning {{attribute ignored}}
  307. #else
  308. #error No test case specified
  309. #endif // defined(TEST_N)