diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index a9570e4..3b8e774 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -226,6 +226,34 @@ warn_function_noreturn (tree decl)
 			   true, warned_about, "noreturn");
 }
 
+/* Emit diagnostic if the callers don't use return value.
+   Only to be called for pure/const function */
+
+static void
+warn_function_unused_ret (struct cgraph_node *node)
+{
+  tree decl = node->decl;
+  int flags = flags_from_decl_or_type (decl);
+
+  if (flags & ECF_NORETURN)
+    return;
+
+  if (!(flags & (ECF_CONST | ECF_PURE))
+        || (flags & ECF_LOOPING_CONST_OR_PURE))
+    return;
+
+  for (cgraph_edge *e = node->callers; e; e = e->next_caller)
+    {
+      gcall *g = e->call_stmt;
+      if (g
+	  && !VOID_TYPE_P (gimple_call_return_type (g))
+	  && gimple_call_lhs (g) == NULL)
+	warning_at (gimple_location (g), OPT_Wunused_value,
+		    "Call from %s to %s has no effect",
+		    e->caller->name (), e->callee->name ());
+    }
+}
+
 /* Return true if we have a function state for NODE.  */
 
 static inline bool
@@ -1475,6 +1503,8 @@ propagate_pure_const (void)
 	  /* Inline clones share declaration with their offline copies;
 	     do not modify their declarations since the offline copy may
 	     be different.  */
+	  bool warn_unused_ret = false;
+
 	  if (!w->global.inlined_to)
 	    switch (this_state)
 	      {
@@ -1482,6 +1512,7 @@ propagate_pure_const (void)
 		if (!TREE_READONLY (w->decl))
 		  {
 		    warn_function_const (w->decl, !this_looping);
+		    warn_unused_ret = true;
 		    if (dump_file)
 		      fprintf (dump_file, "Function found to be %sconst: %s\n",
 			       this_looping ? "looping " : "",
@@ -1496,6 +1527,8 @@ propagate_pure_const (void)
 							      NULL, true);
 		if (w->set_const_flag (true, this_looping))
 		  {
+		    if (warn_unused_ret)
+		      warn_function_unused_ret (w);
 		    if (dump_file)
 		      fprintf (dump_file,
 			       "Declaration updated to be %sconst: %s\n",
@@ -1509,6 +1542,7 @@ propagate_pure_const (void)
 		if (!DECL_PURE_P (w->decl))
 		  {
 		    warn_function_pure (w->decl, !this_looping);
+		    warn_unused_ret = true;
 		    if (dump_file)
 		      fprintf (dump_file, "Function found to be %spure: %s\n",
 			       this_looping ? "looping " : "",
@@ -1521,6 +1555,8 @@ propagate_pure_const (void)
 							      NULL, true);
 		if (w->set_pure_flag (true, this_looping))
 		  {
+		    if (warn_unused_ret)
+		      warn_function_unused_ret (w);
 		    if (dump_file)
 		      fprintf (dump_file,
 			       "Declaration updated to be %spure: %s\n",
@@ -1808,11 +1844,14 @@ pass_local_pure_const::execute (function *fun)
       changed = true;
     }
 
+  bool warn_unused_ret = false;
+
   switch (l->pure_const_state)
     {
     case IPA_CONST:
       if (!TREE_READONLY (current_function_decl))
 	{
+	  warn_unused_ret = true;
 	  warn_function_const (current_function_decl, !l->looping);
 	  if (dump_file)
 	    fprintf (dump_file, "Function found to be %sconst: %s\n",
@@ -1828,6 +1867,8 @@ pass_local_pure_const::execute (function *fun)
 	}
       if (!skip && node->set_const_flag (true, l->looping))
 	{
+	  if (warn_unused_ret)
+	    warn_function_unused_ret (cgraph_node::get_create (current_function_decl));
 	  if (dump_file)
 	    fprintf (dump_file, "Declaration updated to be %sconst: %s\n",
 		     l->looping ? "looping " : "",
@@ -1840,6 +1881,7 @@ pass_local_pure_const::execute (function *fun)
       if (!DECL_PURE_P (current_function_decl))
 	{
 	  warn_function_pure (current_function_decl, !l->looping);
+	  warn_unused_ret = true;
 	  if (dump_file)
 	    fprintf (dump_file, "Function found to be %spure: %s\n",
 		     l->looping ? "looping " : "",
@@ -1854,6 +1896,8 @@ pass_local_pure_const::execute (function *fun)
 	}
       if (!skip && node->set_pure_flag (true, l->looping))
 	{
+	  if (warn_unused_ret)
+	    warn_function_unused_ret (cgraph_node::get_create (current_function_decl));
 	  if (dump_file)
 	    fprintf (dump_file, "Declaration updated to be %spure: %s\n",
 		     l->looping ? "looping " : "",
diff --git a/gcc/testsuite/gcc.dg/Wunused-value-4.c b/gcc/testsuite/gcc.dg/Wunused-value-4.c
new file mode 100644
index 0000000..1f5463c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wunused-value-4.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused-value" } */
+
+__attribute__((noinline, no_icf))
+int f()
+{
+  return 1;
+}
+
+__attribute__((noinline, no_icf, const))
+int g()
+{
+  return 1;
+}   
+
+int foo (void)
+{
+  f ();  /* { dg-warning "Call from foo to f has no effect" } */
+  int k = f ();  /* { dg-bogus "Call from foo to f has no effect" } */
+  g (); /* { dg-warning "statement with no effect" } */
+  return k; 
+}
+
