]> granicus.if.org Git - clang/commitdiff
make the diagnostic in the 'unused result' warning more precise
authorChris Lattner <sabre@nondot.org>
Tue, 13 Oct 2009 04:53:48 +0000 (04:53 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 13 Oct 2009 04:53:48 +0000 (04:53 +0000)
about the reason, rdar://7186119.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83940 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/Expr.cpp
lib/Sema/SemaStmt.cpp
test/Sema/attr-warn_unused_result.c
test/Sema/unused-expr.c

index 5c594cab35a9ae97029762b50f8148f102573b35..d5dff5065d49ef0199f38489d9e46dd086a9feca 100644 (file)
@@ -991,6 +991,9 @@ public:
 
   /// \brief If the callee is a FunctionDecl, return it. Otherwise return 0.
   FunctionDecl *getDirectCallee();
+  const FunctionDecl *getDirectCallee() const {
+    return const_cast<CallExpr*>(this)->getDirectCallee();
+  }
 
   /// getNumArgs - Return the number of actual arguments to this call.
   ///
index 557615bee58a2688ec5f1e38b8e56186b6c56423..f15c028a538cb963bd77d8666a815431661ed2b0 100644 (file)
@@ -1859,6 +1859,9 @@ def warn_unused_expr : Warning<"expression result unused">,
 def warn_unused_property_expr : Warning<
   "property access result unused - getters should not have side effects">,
   InGroup<UnusedValue>;
+def warn_unused_call : Warning<
+  "ignoring return value of function declared with %0 attribute">,
+  InGroup<UnusedValue>;
 
 def err_incomplete_type_used_in_type_trait_expr : Error<
   "incomplete type %0 used in type trait expression">;
index 98348d6efc9c7b469df1bc086f87d8ba7ecacb55..6da11c1cab85716486bf6616479575d4356a3feb 100644 (file)
@@ -692,21 +692,22 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
   case CXXMemberCallExprClass: {
     // If this is a direct call, get the callee.
     const CallExpr *CE = cast<CallExpr>(this);
-    const Expr *CalleeExpr = CE->getCallee()->IgnoreParenCasts();
-    if (const DeclRefExpr *CalleeDRE = dyn_cast<DeclRefExpr>(CalleeExpr)) {
+    if (const FunctionDecl *FD = CE->getDirectCallee()) {
       // If the callee has attribute pure, const, or warn_unused_result, warn
       // about it. void foo() { strlen("bar"); } should warn.
-      if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeDRE->getDecl()))
-        if (FD->getAttr<WarnUnusedResultAttr>() ||
-            FD->getAttr<PureAttr>() || FD->getAttr<ConstAttr>()) {
-          Loc = CE->getCallee()->getLocStart();
-          R1 = CE->getCallee()->getSourceRange();
-
-          if (unsigned NumArgs = CE->getNumArgs())
-            R2 = SourceRange(CE->getArg(0)->getLocStart(),
-                             CE->getArg(NumArgs-1)->getLocEnd());
-          return true;
-        }
+      //
+      // Note: If new cases are added here, DiagnoseUnusedExprResult should be
+      // updated to match for QoI.
+      if (FD->getAttr<WarnUnusedResultAttr>() ||
+          FD->getAttr<PureAttr>() || FD->getAttr<ConstAttr>()) {
+        Loc = CE->getCallee()->getLocStart();
+        R1 = CE->getCallee()->getSourceRange();
+
+        if (unsigned NumArgs = CE->getNumArgs())
+          R2 = SourceRange(CE->getArg(0)->getLocStart(),
+                           CE->getArg(NumArgs-1)->getLocEnd());
+        return true;
+      }
     }
     return false;
   }
index 2a3b9eeea8190bccf8a2719d4c44c866cd9ef060..e8cd6b081de16f5c4baac9e7225df1b720924a89 100644 (file)
@@ -80,6 +80,25 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
   E = E->IgnoreParens();
   if (isa<ObjCImplicitSetterGetterRefExpr>(E))
     DiagID = diag::warn_unused_property_expr;
+  
+  if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+    // If the callee has attribute pure, const, or warn_unused_result, warn with
+    // a more specific message to make it clear what is happening.
+    if (const FunctionDecl *FD = CE->getDirectCallee()) {
+      if (FD->getAttr<WarnUnusedResultAttr>()) {
+        Diag(Loc, diag::warn_unused_call) << R1 << R2 << "warn_unused_result";
+        return;
+      }
+      if (FD->getAttr<PureAttr>()) {
+        Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure";
+        return;
+      }
+      if (FD->getAttr<ConstAttr>()) {
+        Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const";
+        return;
+      }
+    }        
+  }
 
   Diag(Loc, DiagID) << R1 << R2;
 }
index b4ef1bbeaf0ef1283abe51c892e3f4a7b197bd60..08e95f4f61d54aa4363f5e452790c4934f5e8ea5 100644 (file)
@@ -9,9 +9,9 @@ int foo() {
   if (fn1() < 0 || fn2(2,1) < 0 || fn3(2) < 0)  // no warnings
     return -1;
   
-  fn1();  // expected-warning {{expression result unused}}
-  fn2(92, 21);  // expected-warning {{expression result unused}}
-  fn3(42);  // expected-warning {{expression result unused}}
+  fn1();  // expected-warning {{ignoring return value of function declared with warn_unused_result attribute}}
+  fn2(92, 21);  // expected-warning {{ignoring return value of function declared with pure attribute}}
+  fn3(42);  // expected-warning {{ignoring return value of function declared with const attribute}}
   return 0;
 }
 
index 8b5d15612627b968441c1376f54f8cf1eadfe5f1..f8e7c91474a593cb9264a96de9f17e3067a53dd2 100644 (file)
@@ -25,7 +25,7 @@ void bar(volatile int *VP, int *P, int A,
   __real__ VC;
   
   // We know this can't change errno because of -fno-math-errno.
-  sqrt(A);  // expected-warning {{expression result unused}}
+  sqrt(A);  // expected-warning {{ignoring return value of function declared with const attribute}}
 }
 
 extern void t1();
@@ -73,4 +73,8 @@ void t4(int a) {
   for (;;b == 1) {} // expected-warning{{expression result unused}}
 }
 
-
+// rdar://7186119
+int t5f(void) __attribute__((warn_unused_result));
+void t5() {
+  t5f();   // expected-warning {{ignoring return value of function declared with warn_unused_result}}
+}