diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
index 04eba3d140e..4926c48da96 100644
--- a/gcc/diagnostic-core.h
+++ b/gcc/diagnostic-core.h
@@ -33,7 +33,10 @@ typedef enum
   DK_LAST_DIAGNOSTIC_KIND,
   /* This is used for tagging pragma pops in the diagnostic
      classification history chain.  */
-  DK_POP
+  DK_POP,
+  /* This is used internally to note that a diagnostic is enabled
+     without mandating any specific type.  */
+  DK_ANY,
 } diagnostic_t;
 
 /* RAII-style class for grouping related diagnostics.  */
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 4f66fa6acaa..fd40018a734 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -1136,8 +1136,7 @@ classify_diagnostic (const diagnostic_context *context,
       if (old_kind == DK_UNSPECIFIED)
 	{
 	  old_kind = !context->option_enabled_p (option_index)
-	    ? DK_IGNORED : (context->warning_as_error_requested_p ()
-			    ? DK_ERROR : DK_WARNING);
+	    ? DK_IGNORED : DK_ANY;
 	  m_classify_diagnostic[option_index] = old_kind;
 	}
 
@@ -1472,7 +1471,15 @@ diagnostic_context::diagnostic_enabled (diagnostic_info *diagnostic)
      option.  */
   if (diag_class == DK_UNSPECIFIED
       && !option_unspecified_p (diagnostic->option_index))
-    diagnostic->kind = m_option_classifier.get_current_override (diagnostic->option_index);
+    {
+      const diagnostic_t new_kind
+	= m_option_classifier.get_current_override (diagnostic->option_index);
+      if (new_kind != DK_ANY)
+	/* DK_ANY means the diagnostic is not to be ignored, but we don't want
+	   to change it specifically to DK_ERROR or DK_WARNING; we want to
+	   preserve whatever the caller has specified.  */
+	diagnostic->kind = new_kind;
+    }
 
   /* This allows for future extensions, like temporarily disabling
      warnings for ranges of source code.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing21a.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing21a.C
new file mode 100644
index 00000000000..fa865987e5f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing21a.C
@@ -0,0 +1,14 @@
+/* PR c++/111918 */
+/* { dg-do compile { target c++11 } } */
+/* { dg-options "" } Suppress default -pedantic-errors so we can test permerror functionality.  */
+extern int g ();
+float f1{123456789}; /* { dg-error "-Wnarrowing" } */
+float f2{g ()}; /* { dg-warning "-Wnarrowing" } */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnarrowing"
+float f3{123456789}; /* { dg-bogus "-Wnarrowing" } */
+float f4{g ()}; /* { dg-bogus "-Wnarrowing" } */
+#pragma GCC diagnostic pop
+float f5{123456789}; /* { dg-bogus "warning" "warning in place of error" } */
+                     /* { dg-error "-Wnarrowing" "" { target *-*-* } .-1 } */
+float f6{g ()}; /* { dg-warning "-Wnarrowing" } */
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing21b.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing21b.C
new file mode 100644
index 00000000000..b8049358acc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing21b.C
@@ -0,0 +1,9 @@
+/* PR c++/111918 */
+/* { dg-do compile { target c++11 } } */
+/* { dg-options "-Wno-error=narrowing" } */
+float f1{123456789}; /* { dg-warning "-Wnarrowing" } */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnarrowing"
+float f2{123456789}; /* { dg-bogus "-Wnarrowing" } */
+#pragma GCC diagnostic pop
+float f3{123456789}; /* { dg-warning "-Wnarrowing" } */
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing21c.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing21c.C
new file mode 100644
index 00000000000..6a98dd08176
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing21c.C
@@ -0,0 +1,9 @@
+/* PR c++/111918 */
+/* { dg-do compile { target c++11 } } */
+/* { dg-options "-fpermissive" } */
+float f1{123456789}; /* { dg-warning "-Wnarrowing" } */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnarrowing"
+float f2{123456789}; /* { dg-bogus "-Wnarrowing" } */
+#pragma GCC diagnostic pop
+float f3{123456789}; /* { dg-warning "-Wnarrowing" } */
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing21d.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing21d.C
new file mode 100644
index 00000000000..a371e0a964f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing21d.C
@@ -0,0 +1,9 @@
+/* PR c++/111918 */
+/* { dg-do compile { target c++11 } } */
+/* { dg-options "-Wno-narrowing" } */
+float f1{123456789}; /* { dg-bogus "-Wnarrowing" } */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic warning "-Wnarrowing"
+float f2{123456789}; /* { dg-warning "-Wnarrowing" } */
+#pragma GCC diagnostic pop
+float f3{123456789}; /* { dg-bogus "-Wnarrowing" } */
