| // RUN: %clang_cc1 -Wread-only-types %s -verify -fsyntax-only |
| // RUN: %clang_cc1 -std=c++2a -Wread-only-types %s -verify -fsyntax-only |
| // RUN: %clang_cc1 -std=c++17 -Wread-only-types %s -verify -fsyntax-only |
| |
| struct __attribute__((enforce_read_only_placement)) A { // #A_DECL |
| }; |
| |
| A a1; // expected-warning {{object of type 'A' cannot be placed in read-only memory}} |
| // expected-note@#A_DECL {{type was declared read-only here}} |
| const A a2[10]; // no-warning |
| A a3[20]; // expected-warning {{object of type 'A' cannot be placed in read-only memory}} |
| // expected-note@#A_DECL {{type was declared read-only here}} |
| |
| |
| |
| struct B; |
| struct __attribute__((enforce_read_only_placement)) B { //#B_DECL |
| }; |
| |
| B b1; // expected-warning {{object of type 'B' cannot be placed in read-only memory}} |
| // expected-note@#B_DECL {{type was declared read-only here}} |
| const B b2; // no-warning |
| const B b3[4]; // no-warning |
| B b4[5]; // expected-warning {{object of type 'B' cannot be placed in read-only memory}} |
| // expected-note@#B_DECL {{type was declared read-only here}} |
| B b5[5][5]; // expected-warning {{object of type 'B' cannot be placed in read-only memory}} |
| // expected-note@#B_DECL {{type was declared read-only here}} |
| B b10[5][5][5]; // expected-warning {{object of type 'B' cannot be placed in read-only memory}} |
| // expected-note@#B_DECL {{type was declared read-only here}} |
| |
| void method1() { |
| static const B b6; |
| static B b7;// expected-warning {{object of type 'B' cannot be placed in read-only memory}} |
| // expected-note@#B_DECL {{type was declared read-only here}} |
| B b8; // no-warning |
| const B b9; // no-warning |
| } |
| |
| struct C; |
| struct __attribute__((enforce_read_only_placement)) C; // expected-note {{type was declared read-only here}} |
| struct C { // no-note. The note should be attached to the definition/declaration bearing the attribute |
| }; |
| |
| C c1; // expected-warning {{object of type 'C' cannot be placed in read-only memory}} |
| |
| // Cases to be handled by the follow-up patches. |
| |
| // Attaching and checking the attribute in reverse, where the attribute is attached after the |
| // type definition |
| struct D; |
| struct D { //expected-note{{previous definition is here}} |
| }; |
| struct __attribute__((enforce_read_only_placement)) D; // #3 |
| // expected-warning@#3{{attribute declaration must precede definition}} |
| |
| D d1; // We do not emit a warning here, as there is another warning for declaring |
| // a type after the definition |
| |
| |
| // Cases where the attribute must be explicitly attached to another type |
| // Case 1: Inheriting from a type that has the attribute |
| struct E : C { // FIXME: warn the user declarations of type `E`, that extends `C`, won't be |
| // checked for read only placement because `E` is not marked as `C` is. |
| }; |
| |
| // Case 2: Declaring a field of the type that has the attribute |
| struct F { |
| C c1; // FIXME: warn the user type `F` that wraps type `C` won't be checked for |
| // read only placement |
| }; |
| |
| struct BaseWithoutAttribute { |
| int a; |
| }; |
| |
| struct __attribute__((enforce_read_only_placement)) J : BaseWithoutAttribute { // no-warning |
| }; |
| |
| struct __attribute__((enforce_read_only_placement)) BaseWithAttribute { |
| int i; |
| }; |
| |
| struct __attribute__((enforce_read_only_placement)) Derived : BaseWithAttribute { // no-warning |
| int j; |
| }; |
| |
| struct __attribute__((enforce_read_only_placement)) WrapperToAttributeInstance { // no-warning |
| BaseWithAttribute b; |
| }; |
| |
| struct __attribute__((enforce_read_only_placement)) WrapperToNoAttributeInstance { // no-warning |
| BaseWithoutAttribute b; |
| }; |
| |
| // Cases where the const qualification doesn't ensure read-only memory placement |
| // of an instance. |
| |
| // Case 1: The type defines/inherits mutable data members |
| struct __attribute__((enforce_read_only_placement)) G { |
| mutable int x; // FIXME: warn the user type `G` won't be placed in the read only program memory |
| }; |
| |
| struct __attribute__((enforce_read_only_placement)) H : public G { // FIXME: Warn the user type `H` |
| // won't be placed in the read only program memory |
| }; |
| |
| struct __attribute__((enforce_read_only_placement)) K { // FIXME : Warn the user type `K` w on't be |
| // placed in the read only program memory |
| G g; |
| }; |
| |
| |
| // Case 2: The type has a constructor that makes its fields modifiable |
| struct __attribute__((enforce_read_only_placement)) L { |
| int b; |
| L(int val) { // FIXME: warn the user type `L` won't be placed in the read only program memory |
| b = val; |
| } |
| }; |
| |
| struct __attribute__((enforce_read_only_placement)) ConstInClassInitializers { // no-warning |
| int b = 12; |
| |
| ConstInClassInitializers() = default; |
| }; |
| |
| int foo(); |
| struct __attribute__((enforce_read_only_placement)) NonConstInClassInitializers { |
| int b = foo(); // FIXME: warn the user type `NonConstInClassInitializers` won't be placed |
| // in the read only program memory |
| |
| NonConstInClassInitializers() = default; |
| }; |
| |
| #if (__cplusplus >= 202002L) |
| struct __attribute__((enforce_read_only_placement)) ConstevalCtor { |
| int b; |
| |
| consteval ConstevalCtor(int B) : b(B) {} // no-warning |
| }; |
| #endif |
| |
| #if (__cplusplus >= 201103L) |
| struct __attribute__((enforce_read_only_placement)) ConstExprCtor { // no-warning |
| int b; |
| |
| constexpr ConstExprCtor(int B) : b(B) {} |
| }; |
| |
| constexpr ConstExprCtor cec1(10); // no-warning |
| |
| #endif |
| |
| // Cases where an object is allocated on the heap or on the stack |
| C *c2 = new C; // FIXME: warn the user this instance of 'C' won't be placed in the read only program memory |
| |
| void func1(C c); // FIXME: warn the user the instance of 'C' won't be placed in the read only program memory |
| |
| void func2(const C c); // FIXME: warn the user the instance of 'C' won't be placed in the read |
| // only program memory |
| |
| C func3(); // FIXME: warn the user the instance of 'C' won't be placed in the read only program memory |
| |
| void func4() { |
| C c; // FIXME: warn the user the instance of 'C' won't be placed in the read only program memory |
| } |
| |
| #if (__cplusplus >= 202002L) |
| consteval void func4(C c); // no-warning |
| #endif |