187 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11,cxx11-17 -pedantic %s2// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify=expected,cxx11-17,since-cxx17 -pedantic %s3// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=expected,since-cxx17 -pedantic %s4// RUN: %clang_cc1 -fsyntax-only -std=c++23 -verify=expected,since-cxx17 -pedantic %s5 6struct [[nodiscard]] S {};7// cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}8S get_s();9S& get_s_ref();10 11enum [[nodiscard]] E {};12// cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}13E get_e();14 15[[nodiscard]] int get_i();16// cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}17[[nodiscard]] volatile int &get_vi();18// cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}19 20void f() {21 get_s(); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard' attribute}}22 get_i(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}23 get_vi(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}24 get_e(); // expected-warning {{ignoring return value of type 'E' declared with 'nodiscard' attribute}}25 26 // Okay, warnings are not encouraged27 get_s_ref();28 (void)get_s();29 (void)get_i();30 (void)get_vi();31 (void)get_e();32}33 34[[nodiscard]] volatile char &(*fp)(); // expected-warning {{'nodiscard' attribute only applies to functions, classes, or enumerations}}35// cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}36void g() {37 fp(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}38 39 // OK, warning suppressed.40 (void)fp();41}42 43namespace PR31526 {44typedef E (*fp1)();45typedef S (*fp2)();46 47typedef S S_alias;48typedef S_alias (*fp3)();49 50typedef fp2 fp2_alias;51 52void f() {53 fp1 one;54 fp2 two;55 fp3 three;56 fp2_alias four;57 58 one(); // expected-warning {{ignoring return value of type 'E' declared with 'nodiscard' attribute}}59 two(); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard' attribute}}60 three(); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard' attribute}}61 four(); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard' attribute}}62 63 // These are all okay because of the explicit cast to void.64 (void)one();65 (void)two();66 (void)three();67 (void)four();68}69} // namespace PR3152670 71struct [[nodiscard("reason")]] ReasonStruct {};72// cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 extension}}73struct LaterReason;74struct [[nodiscard("later reason")]] LaterReason {};75// cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 extension}}76 77ReasonStruct get_reason();78LaterReason get_later_reason();79[[nodiscard("another reason")]] int another_reason();80// cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 extension}}81 82[[nodiscard("conflicting reason")]] int conflicting_reason();83// cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 extension}}84[[nodiscard("special reason")]] int conflicting_reason();85// cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 extension}}86 87void cxx20_use() {88 get_reason(); // expected-warning {{ignoring return value of type 'ReasonStruct' declared with 'nodiscard' attribute: reason}}89 get_later_reason(); // expected-warning {{ignoring return value of type 'LaterReason' declared with 'nodiscard' attribute: later reason}}90 another_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: another reason}}91 conflicting_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: special reason}}92}93 94namespace p1771 {95struct[[nodiscard("Don't throw me away!")]] ConvertTo{};96// cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 extension}}97struct S {98 [[nodiscard]] S();99 // cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}100 [[nodiscard("Don't let that S-Char go!")]] S(char);101 // cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 extension}}102 S(int);103 [[gnu::warn_unused_result]] S(double);104 operator ConvertTo();105 [[nodiscard]] operator int();106 // cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}107 [[nodiscard("Don't throw away as a double")]] operator double();108 // cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 extension}}109};110 111struct[[nodiscard("Don't throw me away either!")]] Y{};112// cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 extension}}113 114void usage() {115 S(); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute}}116 S('A'); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't let that S-Char go!}}117 S(1);118 S(2.2); // expected-warning {{ignoring temporary created by a constructor declared with 'gnu::warn_unused_result' attribute}}119 Y(); // expected-warning {{ignoring temporary of type 'Y' declared with 'nodiscard' attribute: Don't throw me away either!}}120 S s;121 ConvertTo{}; // expected-warning {{ignoring return value of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}}122 123 // AST is different in C++17 mode. Before, a move ctor for ConvertTo is there124 // as well, hence the constructor warning.125 126 // since-cxx17-warning@+2 {{ignoring return value of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}}127 // cxx11-warning@+1 {{ignoring temporary of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}}128 (ConvertTo) s;129 (int)s; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}130 (S)'c'; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't let that S-Char go!}}131 // since-cxx17-warning@+2 {{ignoring return value of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}}132 // cxx11-warning@+1 {{ignoring temporary of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}}133 static_cast<ConvertTo>(s);134 static_cast<int>(s); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}135 static_cast<double>(s); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw away as a double}}136}137} // namespace p1771138 139namespace discarded_member_access {140struct X {141 union {142 int variant_member;143 };144 struct { // expected-warning {{anonymous structs are a GNU extension}}145 int anonymous_struct_member;146 };147 int data_member;148 static int static_data_member;149 enum {150 unscoped_enum151 };152 enum class scoped_enum_t {153 scoped_enum154 };155 using enum scoped_enum_t;156 // cxx11-17-warning@-1 {{using enum declaration is a C++20 extension}}157 158 void implicit_object_member_function();159 static void static_member_function();160#if __cplusplus >= 202302L161 void explicit_object_member_function(this X self);162#endif163};164 165[[nodiscard]] X get_X();166// cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}167[[nodiscard]] X* get_Ptr();168// cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}169void f() {170 get_X(); // expected-warning{{ignoring return value of function declared with 'nodiscard' attribute}}171 (void) get_X();172 (void) get_X().variant_member;173 (void) get_X().anonymous_struct_member;174 (void) get_X().data_member;175 (void) get_X().static_data_member;176 (void) get_X().unscoped_enum;177 (void) get_X().scoped_enum;178 (void) get_X().implicit_object_member_function();179 (void) get_X().static_member_function();180 (void) get_Ptr()->implicit_object_member_function();181 (void) get_Ptr()->static_member_function();182#if __cplusplus >= 202302L183 (void) get_X().explicit_object_member_function();184#endif185}186} // namespace discarded_member_access187