1 // RUN: %clang_cc1 -Wread-only-types %s -verify -fsyntax-only 2 // RUN: %clang_cc1 -std=c++2a -Wread-only-types %s -verify -fsyntax-only 3 // RUN: %clang_cc1 -std=c++17 -Wread-only-types %s -verify -fsyntax-only 4 5 struct __attribute__((enforce_read_only_placement)) A { // #A_DECL 6 }; 7 8 A a1; // expected-warning {{object of type 'A' cannot be placed in read-only memory}} 9 // expected-note@#A_DECL {{type was declared read-only here}} 10 const A a2[10]; // no-warning 11 A a3[20]; // expected-warning {{object of type 'A' cannot be placed in read-only memory}} 12 // expected-note@#A_DECL {{type was declared read-only here}} 13 14 15 16 struct B; 17 struct __attribute__((enforce_read_only_placement)) B { //#B_DECL 18 }; 19 20 B b1; // expected-warning {{object of type 'B' cannot be placed in read-only memory}} 21 // expected-note@#B_DECL {{type was declared read-only here}} 22 const B b2; // no-warning 23 const B b3[4]; // no-warning 24 B b4[5]; // expected-warning {{object of type 'B' cannot be placed in read-only memory}} 25 // expected-note@#B_DECL {{type was declared read-only here}} 26 B b5[5][5]; // expected-warning {{object of type 'B' cannot be placed in read-only memory}} 27 // expected-note@#B_DECL {{type was declared read-only here}} 28 B b10[5][5][5]; // expected-warning {{object of type 'B' cannot be placed in read-only memory}} 29 // expected-note@#B_DECL {{type was declared read-only here}} 30 method1()31void method1() { 32 static const B b6; 33 static B b7;// expected-warning {{object of type 'B' cannot be placed in read-only memory}} 34 // expected-note@#B_DECL {{type was declared read-only here}} 35 B b8; // no-warning 36 const B b9; // no-warning 37 } 38 39 struct C; 40 struct __attribute__((enforce_read_only_placement)) C; // expected-note {{type was declared read-only here}} 41 struct C { // no-note. The note should be attached to the definition/declaration bearing the attribute 42 }; 43 44 C c1; // expected-warning {{object of type 'C' cannot be placed in read-only memory}} 45 46 // Cases to be handled by the follow-up patches. 47 48 // Attaching and checking the attribute in reverse, where the attribute is attached after the 49 // type definition 50 struct D; 51 struct D { //expected-note{{previous definition is here}} 52 }; 53 struct __attribute__((enforce_read_only_placement)) D; // #3 54 // expected-warning@#3{{attribute declaration must precede definition}} 55 56 D d1; // We do not emit a warning here, as there is another warning for declaring 57 // a type after the definition 58 59 60 // Cases where the attribute must be explicitly attached to another type 61 // Case 1: Inheriting from a type that has the attribute 62 struct E : C { // FIXME: warn the user declarations of type `E`, that extends `C`, won't be 63 // checked for read only placement because `E` is not marked as `C` is. 64 }; 65 66 // Case 2: Declaring a field of the type that has the attribute 67 struct F { 68 C c1; // FIXME: warn the user type `F` that wraps type `C` won't be checked for 69 // read only placement 70 }; 71 72 struct BaseWithoutAttribute { 73 int a; 74 }; 75 76 struct __attribute__((enforce_read_only_placement)) J : BaseWithoutAttribute { // no-warning 77 }; 78 79 struct __attribute__((enforce_read_only_placement)) BaseWithAttribute { 80 int i; 81 }; 82 83 struct __attribute__((enforce_read_only_placement)) Derived : BaseWithAttribute { // no-warning 84 int j; 85 }; 86 87 struct __attribute__((enforce_read_only_placement)) WrapperToAttributeInstance { // no-warning 88 BaseWithAttribute b; 89 }; 90 91 struct __attribute__((enforce_read_only_placement)) WrapperToNoAttributeInstance { // no-warning 92 BaseWithoutAttribute b; 93 }; 94 95 // Cases where the const qualification doesn't ensure read-only memory placement 96 // of an instance. 97 98 // Case 1: The type defines/inherits mutable data members 99 struct __attribute__((enforce_read_only_placement)) G { 100 mutable int x; // FIXME: warn the user type `G` won't be placed in the read only program memory 101 }; 102 103 struct __attribute__((enforce_read_only_placement)) H : public G { // FIXME: Warn the user type `H` 104 // won't be placed in the read only program memory 105 }; 106 107 struct __attribute__((enforce_read_only_placement)) K { // FIXME : Warn the user type `K` w on't be 108 // placed in the read only program memory 109 G g; 110 }; 111 112 113 // Case 2: The type has a constructor that makes its fields modifiable 114 struct __attribute__((enforce_read_only_placement)) L { 115 int b; LL116 L(int val) { // FIXME: warn the user type `L` won't be placed in the read only program memory 117 b = val; 118 } 119 }; 120 121 struct __attribute__((enforce_read_only_placement)) ConstInClassInitializers { // no-warning 122 int b = 12; 123 124 ConstInClassInitializers() = default; 125 }; 126 127 int foo(); 128 struct __attribute__((enforce_read_only_placement)) NonConstInClassInitializers { 129 int b = foo(); // FIXME: warn the user type `NonConstInClassInitializers` won't be placed 130 // in the read only program memory 131 132 NonConstInClassInitializers() = default; 133 }; 134 135 #if (__cplusplus >= 202002L) 136 struct __attribute__((enforce_read_only_placement)) ConstevalCtor { 137 int b; 138 ConstevalCtorConstevalCtor139 consteval ConstevalCtor(int B) : b(B) {} // no-warning 140 }; 141 #endif 142 143 #if (__cplusplus >= 201103L) 144 struct __attribute__((enforce_read_only_placement)) ConstExprCtor { // no-warning 145 int b; 146 ConstExprCtorConstExprCtor147 constexpr ConstExprCtor(int B) : b(B) {} 148 }; 149 150 constexpr ConstExprCtor cec1(10); // no-warning 151 152 #endif 153 154 // Cases where an object is allocated on the heap or on the stack 155 C *c2 = new C; // FIXME: warn the user this instance of 'C' won't be placed in the read only program memory 156 157 void func1(C c); // FIXME: warn the user the instance of 'C' won't be placed in the read only program memory 158 159 void func2(const C c); // FIXME: warn the user the instance of 'C' won't be placed in the read 160 // only program memory 161 162 C func3(); // FIXME: warn the user the instance of 'C' won't be placed in the read only program memory 163 func4()164void func4() { 165 C c; // FIXME: warn the user the instance of 'C' won't be placed in the read only program memory 166 } 167 168 #if (__cplusplus >= 202002L) 169 consteval void func4(C c); // no-warning 170 #endif 171