diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d918e6803ae44a94766b2d6735c5c22cae43a7ff..be50af5301dd2bc5572041bb2334c23fadb1b734 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,20 @@
+2008-07-25  Jan Hubicka  <jh@suse.cz>
+
+	* typeck.c (inline_conversion): Remove.
+	(cp_build_function_call): Do not use inline_conversion.
+	* decl.c (duplicate_decls): Do not insist on inline being declared
+	early.
+	(start_cleanup_fn): Do not assume that INLINE flags prevent function
+	from being output.  We now remove static functions always.
+	(finish_function): Do return warning on all static functions.
+	* call.c (build_over_call): Do not use inline_conversion.
+	* cp-tree.h (possibly_inlined_p): Declare.
+	(inline_conversion): Remove.
+	* pt.c (instantiate_decl): Use possibly_inlined_p predicate.
+	* decl2.c (cp_write_global_declarations): Likewise.
+	(mark_used): Likewise.
+	(possibly_inlined_p): New functions.
+
 2008-07-25  Jason Merrill  <jason@redhat.com>
 
 	* class.c (type_has_user_provided_default_constructor): Handle
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 2304b5da71be3cfa11a38bee2050632f1599c260..cb07c82f1ab884913c7e35c42808a3cc2ff5ad2d 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5400,8 +5400,6 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	fn = build_vfn_ref (argarray[0], DECL_VINDEX (fn));
       TREE_TYPE (fn) = t;
     }
-  else if (DECL_INLINE (fn))
-    fn = inline_conversion (fn);
   else
     fn = build_addr_func (fn);
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1488d4ce6f96340bddc89e69ce23d658cc54034d..13c1797795f782ee0eef91e6c7e444a64a63c6d6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4334,6 +4334,7 @@ extern void mark_needed				(tree);
 extern bool decl_needed_p			(tree);
 extern void note_vague_linkage_fn		(tree);
 extern tree build_artificial_parm		(tree, tree);
+extern bool possibly_inlined_p			(tree);
 
 /* in error.c */
 extern void init_error				(void);
@@ -4812,7 +4813,6 @@ extern int comp_cv_qual_signature		(tree, tree);
 extern tree cxx_sizeof_or_alignof_expr		(tree, enum tree_code, bool);
 extern tree cxx_sizeof_or_alignof_type		(tree, enum tree_code, bool);
 extern tree cxx_sizeof_nowarn                   (tree);
-extern tree inline_conversion			(tree);
 extern tree is_bitfield_expr_with_lowered_type  (const_tree);
 extern tree unlowered_expr_type                 (const_tree);
 extern tree decay_conversion			(tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1bc83d47a902e3b835d76b6c5fc4faf97e0e3024..b762f680d8339736f2ca656b404bcd603bd41c6a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1551,14 +1551,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
 				 olddecl);
 		  }
 	      }
-
-	  if (DECL_DECLARED_INLINE_P (newdecl)
-	      && ! DECL_DECLARED_INLINE_P (olddecl)
-	      && TREE_ADDRESSABLE (olddecl) && warn_inline)
-	    {
-	      warning (0, "%q#D was used before it was declared inline", newdecl);
-	      warning (0, "%Jprevious non-inline declaration here", olddecl);
-	    }
 	}
     }
 
@@ -5954,8 +5946,6 @@ start_cleanup_fn (void)
      actually needed.  It is unlikely that it will be inlined, since
      it is only called via a function pointer, but we avoid unnecessary
      emissions this way.  */
-  DECL_INLINE (fndecl) = 1;
-  DECL_DECLARED_INLINE_P (fndecl) = 1;
   DECL_INTERFACE_KNOWN (fndecl) = 1;
   /* Build the parameter.  */
   if (use_cxa_atexit)
@@ -12011,13 +12001,15 @@ finish_function (int flags)
       /* Don't complain if we abort or throw.  */
       && !current_function_returns_abnormally
       && !DECL_NAME (DECL_RESULT (fndecl))
-      /* Normally, with -Wreturn-type, flow will complain.  Unless we're an
-	 inline function, as we might never be compiled separately.  */
-      && (DECL_INLINE (fndecl) || processing_template_decl)
+      && !TREE_NO_WARNING (fndecl)
       /* Structor return values (if any) are set by the compiler.  */
       && !DECL_CONSTRUCTOR_P (fndecl)
       && !DECL_DESTRUCTOR_P (fndecl))
