Skip to content

Commit 113585a

Browse files
committed
Revert "[Clang] Improve diagnostic on [[nodiscard]] attribute (llvm#112521)"
This reverts commit 422a454. Change-Id: Ic924284ad9180c46f8942300f505d7950dff3c53
1 parent 78d6846 commit 113585a

File tree

10 files changed

+81
-159
lines changed

10 files changed

+81
-159
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,7 @@ Improvements to Clang's diagnostics
672672
getS(); // Now diagnoses "Reason 2", previously diagnoses "Reason 1"
673673
}
674674

675+
- Clang now diagnoses ``= delete("reason")`` extension warnings only in pedantic mode rather than on by default. (#GH109311).
675676

676677
- Clang now diagnoses missing return value in functions containing ``if consteval`` (#GH116485).
677678

clang/include/clang/AST/Expr.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3181,14 +3181,12 @@ class CallExpr : public Expr {
31813181
QualType getCallReturnType(const ASTContext &Ctx) const;
31823182

31833183
/// Returns the WarnUnusedResultAttr that is either declared on the called
3184-
/// function, or its return type declaration, together with a NamedDecl that
3185-
/// refers to the declaration the attribute is attached onto.
3186-
std::pair<const NamedDecl *, const Attr *>
3187-
getUnusedResultAttr(const ASTContext &Ctx) const;
3184+
/// function, or its return type declaration.
3185+
const Attr *getUnusedResultAttr(const ASTContext &Ctx) const;
31883186

31893187
/// Returns true if this call expression should warn on unused results.
31903188
bool hasUnusedResultAttr(const ASTContext &Ctx) const {
3191-
return getUnusedResultAttr(Ctx).second != nullptr;
3189+
return getUnusedResultAttr(Ctx) != nullptr;
31923190
}
31933191

31943192
SourceLocation getRParenLoc() const { return RParenLoc; }

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9307,11 +9307,11 @@ def warn_unused_container_subscript_expr : Warning<
93079307
def warn_unused_call : Warning<
93089308
"ignoring return value of function declared with %0 attribute">,
93099309
InGroup<UnusedValue>;
9310-
def warn_unused_return_type : Warning<
9311-
"ignoring %select{return value|temporary}0 of type %2 declared with %1 attribute%select{|: %4}3">,
9312-
InGroup<UnusedValue>;
93139310
def warn_unused_constructor : Warning<
9314-
"ignoring temporary created by a constructor declared with %0 attribute%select{|: %2}1">,
9311+
"ignoring temporary created by a constructor declared with %0 attribute">,
9312+
InGroup<UnusedValue>;
9313+
def warn_unused_constructor_msg : Warning<
9314+
"ignoring temporary created by a constructor declared with %0 attribute: %1">,
93159315
InGroup<UnusedValue>;
93169316
def warn_side_effects_unevaluated_context : Warning<
93179317
"expression with side effects has no effect in an unevaluated context">,
@@ -9320,7 +9320,10 @@ def warn_side_effects_typeid : Warning<
93209320
"expression with side effects will be evaluated despite being used as an "
93219321
"operand to 'typeid'">, InGroup<PotentiallyEvaluatedExpression>;
93229322
def warn_unused_result : Warning<
9323-
"ignoring return value of function declared with %0 attribute%select{|: %2}1">,
9323+
"ignoring return value of function declared with %0 attribute">,
9324+
InGroup<UnusedResult>;
9325+
def warn_unused_result_msg : Warning<
9326+
"ignoring return value of function declared with %0 attribute: %1">,
93249327
InGroup<UnusedResult>;
93259328
def warn_unused_result_typedef_unsupported_spelling : Warning<
93269329
"'[[%select{nodiscard|gnu::warn_unused_result}0]]' attribute ignored when "

clang/lib/AST/Expr.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,24 +1615,22 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const {
16151615
return FnType->getReturnType();
16161616
}
16171617

1618-
std::pair<const NamedDecl *, const Attr *>
1619-
CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const {
1620-
// If the callee is marked nodiscard, return that attribute
1621-
const Decl *D = getCalleeDecl();
1622-
if (const auto *A = D->getAttr<WarnUnusedResultAttr>())
1623-
return {nullptr, A};
1624-
1618+
const Attr *CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const {
16251619
// If the return type is a struct, union, or enum that is marked nodiscard,
16261620
// then return the return type attribute.
16271621
if (const TagDecl *TD = getCallReturnType(Ctx)->getAsTagDecl())
16281622
if (const auto *A = TD->getAttr<WarnUnusedResultAttr>())
1629-
return {TD, A};
1623+
return A;
16301624

16311625
for (const auto *TD = getCallReturnType(Ctx)->getAs<TypedefType>(); TD;
16321626
TD = TD->desugar()->getAs<TypedefType>())
16331627
if (const auto *A = TD->getDecl()->getAttr<WarnUnusedResultAttr>())
1634-
return {TD->getDecl(), A};
1635-
return {nullptr, nullptr};
1628+
return A;
1629+
1630+
// Otherwise, see if the callee is marked nodiscard and return that attribute
1631+
// instead.
1632+
const Decl *D = getCalleeDecl();
1633+
return D ? D->getAttr<WarnUnusedResultAttr>() : nullptr;
16361634
}
16371635

16381636
SourceLocation CallExpr::getBeginLoc() const {

clang/lib/Sema/SemaStmt.cpp

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -200,30 +200,23 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
200200
return true;
201201
}
202202

203-
static bool DiagnoseNoDiscard(Sema &S, const NamedDecl *OffendingDecl,
204-
const WarnUnusedResultAttr *A, SourceLocation Loc,
205-
SourceRange R1, SourceRange R2, bool IsCtor) {
203+
static bool DiagnoseNoDiscard(Sema &S, const WarnUnusedResultAttr *A,
204+
SourceLocation Loc, SourceRange R1,
205+
SourceRange R2, bool IsCtor) {
206206
if (!A)
207207
return false;
208208
StringRef Msg = A->getMessage();
209209

210210
if (Msg.empty()) {
211-
if (OffendingDecl)
212-
return S.Diag(Loc, diag::warn_unused_return_type)
213-
<< IsCtor << A << OffendingDecl << false << R1 << R2;
214211
if (IsCtor)
215-
return S.Diag(Loc, diag::warn_unused_constructor)
216-
<< A << false << R1 << R2;
217-
return S.Diag(Loc, diag::warn_unused_result) << A << false << R1 << R2;
212+
return S.Diag(Loc, diag::warn_unused_constructor) << A << R1 << R2;
213+
return S.Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
218214
}
219215

220-
if (OffendingDecl)
221-
return S.Diag(Loc, diag::warn_unused_return_type)
222-
<< IsCtor << A << OffendingDecl << true << Msg << R1 << R2;
223216
if (IsCtor)
224-
return S.Diag(Loc, diag::warn_unused_constructor)
225-
<< A << true << Msg << R1 << R2;
226-
return S.Diag(Loc, diag::warn_unused_result) << A << true << Msg << R1 << R2;
217+
return S.Diag(Loc, diag::warn_unused_constructor_msg) << A << Msg << R1
218+
<< R2;
219+
return S.Diag(Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
227220
}
228221

229222
void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
@@ -293,10 +286,9 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
293286
if (E->getType()->isVoidType())
294287
return;
295288

296-
auto [OffendingDecl, A] = CE->getUnusedResultAttr(Context);
297-
if (DiagnoseNoDiscard(*this, OffendingDecl,
298-
cast_or_null<WarnUnusedResultAttr>(A), Loc, R1, R2,
299-
/*isCtor=*/false))
289+
if (DiagnoseNoDiscard(*this, cast_or_null<WarnUnusedResultAttr>(
290+
CE->getUnusedResultAttr(Context)),
291+
Loc, R1, R2, /*isCtor=*/false))
300292
return;
301293

302294
// If the callee has attribute pure, const, or warn_unused_result, warn with
@@ -317,21 +309,16 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
317309
}
318310
} else if (const auto *CE = dyn_cast<CXXConstructExpr>(E)) {
319311
if (const CXXConstructorDecl *Ctor = CE->getConstructor()) {
320-
const NamedDecl *OffendingDecl = nullptr;
321312
const auto *A = Ctor->getAttr<WarnUnusedResultAttr>();
322-
if (!A) {
323-
OffendingDecl = Ctor->getParent();
324-
A = OffendingDecl->getAttr<WarnUnusedResultAttr>();
325-
}
326-
if (DiagnoseNoDiscard(*this, OffendingDecl, A, Loc, R1, R2,
327-
/*isCtor=*/true))
313+
A = A ? A : Ctor->getParent()->getAttr<WarnUnusedResultAttr>();
314+
if (DiagnoseNoDiscard(*this, A, Loc, R1, R2, /*isCtor=*/true))
328315
return;
329316
}
330317
} else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
331318
if (const TagDecl *TD = ILE->getType()->getAsTagDecl()) {
332319

333-
if (DiagnoseNoDiscard(*this, TD, TD->getAttr<WarnUnusedResultAttr>(), Loc,
334-
R1, R2, /*isCtor=*/false))
320+
if (DiagnoseNoDiscard(*this, TD->getAttr<WarnUnusedResultAttr>(), Loc, R1,
321+
R2, /*isCtor=*/false))
335322
return;
336323
}
337324
} else if (ShouldSuppress)
@@ -345,8 +332,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
345332
}
346333
const ObjCMethodDecl *MD = ME->getMethodDecl();
347334
if (MD) {
348-
if (DiagnoseNoDiscard(*this, nullptr, MD->getAttr<WarnUnusedResultAttr>(),
349-
Loc, R1, R2, /*isCtor=*/false))
335+
if (DiagnoseNoDiscard(*this, MD->getAttr<WarnUnusedResultAttr>(), Loc, R1,
336+
R2, /*isCtor=*/false))
350337
return;
351338
}
352339
} else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {

clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ E get_e();
1717
// cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}
1818

1919
void f() {
20-
get_s(); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard' attribute}}
20+
get_s(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
2121
get_i(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
2222
get_vi(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
23-
get_e(); // expected-warning {{ignoring return value of type 'E' declared with 'nodiscard' attribute}}
23+
get_e(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
2424

2525
// Okay, warnings are not encouraged
2626
get_s_ref();
@@ -54,10 +54,10 @@ void f() {
5454
fp3 three;
5555
fp2_alias four;
5656

57-
one(); // expected-warning {{ignoring return value of type 'E' declared with 'nodiscard' attribute}}
58-
two(); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard' attribute}}
59-
three(); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard' attribute}}
60-
four(); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard' attribute}}
57+
one(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
58+
two(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
59+
three(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
60+
four(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
6161

6262
// These are all okay because of the explicit cast to void.
6363
(void)one();
@@ -84,8 +84,8 @@ LaterReason get_later_reason();
8484
// cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 extension}}
8585

8686
void cxx20_use() {
87-
get_reason(); // expected-warning {{ignoring return value of type 'ReasonStruct' declared with 'nodiscard' attribute: reason}}
88-
get_later_reason(); // expected-warning {{ignoring return value of type 'LaterReason' declared with 'nodiscard' attribute: later reason}}
87+
get_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: reason}}
88+
get_later_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: later reason}}
8989
another_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: another reason}}
9090
conflicting_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: special reason}}
9191
}
@@ -115,20 +115,20 @@ void usage() {
115115
S('A'); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't let that S-Char go!}}
116116
S(1);
117117
S(2.2);
118-
Y(); // expected-warning {{ignoring temporary of type 'Y' declared with 'nodiscard' attribute: Don't throw me away either!}}
118+
Y(); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't throw me away either!}}
119119
S s;
120-
ConvertTo{}; // expected-warning {{ignoring return value of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}}
120+
ConvertTo{}; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw me away!}}
121121

122122
// AST is different in C++17 mode. Before, a move ctor for ConvertTo is there
123123
// as well, hence the constructor warning.
124124

125-
// since-cxx17-warning@+2 {{ignoring return value of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}}
126-
// cxx11-warning@+1 {{ignoring temporary of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}}
125+
// since-cxx17-warning@+2 {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw me away!}}
126+
// cxx11-warning@+1 {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't throw me away!}}
127127
(ConvertTo) s;
128128
(int)s; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
129129
(S)'c'; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't let that S-Char go!}}
130-
// since-cxx17-warning@+2 {{ignoring return value of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}}
131-
// cxx11-warning@+1 {{ignoring temporary of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}}
130+
// since-cxx17-warning@+2 {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw me away!}}
131+
// cxx11-warning@+1 {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't throw me away!}}
132132
static_cast<ConvertTo>(s);
133133
static_cast<int>(s); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
134134
static_cast<double>(s); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw away as a double}}

clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p3.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace std_example {
88
error_info enable_missile_safety_mode();
99
void launch_missiles();
1010
void test_missiles() {
11-
enable_missile_safety_mode(); // expected-warning {{ignoring return value of type 'error_info' declared with 'nodiscard'}}
11+
enable_missile_safety_mode(); // expected-warning {{ignoring return value of function declared with 'nodiscard'}}
1212
launch_missiles();
1313
}
1414

clang/test/Sema/c2x-nodiscard.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ enum E2 get_e(void);
3131
[[nodiscard]] int get_i(void);
3232

3333
void f2(void) {
34-
get_s(); // expected-warning {{ignoring return value of type 'S4' declared with 'nodiscard' attribute}}
35-
get_s3(); // expected-warning {{ignoring return value of type 'S3' declared with 'nodiscard' attribute: Wrong}}
34+
get_s(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
35+
get_s3(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: Wrong}}
3636
get_i(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
37-
get_e(); // expected-warning {{ignoring return value of type 'E2' declared with 'nodiscard' attribute}}
37+
get_e(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
3838

3939
// Okay, warnings are not encouraged
4040
(void)get_s();
@@ -50,7 +50,7 @@ struct [[nodiscard]] error_info{
5050
struct error_info enable_missile_safety_mode(void);
5151
void launch_missiles(void);
5252
void test_missiles(void) {
53-
enable_missile_safety_mode(); // expected-warning {{ignoring return value of type 'error_info' declared with 'nodiscard'}}
53+
enable_missile_safety_mode(); // expected-warning {{ignoring return value of function declared with 'nodiscard'}}
5454
launch_missiles();
5555
}
5656

0 commit comments

Comments
 (0)