Index: cgraph.c
===================================================================
--- cgraph.c	(revision 235830)
+++ cgraph.c	(working copy)
@@ -859,9 +859,15 @@ symbol_table::create_edge (cgraph_node *
       && callee && callee->decl
       && !gimple_check_call_matching_types (call_stmt, callee->decl,
 					    false))
-    edge->call_stmt_cannot_inline_p = true;
+    {
+      edge->inline_failed = CIF_MISMATCHED_ARGUMENTS;
+      edge->call_stmt_cannot_inline_p = true;
+    }
   else
-    edge->call_stmt_cannot_inline_p = false;
+    {
+      edge->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
+      edge->call_stmt_cannot_inline_p = false;
+    }
 
   edge->indirect_info = NULL;
   edge->indirect_inlining_edge = 0;
@@ -1240,10 +1246,12 @@ cgraph_edge::make_direct (cgraph_node *c
   /* Insert to callers list of the new callee.  */
   edge->set_callee (callee);
 
-  if (call_stmt)
-    call_stmt_cannot_inline_p
-      = !gimple_check_call_matching_types (call_stmt, callee->decl,
-					   false);
+  if (call_stmt
+      && !gimple_check_call_matching_types (call_stmt, callee->decl, false))
+    {
+      call_stmt_cannot_inline_p = true;
+      inline_failed = CIF_MISMATCHED_ARGUMENTS;
+    }
 
   /* We need to re-determine the inlining status of the edge.  */
   initialize_inline_failed (edge);
@@ -1996,6 +2004,8 @@ cgraph_edge::dump_edge_flags (FILE *f)
     fprintf (f, "(speculative) ");
   if (!inline_failed)
     fprintf (f, "(inlined) ");
+  if (call_stmt_cannot_inline_p)
+    fprintf (f, "(call_stmt_cannot_inline_p) ");
   if (indirect_inlining_edge)
     fprintf (f, "(indirect_inlining) ");
   if (count)
Index: cgraphclones.c
===================================================================
--- cgraphclones.c	(revision 235830)
+++ cgraphclones.c	(working copy)
@@ -338,6 +338,7 @@ duplicate_thunk_for_node (cgraph_node *t
   cgraph_edge *e = new_thunk->create_edge (node, NULL, 0,
 						  CGRAPH_FREQ_BASE);
   e->call_stmt_cannot_inline_p = true;
+  e->inline_failed = CIF_THUNK;
   symtab->call_edge_duplication_hooks (thunk->callees, e);
   symtab->call_cgraph_duplication_hooks (thunk, new_thunk);
   return new_thunk;
Index: cif-code.def
===================================================================
--- cif-code.def	(revision 235830)
+++ cif-code.def	(working copy)
@@ -92,8 +92,12 @@ DEFCIFCODE(MISMATCHED_ARGUMENTS, CIF_FIN
 	   N_("mismatched arguments"))
 
 /* Caller and callee disagree on the arguments.  */
-DEFCIFCODE(THUNK, CIF_FINAL_ERROR,
-	   N_("thunk call"))
+DEFCIFCODE(LTO_MISMATCHED_DECLARATIONS, CIF_FINAL_ERROR,
+	   N_("mismatched declarations during linktime optimization"))
+
+/* Caller is thunk.  */
+DEFCIFCODE(THUNK, CIF_FINAL_ERROR,                                             
+          N_("thunk call"))                                                    
 
 /* Call was originally indirect.  */
 DEFCIFCODE(ORIGINALLY_INDIRECT_CALL, CIF_FINAL_NORMAL,
Index: ipa-inline-analysis.c
===================================================================
--- ipa-inline-analysis.c	(revision 235830)
+++ ipa-inline-analysis.c	(working copy)
@@ -1490,19 +1490,23 @@ initialize_inline_failed (struct cgraph_
 {
   struct cgraph_node *callee = e->callee;
 
-  if (e->indirect_unknown_callee)
+  if (e->inline_failed && e->inline_failed != CIF_BODY_NOT_AVAILABLE
+      && cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
+    ;
+  else if (e->indirect_unknown_callee)
     e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL;
   else if (!callee->definition)
     e->inline_failed = CIF_BODY_NOT_AVAILABLE;
   else if (callee->local.redefined_extern_inline)
     e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
-  else if (e->call_stmt_cannot_inline_p)
-    e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
   else if (cfun && fn_contains_cilk_spawn_p (cfun))
     /* We can't inline if the function is spawing a function.  */
-    e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
+    e->inline_failed = CIF_CILK_SPAWN;
   else
     e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
+  gcc_checking_assert (!e->call_stmt_cannot_inline_p
+		       || cgraph_inline_failed_type (e->inline_failed)
+			    == CIF_FINAL_ERROR);
 }
 
 /* Callback of walk_aliased_vdefs.  Flags that it has been invoked to the
@@ -2925,7 +2929,7 @@ compute_inline_parameters (struct cgraph
       struct predicate t = true_predicate ();
 
       info->inlinable = 0;
-      node->callees->call_stmt_cannot_inline_p = true;
+      node->callees->inline_failed = CIF_THUNK;
       node->local.can_change_signature = false;
       es->call_stmt_time = 1;
       es->call_stmt_size = 1;
@@ -4107,17 +4111,9 @@ inline_analyze_function (struct cgraph_n
     {
       struct cgraph_edge *e;
       for (e = node->callees; e; e = e->next_callee)
-	{
-	  if (e->inline_failed == CIF_FUNCTION_NOT_CONSIDERED)
-	    e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
-	  e->call_stmt_cannot_inline_p = true;
-	}
+	e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
       for (e = node->indirect_calls; e; e = e->next_callee)
-	{
-	  if (e->inline_failed == CIF_FUNCTION_NOT_CONSIDERED)
-	    e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
-	  e->call_stmt_cannot_inline_p = true;
-	}
+	e->inline_failed = CIF_FUNCTION_NOT_OPTIMIZED;
     }
 
   pop_cfun ();
Index: ipa-inline.c
===================================================================
--- ipa-inline.c	(revision 235830)
+++ ipa-inline.c	(working copy)
@@ -335,12 +335,10 @@ can_inline_edge_p (struct cgraph_edge *e
       e->inline_failed = CIF_OVERWRITABLE;
       inlinable = false;
     }
+  /* All edges with call_stmt_cannot_inline_p should have inline_failed
+     initialized to one of FINAL_ERROR reasons.  */
   else if (e->call_stmt_cannot_inline_p)
-    {
-      if (e->inline_failed != CIF_FUNCTION_NOT_OPTIMIZED)
-        e->inline_failed = e->caller->thunk.thunk_p ? CIF_THUNK : CIF_MISMATCHED_ARGUMENTS;
-      inlinable = false;
-    }
+    gcc_unreachable ();
   /* Don't inline if the functions have different EH personalities.  */
   else if (DECL_FUNCTION_PERSONALITY (caller->decl)
 	   && DECL_FUNCTION_PERSONALITY (callee->decl)
@@ -529,6 +527,8 @@ can_early_inline_edge_p (struct cgraph_e
   /* Early inliner might get called at WPA stage when IPA pass adds new
      function.  In this case we can not really do any of early inlining
      because function bodies are missing.  */
+  if (cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
+    return false;
   if (!gimple_has_body_p (callee->decl))
     {
       e->inline_failed = CIF_BODY_NOT_AVAILABLE;
@@ -2741,7 +2741,10 @@ early_inliner (function *fun)
 	      if (edge->callee->decl
 		  && !gimple_check_call_matching_types (
 		      edge->call_stmt, edge->callee->decl, false))
-		edge->call_stmt_cannot_inline_p = true;
+		{
+ 		  edge->inline_failed = CIF_MISMATCHED_ARGUMENTS;
+		  edge->call_stmt_cannot_inline_p = true;
+		}
 	    }
 	  if (iterations < PARAM_VALUE (PARAM_EARLY_INLINER_MAX_ITERATIONS) - 1)
 	    inline_update_overall_summary (node);
Index: lto/lto-symtab.c
===================================================================
--- lto/lto-symtab.c	(revision 235830)
+++ lto/lto-symtab.c	(working copy)
@@ -81,7 +81,10 @@ lto_cgraph_replace_node (struct cgraph_n
 	 ???  We really need a way to match function signatures for ABI
 	 compatibility and perform related promotions at inlining time.  */
       if (!compatible_p)
-	e->call_stmt_cannot_inline_p = 1;
+	{
+	  e->inline_failed = CIF_LTO_MISMATCHED_DECLARATIONS;
+	  e->call_stmt_cannot_inline_p = 1;
+	}
     }
   /* Redirect incomming references.  */
   prevailing_node->clone_referring (node);
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 235830)
+++ lto-cgraph.c	(working copy)
@@ -268,6 +268,8 @@ lto_output_edge (struct lto_simple_outpu
   bp_pack_value (&bp, edge->indirect_inlining_edge, 1);
   bp_pack_value (&bp, edge->speculative, 1);
   bp_pack_value (&bp, edge->call_stmt_cannot_inline_p, 1);
+  gcc_assert (!edge->call_stmt_cannot_inline_p
+	      || edge->inline_failed != CIF_BODY_NOT_AVAILABLE);
   bp_pack_value (&bp, edge->can_throw_external, 1);
   bp_pack_value (&bp, edge->in_polymorphic_cdtor, 1);
   if (edge->indirect_unknown_callee)
