diff --git a/compiler/GHC/Hs/Decls.hs b/compiler/GHC/Hs/Decls.hs
index 8c098c9be50421ac9e4886fe30a7695af01e72b3..0c9fa7e8abe92f324ee560065261cf80c1721c79 100644
--- a/compiler/GHC/Hs/Decls.hs
+++ b/compiler/GHC/Hs/Decls.hs
@@ -1268,7 +1268,7 @@ type instance XXWarnDecl    (GhcPass _) = DataConCantHappen
 instance OutputableBndrId p
         => Outputable (WarnDecls (GhcPass p)) where
     ppr (Warnings ext decls)
-      = ftext src <+> vcat (punctuate comma (map ppr decls)) <+> text "#-}"
+      = ftext src <+> vcat (punctuate semi (map ppr decls)) <+> text "#-}"
       where src = case ghcPass @p of
               GhcPs | (_, SourceText src) <- ext -> src
               GhcRn | SourceText src <- ext -> src
diff --git a/compiler/GHC/Parser.y b/compiler/GHC/Parser.y
index 9536d1e33d07e7cdc7154e0864ba1d9ebc10d8c6..963af26a9aaf3f5d59e91b484c4911463cc7e08d 100644
--- a/compiler/GHC/Parser.y
+++ b/compiler/GHC/Parser.y
@@ -2002,8 +2002,8 @@ warnings :: { OrdList (LWarnDecl GhcPs) }
 -- SUP: TEMPORARY HACK, not checking for `module Foo'
 warning :: { OrdList (LWarnDecl GhcPs) }
         : warning_category namelist strings
-                {% fmap unitOL $ acsA (\cs -> sLL $2 $>
-                     (Warning (EpAnn (glR $2) (fst $ unLoc $3) cs) (unLoc $2)
+                {% fmap unitOL $ acsA (\cs -> L (comb3 $1 $2 $3)
+                     (Warning (EpAnn (glMR $1 $2) (fst $ unLoc $3) cs) (unLoc $2)
                               (WarningTxt $1 NoSourceText $ map stringLiteralToHsDocWst $ snd $ unLoc $3))) }
 
 deprecations :: { OrdList (LWarnDecl GhcPs) }
@@ -4300,6 +4300,10 @@ glN = getLocA
 glR :: Located a -> Anchor
 glR la = Anchor (realSrcSpan $ getLoc la) UnchangedAnchor
 
+glMR :: Maybe (Located a) -> Located b -> Anchor
+glMR (Just la) _ = glR la
+glMR _ la = glR la
+
 glAA :: Located a -> EpaLocation
 glAA = srcSpan2e . getLoc
 
@@ -4554,5 +4558,4 @@ adaptWhereBinds (Just (L l (b, mc))) = L l (b, maybe emptyComments id mc)
 
 combineHasLocs :: (HasLoc a, HasLoc b) => a -> b -> SrcSpan
 combineHasLocs a b = combineSrcSpans (getHasLoc a) (getHasLoc b)
-
 }
diff --git a/compiler/GHC/Parser/Annotation.hs b/compiler/GHC/Parser/Annotation.hs
index 0fb917b96b6853b65e41e1e7adc5b303986fa3b0..ae7dcd74315da7a230d4be5ebaff24b4583c516e 100644
--- a/compiler/GHC/Parser/Annotation.hs
+++ b/compiler/GHC/Parser/Annotation.hs
@@ -1029,6 +1029,10 @@ instance HasLoc (Located a) where
 instance HasLoc (GenLocated (SrcSpanAnn' a) e) where
   getHasLoc (L (SrcSpanAnn _ l) _) = l
 
+instance (HasLoc a) => (HasLoc (Maybe a)) where
+  getHasLoc (Just a) = getHasLoc a
+  getHasLoc Nothing = noSrcSpan
+
 getHasLocList :: HasLoc a => [a] -> SrcSpan
 getHasLocList [] = noSrcSpan
 getHasLocList xs = foldl1' combineSrcSpans $ map getHasLoc xs
diff --git a/testsuite/tests/printer/Makefile b/testsuite/tests/printer/Makefile
index b82a65b56b3d4150ba6840c9e03bb0de2e357c82..ea796268a460a81aae1ef2e0bfc7ae9f0d141e21 100644
--- a/testsuite/tests/printer/Makefile
+++ b/testsuite/tests/printer/Makefile
@@ -796,12 +796,12 @@ Test22771:
 	$(CHECK_PPR)   $(LIBDIR) Test22771.hs
 	$(CHECK_EXACT) $(LIBDIR) Test22771.hs
 
-.PHONY: Test23464
+.PHONY: Test23465
 Test23465:
-	$(CHECK_PPR)   $(LIBDIR) Test23464.hs
-	$(CHECK_EXACT) $(LIBDIR) Test23464.hs
+	$(CHECK_PPR)   $(LIBDIR) Test23465.hs
+	$(CHECK_EXACT) $(LIBDIR) Test23465.hs
 
 .PHONY: Test23887
-Test23465:
+Test23887:
 	$(CHECK_PPR)   $(LIBDIR) Test23887.hs
 	$(CHECK_EXACT) $(LIBDIR) Test23887.hs
diff --git a/testsuite/tests/printer/Test23464.hs b/testsuite/tests/printer/Test23464.hs
deleted file mode 100644
index 885b41b9f3d8222146c8a76fad8ddbf02df67391..0000000000000000000000000000000000000000
--- a/testsuite/tests/printer/Test23464.hs
+++ /dev/null
@@ -1,4 +0,0 @@
-module T23465 {-# WaRNING in "x-a" "b" #-} where
-
-{-# WARNInG in "x-c" e "d" #-}
-e = e
diff --git a/testsuite/tests/printer/Test23465.hs b/testsuite/tests/printer/Test23465.hs
new file mode 100644
index 0000000000000000000000000000000000000000..dd4cd604f2e229a8314f8d5710e429400b5d2a7f
--- /dev/null
+++ b/testsuite/tests/printer/Test23465.hs
@@ -0,0 +1,14 @@
+module Test23465 {-# WaRNING in "x-a" "b" #-} where
+
+{-# WARNInG in "x-c" e "d" #-}
+e = e
+
+{-# WARNInG
+   in "x-f" f "fw" ;
+   in "x-f" g "gw"
+#-}
+f = f
+g = g
+
+{-# WARNinG h "hw" #-}
+h = h
diff --git a/testsuite/tests/printer/all.T b/testsuite/tests/printer/all.T
index 454b0724cfa089541088464683e2119546aca6f8..acf497b863c1848cced8a2779ef80cc39254ce2a 100644
--- a/testsuite/tests/printer/all.T
+++ b/testsuite/tests/printer/all.T
@@ -191,5 +191,5 @@ test('T20531_red_ticks', extra_files(['T20531_defs.hs']), ghci_script, ['T20531_
 test('HsDocTy', [ignore_stderr, req_ppr_deps], makefile_test, ['HsDocTy'])
 test('Test22765', [ignore_stderr, req_ppr_deps], makefile_test, ['Test22765'])
 test('Test22771', [ignore_stderr, req_ppr_deps], makefile_test, ['Test22771'])
-test('Test23464', [ignore_stderr, req_ppr_deps], makefile_test, ['Test23464'])
-test('Test23887', [ignore_stderr, req_ppr_deps], makefile_test, ['Test23887'])
+test('Test23465', [ignore_stderr, req_ppr_deps], makefile_test, ['Test23465'])
+test('Test23887', [ignore_stderr, req_ppr_deps], makefile_test, ['Test23887'])
\ No newline at end of file
diff --git a/utils/check-exact/ExactPrint.hs b/utils/check-exact/ExactPrint.hs
index ff0671611c66af0c2c0199599614f3249a0bf6b8..189a0e294abaa8d687f0a103acd241656ac72a6c 100644
--- a/utils/check-exact/ExactPrint.hs
+++ b/utils/check-exact/ExactPrint.hs
@@ -617,6 +617,15 @@ markEpAnnLMS' (EpAnn anc a cs) l kw (Just str) = do
 
 -- ---------------------------------------------------------------------
 
+markLToken :: forall m w tok . (Monad m, Monoid w, KnownSymbol tok)
+  => Located (HsToken tok) -> EP w m (Located (HsToken tok))
+markLToken (L (RealSrcSpan aa mb) t) = do
+  epaLoc'<-  printStringAtAA (EpaSpan aa mb) (symbolVal (Proxy @tok))
+  case epaLoc' of
+    EpaSpan aa' mb' -> return (L (RealSrcSpan aa' mb') t)
+    _               -> return (L (RealSrcSpan aa  mb ) t)
+markLToken (L lt t) = return (L lt t)
+
 markToken :: forall m w tok . (Monad m, Monoid w, KnownSymbol tok)
   => LHsToken tok GhcPs -> EP w m (LHsToken tok GhcPs)
 markToken (L NoTokenLoc t) = return (L NoTokenLoc t)
@@ -1411,11 +1420,12 @@ instance ExactPrint (LocatedP (WarningTxt GhcPs)) where
 
   exact (L (SrcSpanAnn an l) (WarningTxt mb_cat src ws)) = do
     an0 <- markAnnOpenP an src "{-# WARNING"
+    mb_cat' <- markAnnotated mb_cat
     an1 <- markEpAnnL an0 lapr_rest AnnOpenS
     ws' <- markAnnotated ws
     an2 <- markEpAnnL an1 lapr_rest AnnCloseS
     an3 <- markAnnCloseP an2
-    return (L (SrcSpanAnn an3 l) (WarningTxt mb_cat src ws'))
+    return (L (SrcSpanAnn an3 l) (WarningTxt mb_cat' src ws'))
 
   exact (L (SrcSpanAnn an l) (DeprecatedTxt src ws)) = do
     an0 <- markAnnOpenP an src "{-# DEPRECATED"
@@ -1425,6 +1435,25 @@ instance ExactPrint (LocatedP (WarningTxt GhcPs)) where
     an3 <- markAnnCloseP an2
     return (L (SrcSpanAnn an3 l) (DeprecatedTxt src ws'))
 
+instance ExactPrint InWarningCategory where
+  getAnnotationEntry _ = NoEntryVal
+  setAnnotationAnchor a _ _ = a
+
+  exact (InWarningCategory tkIn source (L l wc)) = do
+      tkIn' <- markLToken tkIn
+      L _ (_,wc') <- markAnnotated (L l (source, wc))
+      return (InWarningCategory tkIn' source (L l wc'))
+
+instance ExactPrint (SourceText, WarningCategory) where
+  getAnnotationEntry _ = NoEntryVal
+  setAnnotationAnchor a _ _ = a
+
+  exact (st, WarningCategory wc) = do
+      case st of
+          NoSourceText -> printStringAdvance $ "\"" ++ (unpackFS wc) ++ "\""
+          SourceText src -> printStringAdvance $ (unpackFS src)
+      return (st, WarningCategory wc)
+
 -- ---------------------------------------------------------------------
 
 instance ExactPrint (ImportDecl GhcPs) where
@@ -1748,19 +1777,20 @@ instance ExactPrint (WarnDecl GhcPs) where
   getAnnotationEntry (Warning an _ _) = fromAnn an
   setAnnotationAnchor (Warning an a b) anc cs = Warning (setAnchorEpa an anc cs) a b
 
-  exact (Warning an lns txt) = do
+  exact (Warning an lns  (WarningTxt mb_cat src ls )) = do
+    mb_cat' <- markAnnotated mb_cat
     lns' <- markAnnotated lns
     an0 <- markEpAnnL an lidl AnnOpenS -- "["
-    txt' <-
-      case txt of
-        WarningTxt mb_cat src ls -> do
-          ls' <- markAnnotated ls
-          return (WarningTxt mb_cat src ls')
-        DeprecatedTxt src ls -> do
-          ls' <- markAnnotated ls
-          return (DeprecatedTxt src ls')
+    ls' <- markAnnotated ls
     an1 <- markEpAnnL an0 lidl AnnCloseS -- "]"
-    return (Warning an1 lns' txt')
+    return (Warning an1 lns'  (WarningTxt mb_cat' src ls'))
+
+  exact (Warning an lns (DeprecatedTxt src ls)) = do
+    lns' <- markAnnotated lns
+    an0 <- markEpAnnL an lidl AnnOpenS -- "["
+    ls' <- markAnnotated ls
+    an1 <- markEpAnnL an0 lidl AnnCloseS -- "]"
+    return (Warning an1 lns' (DeprecatedTxt src ls'))
 
 -- ---------------------------------------------------------------------
 
@@ -1783,7 +1813,6 @@ instance ExactPrint FastString where
   -- exact fs = printStringAdvance (show (unpackFS fs))
   exact fs = printStringAdvance (unpackFS fs) >> return fs
 
-
 -- ---------------------------------------------------------------------
 
 instance ExactPrint (RuleDecls GhcPs) where
@@ -3122,7 +3151,6 @@ instance (ExactPrint body)
 
 -- ---------------------------------------------------------------------
 
--- instance ExactPrint (HsRecUpdField GhcPs q) where
 instance (ExactPrint (LocatedA body))
     => ExactPrint (HsFieldBind (LocatedAn NoEpAnns (AmbiguousFieldOcc GhcPs)) (LocatedA body)) where
   getAnnotationEntry x = fromAnn (hfbAnn x)
diff --git a/utils/check-exact/Main.hs b/utils/check-exact/Main.hs
index a149a978404aa116292204c492a5806797cf3a85..9d9f321160a57bff8b82cadb0c0d6102231a5360 100644
--- a/utils/check-exact/Main.hs
+++ b/utils/check-exact/Main.hs
@@ -206,7 +206,7 @@ _tt = testOneFile changers "/home/alanz/mysrc/git.haskell.org/worktree/epw/_buil
  -- "../../testsuite/tests/printer/HsDocTy.hs" Nothing
 --  "../../testsuite/tests/printer/Test22765.hs" Nothing
  -- "../../testsuite/tests/printer/Test22771.hs" Nothing
- "../../testsuite/tests/typecheck/should_fail/T22560_fail_c.hs" Nothing
+ "../../testsuite/tests/printer/Test23465.hs" Nothing
 
 -- cloneT does not need a test, function can be retired