@@ -196,6 +196,25 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
196
196
return true ;
197
197
}
198
198
199
+ static bool DiagnoseNoDiscard (Sema &S, const WarnUnusedResultAttr *A,
200
+ SourceLocation Loc, SourceRange R1,
201
+ SourceRange R2, bool IsCtor) {
202
+ if (!A)
203
+ return false ;
204
+ StringRef Msg = A->getMessage ();
205
+
206
+ if (Msg.empty ()) {
207
+ if (IsCtor)
208
+ return S.Diag (Loc, diag::warn_unused_constructor) << A << R1 << R2;
209
+ return S.Diag (Loc, diag::warn_unused_result) << A << R1 << R2;
210
+ }
211
+
212
+ if (IsCtor)
213
+ return S.Diag (Loc, diag::warn_unused_constructor_msg) << A << Msg << R1
214
+ << R2;
215
+ return S.Diag (Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
216
+ }
217
+
199
218
void Sema::DiagnoseUnusedExprResult (const Stmt *S) {
200
219
if (const LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))
201
220
return DiagnoseUnusedExprResult (Label->getSubStmt ());
@@ -254,19 +273,19 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
254
273
return ;
255
274
256
275
E = WarnExpr;
276
+ if (const auto *Cast = dyn_cast<CastExpr>(E))
277
+ if (Cast->getCastKind () == CK_NoOp ||
278
+ Cast->getCastKind () == CK_ConstructorConversion)
279
+ E = Cast->getSubExpr ()->IgnoreImpCasts ();
280
+
257
281
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
258
282
if (E->getType ()->isVoidType ())
259
283
return ;
260
284
261
- if (const auto *A = cast_or_null<WarnUnusedResultAttr>(
262
- CE->getUnusedResultAttr (Context))) {
263
- StringRef Msg = A->getMessage ();
264
- if (!Msg.empty ())
265
- Diag (Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
266
- else
267
- Diag (Loc, diag::warn_unused_result) << A << R1 << R2;
285
+ if (DiagnoseNoDiscard (*this , cast_or_null<WarnUnusedResultAttr>(
286
+ CE->getUnusedResultAttr (Context)),
287
+ Loc, R1, R2, /* isCtor=*/ false ))
268
288
return ;
269
- }
270
289
271
290
// If the callee has attribute pure, const, or warn_unused_result, warn with
272
291
// a more specific message to make it clear what is happening. If the call
@@ -284,24 +303,34 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
284
303
return ;
285
304
}
286
305
}
306
+ } else if (const auto *CE = dyn_cast<CXXConstructExpr>(E)) {
307
+ if (const CXXConstructorDecl *Ctor = CE->getConstructor ()) {
308
+ const auto *A = Ctor->getAttr <WarnUnusedResultAttr>();
309
+ A = A ? A : Ctor->getParent ()->getAttr <WarnUnusedResultAttr>();
310
+ if (DiagnoseNoDiscard (*this , A, Loc, R1, R2, /* isCtor=*/ true ))
311
+ return ;
312
+ }
313
+ } else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
314
+ if (const TagDecl *TD = ILE->getType ()->getAsTagDecl ()) {
315
+
316
+ if (DiagnoseNoDiscard (*this , TD->getAttr <WarnUnusedResultAttr>(), Loc, R1,
317
+ R2, /* isCtor=*/ false ))
318
+ return ;
319
+ }
287
320
} else if (ShouldSuppress)
288
321
return ;
289
322
323
+ E = WarnExpr;
290
324
if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
291
325
if (getLangOpts ().ObjCAutoRefCount && ME->isDelegateInitCall ()) {
292
326
Diag (Loc, diag::err_arc_unused_init_message) << R1;
293
327
return ;
294
328
}
295
329
const ObjCMethodDecl *MD = ME->getMethodDecl ();
296
330
if (MD) {
297
- if (const auto *A = MD->getAttr <WarnUnusedResultAttr>()) {
298
- StringRef Msg = A->getMessage ();
299
- if (!Msg.empty ())
300
- Diag (Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
301
- else
302
- Diag (Loc, diag::warn_unused_result) << A << R1 << R2;
331
+ if (DiagnoseNoDiscard (*this , MD->getAttr <WarnUnusedResultAttr>(), Loc, R1,
332
+ R2, /* isCtor=*/ false ))
303
333
return ;
304
- }
305
334
}
306
335
} else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
307
336
const Expr *Source = POE->getSyntacticForm ();
0 commit comments