xref: /llvm-project/clang/test/Sema/attr-read-only-placement.cpp (revision 678ded017f21b22da3ab20ffafe2bc2dc4457493)
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()31 void 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()164 void 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