@@ -200,23 +200,30 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
200200 return true ;
201201}
202202
203- static bool DiagnoseNoDiscard (Sema &S, const WarnUnusedResultAttr *A ,
204- SourceLocation Loc, SourceRange R1 ,
205- SourceRange R2, bool IsCtor) {
203+ static bool DiagnoseNoDiscard (Sema &S, const NamedDecl *OffendingDecl ,
204+ const WarnUnusedResultAttr *A, SourceLocation Loc ,
205+ SourceRange R1, 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;
211214 if (IsCtor)
212- return S.Diag (Loc, diag::warn_unused_constructor) << A << R1 << R2;
213- return S.Diag (Loc, diag::warn_unused_result) << A << R1 << R2;
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;
214218 }
215219
220+ if (OffendingDecl)
221+ return S.Diag (Loc, diag::warn_unused_return_type)
222+ << IsCtor << A << OffendingDecl << true << Msg << R1 << R2;
216223 if (IsCtor)
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;
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;
220227}
221228
222229namespace {
@@ -288,9 +295,10 @@ void DiagnoseUnused(Sema &S, const Expr *E, std::optional<unsigned> DiagID) {
288295 if (E->getType ()->isVoidType ())
289296 return ;
290297
291- if (DiagnoseNoDiscard (S, cast_or_null<WarnUnusedResultAttr>(
292- CE->getUnusedResultAttr (S.Context )),
293- Loc, R1, R2, /* isCtor=*/ false ))
298+ auto [OffendingDecl, A] = CE->getUnusedResultAttr (S.Context );
299+ if (DiagnoseNoDiscard (S, OffendingDecl,
300+ cast_or_null<WarnUnusedResultAttr>(A), Loc, R1, R2,
301+ /* isCtor=*/ false ))
294302 return ;
295303
296304 // If the callee has attribute pure, const, or warn_unused_result, warn with
@@ -311,15 +319,20 @@ void DiagnoseUnused(Sema &S, const Expr *E, std::optional<unsigned> DiagID) {
311319 }
312320 } else if (const auto *CE = dyn_cast<CXXConstructExpr>(E)) {
313321 if (const CXXConstructorDecl *Ctor = CE->getConstructor ()) {
322+ const NamedDecl *OffendingDecl = nullptr ;
314323 const auto *A = Ctor->getAttr <WarnUnusedResultAttr>();
315- A = A ? A : Ctor->getParent ()->getAttr <WarnUnusedResultAttr>();
316- if (DiagnoseNoDiscard (S, A, Loc, R1, R2, /* isCtor=*/ true ))
324+ if (!A) {
325+ OffendingDecl = Ctor->getParent ();
326+ A = OffendingDecl->getAttr <WarnUnusedResultAttr>();
327+ }
328+ if (DiagnoseNoDiscard (S, OffendingDecl, A, Loc, R1, R2,
329+ /* isCtor=*/ true ))
317330 return ;
318331 }
319332 } else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
320333 if (const TagDecl *TD = ILE->getType ()->getAsTagDecl ()) {
321334
322- if (DiagnoseNoDiscard (S, TD->getAttr <WarnUnusedResultAttr>(), Loc, R1,
335+ if (DiagnoseNoDiscard (S, TD, TD ->getAttr <WarnUnusedResultAttr>(), Loc, R1,
323336 R2, /* isCtor=*/ false ))
324337 return ;
325338 }
@@ -334,8 +347,9 @@ void DiagnoseUnused(Sema &S, const Expr *E, std::optional<unsigned> DiagID) {
334347 }
335348 const ObjCMethodDecl *MD = ME->getMethodDecl ();
336349 if (MD) {
337- if (DiagnoseNoDiscard (S, MD->getAttr <WarnUnusedResultAttr>(), Loc, R1,
338- R2, /* isCtor=*/ false ))
350+ if (DiagnoseNoDiscard (S, nullptr , MD->getAttr <WarnUnusedResultAttr>(),
351+ Loc, R1, R2,
352+ /* isCtor=*/ false ))
339353 return ;
340354 }
341355 } else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
0 commit comments