|
1 | | -// RUN: %clang_cc1 -fsyntax-only -fblocks -fcxx-exceptions -verify -Wfunction-effects %s |
2 | | -// RUN: %clang_cc1 -fsyntax-only -fblocks -verify -x c -std=c23 -Wfunction-effects %s |
| 1 | +// RUN: %clang_cc1 -fsyntax-only -fblocks -fcxx-exceptions -verify -Wfunction-effects -Wfunction-effect-redeclarations %s |
| 2 | +// RUN: %clang_cc1 -fsyntax-only -fblocks -verify -x c -std=c23 -Wfunction-effects -Wfunction-effect-redeclarations %s |
3 | 3 |
|
4 | 4 | #if !__has_attribute(nonblocking) |
5 | 5 | #error "the 'nonblocking' attribute is not available" |
@@ -127,29 +127,35 @@ void type_conversions_2() |
127 | 127 | #endif |
128 | 128 |
|
129 | 129 | // --- VIRTUAL METHODS --- |
130 | | -// Attributes propagate to overridden methods, so no diagnostics except for conflicts. |
| 130 | +// Attributes propagate to overridden methods. |
131 | 131 | // Check this in the syntax tests too. |
132 | 132 | #ifdef __cplusplus |
133 | 133 | struct Base { |
134 | 134 | virtual void f1(); |
135 | | - virtual void nonblocking() noexcept [[clang::nonblocking]]; |
136 | | - virtual void nonallocating() noexcept [[clang::nonallocating]]; |
| 135 | + virtual void nonblocking() noexcept [[clang::nonblocking]]; // expected-note {{overridden virtual function is here}} |
| 136 | + virtual void nonallocating() noexcept [[clang::nonallocating]]; // expected-note {{overridden virtual function is here}} |
137 | 137 | virtual void f2() [[clang::nonallocating]]; // expected-note {{previous declaration is here}} |
| 138 | + virtual void f3() [[clang::nonblocking]]; // expected-note {{overridden virtual function is here}} |
138 | 139 | }; |
139 | 140 |
|
140 | 141 | struct Derived : public Base { |
141 | 142 | void f1() [[clang::nonblocking]] override; |
142 | | - void nonblocking() noexcept override; |
143 | | - void nonallocating() noexcept override; |
| 143 | + void nonblocking() noexcept override; // expected-warning {{overriding function is missing 'nonblocking' attribute from base declaration}} |
| 144 | + void nonallocating() noexcept override; // expected-warning {{overriding function is missing 'nonallocating' attribute from base declaration}} |
144 | 145 | void f2() [[clang::allocating]] override; // expected-warning {{effects conflict when merging declarations; kept 'allocating', discarded 'nonallocating'}} |
145 | 146 | }; |
| 147 | + |
| 148 | +template <bool B> |
| 149 | +struct TDerived : public Base { |
| 150 | + void f3() [[clang::nonblocking(B)]] override; // expected-warning {{attribute 'nonblocking' on overriding function conflicts with base declaration}} |
| 151 | +}; |
146 | 152 | #endif // __cplusplus |
147 | 153 |
|
148 | 154 | // --- REDECLARATIONS --- |
149 | 155 |
|
150 | 156 | void f2(); |
151 | 157 | void f2() [[clang::nonblocking]]; // expected-note {{previous declaration is here}} |
152 | | -void f2(); // expected-warning {{attribute 'nonblocking' on function does not match previous declaration}} |
| 158 | +void f2(); // expected-warning {{redeclaration is missing 'nonblocking' attribute from previous declaration}} |
153 | 159 | // Note: we verify that the attribute is actually seen during the constraints tests. |
154 | 160 |
|
155 | 161 | void f3() [[clang::blocking]]; // expected-note {{previous declaration is here}} |
|
0 commit comments