1 // RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify -Wc++20-extensions %s
2 // RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -Wc++17-extensions %s
3 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -DEXT -Wc++17-extensions -Wc++20-extensions %s
4
5 struct [[nodiscard]] S {};
6 S get_s();
7 S& get_s_ref();
8
9 enum [[nodiscard]] E {};
10 E get_e();
11
12 [[nodiscard]] int get_i();
13 [[nodiscard]] volatile int &get_vi();
14
f()15 void f() {
16 get_s(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
17 get_i(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
18 get_vi(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
19 get_e(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
20
21 // Okay, warnings are not encouraged
22 get_s_ref();
23 (void)get_s();
24 (void)get_i();
25 (void)get_vi();
26 (void)get_e();
27 }
28
29 [[nodiscard]] volatile char &(*fp)(); // expected-warning {{'nodiscard' attribute only applies to functions, classes, or enumerations}}
g()30 void g() {
31 fp(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
32
33 // OK, warning suppressed.
34 (void)fp();
35 }
36
37 namespace PR31526 {
38 typedef E (*fp1)();
39 typedef S (*fp2)();
40
41 typedef S S_alias;
42 typedef S_alias (*fp3)();
43
44 typedef fp2 fp2_alias;
45
f()46 void f() {
47 fp1 one;
48 fp2 two;
49 fp3 three;
50 fp2_alias four;
51
52 one(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
53 two(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
54 three(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
55 four(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
56
57 // These are all okay because of the explicit cast to void.
58 (void)one();
59 (void)two();
60 (void)three();
61 (void)four();
62 }
63 } // namespace PR31526
64
65 struct [[nodiscard("reason")]] ReasonStruct {};
66 struct LaterReason;
67 struct [[nodiscard("later reason")]] LaterReason {};
68
69 ReasonStruct get_reason();
70 LaterReason get_later_reason();
71 [[nodiscard("another reason")]] int another_reason();
72
73 [[nodiscard("conflicting reason")]] int conflicting_reason();
74 [[nodiscard("special reason")]] int conflicting_reason();
75
cxx20_use()76 void cxx20_use() {
77 get_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: reason}}
78 get_later_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: later reason}}
79 another_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: another reason}}
80 conflicting_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: special reason}}
81 }
82
83 namespace p1771 {
84 struct[[nodiscard("Don't throw me away!")]] ConvertTo{};
85 struct S {
86 [[nodiscard]] S();
87 [[nodiscard("Don't let that S-Char go!")]] S(char);
88 S(int);
89 [[gnu::warn_unused_result]] S(double);
90 operator ConvertTo();
91 [[nodiscard]] operator int();
92 [[nodiscard("Don't throw away as a double")]] operator double();
93 };
94
95 struct[[nodiscard("Don't throw me away either!")]] Y{};
96
usage()97 void usage() {
98 S(); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}
99 S('A'); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't let that S-Char go!}}
100 S(1);
101 S(2.2);
102 Y(); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't throw me away either!}}
103 S s;
104 ConvertTo{}; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw me away!}}
105
106 // AST is different in C++20 mode, pre-2017 a move ctor for ConvertTo is there
107 // as well, hense the constructor warning.
108 #if __cplusplus >= 201703L
109 // expected-warning@+4 {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw me away!}}
110 #else
111 // expected-warning@+2 {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't throw me away!}}
112 #endif
113 (ConvertTo) s;
114 (int)s; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
115 (S)'c'; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't let that S-Char go!}}
116 #if __cplusplus >= 201703L
117 // expected-warning@+4 {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw me away!}}
118 #else
119 // expected-warning@+2 {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't throw me away!}}
120 #endif
121 static_cast<ConvertTo>(s);
122 static_cast<int>(s); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
123 static_cast<double>(s); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw away as a double}}
124 }
125 }; // namespace p1771
126
127 #ifdef EXT
128 // expected-warning@5 {{use of the 'nodiscard' attribute is a C++17 extension}}
129 // expected-warning@9 {{use of the 'nodiscard' attribute is a C++17 extension}}
130 // expected-warning@12 {{use of the 'nodiscard' attribute is a C++17 extension}}
131 // expected-warning@13 {{use of the 'nodiscard' attribute is a C++17 extension}}
132 // expected-warning@29 {{use of the 'nodiscard' attribute is a C++17 extension}}
133 // expected-warning@65 {{use of the 'nodiscard' attribute is a C++20 extension}}
134 // expected-warning@67 {{use of the 'nodiscard' attribute is a C++20 extension}}
135 // expected-warning@71 {{use of the 'nodiscard' attribute is a C++20 extension}}
136 // expected-warning@73 {{use of the 'nodiscard' attribute is a C++20 extension}}
137 // expected-warning@74 {{use of the 'nodiscard' attribute is a C++20 extension}}
138 // expected-warning@84 {{use of the 'nodiscard' attribute is a C++20 extension}}
139 // expected-warning@86 {{use of the 'nodiscard' attribute is a C++17 extension}}
140 // expected-warning@87 {{use of the 'nodiscard' attribute is a C++20 extension}}
141 // expected-warning@91 {{use of the 'nodiscard' attribute is a C++17 extension}}
142 // expected-warning@92 {{use of the 'nodiscard' attribute is a C++20 extension}}
143 // expected-warning@95 {{use of the 'nodiscard' attribute is a C++20 extension}}
144 #endif
145