@@ -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
222229void Sema::DiagnoseUnusedExprResult (const Stmt *S, unsigned DiagID) {
@@ -286,9 +293,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
286293 if (E->getType ()->isVoidType ())
287294 return ;
288295
289- if (DiagnoseNoDiscard (*this , cast_or_null<WarnUnusedResultAttr>(
290- CE->getUnusedResultAttr (Context)),
291- Loc, R1, R2, /* isCtor=*/ false ))
296+ auto [OffendingDecl, A] = CE->getUnusedResultAttr (Context);
297+ if (DiagnoseNoDiscard (*this , OffendingDecl,
298+ cast_or_null<WarnUnusedResultAttr>(A), Loc, R1, R2,
299+ /* isCtor=*/ false ))
292300 return ;
293301
294302 // If the callee has attribute pure, const, or warn_unused_result, warn with
@@ -309,16 +317,21 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
309317 }
310318 } else if (const auto *CE = dyn_cast<CXXConstructExpr>(E)) {
311319 if (const CXXConstructorDecl *Ctor = CE->getConstructor ()) {
320+ const NamedDecl *OffendingDecl = nullptr ;
312321 const auto *A = Ctor->getAttr <WarnUnusedResultAttr>();
313- A = A ? A : Ctor->getParent ()->getAttr <WarnUnusedResultAttr>();
314- if (DiagnoseNoDiscard (*this , A, Loc, R1, R2, /* isCtor=*/ true ))
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 ))
315328 return ;
316329 }
317330 } else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
318331 if (const TagDecl *TD = ILE->getType ()->getAsTagDecl ()) {
319332
320- if (DiagnoseNoDiscard (*this , TD->getAttr <WarnUnusedResultAttr>(), Loc, R1 ,
321- R2, /* isCtor=*/ false ))
333+ if (DiagnoseNoDiscard (*this , TD, TD ->getAttr <WarnUnusedResultAttr>(), Loc,
334+ R1, R2, /* isCtor=*/ false ))
322335 return ;
323336 }
324337 } else if (ShouldSuppress)
@@ -332,8 +345,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
332345 }
333346 const ObjCMethodDecl *MD = ME->getMethodDecl ();
334347 if (MD) {
335- if (DiagnoseNoDiscard (*this , MD->getAttr <WarnUnusedResultAttr>(), Loc, R1 ,
336- R2, /* isCtor=*/ false ))
348+ if (DiagnoseNoDiscard (*this , nullptr , MD->getAttr <WarnUnusedResultAttr>(),
349+ Loc, R1, R2, /* isCtor=*/ false ))
337350 return ;
338351 }
339352 } else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
0 commit comments