-    warning (OPT_Wreturn_type, "no return statement in function returning non-void");
+    {
+      warning (OPT_Wreturn_type,
+ 	       "no return statement in function returning non-void");
+      TREE_NO_WARNING (fndecl) = 1;
+    }
 
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 6e6151d23f753045c783a86886fd0cebfe7b4c57..a156e32dcdb9227dfbb991677f1f14a08034bbde 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3422,7 +3422,7 @@ cp_write_global_declarations (void)
 	{
 	  /* Does it need synthesizing?  */
 	  if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
-	      && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
+	      && (! DECL_REALLY_EXTERN (decl) || possibly_inlined_p (decl)))
 	    {
 	      /* Even though we're already at the top-level, we push
 		 there again.  That way, when we pop back a few lines
@@ -3683,6 +3683,22 @@ check_default_args (tree x)
     }
 }
 
+/* Return true if function DECL can be inlined.  This is used to force
+   instantiation of methods that might be interesting for inlining.  */
+bool
+possibly_inlined_p (tree decl)
+{
+  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+  if (DECL_UNINLINABLE (decl))
+    return false;
+  if (!optimize)
+    return DECL_DECLARED_INLINE_P (decl);
+  /* When optimizing, we might inline everything when flatten
+     attribute or heuristics inlining for size or autoinlining
+     is used.  */
+  return true;
+}
+
 /* Mark DECL (either a _DECL or a BASELINK) as "used" in the program.
    If DECL is a specialization or implicitly declared class member,
    generate the actual definition.  */
@@ -3780,8 +3796,9 @@ mark_used (tree decl)
 	   && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
 	   && (!DECL_EXPLICIT_INSTANTIATION (decl)
 	       || (TREE_CODE (decl) == FUNCTION_DECL
-		   && DECL_INLINE (DECL_TEMPLATE_RESULT
-				   (template_for_substitution (decl))))
+		   && possibly_inlined_p
+		       (DECL_TEMPLATE_RESULT (
+		         template_for_substitution (decl))))
 	       /* We need to instantiate static data members so that there
 		  initializers are available in integral constant
 		  expressions.  */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ef4fa36be7ce69801e669d940983de5efefb96a5..b47ee5e6b3f842d6c178e8cf3efbf0fdde6210f6 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15144,7 +15144,8 @@ instantiate_decl (tree d, int defer_ok,
   if (external_p
       /* ... but we instantiate inline functions so that we can inline
 	 them and ... */
-      && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d))
+      && ! (TREE_CODE (d) == FUNCTION_DECL
+	    && possibly_inlined_p (d))
       /* ... we instantiate static data members whose values are
 	 needed in integral constant expressions.  */
       && ! (TREE_CODE (d) == VAR_DECL
@@ -15221,8 +15222,7 @@ instantiate_decl (tree d, int defer_ok,
       /* Instantiate inline functions so that the inliner can do its
 	 job, even though we'll not be emitting a copy of this
 	 function.  */
-      if (!(TREE_CODE (d) == FUNCTION_DECL
-	    && DECL_DECLARED_INLINE_P (d)))
+      if (!(TREE_CODE (d) == FUNCTION_DECL && possibly_inlined_p (d)))
 	goto out;
     }
 
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 67511f948774ea26eaa26b24320b88c458f6f0a3..fcf52dc9db42b67bd2d234c174bb0a46f455f7b0 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1698,18 +1698,6 @@ perform_integral_promotions (tree expr)
   return expr;
 }
 
-/* Take the address of an inline function without setting TREE_ADDRESSABLE
-   or TREE_USED.  */
-
-tree
-inline_conversion (tree exp)
-{
-  if (TREE_CODE (exp) == FUNCTION_DECL)
-    exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
-
-  return exp;
-}
-
 /* Returns nonzero iff exp is a STRING_CST or the result of applying
    decay_conversion to one.  */
 
@@ -2828,14 +2816,7 @@ cp_build_function_call (tree function, tree params, tsubst_flags_t complain)
 	pedwarn (OPT_pedantic, 
 		 "ISO C++ forbids calling %<::main%> from within program");
 
-      /* Differs from default_conversion by not setting TREE_ADDRESSABLE
-	 (because calling an inline function does not mean the function
-	 needs to be separately compiled).  */
-
-      if (DECL_INLINE (function))
-	function = inline_conversion (function);
-      else
-	function = build_addr_func (function);
+      function = build_addr_func (function);
     }
   else
     {