Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 180234)
+++ gcc/doc/invoke.texi	(working copy)
@@ -2120,7 +2120,7 @@
 @item -fvisibility-inlines-hidden
 @opindex fvisibility-inlines-hidden
 This switch declares that the user does not attempt to compare
-pointers to inline methods where the addresses of the two functions
+pointers to inline functions or methods where the addresses of the two functions
 were taken in different shared objects.
 
 The effect of this is that GCC may, effectively, mark inline methods with
Index: gcc/c-family/c.opt
===================================================================
--- gcc/c-family/c.opt	(revision 180234)
+++ gcc/c-family/c.opt	(working copy)
@@ -1043,7 +1043,7 @@
 
 fvisibility-inlines-hidden
 C++ ObjC++
-Marks all inlined methods as having hidden visibility
+Marks all inlined functions and methods as having hidden visibility
 
 fvisibility-ms-compat
 C++ ObjC++ Var(flag_visibility_ms_compat)
Index: gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-4.C
===================================================================
--- gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-4.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-4.C	(revision 0)
@@ -0,0 +1,18 @@
+/* PR c++/30066: Test that -fvisibility-inlines-hidden affects functions. */
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-options "-fvisibility-inlines-hidden" } */
+/* { dg-final { scan-hidden "_Z3barv" } } */
+/* { dg-final { scan-hidden "_Z3fooIvEvv" } } */
+
+inline void bar() { }
+
+template <class T>
+inline void foo() { }
+
+int main(void)
+{
+  bar();
+  foo<void>();
+  return 0;
+}
Index: gcc/cp/decl2.c
===================================================================
--- gcc/cp/decl2.c	(revision 180234)
+++ gcc/cp/decl2.c	(working copy)
@@ -86,6 +86,7 @@
 static void import_export_class (tree);
 static tree get_guard_bits (tree);
 static void determine_visibility_from_class (tree, tree);
+static bool determine_hidden_inline (tree);
 static bool decl_defined_p (tree);
 
 /* A list of static class variables.  This is needed, because a
@@ -2131,13 +2132,16 @@
 	}
       else if (use_template)
 	/* Template instantiations and specializations get visibility based
-	   on their template unless they override it with an attribute.  */;
+ 	   on their template unless they override it with an attribute.  */;
       else if (! DECL_VISIBILITY_SPECIFIED (decl))
 	{
-	  /* Set default visibility to whatever the user supplied with
-	     #pragma GCC visibility or a namespace visibility attribute.  */
-	  DECL_VISIBILITY (decl) = default_visibility;
-	  DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+          if (!determine_hidden_inline (decl))
+            {
+	      /* Set default visibility to whatever the user supplied with
+	         #pragma GCC visibility or a namespace visibility attribute.  */
+	      DECL_VISIBILITY (decl) = default_visibility;
+	      DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+            }
 	}
     }
 
@@ -2155,7 +2159,9 @@
 	  int depth = TMPL_ARGS_DEPTH (args);
 	  tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo));
 
-	  if (!DECL_VISIBILITY_SPECIFIED (decl))
+	  if (!DECL_VISIBILITY_SPECIFIED (decl)
+	      && (DECL_VISIBILITY_SPECIFIED (pattern) 
+	          || !determine_hidden_inline (decl)))
 	    {
 	      DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern);
 	      DECL_VISIBILITY_SPECIFIED (decl)
@@ -2214,17 +2220,7 @@
   if (DECL_VISIBILITY_SPECIFIED (decl))
     return;
 
-  if (visibility_options.inlines_hidden
-      /* Don't do this for inline templates; specializations might not be
-	 inline, and we don't want them to inherit the hidden
-	 visibility.  We'll set it here for all inline instantiations.  */
-      && !processing_template_decl
-      && TREE_CODE (decl) == FUNCTION_DECL
-      && DECL_DECLARED_INLINE_P (decl)
-      && (! DECL_LANG_SPECIFIC (decl)
-	  || ! DECL_EXPLICIT_INSTANTIATION (decl)))
-    DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
-  else
+  if (!determine_hidden_inline (decl))
     {
       /* Default to the class visibility.  */
       DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
@@ -2247,6 +2243,26 @@
     targetm.cxx.determine_class_data_visibility (decl);
 }
 
+static bool
+determine_hidden_inline (tree decl)
+{
+  if (visibility_options.inlines_hidden
+      /* Don't do this for inline templates; specializations might not be
+       * inline, and we don't want them to inherit the hidden
+       * visibility.  We'll set it here for all inline instantiations.  */
+      && !processing_template_decl
+      && TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_DECLARED_INLINE_P (decl)
+      && (! DECL_LANG_SPECIFIC (decl)
+          || ! DECL_EXPLICIT_INSTANTIATION (decl)))
+    {
+      DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+      return true;
+    }
+
+  return false;
+}
+
 /* Constrain the visibility of a class TYPE based on the visibility of its
    field types.  Warn if any fields require lesser visibility.  */
 
