[PATCH] D55949: Correctly handle function pointers returning a type marked nodiscard

Aaron Ballman via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 20 12:39:19 PST 2018


aaron.ballman created this revision.
aaron.ballman added reviewers: rsmith, Quuxplusone, erik.pilkington.

When a function returns a type and that type was declared `[[nodiscard]]`, we diagnose any unused results from that call as though the function were marked nodiscard. The same behavior should apply to calls through a function pointer.

This addresses PR31526.


https://reviews.llvm.org/D55949

Files:
  lib/AST/Expr.cpp
  lib/Sema/SemaStmt.cpp
  test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp


Index: test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp
===================================================================
--- test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp
+++ test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp
@@ -32,6 +32,35 @@
   // OK, warning suppressed.
   (void)fp();
 }
+
+namespace PR31526 {
+typedef E (*fp1)();
+typedef S (*fp2)();
+
+typedef S S_alias;
+typedef S_alias (*fp3)();
+
+typedef fp2 fp2_alias;
+
+void f() {
+  fp1 one;
+  fp2 two;
+  fp3 three;
+  fp2_alias four;
+
+  one(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  two(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  three(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  four(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+  // These are all okay because of the explicit cast to void.
+  (void)one();
+  (void)two();
+  (void)three();
+  (void)four();
+}
+} // namespace PR31526
+
 #ifdef EXT
 // expected-warning at 4 {{use of the 'nodiscard' attribute is a C++17 extension}}
 // expected-warning at 8 {{use of the 'nodiscard' attribute is a C++17 extension}}
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -270,6 +270,12 @@
         Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
         return;
       }
+      if (const TagDecl *TD = CE->getCallReturnType(Context)->getAsTagDecl()) {
+        if (const Attr *A = TD->getAttr<WarnUnusedResultAttr>()) {
+          Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
+          return;
+        }
+      }
       if (ShouldSuppress)
         return;
       if (FD->hasAttr<PureAttr>()) {
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -2278,6 +2278,13 @@
       bool HasWarnUnusedResultAttr = Func ? Func->hasUnusedResultAttr()
                                           : FD->hasAttr<WarnUnusedResultAttr>();
 
+      // If there is no FunctionDecl for the call, check the return type of the
+      // callee to see if it was declared with the WarnUnusedResult attribute.
+      if (!Func && !HasWarnUnusedResultAttr) {
+        if (const TagDecl *TD = CE->getCallReturnType(Ctx)->getAsTagDecl())
+          HasWarnUnusedResultAttr = TD->hasAttr<WarnUnusedResultAttr>();
+      }
+
       // If the callee has attribute pure, const, or warn_unused_result, warn
       // about it. void foo() { strlen("bar"); } should warn.
       //


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D55949.179128.patch
Type: text/x-patch
Size: 2764 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20181220/a30b1205/attachment.bin>


More information about the cfe-commits mailing list