@@ -204,22 +204,28 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
204204 return true ;
205205}
206206
207- static bool DiagnoseNoDiscard (Sema &S, const WarnUnusedResultAttr *A ,
208- SourceLocation Loc, SourceRange R1 ,
209- SourceRange R2, bool IsCtor) {
207+ static bool DiagnoseNoDiscard (Sema &S, const NamedDecl *OffendingDecl ,
208+ const WarnUnusedResultAttr *A, SourceLocation Loc ,
209+ SourceRange R1, SourceRange R2, bool IsCtor) {
210210 if (!A)
211211 return false ;
212212 StringRef Msg = A->getMessage ();
213213
214214 if (Msg.empty ()) {
215+ if (OffendingDecl)
216+ return S.Diag (Loc, diag::warn_unused_return_type)
217+ << IsCtor << A << OffendingDecl << R1 << R2;
215218 if (IsCtor)
216219 return S.Diag (Loc, diag::warn_unused_constructor) << A << R1 << R2;
217220 return S.Diag (Loc, diag::warn_unused_result) << A << R1 << R2;
218221 }
219222
223+ if (OffendingDecl)
224+ return S.Diag (Loc, diag::warn_unused_return_type_msg)
225+ << IsCtor << A << OffendingDecl << Msg << R1 << R2;
220226 if (IsCtor)
221- return S.Diag (Loc, diag::warn_unused_constructor_msg) << A << Msg << R1
222- << R2;
227+ return S.Diag (Loc, diag::warn_unused_constructor_msg)
228+ << A << Msg << R1 << R2;
223229 return S.Diag (Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
224230}
225231
@@ -290,9 +296,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
290296 if (E->getType ()->isVoidType ())
291297 return ;
292298
293- if (DiagnoseNoDiscard (*this , cast_or_null<WarnUnusedResultAttr>(
294- CE->getUnusedResultAttr (Context)),
295- Loc, R1, R2, /* isCtor=*/ false ))
299+ auto [OffendingDecl, A] = CE->getUnusedResultAttr (Context);
300+ if (DiagnoseNoDiscard (*this , OffendingDecl,
301+ cast_or_null<WarnUnusedResultAttr>(A), Loc, R1, R2,
302+ /* isCtor=*/ false ))
296303 return ;
297304
298305 // If the callee has attribute pure, const, or warn_unused_result, warn with
@@ -313,16 +320,21 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
313320 }
314321 } else if (const auto *CE = dyn_cast<CXXConstructExpr>(E)) {
315322 if (const CXXConstructorDecl *Ctor = CE->getConstructor ()) {
323+ const NamedDecl *OffendingDecl = nullptr ;
316324 const auto *A = Ctor->getAttr <WarnUnusedResultAttr>();
317- A = A ? A : Ctor->getParent ()->getAttr <WarnUnusedResultAttr>();
318- if (DiagnoseNoDiscard (*this , A, Loc, R1, R2, /* isCtor=*/ true ))
325+ if (!A) {
326+ OffendingDecl = Ctor->getParent ();
327+ A = OffendingDecl->getAttr <WarnUnusedResultAttr>();
328+ }
329+ if (DiagnoseNoDiscard (*this , OffendingDecl, A, Loc, R1, R2,
330+ /* isCtor=*/ true ))
319331 return ;
320332 }
321333 } else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
322334 if (const TagDecl *TD = ILE->getType ()->getAsTagDecl ()) {
323335
324- if (DiagnoseNoDiscard (*this , TD->getAttr <WarnUnusedResultAttr>(), Loc, R1 ,
325- R2, /* isCtor=*/ false ))
336+ if (DiagnoseNoDiscard (*this , TD, TD ->getAttr <WarnUnusedResultAttr>(), Loc,
337+ R1, R2, /* isCtor=*/ false ))
326338 return ;
327339 }
328340 } else if (ShouldSuppress)
@@ -336,8 +348,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
336348 }
337349 const ObjCMethodDecl *MD = ME->getMethodDecl ();
338350 if (MD) {
339- if (DiagnoseNoDiscard (*this , MD->getAttr <WarnUnusedResultAttr>(), Loc, R1 ,
340- R2, /* isCtor=*/ false ))
351+ if (DiagnoseNoDiscard (*this , nullptr , MD->getAttr <WarnUnusedResultAttr>(),
352+ Loc, R1, R2, /* isCtor=*/ false ))
341353 return ;
342354 }
343355 } else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
0 commit comments