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
5 struct __attribute__((enforce_read_only_placement
)) A
{ // #A_DECL
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}}
17 struct __attribute__((enforce_read_only_placement
)) B
{ //#B_DECL
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}}
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}}
36 const B b9
; // no-warning
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
44 C c1
; // expected-warning {{object of type 'C' cannot be placed in read-only memory}}
46 // Cases to be handled by the follow-up patches.
48 // Attaching and checking the attribute in reverse, where the attribute is attached after the
51 struct D
{ //expected-note{{previous definition is here}}
53 struct __attribute__((enforce_read_only_placement
)) D
; // #3
54 // expected-warning@#3{{attribute declaration must precede definition}}
56 D d1
; // We do not emit a warning here, as there is another warning for declaring
57 // a type after the definition
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.
66 // Case 2: Declaring a field of the type that has the attribute
68 C c1
; // FIXME: warn the user type `F` that wraps type `C` won't be checked for
69 // read only placement
72 struct BaseWithoutAttribute
{
76 struct __attribute__((enforce_read_only_placement
)) J
: BaseWithoutAttribute
{ // no-warning
79 struct __attribute__((enforce_read_only_placement
)) BaseWithAttribute
{
83 struct __attribute__((enforce_read_only_placement
)) Derived
: BaseWithAttribute
{ // no-warning
87 struct __attribute__((enforce_read_only_placement
)) WrapperToAttributeInstance
{ // no-warning
91 struct __attribute__((enforce_read_only_placement
)) WrapperToNoAttributeInstance
{ // no-warning
92 BaseWithoutAttribute b
;
95 // Cases where the const qualification doesn't ensure read-only memory placement
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
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
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
113 // Case 2: The type has a constructor that makes its fields modifiable
114 struct __attribute__((enforce_read_only_placement
)) L
{
116 L(int val
) { // FIXME: warn the user type `L` won't be placed in the read only program memory
121 struct __attribute__((enforce_read_only_placement
)) ConstInClassInitializers
{ // no-warning
124 ConstInClassInitializers() = default;
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
132 NonConstInClassInitializers() = default;
135 #if (__cplusplus >= 202002L)
136 struct __attribute__((enforce_read_only_placement
)) ConstevalCtor
{
139 consteval
ConstevalCtor(int B
) : b(B
) {} // no-warning
143 #if (__cplusplus >= 201103L)
144 struct __attribute__((enforce_read_only_placement
)) ConstExprCtor
{ // no-warning
147 constexpr ConstExprCtor(int B
) : b(B
) {}
150 constexpr ConstExprCtor
cec1(10); // no-warning
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
157 void func1(C c
); // FIXME: warn the user the instance of 'C' won't be placed in the read only program memory
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
162 C
func3(); // FIXME: warn the user the instance of 'C' won't be placed in the read only program memory
165 C c
; // FIXME: warn the user the instance of 'C' won't be placed in the read only program memory
168 #if (__cplusplus >= 202002L)
169 consteval
void func4(C c
); // no-warning