diff --git a/compiler/GHC.hs b/compiler/GHC.hs
index 66432aa1634352e1c814c993910dcfd85eee846a..cb4ba5f1e9843dc19dfb31491ce26e1b20de8b98 100644
--- a/compiler/GHC.hs
+++ b/compiler/GHC.hs
@@ -1419,7 +1419,7 @@ getPackageModuleInfo hsc_env mdl
             tys    = [ ty | name <- concatMap availNames avails,
                             Just ty <- [lookupTypeEnv pte name] ]
 
-        let !rdr_env = availsToGlobalRdrEnv hsc_env (moduleName mdl) avails
+        let !rdr_env = availsToGlobalRdrEnv hsc_env mdl avails
         -- See Note [Forcing GREInfo] in GHC.Types.GREInfo.
 
         return (Just (ModuleInfo {
@@ -1432,7 +1432,7 @@ getPackageModuleInfo hsc_env mdl
                         minf_modBreaks = emptyModBreaks
                 }))
 
-availsToGlobalRdrEnv :: HasDebugCallStack => HscEnv -> ModuleName -> [AvailInfo] -> IfGlobalRdrEnv
+availsToGlobalRdrEnv :: HasDebugCallStack => HscEnv -> Module -> [AvailInfo] -> IfGlobalRdrEnv
 availsToGlobalRdrEnv hsc_env mod avails
   = forceGlobalRdrEnv rdr_env
     -- See Note [Forcing GREInfo] in GHC.Types.GREInfo.
@@ -1441,7 +1441,7 @@ availsToGlobalRdrEnv hsc_env mod avails
       -- We're building a GlobalRdrEnv as if the user imported
       -- all the specified modules into the global interactive module
     imp_spec = ImpSpec { is_decl = decl, is_item = ImpAll}
-    decl = ImpDeclSpec { is_mod = mod, is_as = mod,
+    decl = ImpDeclSpec { is_mod = mod, is_as = moduleName mod,
                          is_qual = False,
                          is_dloc = srcLocSpan interactiveSrcLoc }
 
diff --git a/compiler/GHC/Driver/Flags.hs b/compiler/GHC/Driver/Flags.hs
index e06d6e9d18108d79ec483736df25a4d0f7f3bab6..fec6508b6d68c7b803a1e7b2463b2d2e4fec4906 100644
--- a/compiler/GHC/Driver/Flags.hs
+++ b/compiler/GHC/Driver/Flags.hs
@@ -647,6 +647,7 @@ data WarningFlag =
    | Opt_WarnTermVariableCapture                     -- Since 9.8
    | Opt_WarnMissingRoleAnnotations                  -- Since 9.8
    | Opt_WarnImplicitRhsQuantification               -- Since 9.8
+   | Opt_WarnIncompleteExportWarnings                -- Since 9.8
    deriving (Eq, Ord, Show, Enum)
 
 -- | Return the names of a WarningFlag
@@ -756,6 +757,7 @@ warnFlagNames wflag = case wflag of
   Opt_WarnTypeEqualityRequiresOperators           -> "type-equality-requires-operators" :| []
   Opt_WarnMissingRoleAnnotations                  -> "missing-role-annotations" :| []
   Opt_WarnImplicitRhsQuantification               -> "implicit-rhs-quantification" :| []
+  Opt_WarnIncompleteExportWarnings                -> "incomplete-export-warnings" :| []
 
 -- -----------------------------------------------------------------------------
 -- Standard sets of warning options
@@ -928,7 +930,8 @@ minusWallOpts
         Opt_WarnUnusedRecordWildcards,
         Opt_WarnRedundantRecordWildcards,
         Opt_WarnIncompleteUniPatterns,
-        Opt_WarnIncompletePatternsRecUpd
+        Opt_WarnIncompletePatternsRecUpd,
+        Opt_WarnIncompleteExportWarnings
       ]
 
 -- | Things you get with -Weverything, i.e. *all* known warnings flags
diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs
index f7c32113debb53c26e922e565043ca4fe2a2d4e1..6331774b3f6720ef3d7847dd95267754022c297d 100644
--- a/compiler/GHC/Driver/Session.hs
+++ b/compiler/GHC/Driver/Session.hs
@@ -2271,7 +2271,8 @@ wWarningFlagsDeps = mconcat [
   warnSpec    Opt_WarnTypeEqualityRequiresOperators,
   warnSpec    Opt_WarnTermVariableCapture,
   warnSpec    Opt_WarnMissingRoleAnnotations,
-  warnSpec    Opt_WarnImplicitRhsQuantification
+  warnSpec    Opt_WarnImplicitRhsQuantification,
+  warnSpec    Opt_WarnIncompleteExportWarnings
  ]
 
 warningGroupsDeps :: [(Deprecation, FlagSpec WarningGroup)]
diff --git a/compiler/GHC/Hs/ImpExp.hs b/compiler/GHC/Hs/ImpExp.hs
index 06a6cc783ea45b8316b2a2cf69752c4df3b6fdb9..5e25893cb962eb50e150cea80f7be2edb0d9b637 100644
--- a/compiler/GHC/Hs/ImpExp.hs
+++ b/compiler/GHC/Hs/ImpExp.hs
@@ -38,6 +38,8 @@ import GHC.Hs.Extension
 import GHC.Utils.Outputable
 import GHC.Utils.Panic
 
+import GHC.Unit.Module.Warnings (WarningTxt)
+
 import Data.Data
 import Data.Maybe
 
@@ -198,16 +200,39 @@ type instance Anno (IEWrappedName (GhcPass _)) = SrcSpanAnnA
 
 type instance Anno (IE (GhcPass p)) = SrcSpanAnnA
 
-type instance XIEVar             GhcPs = NoExtField
-type instance XIEVar             GhcRn = NoExtField
-type instance XIEVar             GhcTc = NoExtField
-
-type instance XIEThingAbs        (GhcPass _) = EpAnn [AddEpAnn]
-type instance XIEThingAll        (GhcPass _) = EpAnn [AddEpAnn]
-type instance XIEThingWith       (GhcPass _) = EpAnn [AddEpAnn]
-
-type instance XIEModuleContents  GhcPs = EpAnn [AddEpAnn]
-type instance XIEModuleContents  GhcRn = NoExtField
+-- The additional field of type 'Maybe (WarningTxt pass)' holds information
+-- about export deprecation annotations and is thus set to Nothing when `IE`
+-- is used in an import list (since export deprecation can only be used in exports)
+type instance XIEVar       GhcPs = Maybe (LocatedP (WarningTxt GhcPs))
+type instance XIEVar       GhcRn = Maybe (LocatedP (WarningTxt GhcRn))
+type instance XIEVar       GhcTc = NoExtField
+
+-- The additional field of type 'Maybe (WarningTxt pass)' holds information
+-- about export deprecation annotations and is thus set to Nothing when `IE`
+-- is used in an import list (since export deprecation can only be used in exports)
+type instance XIEThingAbs  GhcPs = (Maybe (LocatedP (WarningTxt GhcPs)), EpAnn [AddEpAnn])
+type instance XIEThingAbs  GhcRn = (Maybe (LocatedP (WarningTxt GhcRn)), EpAnn [AddEpAnn])
+type instance XIEThingAbs  GhcTc = EpAnn [AddEpAnn]
+
+-- The additional field of type 'Maybe (WarningTxt pass)' holds information
+-- about export deprecation annotations and is thus set to Nothing when `IE`
+-- is used in an import list (since export deprecation can only be used in exports)
+type instance XIEThingAll  GhcPs = (Maybe (LocatedP (WarningTxt GhcPs)), EpAnn [AddEpAnn])
+type instance XIEThingAll  GhcRn = (Maybe (LocatedP (WarningTxt GhcRn)), EpAnn [AddEpAnn])
+type instance XIEThingAll  GhcTc = EpAnn [AddEpAnn]
+
+-- The additional field of type 'Maybe (WarningTxt pass)' holds information
+-- about export deprecation annotations and is thus set to Nothing when `IE`
+-- is used in an import list (since export deprecation can only be used in exports)
+type instance XIEThingWith GhcPs = (Maybe (LocatedP (WarningTxt GhcPs)), EpAnn [AddEpAnn])
+type instance XIEThingWith GhcRn = (Maybe (LocatedP (WarningTxt GhcRn)), EpAnn [AddEpAnn])
+type instance XIEThingWith GhcTc = EpAnn [AddEpAnn]
+
+-- The additional field of type 'Maybe (WarningTxt pass)' holds information
+-- about export deprecation annotations and is thus set to Nothing when `IE`
+-- is used in an import list (since export deprecation can only be used in exports)
+type instance XIEModuleContents  GhcPs = (Maybe (LocatedP (WarningTxt GhcPs)), EpAnn [AddEpAnn])
+type instance XIEModuleContents  GhcRn = Maybe (LocatedP (WarningTxt GhcRn))
 type instance XIEModuleContents  GhcTc = NoExtField
 
 type instance XIEGroup           (GhcPass _) = NoExtField
@@ -236,6 +261,22 @@ ieNames (IEGroup          {})     = []
 ieNames (IEDoc            {})     = []
 ieNames (IEDocNamed       {})     = []
 
+ieDeprecation :: forall p. IsPass p => IE (GhcPass p) -> Maybe (WarningTxt (GhcPass p))
+ieDeprecation = fmap unLoc . ie_deprecation (ghcPass @p)
+  where
+    ie_deprecation :: GhcPass p -> IE (GhcPass p) -> Maybe (LocatedP (WarningTxt (GhcPass p)))
+    ie_deprecation GhcPs (IEVar xie _) = xie
+    ie_deprecation GhcPs (IEThingAbs (xie, _) _) = xie
+    ie_deprecation GhcPs (IEThingAll (xie, _) _) = xie
+    ie_deprecation GhcPs (IEThingWith (xie, _) _ _ _) = xie
+    ie_deprecation GhcPs (IEModuleContents (xie, _) _) = xie
+    ie_deprecation GhcRn (IEVar xie _) = xie
+    ie_deprecation GhcRn (IEThingAbs (xie, _) _) = xie
+    ie_deprecation GhcRn (IEThingAll (xie, _) _) = xie
+    ie_deprecation GhcRn (IEThingWith (xie, _) _ _ _) = xie
+    ie_deprecation GhcRn (IEModuleContents xie _) = xie
+    ie_deprecation _ _ = Nothing
+
 ieWrappedLName :: IEWrappedName (GhcPass p) -> LIdP (GhcPass p)
 ieWrappedLName (IEName    _ (L l n)) = L l n
 ieWrappedLName (IEPattern _ (L l n)) = L l n
@@ -260,11 +301,11 @@ replaceLWrappedName :: LIEWrappedName GhcPs -> IdP GhcRn -> LIEWrappedName GhcRn
 replaceLWrappedName (L l n) n' = L l (replaceWrappedName n n')
 
 instance OutputableBndrId p => Outputable (IE (GhcPass p)) where
-    ppr (IEVar       _     var) = ppr (unLoc var)
-    ppr (IEThingAbs  _   thing) = ppr (unLoc thing)
-    ppr (IEThingAll  _   thing) = hcat [ppr (unLoc thing), text "(..)"]
-    ppr (IEThingWith _ thing wc withs)
-        = ppr (unLoc thing) <> parens (fsep (punctuate comma ppWiths))
+    ppr ie@(IEVar       _     var) = sep $ catMaybes [ppr <$> ieDeprecation ie, Just $ ppr (unLoc var)]
+    ppr ie@(IEThingAbs  _   thing) = sep $ catMaybes [ppr <$> ieDeprecation ie, Just $ ppr (unLoc thing)]
+    ppr ie@(IEThingAll  _   thing) = sep $ catMaybes [ppr <$> ieDeprecation ie, Just $ hcat [ppr (unLoc thing), text "(..)"]]
+    ppr ie@(IEThingWith _ thing wc withs)
+        = sep $ catMaybes [ppr <$> ieDeprecation ie, Just $ ppr (unLoc thing) <> parens (fsep (punctuate comma ppWiths))]
       where
         ppWiths =
           case wc of
@@ -273,8 +314,8 @@ instance OutputableBndrId p => Outputable (IE (GhcPass p)) where
               IEWildcard pos ->
                 let (bs, as) = splitAt pos (map (ppr . unLoc) withs)
                 in bs ++ [text ".."] ++ as
-    ppr (IEModuleContents _ mod')
-        = text "module" <+> ppr mod'
+    ppr ie@(IEModuleContents _ mod')
+        = sep $ catMaybes [ppr <$> ieDeprecation ie, Just $ text "module" <+> ppr mod']
     ppr (IEGroup _ n _)           = text ("<IEGroup: " ++ show n ++ ">")
     ppr (IEDoc _ doc)             = ppr doc
     ppr (IEDocNamed _ string)     = text ("<IEDocNamed: " ++ string ++ ">")
diff --git a/compiler/GHC/Iface/Make.hs b/compiler/GHC/Iface/Make.hs
index dd84d399f59bfe8120b04dcc4c0a624a7c9bc0c7..2dc05841f78d316240730d9003c92d07d7bb2f44 100644
--- a/compiler/GHC/Iface/Make.hs
+++ b/compiler/GHC/Iface/Make.hs
@@ -396,9 +396,11 @@ ifaceRoughMatchTcs tcs = map do_rough tcs
 
 --------------------------
 toIfaceWarnings :: Warnings GhcRn -> IfaceWarnings
-toIfaceWarnings NoWarnings = IfNoWarnings
 toIfaceWarnings (WarnAll txt) = IfWarnAll (toIfaceWarningTxt txt)
-toIfaceWarnings (WarnSome prs) = IfWarnSome [(occ, toIfaceWarningTxt txt) | (occ, txt) <- prs]
+toIfaceWarnings (WarnSome vs ds) = IfWarnSome vs' ds'
+  where
+    vs' = [(occ, toIfaceWarningTxt txt) | (occ, txt) <- vs]
+    ds' = [(occ, toIfaceWarningTxt txt) | (occ, txt) <- ds]
 
 toIfaceWarningTxt :: WarningTxt GhcRn -> IfaceWarningTxt
 toIfaceWarningTxt (WarningTxt mb_cat src strs) = IfWarningTxt (unLoc <$> mb_cat) (unLoc src) (map (toIfaceStringLiteralWithNames . unLoc) strs)
diff --git a/compiler/GHC/Iface/Recomp.hs b/compiler/GHC/Iface/Recomp.hs
index 48b24b903b785a5a2a8fa6bab0e0ab05bafce31b..da47ecd8d59fd269f7166efc29840c139c35fcdc 100644
--- a/compiler/GHC/Iface/Recomp.hs
+++ b/compiler/GHC/Iface/Recomp.hs
@@ -964,7 +964,8 @@ addFingerprints hsc_env iface0
    eps <- hscEPS hsc_env
    let
        decls = mi_decls iface0
-       warn_fn = mkIfaceWarnCache (fromIfaceWarnings $ mi_warns iface0)
+       decl_warn_fn = mkIfaceDeclWarnCache (fromIfaceWarnings $ mi_warns iface0)
+       export_warn_fn = mkIfaceExportWarnCache (fromIfaceWarnings $ mi_warns iface0)
        fix_fn = mkIfaceFixCache (mi_fixities iface0)
 
         -- The ABI of a declaration represents everything that is made
@@ -1265,22 +1266,23 @@ addFingerprints hsc_env iface0
 
    let
     final_iface_exts = ModIfaceBackend
-      { mi_iface_hash  = iface_hash
-      , mi_mod_hash    = mod_hash
-      , mi_flag_hash   = flag_hash
-      , mi_opt_hash    = opt_hash
-      , mi_hpc_hash    = hpc_hash
-      , mi_plugin_hash = plugin_hash
-      , mi_orphan      = not (   all ifRuleAuto orph_rules
-                                   -- See Note [Orphans and auto-generated rules]
-                              && null orph_insts
-                              && null orph_fis)
-      , mi_finsts      = not (null (mi_fam_insts iface0))
-      , mi_exp_hash    = export_hash
-      , mi_orphan_hash = orphan_hash
-      , mi_warn_fn     = warn_fn
-      , mi_fix_fn      = fix_fn
-      , mi_hash_fn     = lookupOccEnv local_env
+      { mi_iface_hash     = iface_hash
+      , mi_mod_hash       = mod_hash
+      , mi_flag_hash      = flag_hash
+      , mi_opt_hash       = opt_hash
+      , mi_hpc_hash       = hpc_hash
+      , mi_plugin_hash    = plugin_hash
+      , mi_orphan         = not (   all ifRuleAuto orph_rules
+                                      -- See Note [Orphans and auto-generated rules]
+                                 && null orph_insts
+                                 && null orph_fis)
+      , mi_finsts         = not (null (mi_fam_insts iface0))
+      , mi_exp_hash       = export_hash
+      , mi_orphan_hash    = orphan_hash
+      , mi_decl_warn_fn   = decl_warn_fn
+      , mi_export_warn_fn = export_warn_fn
+      , mi_fix_fn         = fix_fn
+      , mi_hash_fn        = lookupOccEnv local_env
       }
     final_iface = iface0 { mi_decls = sorted_decls, mi_extra_decls = sorted_extra_decls, mi_final_exts = final_iface_exts }
    --
diff --git a/compiler/GHC/Iface/Syntax.hs b/compiler/GHC/Iface/Syntax.hs
index 39579b69b2b89b714fcf730e10a5cc347337be98..84716f9ad32e80eb5a2534a9416f15aec1c7fce4 100644
--- a/compiler/GHC/Iface/Syntax.hs
+++ b/compiler/GHC/Iface/Syntax.hs
@@ -345,9 +345,9 @@ data IfaceRule
     }
 
 data IfaceWarnings
-  = IfNoWarnings
-  | IfWarnAll IfaceWarningTxt
+  = IfWarnAll IfaceWarningTxt
   | IfWarnSome [(OccName, IfaceWarningTxt)]
+               [(IfExtName, IfaceWarningTxt)]
 
 data IfaceWarningTxt
   = IfWarningTxt (Maybe WarningCategory) SourceText [(IfaceStringLiteral, [IfExtName])]
@@ -584,9 +584,9 @@ ifaceDeclFingerprints hash decl
 
 fromIfaceWarnings :: IfaceWarnings -> Warnings GhcRn
 fromIfaceWarnings = \case
-    IfNoWarnings -> NoWarnings
     IfWarnAll txt -> WarnAll (fromIfaceWarningTxt txt)
-    IfWarnSome prs -> WarnSome [(occ, fromIfaceWarningTxt txt) | (occ, txt) <- prs]
+    IfWarnSome vs ds -> WarnSome [(occ, fromIfaceWarningTxt txt) | (occ, txt) <- vs]
+                                 [(occ, fromIfaceWarningTxt txt) | (occ, txt) <- ds]
 
 fromIfaceWarningTxt :: IfaceWarningTxt -> WarningTxt GhcRn
 fromIfaceWarningTxt = \case
@@ -753,9 +753,11 @@ pprAxBranch pp_tc idx (IfaceAxBranch { ifaxbTyVars = tvs
 
 instance Outputable IfaceWarnings where
     ppr = \case
-        IfNoWarnings -> empty
         IfWarnAll txt -> text "Warn all" <+> ppr txt
-        IfWarnSome prs -> text "Warnings:" <+> vcat [ppr name <+> ppr txt | (name, txt) <- prs]
+        IfWarnSome vs ds ->
+          hang (text "Warnings:") 2 $
+            text "Deprecated names:" <+> vcat [ppr name <+> ppr txt | (name, txt) <- vs] $$
+            text "Deprecated exports:" <+> vcat [ppr name <+> ppr txt | (name, txt) <- ds]
 
 instance Outputable IfaceWarningTxt where
     ppr = \case
@@ -2322,13 +2324,12 @@ instance Binary IfaceRule where
 
 instance Binary IfaceWarnings where
     put_ bh = \case
-        IfNoWarnings   -> putByte bh 0
-        IfWarnAll txt  -> putByte bh 1 *> put_ bh txt
-        IfWarnSome prs -> putByte bh 2 *> put_ bh prs
+        IfWarnAll txt  -> putByte bh 0 *> put_ bh txt
+        IfWarnSome vs ds -> putByte bh 1 *> put_ bh vs *> put_ bh ds
     get bh = getByte bh >>= \case
-        0 -> pure IfNoWarnings
-        1 -> pure IfWarnAll    <*> get bh
-        _ -> pure IfWarnSome   <*> get bh
+        0 -> pure IfWarnAll    <*> get bh
+        1 -> pure IfWarnSome   <*> get bh <*> get bh
+        _ -> fail "invalid tag(IfaceWarnings)"
 
 instance Binary IfaceWarningTxt where
     put_ bh = \case
@@ -2901,9 +2902,8 @@ instance NFData IfaceClsInst where
 
 instance NFData IfaceWarnings where
   rnf = \case
-      IfNoWarnings    -> ()
       IfWarnAll txt   -> rnf txt
-      IfWarnSome txts -> rnf txts
+      IfWarnSome vs ds -> rnf vs `seq` rnf ds
 
 instance NFData IfaceWarningTxt where
     rnf = \case
diff --git a/compiler/GHC/Parser.y b/compiler/GHC/Parser.y
index a61a1335743cd4c14fa8cdc1bb548295d6d39793..37844ff46f97f976dbc6c0a164ad7012a5b2a334 100644
--- a/compiler/GHC/Parser.y
+++ b/compiler/GHC/Parser.y
@@ -1026,11 +1026,24 @@ exportlist1 :: { OrdList (LIE GhcPs) }
    -- No longer allow things like [] and (,,,) to be exported
    -- They are built in syntax, always available
 export  :: { OrdList (LIE GhcPs) }
-        : qcname_ext export_subspec  {% mkModuleImpExp (fst $ unLoc $2) $1 (snd $ unLoc $2)
-                                          >>= \ie -> fmap (unitOL . reLocA) (return (sLL (reLoc $1) $> ie)) }
-        |  'module' modid            {% fmap (unitOL . reLocA) (acs (\cs -> sLL $1 (reLoc $>) (IEModuleContents (EpAnn (glR $1) [mj AnnModule $1] cs) $2))) }
-        |  'pattern' qcon            { unitOL (reLocA (sLL $1 (reLocN $>)
-                                              (IEVar noExtField (sLLa $1 (reLocN $>) (IEPattern (glAA $1) $2))))) }
+        : maybeexportwarning qcname_ext export_subspec {% do { let { span = (maybe comb2 (comb3 . reLoc) $1) (reLoc $2) $> }
+                                                          ; impExp <- mkModuleImpExp $1 (fst $ unLoc $3) $2 (snd $ unLoc $3)
+                                                          ; return $ unitOL $ reLocA $ sL span $ impExp } }
+        | maybeexportwarning 'module' modid            {% do { let { span = (maybe comb2 (comb3 . reLoc) $1) $2 (reLoc $>)
+                                                                   ; anchor = (maybe glR (\loc -> spanAsAnchor . comb2 (reLoc loc)) $1) $2 }
+                                                          ; locImpExp <- acs (\cs -> sL span (IEModuleContents ($1, EpAnn anchor [mj AnnModule $2] cs) $3))
+                                                          ; return $ unitOL $ reLocA $ locImpExp } }
+        | maybeexportwarning 'pattern' qcon            { let span = (maybe comb2 (comb3 . reLoc) $1) $2 (reLoc $>)
+                                                       in unitOL $ reLocA $ sL span $ IEVar $1 (sLLa $2 (reLocN $>) (IEPattern (glAA $2) $3)) }
+
+maybeexportwarning :: { Maybe (LocatedP (WarningTxt GhcPs)) }
+        : '{-# DEPRECATED' strings '#-}'
+                            {% fmap Just $ amsrp (sLL $1 $> $ DeprecatedTxt (sL1 $1 $ getDEPRECATED_PRAGs $1) (map stringLiteralToHsDocWst $ snd $ unLoc $2))
+                                (AnnPragma (mo $1) (mc $3) (fst $ unLoc $2)) }
+        | '{-# WARNING' warning_category strings '#-}'
+                            {% fmap Just $ amsrp (sLL $1 $> $ WarningTxt $2 (sL1 $1 $ getWARNING_PRAGs $1) (map stringLiteralToHsDocWst $ snd $ unLoc $3))
+                                (AnnPragma (mo $1) (mc $4) (fst $ unLoc $3))}
+        |  {- empty -}      { Nothing }
 
 export_subspec :: { Located ([AddEpAnn],ImpExpSubSpec) }
         : {- empty -}             { sL0 ([],ImpExpAbs) }
@@ -1166,13 +1179,40 @@ maybeimpspec :: { Located (Maybe (ImportListInterpretation, LocatedL [LIE GhcPs]
         | {- empty -}              { noLoc Nothing }
 
 impspec :: { Located (ImportListInterpretation, LocatedL [LIE GhcPs]) }
-        :  '(' exportlist ')'               {% do { es <- amsrl (sLL $1 $> $ fromOL $ snd $2)
+        :  '(' importlist ')'               {% do { es <- amsrl (sLL $1 $> $ fromOL $ snd $2)
                                                                (AnnList Nothing (Just $ mop $1) (Just $ mcp $3) (fst $2) [])
                                                   ; return $ sLL $1 $> (Exactly, es)} }
-        |  'hiding' '(' exportlist ')'      {% do { es <- amsrl (sLL $1 $> $ fromOL $ snd $3)
+        |  'hiding' '(' importlist ')'      {% do { es <- amsrl (sLL $1 $> $ fromOL $ snd $3)
                                                                (AnnList Nothing (Just $ mop $2) (Just $ mcp $4) (mj AnnHiding $1:fst $3) [])
                                                   ; return $ sLL $1 $> (EverythingBut, es)} }
 
+importlist :: { ([AddEpAnn], OrdList (LIE GhcPs)) }
+        : importlist1     { ([], $1) }
+        | {- empty -}     { ([], nilOL) }
+
+        -- trailing comma:
+        | importlist1 ',' {% case $1 of
+                               SnocOL hs t -> do
+                                 t' <- addTrailingCommaA t (gl $2)
+                                 return ([], snocOL hs t')}
+        | ','             { ([mj AnnComma $1], nilOL) }
+
+importlist1 :: { OrdList (LIE GhcPs) }
+        : importlist1 ',' import
+                          {% let ls = $1
+                             in if isNilOL ls
+                                  then return (ls `appOL` $3)
+                                  else case ls of
+                                         SnocOL hs t -> do
+                                           t' <- addTrailingCommaA t (gl $2)
+                                           return (snocOL hs t' `appOL` $3)}
+        | import          { $1 }
+
+import  :: { OrdList (LIE GhcPs) }
+        : qcname_ext export_subspec {% fmap (unitOL . reLocA . (sLL (reLoc $1) $>)) $ mkModuleImpExp Nothing (fst $ unLoc $2) $1 (snd $ unLoc $2) }
+        | 'module' modid            {% fmap (unitOL . reLocA) $ acs (\cs -> sLL $1 (reLoc $>) (IEModuleContents (Nothing, EpAnn (glR $1) [mj AnnModule $1] cs) $2)) }
+        | 'pattern' qcon            { unitOL $ reLocA $ sLL $1 (reLocN $>) $ IEVar Nothing (sLLa $1 (reLocN $>) (IEPattern (glAA $1) $2)) }
+
 -----------------------------------------------------------------------------
 -- Fixity Declarations
 
diff --git a/compiler/GHC/Parser/PostProcess.hs b/compiler/GHC/Parser/PostProcess.hs
index c5bc296441c5698b92d6a1444a1fdc2af97b4b23..d37744ab413685d33338567d3e09a27761831b35 100644
--- a/compiler/GHC/Parser/PostProcess.hs
+++ b/compiler/GHC/Parser/PostProcess.hs
@@ -153,6 +153,7 @@ import Data.Either
 import Data.List        ( findIndex )
 import Data.Foldable
 import qualified Data.Semigroup as Semi
+import GHC.Unit.Module.Warnings
 import GHC.Utils.Panic
 import GHC.Utils.Panic.Plain
 import qualified GHC.Data.Strict as Strict
@@ -2791,18 +2792,20 @@ data ImpExpQcSpec = ImpExpQcName (LocatedN RdrName)
                   | ImpExpQcType EpaLocation (LocatedN RdrName)
                   | ImpExpQcWildcard
 
-mkModuleImpExp :: [AddEpAnn] -> LocatedA ImpExpQcSpec -> ImpExpSubSpec -> P (IE GhcPs)
-mkModuleImpExp anns (L l specname) subs = do
+mkModuleImpExp :: Maybe (LocatedP (WarningTxt GhcPs)) -> [AddEpAnn] -> LocatedA ImpExpQcSpec
+               -> ImpExpSubSpec -> P (IE GhcPs)
+mkModuleImpExp warning anns (L l specname) subs = do
   cs <- getCommentsFor (locA l) -- AZ: IEVar can discard comments
-  let ann = EpAnn (spanAsAnchor $ locA l) anns cs
+  let ann = EpAnn (spanAsAnchor $ maybe (locA l) getLocA warning) anns cs
   case subs of
     ImpExpAbs
       | isVarNameSpace (rdrNameSpace name)
-                       -> return $ IEVar noExtField (L l (ieNameFromSpec specname))
-      | otherwise      -> IEThingAbs ann . L l <$> nameT
-    ImpExpAll          -> IEThingAll ann . L l <$> nameT
+                       -> return $ IEVar warning
+                           (L l (ieNameFromSpec specname))
+      | otherwise      -> IEThingAbs (warning, ann) . L l <$> nameT
+    ImpExpAll          -> IEThingAll (warning, ann) . L l <$> nameT
     ImpExpList xs      ->
-      (\newName -> IEThingWith ann (L l newName)
+      (\newName -> IEThingWith (warning, ann) (L l newName)
         NoIEWildcard (wrapped xs)) <$> nameT
     ImpExpAllWith xs                       ->
       do allowed <- getBit PatternSynonymsBit
@@ -2814,7 +2817,7 @@ mkModuleImpExp anns (L l specname) subs = do
                 ies :: [LocatedA (IEWrappedName GhcPs)]
                 ies   = wrapped $ filter (not . isImpExpQcWildcard . unLoc) xs
             in (\newName
-                        -> IEThingWith ann (L l newName) pos ies)
+                        -> IEThingWith (warning, ann) (L l newName) pos ies)
                <$> nameT
           else addFatalError $ mkPlainErrorMsgEnvelope (locA l) $
                  PsErrIllegalPatSynExport
diff --git a/compiler/GHC/Rename/Env.hs b/compiler/GHC/Rename/Env.hs
index ab70fe462c3f0fdfb93ff639891fde8384040e43..50ad92b792cea1c6f8b86a36e26f223389b20897 100644
--- a/compiler/GHC/Rename/Env.hs
+++ b/compiler/GHC/Rename/Env.hs
@@ -2,7 +2,7 @@
 {-# LANGUAGE GADTs            #-}
 {-# LANGUAGE MultiWayIf       #-}
 {-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE GADTs            #-}
+{-# LANGUAGE TupleSections    #-}
 
 {-
 (c) The GRASP/AQUA Project, Glasgow University, 1992-2006
@@ -79,7 +79,7 @@ import GHC.Parser.PostProcess ( setRdrNameSpace )
 import GHC.Builtin.Types
 import GHC.Types.Name
 import GHC.Types.Name.Set
-import GHC.Types.Name.Env ( lookupNameEnv )
+import GHC.Types.Name.Env
 import GHC.Types.Avail
 import GHC.Types.Hint
 import GHC.Types.Error
@@ -116,6 +116,7 @@ import Control.Monad
 import Data.Either      ( partitionEithers )
 import Data.Function    ( on )
 import Data.List        ( find, partition, groupBy, sortBy )
+import Data.Foldable    ( for_ )
 import qualified Data.List.NonEmpty as NE
 import qualified Data.Semigroup as Semi
 import System.IO.Unsafe ( unsafePerformIO )
@@ -408,7 +409,7 @@ lookupInstDeclBndr cls what rdr
                 -- to use a qualified name for the method
                 -- (Although it'd make perfect sense.)
        ; mb_name <- lookupSubBndrOcc
-                          DisableDeprecationWarnings
+                          NoDeprecationWarnings
                                 -- we don't give deprecated
                                 -- warnings when a deprecated class
                                 -- method is defined. We only warn
@@ -554,7 +555,7 @@ lookupRecFieldOcc mb_con rdr_name
                         , text "rdr_name:" <+> ppr rdr_name
                         , text "flds:" <+> ppr flds
                         , text "mb_gre:" <+> ppr mb_gre ]
-               ; mapM_ (addUsedGRE EnableDeprecationWarnings) mb_gre
+               ; mapM_ (addUsedGRE AllDeprecationWarnings) mb_gre
                ; return $ flSelector . fieldGRELabel <$> mb_gre }
        ; case mb_nm of
           { Nothing  -> do { addErr (badFieldConErr con lbl)
@@ -1415,7 +1416,7 @@ lookupFieldGREs env (L loc rdr)
 lookupGlobalOccRn_overloaded :: RdrName -> RnM (Maybe GlobalRdrElt)
 lookupGlobalOccRn_overloaded rdr_name =
   lookupExactOrOrig_maybe rdr_name id $
-    do { res <- lookupGreRn_helper (IncludeFields WantNormal) rdr_name EnableDeprecationWarnings
+    do { res <- lookupGreRn_helper (IncludeFields WantNormal) rdr_name AllDeprecationWarnings
        ; case res of
            GreNotFound        -> lookupOneQualifiedNameGHCi WantNormal rdr_name
            OneNameMatch gre   -> return $ Just gre
@@ -1635,7 +1636,7 @@ lookupGreRn_maybe :: WhichGREs GREInfo -> RdrName -> RnM (Maybe GlobalRdrElt)
 -- Uses addUsedRdrName to record use and deprecations
 lookupGreRn_maybe which_gres rdr_name
   = do
-      res <- lookupGreRn_helper which_gres rdr_name EnableDeprecationWarnings
+      res <- lookupGreRn_helper which_gres rdr_name AllDeprecationWarnings
       case res of
         OneNameMatch gre ->  return $ Just gre
         MultipleNames gres -> do
@@ -1688,7 +1689,7 @@ lookupGreAvailRn :: RdrName -> RnM (Maybe GlobalRdrElt)
 -- Uses addUsedRdrName to record use and deprecations
 lookupGreAvailRn rdr_name
   = do
-      mb_gre <- lookupGreRn_helper (IncludeFields WantNormal) rdr_name DisableDeprecationWarnings
+      mb_gre <- lookupGreRn_helper (IncludeFields WantNormal) rdr_name ExportDeprecationWarnings
       case mb_gre of
         GreNotFound ->
           do
@@ -1713,7 +1714,7 @@ lookupGreAvailRn rdr_name
 Note [Handling of deprecations]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * We report deprecations at each *occurrence* of the deprecated thing
-  (see #5867)
+  (see #5867 and #4879)
 
 * We do not report deprecations for locally-defined names. For a
   start, we may be exporting a deprecated thing. Also we may use a
@@ -1721,6 +1722,10 @@ Note [Handling of deprecations]
   even use a deprecated thing in the defn of a non-deprecated thing,
   when changing a module's interface.
 
+* We also report deprecations at export sites, but only for names
+  deprecated with export deprecations (since those are not transitive as opposed
+  to regular name deprecations and are only reported at the importing module)
+
 * addUsedGREs: we do not report deprecations for sub-binders:
      - the ".." completion for records
      - the ".." in an export item 'T(..)'
@@ -1730,39 +1735,43 @@ Note [Handling of deprecations]
 addUsedDataCons :: GlobalRdrEnv -> TyCon -> RnM ()
 -- Remember use of in-scope data constructors (#7969)
 addUsedDataCons rdr_env tycon
-  = addUsedGREs [ gre
-                | dc <- tyConDataCons tycon
-                , Just gre <- [lookupGRE_Name rdr_env (dataConName dc)] ]
+  = addUsedGREs NoDeprecationWarnings
+      [ gre
+      | dc <- tyConDataCons tycon
+      , Just gre <- [lookupGRE_Name rdr_env (dataConName dc)] ]
 
 -- | Whether to report deprecation warnings when registering a used GRE
+--
+-- There is no option to only emit declaration warnings since everywhere
+-- we emit the declaration warnings we also emit export warnings
+-- (See Note [Handling of deprecations] for details)
 data DeprecationWarnings
-  = DisableDeprecationWarnings
-  | EnableDeprecationWarnings
+  = NoDeprecationWarnings
+  | ExportDeprecationWarnings
+  | AllDeprecationWarnings
 
 addUsedGRE :: DeprecationWarnings -> GlobalRdrElt -> RnM ()
 -- Called for both local and imported things
 -- Add usage *and* warn if deprecated
 addUsedGRE warn_if_deprec gre
-  = do { case warn_if_deprec of
-           EnableDeprecationWarnings  -> warnIfDeprecated gre
-           DisableDeprecationWarnings -> return ()
+  = do { condWarnIfDeprecated warn_if_deprec [gre]
        ; when (isImportedGRE gre) $ -- See Note [Using isImportedGRE in addUsedGRE]
          do { env <- getGblEnv
              -- Do not report the GREInfo (#23424)
             ; traceRn "addUsedGRE" (ppr $ greName gre)
             ; updTcRef (tcg_used_gres env) (gre :) } }
 
-addUsedGREs :: [GlobalRdrElt] -> RnM ()
+addUsedGREs :: DeprecationWarnings -> [GlobalRdrElt] -> RnM ()
 -- Record uses of any *imported* GREs
 -- Used for recording used sub-bndrs
 -- NB: no call to warnIfDeprecated; see Note [Handling of deprecations]
-addUsedGREs gres
-  | null imp_gres = return ()
-  | otherwise     = do { env <- getGblEnv
-                        -- Do not report the GREInfo (#23424)
-                       ; traceRn "addUsedGREs"
-                             (ppr $ map greName imp_gres)
-                       ; updTcRef (tcg_used_gres env) (imp_gres ++) }
+addUsedGREs warn_if_deprec gres
+  = do { condWarnIfDeprecated warn_if_deprec gres
+       ; unless (null imp_gres) $
+         do { env <- getGblEnv
+              -- Do not report the GREInfo (#23424)
+            ; traceRn "addUsedGREs" (ppr $ map greName imp_gres)
+            ; updTcRef (tcg_used_gres env) (imp_gres ++) } }
   where
     imp_gres = filter isImportedGRE gres
     -- See Note [Using isImportedGRE in addUsedGRE]
@@ -1781,22 +1790,32 @@ in which case we have both gre_lcl = False and gre_imp = emptyBag.
 Geting this wrong can lead to panics in e.g. bestImport, see #23240.
 -}
 
-warnIfDeprecated :: GlobalRdrElt -> RnM ()
-warnIfDeprecated gre@(GRE { gre_imp = iss })
+condWarnIfDeprecated :: DeprecationWarnings -> [GlobalRdrElt] -> RnM ()
+condWarnIfDeprecated NoDeprecationWarnings _ = return ()
+condWarnIfDeprecated opt gres = do
+  this_mod <- getModule
+  let external_gres
+        = filterOut (nameIsLocalOrFrom this_mod . greName) gres
+  mapM_ (\gre -> warnIfExportDeprecated gre >> maybeWarnDeclDepr gre) external_gres
+  where
+    maybeWarnDeclDepr = case opt of
+      ExportDeprecationWarnings -> const $ return ()
+      AllDeprecationWarnings    -> warnIfDeclDeprecated
+
+warnIfDeclDeprecated :: GlobalRdrElt -> RnM ()
+warnIfDeclDeprecated gre@(GRE { gre_imp = iss })
   | Just imp_spec <- headMaybe iss
   = do { dflags <- getDynFlags
-       ; this_mod <- getModule
-       ; when (wopt_any_custom dflags &&
-               not (nameIsLocalOrFrom this_mod name)) $
+       ; when (wopt_any_custom dflags) $
                    -- See Note [Handling of deprecations]
          do { iface <- loadInterfaceForName doc name
-            ; case lookupImpDeprec iface gre of
+            ; case lookupImpDeclDeprec iface gre of
                 Just deprText -> addDiagnostic $
                   TcRnPragmaWarning {
                     pragma_warning_occ = occ,
                     pragma_warning_msg = deprText,
                     pragma_warning_import_mod = importSpecModule imp_spec,
-                    pragma_warning_defined_mod = definedMod
+                    pragma_warning_defined_mod = Just definedMod
                   }
                 Nothing  -> return () } }
   | otherwise
@@ -1807,13 +1826,35 @@ warnIfDeprecated gre@(GRE { gre_imp = iss })
     definedMod = moduleName $ assertPpr (isExternalName name) (ppr name) (nameModule name)
     doc = text "The name" <+> quotes (ppr occ) <+> text "is mentioned explicitly"
 
-lookupImpDeprec :: ModIface -> GlobalRdrElt -> Maybe (WarningTxt GhcRn)
-lookupImpDeprec iface gre
-  = mi_warn_fn (mi_final_exts iface) (greOccName gre) `mplus`  -- Bleat if the thing,
+lookupImpDeclDeprec :: ModIface -> GlobalRdrElt -> Maybe (WarningTxt GhcRn)
+lookupImpDeclDeprec iface gre
+  = mi_decl_warn_fn (mi_final_exts iface) (greOccName gre) `mplus`  -- Bleat if the thing,
     case gre_par gre of                      -- or its parent, is warn'd
-       ParentIs  p              -> mi_warn_fn (mi_final_exts iface) (nameOccName p)
+       ParentIs  p              -> mi_decl_warn_fn (mi_final_exts iface) (nameOccName p)
        NoParent                 -> Nothing
 
+warnIfExportDeprecated :: GlobalRdrElt -> RnM ()
+warnIfExportDeprecated gre@(GRE { gre_imp = iss })
+  = do { mod_warn_mbs <- mapBagM process_import_spec iss
+       ; for_ (sequence mod_warn_mbs) $ mapM
+           $ \(importing_mod, warn_txt) -> addDiagnostic $
+             TcRnPragmaWarning {
+               pragma_warning_occ = occ,
+               pragma_warning_msg = warn_txt,
+               pragma_warning_import_mod = importing_mod,
+               pragma_warning_defined_mod = Nothing
+             } }
+  where
+    occ = greOccName gre
+    name = greName gre
+    doc = text "The name" <+> quotes (ppr occ) <+> text "is mentioned explicitly"
+    process_import_spec :: ImportSpec -> RnM (Maybe (ModuleName, WarningTxt GhcRn))
+    process_import_spec is = do
+      let mod = is_mod $ is_decl is
+      iface <- loadInterfaceForModule doc mod
+      let mb_warn_txt = mi_export_warn_fn (mi_final_exts iface) name
+      return $ (moduleName mod, ) <$> mb_warn_txt
+
 {-
 Note [Used names with interface not loaded]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1902,12 +1943,12 @@ lookupQualifiedNameGHCi fos rdr_name
 
   where
     go_for_it dflags is_ghci
-      | Just (mod,occ) <- isQual_maybe rdr_name
+      | Just (mod_name,occ) <- isQual_maybe rdr_name
       , let ns = occNameSpace occ
       , is_ghci
       , gopt Opt_ImplicitImportQualified dflags   -- Enables this GHCi behaviour
       , not (safeDirectImpsReq dflags)            -- See Note [Safe Haskell and GHCi]
-      = do { res <- loadSrcInterface_maybe doc mod NotBoot NoPkgQual
+      = do { res <- loadSrcInterface_maybe doc mod_name NotBoot NoPkgQual
            ; case res of
                 Succeeded iface
                   -> do { hsc_env <- getTopEnv
@@ -1919,7 +1960,8 @@ lookupQualifiedNameGHCi fos rdr_name
                                       lk_ns  = occNameSpace lk_occ
                                 , occNameFS occ == occNameFS lk_occ
                                 , ns == lk_ns || (ns == varName && isFieldNameSpace lk_ns)
-                                , let gre = lookupGRE_PTE mod hsc_env gname
+                                , let mod = mi_module iface
+                                      gre = lookupGRE_PTE mod hsc_env gname
                                 , allowGRE fos gre
                                   -- Include a field if it has a selector or we are looking for all fields;
                                   -- see Note [NoFieldSelectors].
@@ -1939,7 +1981,7 @@ lookupQualifiedNameGHCi fos rdr_name
 
     -- Lookup a Name for an implicit qualified import in GHCi
     -- in the given PackageTypeEnv.
-    lookupGRE_PTE :: ModuleName -> HscEnv -> Name -> GlobalRdrElt
+    lookupGRE_PTE :: Module -> HscEnv -> Name -> GlobalRdrElt
     lookupGRE_PTE mod hsc_env nm =
       -- Fake a GRE so we can report a sensible name clash error if
       -- -fimplicit-import-qualified is used with a module that exports the same
@@ -1952,7 +1994,7 @@ lookupQualifiedNameGHCi fos rdr_name
           , gre_info = info }
         where
           info = lookupGREInfo hsc_env nm
-          spec = ImpDeclSpec { is_mod = mod, is_as = mod, is_qual = True, is_dloc = noSrcSpan }
+          spec = ImpDeclSpec { is_mod = mod, is_as = moduleName mod, is_qual = True, is_dloc = noSrcSpan }
           is = ImpSpec { is_decl = spec, is_item = ImpAll }
 
 -- | Look up the 'GREInfo' associated with the given 'Name'
@@ -2098,7 +2140,7 @@ lookupBindGroupOcc ctxt what rdr_name
                           else lookup_top (`elemNameSet` ns)
   where
     lookup_cls_op cls
-      = lookupSubBndrOcc EnableDeprecationWarnings cls doc rdr_name
+      = lookupSubBndrOcc AllDeprecationWarnings cls doc rdr_name
       where
         doc = text "method of class" <+> quotes (ppr cls)
 
diff --git a/compiler/GHC/Rename/Module.hs b/compiler/GHC/Rename/Module.hs
index d7a5fa483324100ade6e5c214b47b4237168b3e0..ebc9f4720c26ea5d434115a8699fa2282c5d00b2 100644
--- a/compiler/GHC/Rename/Module.hs
+++ b/compiler/GHC/Rename/Module.hs
@@ -194,7 +194,7 @@ rnSrcDecls group@(HsGroup { hs_valds   = val_decls,
    -- Rename deprec decls;
    -- check for duplicates and ensure that deprecated things are defined locally
    -- at the moment, we don't keep these around past renaming
-   rn_warns <- rnSrcWarnDecls all_bndrs warn_decls ;
+   rn_decl_warns <- rnSrcWarnDecls all_bndrs warn_decls ;
 
    -- (H) Rename Everything else
 
@@ -236,7 +236,7 @@ rnSrcDecls group@(HsGroup { hs_valds   = val_decls,
 
         final_tcg_env = let tcg_env' = (last_tcg_env `addTcgDUs` src_dus)
                         in -- we return the deprecs in the env, not in the HsGroup above
-                        tcg_env' { tcg_warns = tcg_warns tcg_env' `plusWarns` rn_warns };
+                        tcg_env' { tcg_warns = insertWarnDecls (tcg_warns tcg_env') rn_decl_warns };
        } ;
    traceRn "finish rnSrc" (ppr rn_group) ;
    traceRn "finish Dus" (ppr src_dus ) ;
@@ -266,9 +266,9 @@ gather them together.
 -}
 
 -- checks that the deprecations are defined locally, and that there are no duplicates
-rnSrcWarnDecls :: NameSet -> [LWarnDecls GhcPs] -> RnM (Warnings GhcRn)
+rnSrcWarnDecls :: NameSet -> [LWarnDecls GhcPs] -> RnM (DeclWarnOccNames GhcRn)
 rnSrcWarnDecls _ []
-  = return NoWarnings
+  = return []
 
 rnSrcWarnDecls bndr_set decls'
   = do { -- check for duplicates
@@ -276,7 +276,7 @@ rnSrcWarnDecls bndr_set decls'
                           in addErrAt (locA loc) (TcRnDuplicateWarningDecls lrdr' rdr))
                warn_rdr_dups
        ; pairs_s <- mapM (addLocMA rn_deprec) decls
-       ; return (WarnSome ((concat pairs_s))) }
+       ; return $ concat pairs_s }
  where
    decls = concatMap (wd_warnings . unLoc) decls'
 
diff --git a/compiler/GHC/Rename/Names.hs b/compiler/GHC/Rename/Names.hs
index 79df35d19e80d4357b6314c9940299fd69bb7ffe..503700d8d87875423c77faa6beac7006eb8e6fa8 100644
--- a/compiler/GHC/Rename/Names.hs
+++ b/compiler/GHC/Rename/Names.hs
@@ -387,9 +387,9 @@ rnImportDecl this_mod
     when (mod_safe && not (safeImportsOn dflags)) $
         addErr (TcRnSafeImportsDisabled imp_mod_name)
 
-    let
+    let imp_mod = mi_module iface
         qual_mod_name = fmap unLoc as_mod `orElse` imp_mod_name
-        imp_spec  = ImpDeclSpec { is_mod = imp_mod_name, is_qual = qual_only,
+        imp_spec  = ImpDeclSpec { is_mod = imp_mod, is_qual = qual_only,
                                   is_dloc = locA loc, is_as = qual_mod_name }
 
     -- filter the imports according to the import declaration
@@ -621,7 +621,6 @@ warnUnqualifiedImport decl iface =
     -- Modules for which we warn if we see unqualified imports
     qualifiedMods = mkModuleSet [ dATA_LIST ]
 
-
 {-
 ************************************************************************
 *                                                                      *
@@ -1193,6 +1192,7 @@ filterImports hsc_env iface decl_spec (Just (want_hiding, L l import_items))
 
         return (Just (want_hiding, L l (map fst items2)), gres)
   where
+    import_mod = mi_module iface
     all_avails = mi_exports iface
     hiding_spec = ImpSpec { is_decl = decl_spec, is_item = ImpAll }
     imp_occ_env = mkImportOccEnv hsc_env decl_spec all_avails
@@ -1254,6 +1254,13 @@ filterImports hsc_env iface decl_spec (Just (want_hiding, L l import_items))
               -- 'badImportItemErr'.
               reason <- badImportItemErr iface decl_spec ie BadImportIsParent all_avails
               pure (TcRnDodgyImports (DodgyImportsHiding reason))
+            warning_msg (DeprecatedExport n w) =
+              pure (TcRnPragmaWarning {
+                      pragma_warning_occ = occName n
+                    , pragma_warning_msg = w
+                    , pragma_warning_import_mod = moduleName import_mod
+                    , pragma_warning_defined_mod = Nothing
+                    })
 
             run_lookup :: IELookupM a -> TcRn (Maybe a)
             run_lookup m = case m of
@@ -1283,15 +1290,20 @@ filterImports hsc_env iface decl_spec (Just (want_hiding, L l import_items))
         IEVar _ (L l n) -> do
             -- See Note [Importing DuplicateRecordFields]
             xs <- lookup_names ie (ieWrappedName n)
-            return ( [ (IEVar noExtField (L l (replaceWrappedName n name)), [gre])
-                     | ImpOccItem { imp_item = gre } <- NE.toList xs
+            let gres = map imp_item $ NE.toList xs
+                export_depr_warns
+                  | want_hiding == Exactly
+                      = mapMaybe mk_depr_export_warning gres
+                  | otherwise = []
+            return ( [ (IEVar Nothing (L l (replaceWrappedName n name)), [gre])
+                     | gre <- gres
                      , let name = greName gre ]
-                   , [] )
+                   , export_depr_warns )
 
         IEThingAll _ (L l tc) -> do
             ImpOccItem gre child_gres _ <- lookup_parent ie $ ieWrappedName tc
             let name = greName gre
-                warns
+                imp_list_warn
 
                   | null child_gres
                   -- e.g. f(..) or T(..) where T is a type synonym
@@ -1304,9 +1316,17 @@ filterImports hsc_env iface decl_spec (Just (want_hiding, L l import_items))
                   | otherwise
                   = []
 
-                renamed_ie = IEThingAll noAnn (L l (replaceWrappedName tc name))
+                renamed_ie = IEThingAll (Nothing, noAnn) (L l (replaceWrappedName tc name))
+                export_depr_warn
+                  | want_hiding == Exactly
+                      = maybeToList $ mk_depr_export_warning gre
+                        -- We don't want to warn about the children as they
+                        -- are not explicitly mentioned; the warning will
+                        -- be emitted later on if they are used
+                  | otherwise = []
 
-            return ([(renamed_ie, gre:child_gres)], warns)
+            return ( [(renamed_ie, gre:child_gres)]
+                   , imp_list_warn ++ export_depr_warn)
 
 
         IEThingAbs _ (L l tc')
@@ -1319,33 +1339,38 @@ filterImports hsc_env iface decl_spec (Just (want_hiding, L l import_items))
                in
                case catIELookupM [ tc_name, dc_name ] of
                  []    -> failLookupWith (BadImport ie BadImportIsParent)
-                 names -> return ([mkIEThingAbs tc' l (imp_item name) | name <- names], [])
+                 names -> return ( [mkIEThingAbs tc' l (imp_item name) | name <- names], [])
             | otherwise
             -> do ImpOccItem { imp_item = gre } <- lookup_parent ie (ieWrappedName tc')
-                  return ([mkIEThingAbs tc' l gre], [])
+                  return ( [mkIEThingAbs tc' l gre]
+                         , maybeToList $ mk_depr_export_warning gre)
 
-        IEThingWith xt ltc@(L l rdr_tc) wc rdr_ns -> do
+        IEThingWith (deprecation, ann) ltc@(L l rdr_tc) wc rdr_ns -> do
            ImpOccItem { imp_item = gre, imp_bundled = subnames }
-               <- lookup_parent (IEThingAbs noAnn ltc) (ieWrappedName rdr_tc)
+               <- lookup_parent (IEThingAbs (Nothing, noAnn) ltc) (ieWrappedName rdr_tc)
            let name = greName gre
 
            -- Look up the children in the sub-names of the parent
            -- See Note [Importing DuplicateRecordFields]
            case lookupChildren subnames rdr_ns of
 
-             Failed rdrs -> failLookupWith (BadImport (IEThingWith xt ltc wc rdrs) BadImportIsSubordinate)
+             Failed rdrs -> failLookupWith (BadImport (IEThingWith (deprecation, ann) ltc wc rdrs ) BadImportIsSubordinate)
                                 -- We are trying to import T( a,b,c,d ), and failed
                                 -- to find 'b' and 'd'.  So we make up an import item
                                 -- to report as failing, namely T( b, d ).
                                 -- c.f. #15412
 
              Succeeded childnames ->
-                return ([ (IEThingWith xt (L l name') wc childnames'
-                          ,gre : map unLoc childnames)]
-                       , [])
+                return ([ (IEThingWith (Nothing, ann) (L l name') wc childnames'
+                          ,gres)]
+                       , export_depr_warns)
 
               where name' = replaceWrappedName rdr_tc name
                     childnames' = map (to_ie_post_rn . fmap greName) childnames
+                    gres = gre : map unLoc childnames
+                    export_depr_warns
+                      | want_hiding == Exactly = mapMaybe mk_depr_export_warning gres
+                      | otherwise              = []
 
         _other -> failLookupWith IllegalImport
         -- could be IEModuleContents, IEGroup, IEDoc, IEDocNamed...
@@ -1353,19 +1378,25 @@ filterImports hsc_env iface decl_spec (Just (want_hiding, L l import_items))
 
       where
         mkIEThingAbs tc l gre
-          = (IEThingAbs noAnn (L l (replaceWrappedName tc n)), [gre])
+          = (IEThingAbs (Nothing, noAnn) (L l (replaceWrappedName tc n)), [gre])
           where n = greName gre
 
         handle_bad_import m = catchIELookup m $ \err -> case err of
           BadImport ie _ | want_hiding == EverythingBut -> return ([], [BadImportW ie])
           _ -> failLookupWith err
 
+        mk_depr_export_warning gre
+          = DeprecatedExport name <$> mi_export_warn_fn (mi_final_exts iface) name
+          where
+            name = greName gre
+
 type IELookupM = MaybeErr IELookupError
 
 data IELookupWarning
   = BadImportW (IE GhcPs)
   | MissingImportList
   | DodgyImport GlobalRdrElt
+  | DeprecatedExport Name (WarningTxt GhcRn)
 
 data BadImportIsSubordinate = BadImportIsParent | BadImportIsSubordinate
 
@@ -1947,10 +1978,10 @@ getMinimalImports ie_decls
     to_ie rdr_env _ (Avail c)  -- Note [Overloaded field import]
       = do { let
                gre = expectJust "getMinimalImports Avail" $ lookupGRE_Name rdr_env c
-           ; return $ [IEVar noExtField (to_ie_post_rn $ noLocA $ greName gre)] }
+           ; return $ [IEVar Nothing (to_ie_post_rn $ noLocA $ greName gre)] }
     to_ie _ _ avail@(AvailTC n [_])  -- Exporting the main decl and nothing else
       | availExportsDecl avail
-      = return [IEThingAbs noAnn (to_ie_post_rn $ noLocA n)]
+      = return [IEThingAbs (Nothing, noAnn) (to_ie_post_rn $ noLocA n)]
     to_ie rdr_env iface (AvailTC n cs) =
       case [ xs | avail@(AvailTC x xs) <- mi_exports iface
            , x == n
@@ -1958,11 +1989,11 @@ getMinimalImports ie_decls
            ] of
         [xs]
           | all_used xs
-          -> return [IEThingAll noAnn (to_ie_post_rn $ noLocA n)]
+          -> return [IEThingAll (Nothing, noAnn) (to_ie_post_rn $ noLocA n)]
           | otherwise
           -> do { let ns_gres = map (expectJust "getMinimalImports AvailTC" . lookupGRE_Name rdr_env) cs
                       ns = map greName ns_gres
-                ; return [IEThingWith noAnn (to_ie_post_rn $ noLocA n) NoIEWildcard
+                ; return [IEThingWith (Nothing, noAnn) (to_ie_post_rn $ noLocA n) NoIEWildcard
                                  (map (to_ie_post_rn . noLocA) (filter (/= n) ns))] }
                                        -- Note [Overloaded field import]
         _other
@@ -1972,8 +2003,8 @@ getMinimalImports ie_decls
                       fs = map fieldGREInfo fs_gres
                 ; return $
                   if all_non_overloaded fs
-                  then map (IEVar noExtField . to_ie_post_rn_var . noLocA) ns
-                  else [IEThingWith noAnn (to_ie_post_rn $ noLocA n) NoIEWildcard
+                  then map (IEVar Nothing . to_ie_post_rn_var . noLocA) ns
+                  else [IEThingWith (Nothing, noAnn) (to_ie_post_rn $ noLocA n) NoIEWildcard
                          (map (to_ie_post_rn . noLocA) (filter (/= n) ns))] }
         where
 
diff --git a/compiler/GHC/Rename/Pat.hs b/compiler/GHC/Rename/Pat.hs
index 7ee4b09a851cb5920b882a8811d8f89f33712e17..312629c0fad457fcd65b24367693f304761fa171 100644
--- a/compiler/GHC/Rename/Pat.hs
+++ b/compiler/GHC/Rename/Pat.hs
@@ -830,7 +830,7 @@ rnHsRecFields ctxt mk_arg (HsRecFields { rec_flds = flds, rec_dotdot = dotdot })
                              HsRecFieldCon {} -> arg_in_scope lbl
                              _other           -> True ]
 
-           ; addUsedGREs dot_dot_gres
+           ; addUsedGREs NoDeprecationWarnings dot_dot_gres
            ; let locn = noAnnSrcSpan loc
            ; return [ L (noAnnSrcSpan loc) (HsFieldBind
                         { hfbAnn = noAnn
diff --git a/compiler/GHC/Runtime/Loader.hs b/compiler/GHC/Runtime/Loader.hs
index 3137195864f3b49dda8258b00017ec114d3313e3..e7fd7a9022d954a4bf05575a2bc665e878a45e0b 100644
--- a/compiler/GHC/Runtime/Loader.hs
+++ b/compiler/GHC/Runtime/Loader.hs
@@ -357,7 +357,7 @@ lookupRdrNameInModuleForPlugins hsc_env mod_name rdr_name = do
             case mb_iface of
                 Just iface -> do
                     -- Try and find the required name in the exports
-                    let decl_spec = ImpDeclSpec { is_mod = mod_name, is_as = mod_name
+                    let decl_spec = ImpDeclSpec { is_mod = mod, is_as = mod_name
                                                 , is_qual = False, is_dloc = noSrcSpan }
                         imp_spec = ImpSpec decl_spec ImpAll
                         env = mkGlobalRdrEnv
diff --git a/compiler/GHC/Tc/Errors/Ppr.hs b/compiler/GHC/Tc/Errors/Ppr.hs
index 5d452803eb7a0fbfed6fcbd7e90357875ad93730..4de575bbfd0f0397c280b8e033371bdce0016626 100644
--- a/compiler/GHC/Tc/Errors/Ppr.hs
+++ b/compiler/GHC/Tc/Errors/Ppr.hs
@@ -1095,8 +1095,14 @@ instance Diagnostic TcRnMessage where
           , pprWarningTxtForMsg pragma_warning_msg ]
           where
             impMsg  = text "imported from" <+> ppr pragma_warning_import_mod <> extra
-            extra | pragma_warning_import_mod == pragma_warning_defined_mod = empty
+            extra | maybe True (pragma_warning_import_mod ==) pragma_warning_defined_mod = empty
                   | otherwise = text ", but defined in" <+> ppr pragma_warning_defined_mod
+    TcRnDifferentExportWarnings name locs
+      -> mkSimpleDecorated $ vcat [quotes (ppr name) <+> text "exported with different error messages",
+                                   text "at" <+> vcat (map ppr $ sortBy leftmost_smallest $ NE.toList locs)]
+    TcRnIncompleteExportWarnings name locs
+      -> mkSimpleDecorated $ vcat [quotes (ppr name) <+> text "will not have its export warned about",
+                                   text "missing export warning at" <+> vcat (map ppr $ sortBy leftmost_smallest $ NE.toList locs)]
     TcRnIllegalHsigDefaultMethods name meths
       -> mkSimpleDecorated $
         text "Illegal default method" <> plural (NE.toList meths) <+> text "in class definition of" <+> ppr name <+> text "in hsig file"
@@ -2180,6 +2186,10 @@ instance Diagnostic TcRnMessage where
       -> WarningWithoutFlag
     TcRnPragmaWarning{pragma_warning_msg}
       -> WarningWithCategory (warningTxtCategory pragma_warning_msg)
+    TcRnDifferentExportWarnings _ _
+      -> ErrorWithoutFlag
+    TcRnIncompleteExportWarnings _ _
+      -> WarningWithFlag Opt_WarnIncompleteExportWarnings
     TcRnIllegalHsigDefaultMethods{}
       -> ErrorWithoutFlag
     TcRnHsigFixityMismatch{}
@@ -2818,6 +2828,10 @@ instance Diagnostic TcRnMessage where
       -> [SuggestSpecialiseVisibilityHints name]
     TcRnPragmaWarning{}
       -> noHints
+    TcRnDifferentExportWarnings _ _
+      -> noHints
+    TcRnIncompleteExportWarnings _ _
+      -> noHints
     TcRnIllegalHsigDefaultMethods{}
       -> noHints
     TcRnIllegalQuasiQuotes{}
@@ -3074,13 +3088,13 @@ instance Diagnostic TcRnMessage where
     TcRnRedundantSourceImport{}
       -> noHints
     TcRnImportLookup (ImportLookupBad k _ is ie patsyns_enabled) ->
-      let mod = is_mod is
+      let mod_name = moduleName $ is_mod is
           occ = rdrNameOcc $ ieName ie
       in case k of
-        BadImportAvailVar         -> [ImportSuggestion occ $ CouldRemoveTypeKeyword mod]
+        BadImportAvailVar         -> [ImportSuggestion occ $ CouldRemoveTypeKeyword mod_name]
         BadImportNotExported      -> noHints
-        BadImportAvailTyCon       -> [ImportSuggestion occ $ CouldAddTypeKeyword (is_mod is)]
-        BadImportAvailDataCon par -> [ImportSuggestion occ $ ImportDataCon (Just (is_mod is, patsyns_enabled)) par]
+        BadImportAvailTyCon       -> [ImportSuggestion occ $ CouldAddTypeKeyword mod_name]
+        BadImportAvailDataCon par -> [ImportSuggestion occ $ ImportDataCon (Just (mod_name, patsyns_enabled)) par]
         BadImportNotExportedSubordinates{} -> noHints
     TcRnImportLookup{}
       -> noHints
@@ -3272,7 +3286,7 @@ dodgy_msg kind tc ie
              , text "but it is not a type constructor or a class" ]
 
 dodgy_msg_insert :: GlobalRdrElt -> IE GhcRn
-dodgy_msg_insert tc_gre = IEThingAll noAnn ii
+dodgy_msg_insert tc_gre = IEThingAll (Nothing, noAnn) ii
   where
     ii = noLocA (IEName noExtField $ noLocA $ greName tc_gre)
 
@@ -5322,7 +5336,7 @@ pprImportLookup = \case
     let
       pprImpDeclSpec :: ModIface -> ImpDeclSpec -> SDoc
       pprImpDeclSpec iface decl_spec =
-        quotes (ppr (is_mod decl_spec)) <+> case mi_boot iface of
+        quotes (ppr (moduleName $ is_mod decl_spec)) <+> case mi_boot iface of
             IsBoot  -> text "(hi-boot interface)"
             NotBoot -> empty
       withContext msgs =
diff --git a/compiler/GHC/Tc/Errors/Types.hs b/compiler/GHC/Tc/Errors/Types.hs
index cd94a3fed4b0130f1c773659d42ccc03e5f1cbdd..f3dc1d10f3d5d717fd65bbca9a9cbb76fcd1488b 100644
--- a/compiler/GHC/Tc/Errors/Types.hs
+++ b/compiler/GHC/Tc/Errors/Types.hs
@@ -2528,9 +2528,31 @@ data TcRnMessage where
     pragma_warning_occ :: OccName,
     pragma_warning_msg :: WarningTxt GhcRn,
     pragma_warning_import_mod :: ModuleName,
-    pragma_warning_defined_mod :: ModuleName
+    pragma_warning_defined_mod :: Maybe ModuleName
   } -> TcRnMessage
 
+  {-| TcRnDifferentExportWarnings is an error that occurs when the
+     warning messages for exports of a name differ between several export items.
+
+     Test case:
+      DifferentExportWarnings
+  -}
+  TcRnDifferentExportWarnings :: !Name -- ^ The name with different export warnings
+                              -> NE.NonEmpty SrcSpan -- ^ The locations of export list items that differ
+                                            --   from the one at which the error is reported
+                              -> TcRnMessage
+
+  {-| TcRnIncompleteExportWarnings is a warning (controlled by -Wincomplete-export-warnings) that
+     occurs when some of the exports of a name do not have an export warning and some do
+
+     Test case:
+      ExportWarnings6
+  -}
+  TcRnIncompleteExportWarnings :: !Name -- ^ The name that is exported
+                               -> NE.NonEmpty SrcSpan -- ^ The locations of export list items that are
+                                             --   missing the export warning
+                               -> TcRnMessage
+
   {-| TcRnIllegalHsigDefaultMethods is an error that occurs when a binding for
      a class default method is provided in a Backpack signature file.
 
diff --git a/compiler/GHC/Tc/Gen/Export.hs b/compiler/GHC/Tc/Gen/Export.hs
index 640104256e731d5ec1984b2bc0462e69674f8d28..8ace4e0aa7bb2385d17c0b0fd4313933c7742d04 100644
--- a/compiler/GHC/Tc/Gen/Export.hs
+++ b/compiler/GHC/Tc/Gen/Export.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RankNTypes        #-}
 {-# LANGUAGE TypeFamilies      #-}
+{-# LANGUAGE TupleSections     #-}
 
 module GHC.Tc.Gen.Export (rnExports, exports_from_avail, classifyGREs) where
 
@@ -15,12 +16,14 @@ import GHC.Tc.Utils.Env
     ( TyThing(AConLike, AnId), tcLookupGlobal, tcLookupTyCon )
 import GHC.Tc.Utils.TcType
 import GHC.Rename.Doc
+import GHC.Rename.Module
 import GHC.Rename.Names
 import GHC.Rename.Env
 import GHC.Rename.Unbound ( reportUnboundName )
 import GHC.Utils.Error
 import GHC.Unit.Module
 import GHC.Unit.Module.Imported
+import GHC.Unit.Module.Warnings
 import GHC.Core.TyCon
 import GHC.Utils.Outputable
 import GHC.Utils.Panic
@@ -33,7 +36,7 @@ import GHC.Driver.DynFlags
 import GHC.Parser.PostProcess ( setRdrNameSpace )
 import qualified GHC.LanguageExtensions as LangExt
 
-import GHC.Types.Unique.Set
+import GHC.Types.Unique.Map
 import GHC.Types.SrcLoc as SrcLoc
 import GHC.Types.Name
 import GHC.Types.Name.Env
@@ -48,6 +51,7 @@ import Control.Arrow ( first )
 import Control.Monad ( when )
 import qualified Data.List.NonEmpty as NE
 import Data.Traversable   ( for )
+import Data.List ( sortBy )
 
 {-
 ************************************************************************
@@ -133,22 +137,34 @@ into @[C{C, T;}, T{T, D;}]@ (which satisfies the AvailTC invariant).
 
 data ExportAccum        -- The type of the accumulating parameter of
                         -- the main worker function in rnExports
-     = ExportAccum
-        ExportOccMap           --  Tracks exported occurrence names
-        (UniqSet ModuleName)   --  Tracks (re-)exported module names
+     = ExportAccum {
+         expacc_exp_occs :: ExportOccMap,
+           -- ^ Tracks exported occurrence names
+         expacc_mods :: UniqMap ModuleName [Name],
+           -- ^ Tracks (re-)exported module names
+           --   and the names they re-export
+         expacc_warn_spans :: ExportWarnSpanNames,
+           -- ^ Information about warnings for names
+         expacc_dont_warn :: DontWarnExportNames
+           -- ^ What names not to export warnings for
+           --   (because they are exported without a warning)
+     }
+
 
 emptyExportAccum :: ExportAccum
-emptyExportAccum = ExportAccum emptyOccEnv emptyUniqSet
+emptyExportAccum = ExportAccum emptyOccEnv emptyUniqMap [] emptyNameEnv
 
-accumExports :: (ExportAccum -> x -> TcRn (Maybe (ExportAccum, y)))
+accumExports :: (ExportAccum -> x -> TcRn (ExportAccum, Maybe y))
              -> [x]
-             -> TcRn [y]
-accumExports f = fmap (catMaybes . snd) . mapAccumLM f' emptyExportAccum
-  where f' acc x = do
-          m <- attemptM (f acc x)
-          pure $ case m of
-            Just (Just (acc', y)) -> (acc', Just y)
-            _                     -> (acc, Nothing)
+             -> TcRn ([y], ExportWarnSpanNames, DontWarnExportNames)
+accumExports f xs = do
+  (ExportAccum _ _ export_warn_spans dont_warn_export, ys)
+    <- mapAccumLM f' emptyExportAccum xs
+  return ( catMaybes ys
+         , export_warn_spans
+         , dont_warn_export )
+  where f' acc x
+          = fromMaybe (acc, Nothing) <$> attemptM (f acc x)
 
 type ExportOccMap = OccEnv (Name, IE GhcPs)
         -- Tracks what a particular exported OccName
@@ -173,6 +189,7 @@ rnExports explicit_mod exports
               TcGblEnv { tcg_mod     = this_mod
                        , tcg_rdr_env = rdr_env
                        , tcg_imports = imports
+                       , tcg_warns   = warns
                        , tcg_src     = hsc_src } = tcg_env
               default_main | mainModIs (hsc_HUE hsc_env) == this_mod
                            , Just main_fun <- mainFunIs dflags
@@ -188,7 +205,7 @@ rnExports explicit_mod exports
         ; let real_exports
                  | explicit_mod = exports
                  | has_main
-                          = Just (noLocA [noLocA (IEVar noExtField
+                          = Just (noLocA [noLocA (IEVar Nothing
                                      (noLocA (IEName noExtField $ noLocA default_main)))])
                         -- ToDo: the 'noLoc' here is unhelpful if 'main'
                         --       turns out to be out of scope
@@ -196,7 +213,7 @@ rnExports explicit_mod exports
 
         -- Rename the export list
         ; let do_it = exports_from_avail real_exports rdr_env imports this_mod
-        ; (rn_exports, final_avails)
+        ; (rn_exports, final_avails, new_export_warns)
             <- if hsc_src == HsigFile
                 then do (mb_r, msgs) <- tryTc do_it
                         case mb_r of
@@ -214,7 +231,17 @@ rnExports explicit_mod exports
                                                 Nothing -> Nothing
                                                 Just _  -> rn_exports
                           , tcg_dus = tcg_dus tcg_env `plusDU`
-                                      usesOnly final_ns }) }
+                                      usesOnly final_ns
+                          , tcg_warns = insertWarnExports
+                                        warns new_export_warns}) }
+
+-- | List of names and the information about their warnings
+--   (warning, export list item span)
+type ExportWarnSpanNames = [(Name, WarningTxt GhcRn, SrcSpan)]
+
+-- | Map from names that should not have export warnings to
+--   the spans of export list items that are missing those warnings
+type DontWarnExportNames = NameEnv (NE.NonEmpty SrcSpan)
 
 exports_from_avail :: Maybe (LocatedL [LIE GhcPs])
                          -- ^ 'Nothing' means no explicit export list
@@ -224,8 +251,8 @@ exports_from_avail :: Maybe (LocatedL [LIE GhcPs])
                          -- @module Foo@ export is valid (it's not valid
                          -- if we didn't import @Foo@!)
                    -> Module
-                   -> RnM (Maybe [(LIE GhcRn, Avails)], Avails)
-                         -- (Nothing, _) <=> no explicit export list
+                   -> RnM (Maybe [(LIE GhcRn, Avails)], Avails, ExportWarnNames GhcRn)
+                         -- (Nothing, _, _) <=> no explicit export list
                          -- if explicit export list is present it contains
                          -- each renamed export item together with its exported
                          -- names.
@@ -240,7 +267,7 @@ exports_from_avail Nothing rdr_env _imports _this_mod
     ; let avails =
             map fix_faminst . gresToAvailInfo
               . filter isLocalGRE . globalRdrEnvElts $ rdr_env
-    ; return (Nothing, avails) }
+    ; return (Nothing, avails, []) }
   where
     -- #11164: when we define a data instance
     -- but not data family, re-export the family
@@ -256,12 +283,14 @@ exports_from_avail Nothing rdr_env _imports _this_mod
 
 
 exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
-  = do ie_avails <- accumExports do_litem rdr_items
+  = do (ie_avails, export_warn_spans, dont_warn_export)
+         <- accumExports do_litem rdr_items
        let final_exports = nubAvails (concatMap snd ie_avails) -- Combine families
-       return (Just ie_avails, final_exports)
+       export_warn_names <- aggregate_warnings export_warn_spans dont_warn_export
+       return (Just ie_avails, final_exports, export_warn_names)
   where
     do_litem :: ExportAccum -> LIE GhcPs
-             -> RnM (Maybe (ExportAccum, (LIE GhcRn, Avails)))
+             -> RnM (ExportAccum, Maybe (LIE GhcRn, Avails))
     do_litem acc lie = setSrcSpan (getLocA lie) (exports_from_item acc lie)
 
     -- Maps a parent to its in-scope children
@@ -282,30 +311,45 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
                        , imv <- importedByUser xs ]
 
     exports_from_item :: ExportAccum -> LIE GhcPs
-                      -> RnM (Maybe (ExportAccum, (LIE GhcRn, Avails)))
-    exports_from_item (ExportAccum occs earlier_mods)
-                      (L loc ie@(IEModuleContents _ lmod@(L _ mod)))
-      | mod `elementOfUniqSet` earlier_mods    -- Duplicate export of M
+                      -> RnM (ExportAccum, Maybe (LIE GhcRn, Avails))
+    exports_from_item expacc@ExportAccum{
+                        expacc_exp_occs   = occs,
+                        expacc_mods       = earlier_mods,
+                        expacc_warn_spans = export_warn_spans,
+                        expacc_dont_warn  = dont_warn_export
+                      } (L loc ie@(IEModuleContents (warn_txt_ps, _) lmod@(L _ mod)))
+      | Just exported_names <- lookupUniqMap earlier_mods mod  -- Duplicate export of M
       = do { addDiagnostic (TcRnDupeModuleExport mod)
-           ; return Nothing}
+           ; (export_warn_spans', dont_warn_export', _) <-
+                process_warning export_warn_spans
+                                dont_warn_export
+                                exported_names
+                                warn_txt_ps
+                                (locA loc)
+                   -- Checks if all the names are exported with the same warning message
+                   -- or if they should not be warned about
+           ; return ( expacc{ expacc_warn_spans = export_warn_spans'
+                            , expacc_dont_warn  = dont_warn_export' }
+                    , Nothing ) }
 
       | otherwise
-      = do { let { exportValid = (mod `elem` imported_modules)
-                               || (moduleName this_mod == mod)
-                 ; gre_prs     = pickGREsModExp mod (globalRdrEnvElts rdr_env)
-                 ; new_gres    = [ gre'
-                                 | (gre, _) <- gre_prs
-                                 , gre' <- expand_tyty_gre gre ]
-                 ; new_exports = map availFromGRE new_gres
-                 ; all_gres    = foldr (\(gre1,gre2) gres -> gre1 : gre2 : gres) [] gre_prs
-                 ; mods        = addOneToUniqSet earlier_mods mod
+      = do { let { exportValid    = (mod `elem` imported_modules)
+                                  || (moduleName this_mod == mod)
+                 ; gre_prs        = pickGREsModExp mod (globalRdrEnvElts rdr_env)
+                 ; new_gres       = [ gre'
+                                    | (gre, _) <- gre_prs
+                                    , gre' <- expand_tyty_gre gre ]
+                 ; new_exports    = map availFromGRE new_gres
+                 ; all_gres       = foldr (\(gre1,gre2) gres -> gre1 : gre2 : gres) [] gre_prs
+                 ; exported_names = map greName new_gres
+                 ; mods           = addToUniqMap earlier_mods mod exported_names
                  }
 
             ; checkErr exportValid (TcRnExportedModNotImported mod)
             ; warnIf (exportValid && null gre_prs) (TcRnNullExportedModule mod)
 
             ; traceRn "efa" (ppr mod $$ ppr all_gres)
-            ; addUsedGREs all_gres
+            ; addUsedGREs ExportDeprecationWarnings all_gres
 
             ; occs' <- check_occs occs ie new_gres
                           -- This check_occs not only finds conflicts
@@ -314,54 +358,114 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
                           -- 'M.x' is in scope in several ways, we'll have
                           -- several members of mod_avails with the same
                           -- OccName.
+            ; (export_warn_spans', dont_warn_export', warn_txt_rn) <-
+                process_warning export_warn_spans
+                                dont_warn_export
+                                exported_names
+                                warn_txt_ps
+                                (locA loc)
+
             ; traceRn "export_mod"
                       (vcat [ ppr mod
                             , ppr new_exports ])
-            ; return $ Just $
-                ( ExportAccum occs' mods
-                , ( L loc (IEModuleContents noExtField lmod)
-                , new_exports) ) }
-
-    exports_from_item acc@(ExportAccum occs mods) (L loc ie) = do
-        m_new_ie <- lookup_doc_ie ie
-        case m_new_ie of
-          Just new_ie -> return $ Just (acc, (L loc new_ie, []))
+            ; return ( ExportAccum { expacc_exp_occs   = occs'
+                                   , expacc_mods       = mods
+                                   , expacc_warn_spans = export_warn_spans'
+                                   , expacc_dont_warn  = dont_warn_export' }
+                     , Just (L loc (IEModuleContents warn_txt_rn lmod), new_exports) ) }
+
+    exports_from_item acc lie = do
+        m_doc_ie <- lookup_doc_ie lie
+        case m_doc_ie of
+          Just new_ie -> return (acc, Just (new_ie, []))
           Nothing -> do
-            let finish (occs', new_ie, avail) = (ExportAccum occs' mods, (L loc new_ie, [avail]))
-            fmap finish <$> lookup_ie occs ie
+            m_ie <- lookup_ie acc lie
+            case m_ie of
+              Nothing -> return (acc, Nothing)
+              Just (acc', new_ie, avail)
+                -> return (acc', Just (new_ie, [avail]))
 
     -------------
-    lookup_ie :: ExportOccMap -> IE GhcPs -> RnM (Maybe (ExportOccMap, IE GhcRn, AvailInfo))
-    lookup_ie occs ie@(IEVar ann l)
+    lookup_ie :: ExportAccum -> LIE GhcPs -> RnM (Maybe (ExportAccum, LIE GhcRn, AvailInfo))
+    lookup_ie expacc@ExportAccum{
+            expacc_exp_occs   = occs,
+            expacc_warn_spans = export_warn_spans,
+            expacc_dont_warn  = dont_warn_export
+          } (L loc ie@(IEVar warn_txt_ps l))
         = do mb_gre <- lookupGreAvailRn $ lieWrappedName l
              for mb_gre $ \ gre -> do
                let avail = availFromGRE gre
                    name = greName gre
-               occs' <- check_occs occs ie [gre]
-               return (occs', IEVar ann (replaceLWrappedName l name), avail)
 
-    lookup_ie occs ie@(IEThingAbs ann l)
+               occs' <- check_occs occs ie [gre]
+               (export_warn_spans', dont_warn_export', warn_txt_rn)
+                 <- process_warning export_warn_spans
+                                    dont_warn_export
+                                    [name]
+                                    warn_txt_ps
+                                    (locA loc)
+
+               return ( expacc{ expacc_exp_occs   = occs'
+                              , expacc_warn_spans = export_warn_spans'
+                              , expacc_dont_warn  = dont_warn_export' }
+                      , L loc (IEVar warn_txt_rn (replaceLWrappedName l name))
+                      , avail )
+
+    lookup_ie expacc@ExportAccum{
+            expacc_exp_occs   = occs,
+            expacc_warn_spans = export_warn_spans,
+            expacc_dont_warn  = dont_warn_export
+          } (L loc ie@(IEThingAbs (warn_txt_ps, ann) l))
         = do mb_gre <- lookupGreAvailRn $ lieWrappedName l
              for mb_gre $ \ gre -> do
                let avail = availFromGRE gre
                    name = greName gre
-               occs' <- check_occs occs ie [gre]
-               return ( occs'
-                      , IEThingAbs ann (replaceLWrappedName l name)
-                      , avail)
 
-    lookup_ie occs ie@(IEThingAll ann l)
+               occs' <- check_occs occs ie [gre]
+               (export_warn_spans', dont_warn_export', warn_txt_rn)
+                 <- process_warning export_warn_spans
+                                    dont_warn_export
+                                    [name]
+                                    warn_txt_ps
+                                    (locA loc)
+
+               return ( expacc{ expacc_exp_occs   = occs'
+                              , expacc_warn_spans = export_warn_spans'
+                              , expacc_dont_warn  = dont_warn_export' }
+                      , L loc (IEThingAbs (warn_txt_rn, ann) (replaceLWrappedName l name))
+                      , avail )
+
+    lookup_ie expacc@ExportAccum{
+            expacc_exp_occs   = occs,
+            expacc_warn_spans = export_warn_spans,
+            expacc_dont_warn  = dont_warn_export
+          } (L loc ie@(IEThingAll (warn_txt_ps, ann) l))
         = do mb_gre <- lookupGreAvailRn $ lieWrappedName l
              for mb_gre $ \ par -> do
                all_kids <- lookup_ie_kids_all ie l par
                let name = greName par
-                   kids_avails = map greName all_kids
-               occs' <- check_occs occs ie (par:all_kids)
-               return ( occs'
-                       , IEThingAll ann (replaceLWrappedName l name)
-                       , AvailTC name (name:kids_avails))
-
-    lookup_ie occs ie@(IEThingWith ann l wc sub_rdrs)
+                   all_gres = par : all_kids
+                   all_names = map greName all_gres
+
+               occs' <- check_occs occs ie all_gres
+               (export_warn_spans', dont_warn_export', warn_txt_rn)
+                 <- process_warning export_warn_spans
+                                    dont_warn_export
+                                    all_names
+                                    warn_txt_ps
+                                    (locA loc)
+
+               return ( expacc{ expacc_exp_occs   = occs'
+                              , expacc_warn_spans = export_warn_spans'
+                              , expacc_dont_warn  = dont_warn_export' }
+                      , L loc (IEThingAll (warn_txt_rn, ann) (replaceLWrappedName l name))
+                      , AvailTC name all_names )
+
+    lookup_ie expacc@ExportAccum{
+            expacc_exp_occs   = occs,
+            expacc_warn_spans = export_warn_spans,
+            expacc_dont_warn  = dont_warn_export
+          } (L loc ie@(IEThingWith (warn_txt_ps, ann) l wc sub_rdrs))
         = do mb_gre <- addExportErrCtxt ie
                      $ lookupGreAvailRn $ lieWrappedName l
              for mb_gre $ \ par -> do
@@ -376,11 +480,22 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
 
                let name = greName par
                    all_kids = with_kids ++ wc_kids
-                   kids_avails = map greName all_kids
-               occs' <- check_occs occs ie (par:all_kids)
-               return ( occs'
-                       , IEThingWith ann (replaceLWrappedName l name) wc subs
-                       , AvailTC name (name:kids_avails))
+                   all_gres = par : all_kids
+                   all_names = map greName all_gres
+
+               occs' <- check_occs occs ie all_gres
+               (export_warn_spans', dont_warn_export', warn_txt_rn)
+                 <- process_warning export_warn_spans
+                                    dont_warn_export
+                                    all_names
+                                    warn_txt_ps
+                                    (locA loc)
+
+               return ( expacc{ expacc_exp_occs   = occs'
+                              , expacc_warn_spans = export_warn_spans'
+                              , expacc_dont_warn  = dont_warn_export' }
+                      , L loc (IEThingWith (warn_txt_rn, ann) (replaceLWrappedName l name) wc subs)
+                      , AvailTC name all_names )
 
     lookup_ie _ _ = panic "lookup_ie"    -- Other cases covered earlier
 
@@ -407,21 +522,102 @@ exports_from_avail (Just (L _ rdr_items)) rdr_env imports this_mod
          ; return gres }
 
     -------------
-    lookup_doc_ie :: IE GhcPs -> RnM (Maybe (IE GhcRn))
-    lookup_doc_ie (IEGroup _ lev doc) = do
+
+    rn_warning_txt_loc :: LocatedP (WarningTxt GhcPs) -> RnM (LocatedP (WarningTxt GhcRn))
+    rn_warning_txt_loc (L loc warn_txt) = L loc <$> rnWarningTxt warn_txt
+
+    -- Runs for every Name
+    -- - If there is no new warning, flags that the old warning should not be
+    --     included (since a warning should only be emitted if all
+    --     of the export statements have a warning)
+    -- - If the Name already has a warning, adds it
+    process_warning :: ExportWarnSpanNames       -- Old aggregate data about warnins
+                    -> DontWarnExportNames       -- Old names not to warn about
+                    -> [Name]                              -- Names to warn about
+                    -> Maybe (LocatedP (WarningTxt GhcPs)) -- Warning
+                    -> SrcSpan                             -- Span of the export list item
+                    -> RnM (ExportWarnSpanNames, -- Aggregate data about the warnings
+                            DontWarnExportNames, -- Names not to warn about in the end
+                                                 -- (when there was a non-warned export)
+                            Maybe (LocatedP (WarningTxt GhcRn))) -- Renamed warning
+    process_warning export_warn_spans
+                    dont_warn_export
+                    names Nothing loc
+      = return ( export_warn_spans
+               , foldr update_dont_warn_export
+                       dont_warn_export names
+               , Nothing )
+      where
+        update_dont_warn_export :: Name -> DontWarnExportNames -> DontWarnExportNames
+        update_dont_warn_export name dont_warn_export'
+          = extendNameEnv_Acc (NE.<|)
+                              NE.singleton
+                              dont_warn_export'
+                              name
+                              loc
+
+    process_warning export_warn_spans
+                    dont_warn_export
+                    names (Just warn_txt_ps) loc
+      = do
+          warn_txt_rn <- rn_warning_txt_loc warn_txt_ps
+          let new_export_warn_spans = map (, unLoc warn_txt_rn, loc) names
+          return ( new_export_warn_spans ++ export_warn_spans
+                 , dont_warn_export
+                 , Just warn_txt_rn )
+
+    -- For each name exported with any warnings throws an error
+    --   if there are any exports of that name with a different warning
+    aggregate_warnings :: ExportWarnSpanNames
+                       -> DontWarnExportNames
+                       -> RnM (ExportWarnNames GhcRn)
+    aggregate_warnings export_warn_spans dont_warn_export
+      = fmap catMaybes
+      $ mapM (aggregate_single . extract_name)
+      $ NE.groupBy (\(n1, _, _) (n2, _, _) -> n1 == n2)
+      $ sortBy (\(n1, _, _) (n2, _, _) -> n1 `compare` n2) export_warn_spans
+      where
+        extract_name :: NE.NonEmpty (Name, WarningTxt GhcRn, SrcSpan)
+                     -> (Name, NE.NonEmpty (WarningTxt GhcRn, SrcSpan))
+        extract_name l@((name, _, _) NE.:| _)
+          = (name, NE.map (\(_, warn_txt, span) -> (warn_txt, span)) l)
+
+        aggregate_single :: (Name, NE.NonEmpty (WarningTxt GhcRn, SrcSpan))
+                         -> RnM (Maybe (Name, WarningTxt GhcRn))
+        aggregate_single (name, (warn_txt_rn, loc) NE.:| warn_spans)
+          = do
+              -- Emit an error if the warnings differ
+              case NE.nonEmpty spans_different of
+                Nothing -> return ()
+                Just spans_different
+                  -> addErrAt loc (TcRnDifferentExportWarnings name spans_different)
+              -- Emit a warning if some export list items do not have a warning
+              case lookupNameEnv dont_warn_export name of
+                Nothing -> return $ Just (name, warn_txt_rn)
+                Just not_warned_spans -> do
+                  addDiagnosticAt loc (TcRnIncompleteExportWarnings name not_warned_spans)
+                  return Nothing
+          where
+            spans_different = map snd $ filter (not . warningTxtSame warn_txt_rn . fst) warn_spans
+
+    -------------
+    lookup_doc_ie :: LIE GhcPs -> RnM (Maybe (LIE GhcRn))
+    lookup_doc_ie (L loc (IEGroup _ lev doc)) = do
       doc' <- rnLHsDoc doc
-      pure $ Just (IEGroup noExtField lev doc')
-    lookup_doc_ie (IEDoc _ doc)       = do
+      pure $ Just (L loc (IEGroup noExtField lev doc'))
+    lookup_doc_ie (L loc (IEDoc _ doc))       = do
       doc' <- rnLHsDoc doc
-      pure $ Just (IEDoc noExtField doc')
-    lookup_doc_ie (IEDocNamed _ str)  = pure $ Just (IEDocNamed noExtField str)
+      pure $ Just (L loc (IEDoc noExtField doc'))
+    lookup_doc_ie (L loc (IEDocNamed _ str))
+      = pure $ Just (L loc (IEDocNamed noExtField str))
     lookup_doc_ie _ = pure Nothing
 
     -- In an export item M.T(A,B,C), we want to treat the uses of
     -- A,B,C as if they were M.A, M.B, M.C
     -- Happily pickGREs does just the right thing
     addUsedKids :: RdrName -> [GlobalRdrElt] -> RnM ()
-    addUsedKids parent_rdr kid_gres = addUsedGREs (pickGREs parent_rdr kid_gres)
+    addUsedKids parent_rdr kid_gres
+      = addUsedGREs ExportDeprecationWarnings (pickGREs parent_rdr kid_gres)
 
 -- Renaming and typechecking of exports happens after everything else has
 -- been typechecked.
@@ -503,7 +699,8 @@ lookupChildrenExport spec_parent rdr_items = mapAndReportM doOne rdr_items
         doOne n = do
 
           let bareName = (ieWrappedName . unLoc) n
-              lkup v = lookupSubBndrOcc_helper False DisableDeprecationWarnings -- Do not report export list deprecations
+                -- Do not report export list declaration deprecations
+              lkup v = lookupSubBndrOcc_helper False ExportDeprecationWarnings
                         spec_parent (setRdrNameSpace bareName v)
 
           name <-  combineChildLookupResult $ map lkup $
diff --git a/compiler/GHC/Tc/Gen/Expr.hs b/compiler/GHC/Tc/Gen/Expr.hs
index 883543499f0a2d10e1fb5eab16414b8b328e658b..2953f1281f1be4fd4b5084eb53966e998679c6e0 100644
--- a/compiler/GHC/Tc/Gen/Expr.hs
+++ b/compiler/GHC/Tc/Gen/Expr.hs
@@ -54,7 +54,7 @@ import GHC.Tc.Gen.Bind        ( tcLocalBinds )
 import GHC.Tc.Instance.Family ( tcGetFamInstEnvs )
 import GHC.Core.FamInstEnv    ( FamInstEnvs )
 import GHC.Rename.Expr        ( mkExpandedExpr )
-import GHC.Rename.Env         ( addUsedGRE, getUpdFieldLbls, DeprecationWarnings(EnableDeprecationWarnings) )
+import GHC.Rename.Env         ( addUsedGRE, getUpdFieldLbls, DeprecationWarnings(..) )
 import GHC.Tc.Utils.Env
 import GHC.Tc.Gen.Arrow
 import GHC.Tc.Gen.Match
@@ -1423,7 +1423,7 @@ disambiguateRecordBinds record_expr record_rho possible_parents rbnds res_ty
              -- Mark the record fields as used, now that we have disambiguated.
              -- There is no risk of duplicate deprecation warnings, as we have
              -- not marked the GREs as used previously.
-           ; setSrcSpanA loc $ mapM_ (addUsedGRE EnableDeprecationWarnings) mb_gre
+           ; setSrcSpanA loc $ mapM_ (addUsedGRE AllDeprecationWarnings) mb_gre
            ; sel <- tcLookupId (greName fld_gre)
            ; return $ L l HsFieldBind
                { hfbAnn = hfbAnn upd
diff --git a/compiler/GHC/Tc/Instance/Class.hs b/compiler/GHC/Tc/Instance/Class.hs
index 8fae1f31b16edcaa501c1d9ad445f3b3d4274604..a22ff699d16ca245e9127488aa929f0eda2f2a16 100644
--- a/compiler/GHC/Tc/Instance/Class.hs
+++ b/compiler/GHC/Tc/Instance/Class.hs
@@ -23,7 +23,7 @@ import GHC.Tc.Utils.TcMType
 import GHC.Tc.Types.Evidence
 import GHC.Tc.Types.Origin (InstanceWhat (..), SafeOverlapping)
 import GHC.Tc.Instance.Family( tcGetFamInstEnvs, tcInstNewTyCon_maybe, tcLookupDataFamInst )
-import GHC.Rename.Env( addUsedGRE, DeprecationWarnings(EnableDeprecationWarnings) )
+import GHC.Rename.Env( addUsedGRE, DeprecationWarnings (..) )
 
 import GHC.Builtin.Types
 import GHC.Builtin.Types.Prim
@@ -942,7 +942,7 @@ matchHasField dflags short_cut clas tys
                      -- it must not be higher-rank.
                    ; if not (isNaughtyRecordSelector sel_id) && isTauTy sel_ty
                      then do { -- See Note [Unused name reporting and HasField]
-                               addUsedGRE EnableDeprecationWarnings gre
+                               addUsedGRE AllDeprecationWarnings gre
                              ; keepAlive (greName gre)
                              ; return OneInst { cir_new_theta   = theta
                                               , cir_mk_ev       = mk_ev
diff --git a/compiler/GHC/Tc/Module.hs b/compiler/GHC/Tc/Module.hs
index 724ebee1b957f0ad6357664b5b331fbb025b2263..64e3df216fa49b03f33ae83191646b7cfe3d714e 100644
--- a/compiler/GHC/Tc/Module.hs
+++ b/compiler/GHC/Tc/Module.hs
@@ -1691,7 +1691,7 @@ tcTopSrcDecls (HsGroup { hs_tyclds = tycl_decls,
                                  -- tcg_dus: see Note [Newtype constructor usage in foreign declarations]
 
         -- See Note [Newtype constructor usage in foreign declarations]
-        addUsedGREs (bagToList fo_gres) ;
+        addUsedGREs NoDeprecationWarnings (bagToList fo_gres) ;
 
         return (tcg_env', tcl_env)
     }}}}}}
diff --git a/compiler/GHC/Tc/Solver/Monad.hs b/compiler/GHC/Tc/Solver/Monad.hs
index 0c7cb0cc3598932d9ad0cb31eff5a6766f5bd365..da38736dbfc7982c7307c63acb09ebdf7c91bd4b 100644
--- a/compiler/GHC/Tc/Solver/Monad.hs
+++ b/compiler/GHC/Tc/Solver/Monad.hs
@@ -198,6 +198,7 @@ import Data.List ( mapAccumL )
 import Data.Foldable
 import qualified Data.Semigroup as S
 import GHC.Types.SrcLoc
+import GHC.Rename.Env
 
 #if defined(DEBUG)
 import GHC.Types.Unique.Set (nonDetEltsUniqSet)
@@ -1372,7 +1373,7 @@ tcLookupTyCon n = wrapTcS $ TcM.tcLookupTyCon n
 -- might), so it's not worth losing sleep over.
 recordUsedGREs :: Bag GlobalRdrElt -> TcS ()
 recordUsedGREs gres
-  = do { wrapTcS $ TcM.addUsedGREs gre_list
+  = do { wrapTcS $ TcM.addUsedGREs NoDeprecationWarnings gre_list
          -- If a newtype constructor was imported, don't warn about not
          -- importing it...
        ; wrapTcS $ traverse_ (TcM.keepAlive . greName) gre_list }
diff --git a/compiler/GHC/Tc/Utils/Backpack.hs b/compiler/GHC/Tc/Utils/Backpack.hs
index b82678e4ee3fbe9c9e3f38c3a60c2d2449d4352b..b1b69868fe80ee7d4200683a5164007e61c0e409 100644
--- a/compiler/GHC/Tc/Utils/Backpack.hs
+++ b/compiler/GHC/Tc/Utils/Backpack.hs
@@ -636,7 +636,7 @@ mergeSignatures
                                             -- because we need module
                                             -- LocalSig (from the local
                                             -- export list) to match it!
-                                            is_mod  = mod_name,
+                                            is_mod  = mi_module ireq_iface,
                                             is_as   = mod_name,
                                             is_qual = False,
                                             is_dloc = locA loc
@@ -649,7 +649,7 @@ mergeSignatures
                                     emptyImportAvails
                                     (tcg_semantic_mod tcg_env)
                         case mb_r of
-                            Just (_, as2) -> return (thinModIface as2 ireq_iface, as2)
+                            Just (_, as2, _) -> return (thinModIface as2 ireq_iface, as2)
                             Nothing -> addMessages msgs >> failM
                     -- We can't thin signatures from non-signature packages
                     _ -> return (ireq_iface, as1)
@@ -676,7 +676,7 @@ mergeSignatures
         exports        = nameShapeExports nsubst
         rdr_env        = mkGlobalRdrEnv (gresFromAvails hsc_env Nothing exports)
         _warn_occs     = filter (not . (`elemOccSet` ok_to_use)) (exportOccs exports)
-        warns          = NoWarnings
+        warns          = emptyWarn
         {-
         -- TODO: Warnings are transitive, but this is not what we want here:
         -- if a module reexports an entity from a signature, that should be OK.
@@ -706,7 +706,7 @@ mergeSignatures
 
     -- Make sure we didn't refer to anything that doesn't actually exist
     -- pprTrace "mergeSignatures: exports_from_avail" (ppr exports) $ return ()
-    (mb_lies, _) <- exports_from_avail mb_exports rdr_env
+    (mb_lies, _, _) <- exports_from_avail mb_exports rdr_env
                         (tcg_imports tcg_env) (tcg_semantic_mod tcg_env)
 
     {- -- NB: This is commented out, because warns above is disabled.
diff --git a/compiler/GHC/Tc/Utils/Monad.hs b/compiler/GHC/Tc/Utils/Monad.hs
index be9049a20923d83534af09ee58c822c3fc55a155..2dd212b95742541f7922eac7477a042ca9af07c1 100644
--- a/compiler/GHC/Tc/Utils/Monad.hs
+++ b/compiler/GHC/Tc/Utils/Monad.hs
@@ -68,7 +68,7 @@ module GHC.Tc.Utils.Monad(
   addErr,
   failWith, failAt,
   addErrAt, addErrs,
-  checkErr,
+  checkErr, checkErrAt,
   addMessages,
   discardWarnings, mkDetailedMessage,
 
@@ -338,7 +338,7 @@ initTc hsc_env hsc_src keep_rn_syntax mod loc do_this
                 tcg_sigs           = emptyNameSet,
                 tcg_ksigs          = emptyNameSet,
                 tcg_ev_binds       = emptyBag,
-                tcg_warns          = NoWarnings,
+                tcg_warns          = emptyWarn,
                 tcg_anns           = [],
                 tcg_tcs            = [],
                 tcg_insts          = [],
@@ -1084,6 +1084,9 @@ checkErr :: Bool -> TcRnMessage -> TcRn ()
 -- Add the error if the bool is False
 checkErr ok msg = unless ok (addErr msg)
 
+checkErrAt :: SrcSpan -> Bool -> TcRnMessage -> TcRn ()
+checkErrAt loc ok msg = unless ok (addErrAt loc msg)
+
 addMessages :: Messages TcRnMessage -> TcRn ()
 addMessages msgs1
   = do { errs_var <- getErrsVar
diff --git a/compiler/GHC/Types/Error/Codes.hs b/compiler/GHC/Types/Error/Codes.hs
index 794e0862aec10d0f3c7b68713c51b87edd153651..0a9c053eb3e78e8dc2b6613742d4c8814e0133af 100644
--- a/compiler/GHC/Types/Error/Codes.hs
+++ b/compiler/GHC/Types/Error/Codes.hs
@@ -472,6 +472,8 @@ type family GhcDiagnosticCode c = n | n -> c where
   GhcDiagnosticCode "TcRnUnexpectedPragmas"                         = 88293
   GhcDiagnosticCode "TcRnNonOverloadedSpecialisePragma"             = 35827
   GhcDiagnosticCode "TcRnSpecialiseNotVisible"                      = 85337
+  GhcDiagnosticCode "TcRnDifferentExportWarnings"                   = 92878
+  GhcDiagnosticCode "TcRnIncompleteExportWarnings"                  = 94721
   GhcDiagnosticCode "TcRnIllegalTypeOperatorDecl"                   = 50649
   GhcDiagnosticCode "TcRnBindVarAlreadyInScope"                     = 69710
   GhcDiagnosticCode "TcRnBindMultipleVariables"                     = 92957
diff --git a/compiler/GHC/Types/Hint/Ppr.hs b/compiler/GHC/Types/Hint/Ppr.hs
index 49913fd2fa73a963aef7b3c67b23fac67b64ec21..39a4e12e69926a0d3ac8c1089c993c78768809be 100644
--- a/compiler/GHC/Types/Hint/Ppr.hs
+++ b/compiler/GHC/Types/Hint/Ppr.hs
@@ -362,7 +362,7 @@ pprSimilarName tried_ns (SimilarRdrName rdr_name how_in_scope)
               RealSrcSpan l _ -> parens (text "line" <+> int (srcSpanStartLine l))
       ImportedBy is ->
         pp_ns rdr_name <+> quotes (ppr rdr_name) <+>
-        parens (text "imported from" <+> ppr (is_mod is))
+        parens (text "imported from" <+> ppr (moduleName $ is_mod is))
 
   where
     pp_ns :: RdrName -> SDoc
diff --git a/compiler/GHC/Types/Name/Env.hs b/compiler/GHC/Types/Name/Env.hs
index f96d3957fb6b484b28914201f27ca2fa8444f237..7aa3f302d86c86d83719e2547725f6e3ec98d1d3 100644
--- a/compiler/GHC/Types/Name/Env.hs
+++ b/compiler/GHC/Types/Name/Env.hs
@@ -15,6 +15,7 @@ module GHC.Types.Name.Env (
 
         -- ** Manipulating these environments
         mkNameEnv, mkNameEnvWith,
+        fromUniqMap,
         emptyNameEnv, isEmptyNameEnv,
         unitNameEnv, nonDetNameEnvElts,
         extendNameEnv_C, extendNameEnv_Acc, extendNameEnv,
@@ -23,6 +24,7 @@ module GHC.Types.Name.Env (
         mapMaybeNameEnv,
         extendNameEnvListWith,
         plusNameEnv, plusNameEnv_C, plusNameEnv_CD, plusNameEnv_CD2, alterNameEnv,
+        plusNameEnvList, plusNameEnvListWith,
         lookupNameEnv, lookupNameEnv_NF, delFromNameEnv, delListFromNameEnv,
         elemNameEnv, mapNameEnv, disjointNameEnv,
         seqEltsNameEnv,
@@ -49,6 +51,7 @@ import GHC.Data.Graph.Directed
 import GHC.Types.Name
 import GHC.Types.Unique.FM
 import GHC.Types.Unique.DFM
+import GHC.Types.Unique.Map
 import GHC.Data.Maybe
 
 {-
@@ -105,6 +108,7 @@ emptyNameEnv       :: NameEnv a
 isEmptyNameEnv     :: NameEnv a -> Bool
 mkNameEnv          :: [(Name,a)] -> NameEnv a
 mkNameEnvWith      :: (a -> Name) -> [a] -> NameEnv a
+fromUniqMap        :: UniqMap Name a -> NameEnv a
 nonDetNameEnvElts  :: NameEnv a -> [a]
 alterNameEnv       :: (Maybe a-> Maybe a) -> NameEnv a -> Name -> NameEnv a
 extendNameEnv_C    :: (a->a->a) -> NameEnv a -> Name -> a -> NameEnv a
@@ -114,6 +118,8 @@ plusNameEnv        :: NameEnv a -> NameEnv a -> NameEnv a
 plusNameEnv_C      :: (a->a->a) -> NameEnv a -> NameEnv a -> NameEnv a
 plusNameEnv_CD     :: (a->a->a) -> NameEnv a -> a -> NameEnv a -> a -> NameEnv a
 plusNameEnv_CD2    :: (Maybe a->Maybe a->a) -> NameEnv a -> NameEnv a -> NameEnv a
+plusNameEnvList    :: [NameEnv a] -> NameEnv a
+plusNameEnvListWith :: (a->a->a) -> [NameEnv a] -> NameEnv a
 extendNameEnvList  :: NameEnv a -> [(Name,a)] -> NameEnv a
 extendNameEnvListWith :: (a -> Name) -> NameEnv a -> [a] -> NameEnv a
 extendNameEnvList_C :: (a->a->a) -> NameEnv a -> [(Name,a)] -> NameEnv a
@@ -141,12 +147,17 @@ lookupNameEnv x y     = lookupUFM x y
 alterNameEnv          = alterUFM
 mkNameEnv     l       = listToUFM l
 mkNameEnvWith f       = mkNameEnv . map (\a -> (f a, a))
+fromUniqMap           = mapUFM snd . getUniqMap
 elemNameEnv x y          = elemUFM x y
 plusNameEnv x y          = plusUFM x y
 plusNameEnv_C f x y      = plusUFM_C f x y
 {-# INLINE plusNameEnv_CD #-}
 plusNameEnv_CD f x d y b = plusUFM_CD f x d y b
 plusNameEnv_CD2 f x y    = plusUFM_CD2 f x y
+{-# INLINE plusNameEnvList #-}
+plusNameEnvList xs       = plusUFMList xs
+{-# INLINE plusNameEnvListWith #-}
+plusNameEnvListWith f xs = plusUFMListWith f xs
 extendNameEnv_C f x y z  = addToUFM_C f x y z
 mapNameEnv f x           = mapUFM f x
 extendNameEnv_Acc x y z a b  = addToUFM_Acc x y z a b
diff --git a/compiler/GHC/Types/Name/Reader.hs b/compiler/GHC/Types/Name/Reader.hs
index 17be091c74d2864057284b385b6f382a3dda2708..c77dd6ba53e986150054c1aacf9af28bab600545 100644
--- a/compiler/GHC/Types/Name/Reader.hs
+++ b/compiler/GHC/Types/Name/Reader.hs
@@ -1503,7 +1503,7 @@ shadowNames drop_only_qualified env new_gres = minusOccEnv_C_Ns do_shadowing env
       = ImpSpec id_spec ImpAll
       where
         old_mod_name = moduleName old_mod
-        id_spec      = ImpDeclSpec { is_mod = old_mod_name
+        id_spec      = ImpDeclSpec { is_mod = old_mod
                                    , is_as = old_mod_name
                                    , is_qual = True
                                    , is_dloc = greDefinitionSrcSpan old_gre }
@@ -1653,7 +1653,7 @@ data ImportSpec = ImpSpec { is_decl :: ImpDeclSpec,
 -- shared among all the 'Provenance's for that decl
 data ImpDeclSpec
   = ImpDeclSpec {
-        is_mod      :: ModuleName, -- ^ Module imported, e.g. @import Muggle@
+        is_mod      :: Module,     -- ^ Module imported, e.g. @import Muggle@
                                    -- Note the @Muggle@ may well not be
                                    -- the defining module for this thing!
 
@@ -1774,7 +1774,7 @@ importSpecLoc (ImpSpec decl ImpAll) = is_dloc decl
 importSpecLoc (ImpSpec _    item)   = is_iloc item
 
 importSpecModule :: ImportSpec -> ModuleName
-importSpecModule is = is_mod (is_decl is)
+importSpecModule = moduleName . is_mod . is_decl
 
 isExplicitItem :: ImpItemSpec -> Bool
 isExplicitItem ImpAll                        = False
diff --git a/compiler/GHC/Unit/Module/ModIface.hs b/compiler/GHC/Unit/Module/ModIface.hs
index 8bdba40bbabb4c03dd11a43c6f367cc86cf08439..0a6b220be6c333c81ef244a28c6d9f27a8659f0a 100644
--- a/compiler/GHC/Unit/Module/ModIface.hs
+++ b/compiler/GHC/Unit/Module/ModIface.hs
@@ -110,8 +110,10 @@ data ModIfaceBackend = ModIfaceBackend
     -- other fields and are not put into the interface file.
     -- Not really produced by the backend but there is no need to create them
     -- any earlier.
-  , mi_warn_fn :: !(OccName -> Maybe (WarningTxt GhcRn))
-    -- ^ Cached lookup for 'mi_warns'
+  , mi_decl_warn_fn :: !(OccName -> Maybe (WarningTxt GhcRn))
+    -- ^ Cached lookup for 'mi_warns' for declaration deprecations
+  , mi_export_warn_fn :: !(Name -> Maybe (WarningTxt GhcRn))
+    -- ^ Cached lookup for 'mi_warns' for export deprecations
   , mi_fix_fn :: !(OccName -> Maybe Fixity)
     -- ^ Cached lookup for 'mi_fixities'
   , mi_hash_fn :: !(OccName -> Maybe (OccName, Fingerprint))
@@ -479,7 +481,8 @@ instance Binary ModIface where
                    mi_finsts = hasFamInsts,
                    mi_exp_hash = exp_hash,
                    mi_orphan_hash = orphan_hash,
-                   mi_warn_fn = mkIfaceWarnCache $ fromIfaceWarnings warns,
+                   mi_decl_warn_fn = mkIfaceDeclWarnCache $ fromIfaceWarnings warns,
+                   mi_export_warn_fn = mkIfaceExportWarnCache $ fromIfaceWarnings warns,
                    mi_fix_fn = mkIfaceFixCache fixities,
                    mi_hash_fn = mkIfaceHashCache decls
                  }})
@@ -498,7 +501,7 @@ emptyPartialModIface mod
                mi_exports     = [],
                mi_used_th     = False,
                mi_fixities    = [],
-               mi_warns       = IfNoWarnings,
+               mi_warns       = IfWarnSome [] [],
                mi_anns        = [],
                mi_insts       = [],
                mi_fam_insts   = [],
@@ -530,7 +533,8 @@ emptyFullModIface mod =
           mi_finsts = False,
           mi_exp_hash = fingerprint0,
           mi_orphan_hash = fingerprint0,
-          mi_warn_fn = emptyIfaceWarnCache,
+          mi_decl_warn_fn = emptyIfaceWarnCache,
+          mi_export_warn_fn = emptyIfaceWarnCache,
           mi_fix_fn = emptyIfaceFixCache,
           mi_hash_fn = emptyIfaceHashCache } }
 
@@ -592,7 +596,8 @@ instance ( NFData (IfaceBackendExts (phase :: ModIfacePhase))
 instance NFData (ModIfaceBackend) where
   rnf (ModIfaceBackend{ mi_iface_hash, mi_mod_hash, mi_flag_hash, mi_opt_hash
                       , mi_hpc_hash, mi_plugin_hash, mi_orphan, mi_finsts, mi_exp_hash
-                      , mi_orphan_hash, mi_warn_fn, mi_fix_fn, mi_hash_fn})
+                      , mi_orphan_hash, mi_decl_warn_fn, mi_export_warn_fn, mi_fix_fn
+                      , mi_hash_fn})
     =     rnf mi_iface_hash
     `seq` rnf mi_mod_hash
     `seq` rnf mi_flag_hash
@@ -603,7 +608,8 @@ instance NFData (ModIfaceBackend) where
     `seq` rnf mi_finsts
     `seq` rnf mi_exp_hash
     `seq` rnf mi_orphan_hash
-    `seq` rnf mi_warn_fn
+    `seq` rnf mi_decl_warn_fn
+    `seq` rnf mi_export_warn_fn
     `seq` rnf mi_fix_fn
     `seq` rnf mi_hash_fn
 
diff --git a/compiler/GHC/Unit/Module/Warnings.hs b/compiler/GHC/Unit/Module/Warnings.hs
index ee49baf55412df3389dfe87d086e0e261f3b7de7..ed122e1037307cd730e7fed869335b883ab28caf 100644
--- a/compiler/GHC/Unit/Module/Warnings.hs
+++ b/compiler/GHC/Unit/Module/Warnings.hs
@@ -5,6 +5,7 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE LambdaCase #-}
 
 -- | Warnings for a module
@@ -24,11 +25,18 @@ module GHC.Unit.Module.Warnings
 
    , Warnings (..)
    , WarningTxt (..)
+   , DeclWarnOccNames
+   , ExportWarnNames
    , warningTxtCategory
+   , warningTxtMessage
+   , warningTxtSame
    , pprWarningTxtForMsg
-   , mkIfaceWarnCache
+   , emptyWarn
+   , mkIfaceDeclWarnCache
+   , mkIfaceExportWarnCache
    , emptyIfaceWarnCache
-   , plusWarns
+   , insertWarnDecls
+   , insertWarnExports
    )
 where
 
@@ -37,6 +45,8 @@ import GHC.Prelude
 import GHC.Data.FastString (FastString, mkFastString, unpackFS)
 import GHC.Types.SourceText
 import GHC.Types.Name.Occurrence
+import GHC.Types.Name.Env
+import GHC.Types.Name (Name)
 import GHC.Types.SrcLoc
 import GHC.Types.Unique
 import GHC.Types.Unique.Set
@@ -190,6 +200,24 @@ warningTxtCategory :: WarningTxt pass -> WarningCategory
 warningTxtCategory (WarningTxt (Just (L _ cat)) _ _) = cat
 warningTxtCategory _ = defaultWarningCategory
 
+-- | The message that the WarningTxt was specified to output
+warningTxtMessage :: WarningTxt p -> [Located (WithHsDocIdentifiers StringLiteral p)]
+warningTxtMessage (WarningTxt _ _ m) = m
+warningTxtMessage (DeprecatedTxt _ m) = m
+
+-- | True if the 2 WarningTxts have the same category and messages
+warningTxtSame :: WarningTxt p1 -> WarningTxt p2 -> Bool
+warningTxtSame w1 w2
+  = warningTxtCategory w1 == warningTxtCategory w2
+  && literal_message w1 == literal_message w2
+  && same_type
+  where
+    literal_message :: WarningTxt p -> [StringLiteral]
+    literal_message = map (hsDocString . unLoc) . warningTxtMessage
+    same_type | DeprecatedTxt {} <- w1, DeprecatedTxt {} <- w2 = True
+              | WarningTxt {} <- w1, WarningTxt {} <- w2       = True
+              | otherwise                                      = False
+
 deriving instance Eq (IdP pass) => Eq (WarningTxt pass)
 deriving instance (Data pass, Data (IdP pass)) => Data (WarningTxt pass)
 
@@ -220,13 +248,13 @@ pprWarningTxtForMsg (DeprecatedTxt _ ds)
                        doubleQuotes (vcat (map (ftext . sl_fs . hsDocString . unLoc) ds))
 
 
--- | Warning information for a module
+-- | Warning information from a module
 data Warnings pass
-  = NoWarnings                          -- ^ Nothing deprecated
-  | WarnAll (WarningTxt pass)                  -- ^ Whole module deprecated
-  | WarnSome [(OccName,WarningTxt pass)]     -- ^ Some specific things deprecated
+  = WarnSome (DeclWarnOccNames pass) -- ^ Names deprecated (may be empty)
+             (ExportWarnNames pass)  -- ^ Exports deprecated (may be empty)
+  | WarnAll (WarningTxt pass)        -- ^ Whole module deprecated
 
-     -- Only an OccName is needed because
+     -- For the module-specific names only an OccName is needed because
      --    (1) a deprecation always applies to a binding
      --        defined in the module in which the deprecation appears.
      --    (2) deprecations are only reported outside the defining module.
@@ -246,22 +274,44 @@ data Warnings pass
      --
      --        this is in contrast with fixity declarations, where we need to map
      --        a Name to its fixity declaration.
+     --
+     -- For export deprecations we need to know where the symbol comes from, since
+     -- we need to be able to check if the deprecated export that was imported is
+     -- the same thing as imported by another import, which would not trigger
+     -- a deprecation message.
+
+-- | Deprecated declarations
+type DeclWarnOccNames pass = [(OccName, WarningTxt pass)]
+
+-- | Names that are deprecated as exports
+type ExportWarnNames pass = [(Name, WarningTxt pass)]
 
 deriving instance Eq (IdP pass) => Eq (Warnings pass)
 
--- | Constructs the cache for the 'mi_warn_fn' field of a 'ModIface'
-mkIfaceWarnCache :: Warnings p -> OccName -> Maybe (WarningTxt p)
-mkIfaceWarnCache NoWarnings  = \_ -> Nothing
-mkIfaceWarnCache (WarnAll t) = \_ -> Just t
-mkIfaceWarnCache (WarnSome pairs) = lookupOccEnv (mkOccEnv pairs)
+emptyWarn :: Warnings p
+emptyWarn = WarnSome [] []
 
-emptyIfaceWarnCache :: OccName -> Maybe (WarningTxt p)
-emptyIfaceWarnCache _ = Nothing
+-- | Constructs the cache for the 'mi_decl_warn_fn' field of a 'ModIface'
+mkIfaceDeclWarnCache :: Warnings p -> OccName -> Maybe (WarningTxt p)
+mkIfaceDeclWarnCache (WarnAll t) = \_ -> Just t
+mkIfaceDeclWarnCache (WarnSome vs _) = lookupOccEnv (mkOccEnv vs)
 
-plusWarns :: Warnings p -> Warnings p -> Warnings p
-plusWarns d NoWarnings = d
-plusWarns NoWarnings d = d
-plusWarns _ (WarnAll t) = WarnAll t
-plusWarns (WarnAll t) _ = WarnAll t
-plusWarns (WarnSome v1) (WarnSome v2) = WarnSome (v1 ++ v2)
+-- | Constructs the cache for the 'mi_export_warn_fn' field of a 'ModIface'
+mkIfaceExportWarnCache :: Warnings p -> Name -> Maybe (WarningTxt p)
+mkIfaceExportWarnCache (WarnAll _) = const Nothing -- We do not want a double report of the module deprecation
+mkIfaceExportWarnCache (WarnSome _ ds) = lookupNameEnv (mkNameEnv ds)
+
+emptyIfaceWarnCache :: name -> Maybe (WarningTxt p)
+emptyIfaceWarnCache _ = Nothing
 
+insertWarnDecls :: Warnings p                -- ^ Existing warnings
+                -> [(OccName, WarningTxt p)] -- ^ New declaration deprecations
+                -> Warnings p                -- ^ Updated warnings
+insertWarnDecls ws@(WarnAll _) _        = ws
+insertWarnDecls (WarnSome wns wes) wns' = WarnSome (wns ++ wns') wes
+
+insertWarnExports :: Warnings p             -- ^ Existing warnings
+                  -> [(Name, WarningTxt p)] -- ^ New export deprecations
+                  -> Warnings p             -- ^ Updated warnings
+insertWarnExports ws@(WarnAll _) _ = ws
+insertWarnExports (WarnSome wns wes) wes' = WarnSome wns (wes ++ wes')
diff --git a/docs/users_guide/9.8.1-notes.rst b/docs/users_guide/9.8.1-notes.rst
index cd1e414d5aff21a37ce6f39e8e7f61dafb811849..95e564109f2db9ddfcfe5776812ef60482418878 100644
--- a/docs/users_guide/9.8.1-notes.rst
+++ b/docs/users_guide/9.8.1-notes.rst
@@ -162,6 +162,23 @@ Compiler
   In a test compiling GHC itself, the size of the :ghc-flag:`-finfo-table-map`
   enabled build results was reduced by over 20% when compression was enabled.
 
+- GHC Proposal `#134
+  <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0134-deprecating-exports-proposal.rst>`_
+  has been implemented. This makes it possible to deprecate certain names exported from a module, without deprecating
+  the name itself. You can check the full specification of the feature at :ref:`warning-deprecated-pragma`.
+
+  For example ::
+
+      module X (
+          {-# WARNING "do not use that constructor" D(D1),
+          D(D2)
+        )
+        D = D1 | D2
+      
+  This allows for changing the structure of a library without immediately breaking user code,
+  but instead being able to warn the user that a change in the library interface
+  will occur in the future.
+
 GHCi
 ~~~~
 
@@ -223,6 +240,11 @@ Runtime system
   This allows how messages are rendered and explained to users to be modified.
   We use this functionality in GHCi to modify how some messages are displayed.
 
+- The extensions fields of constructors of ``IE`` now take ``Maybe (WarningTxt p)``
+  in ``GhcPs`` and ``GhcRn`` variants of the Syntax Tree. 
+  This represents the warning assigned to a certain export item, 
+  which is used for :ref:`deprecated-exports`.
+
 ``ghc-heap`` library
 ~~~~~~~~~~~~~~~~~~~~
 
diff --git a/docs/users_guide/exts/pragmas.rst b/docs/users_guide/exts/pragmas.rst
index 2c8c5d47591f2ee1f3feb3973615a716ae143e01..aff9fc253a7e21d955c2f7f7de8f9c72042dfc14 100644
--- a/docs/users_guide/exts/pragmas.rst
+++ b/docs/users_guide/exts/pragmas.rst
@@ -101,16 +101,16 @@ other compilers.
     :where: declaration or module name
 
     The ``WARNING`` pragma allows you to attach an arbitrary warning to a
-    particular function, class, type, or module.
+    particular function, class, type, export field or module.
 
 .. pragma:: DEPRECATED
 
     :where: declaration or module name
 
     A ``DEPRECATED`` pragma lets you specify that a particular function, class,
-    type, or module is deprecated.
+    type, export or module is deprecated.
 
-There are two ways of using these pragmas.
+There are three ways of using these pragmas.
 
 -  You can work on an entire module thus: ::
 
@@ -141,6 +141,53 @@ There are two ways of using these pragmas.
    both are in scope. If both are in scope, there is currently no way to
    specify one without the other (c.f. fixities :ref:`infix-tycons`).
 
+-  You can also attach a warning to an export field, be it a regular export: ::
+
+          module Wibble (
+              {-# DEPRECATED "Do not use this type" #-} T,
+              {-# WARNING "This is a hacky function" #-} f
+            ) where
+            ...
+    
+    Or a re-export of import from another module: ::
+          
+          module Wibble (
+              {-# DEPRECATED "Import this function from A instead" #-} g
+            ) where
+          import A
+    
+   Or a re-export of an entire module: ::
+        
+          module Wibble (
+              {-# DEPRECATED "This declaration has been moved to B instead"
+                module B
+            ) where
+          import B
+   
+   When you compile any module that imports and uses any of the
+   specified entities, GHC will print the specified message.
+
+   An entity will only be warned about if all of its exports are deprecated: ::
+          
+          module Wibble (
+              {-# WARNING "This would not be warned about" #-} g,
+              module A
+            )
+          import A (g)
+   
+   If the :ghc-flag: `-Wincomplete-export-warnings` is on, 
+   such occurences are warned about.
+
+   Moreover, all warning declarations of a specific name have to 
+   be warned with the same pragma and message: ::
+          
+          module Wibble (
+              {-# WARNING "This would throw an error" #-} T(T1),
+              {-# WARNING "Because the warning messages differ for T" #-} T,
+          )
+          ...
+
+
 Also note that the argument to ``DEPRECATED`` and ``WARNING`` can also be a list
 of strings, in which case the strings will be presented on separate lines in the
 resulting warning message, ::
@@ -148,10 +195,12 @@ resulting warning message, ::
     {-# DEPRECATED foo, bar ["Don't use these", "Use gar instead"] #-}
 
 Warnings and deprecations are not reported for (a) uses within the
-defining module, (b) defining a method in a class instance, and (c) uses
-in an export list. The latter reduces spurious complaints within a
-library in which one module gathers together and re-exports the exports
-of several others.
+defining module, (b) defining a method in a class instance, 
+(c) unqualified uses of an entity imported through different modules 
+when not all of them are warned about, and (d) uses in an 
+export list (except for export warnings). The latter reduces 
+spurious complaints within a library in which one module gathers together 
+and re-exports the exports of several others.
 
 A ``WARNING`` pragma (but not a ``DEPRECATED`` pragma) may optionally specify a
 *warning category* as a string literal following the ``in`` keyword.  This affects the flag used to suppress
@@ -168,7 +217,7 @@ suppressed with ``-Wno-x-partial``::
 
 Alternatively, warnings from all ``WARNING`` and ``DEPRECATED`` pragmas
 regardless of category can be suppressed with
-:ghc-flag:`-Wno-extended-warnings <-Wextended-warnings>`).
+:ghc-flag:`-Wno-extended-warnings <-Wextended-warnings>`.
 
 
 .. _minimal-pragma:
diff --git a/docs/users_guide/using-warnings.rst b/docs/users_guide/using-warnings.rst
index 7f57eda6cab4f44c90bf219367a7d3689314aa75..37ae36ae50a551b4cad78d17fefeb26763228e34 100644
--- a/docs/users_guide/using-warnings.rst
+++ b/docs/users_guide/using-warnings.rst
@@ -131,6 +131,7 @@ as ``-Wno-...`` for every individual warning in the group.
         * :ghc-flag:`-Wtype-defaults`
         * :ghc-flag:`-Wunused-do-bind`
         * :ghc-flag:`-Wunused-record-wildcards`
+        * :ghc-flag:`-Wincomplete-export-warnings`
 
 .. ghc-flag:: -Weverything
     :shortdesc: enable all warnings supported by GHC
@@ -2467,3 +2468,33 @@ of ``-W(no-)*``.
 If you're feeling really paranoid, the :ghc-flag:`-dcore-lint` option is a good choice.
 It turns on heavyweight intra-pass sanity-checking within GHC. (It checks GHC's
 sanity, not yours.)
+
+.. ghc-flag:: -Wincomplete-export-warnings
+    :shortdesc: warn when some but not all of exports for a name are warned about
+    :type: dynamic
+    :reverse: -Wno-incomplete-export-warnings
+
+    :since: 9.8.1
+
+    Ino accordance with `GHC Proposal #134
+    <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0134-deprecating-exports-proposal.rst>`__,
+    it is now possible to deprecate certain exports of a name without deprecating the name itself.
+
+    As explained in :ref:`warning-deprecated-pragma`, when a name is exported in several ways in the same module, 
+    but only some of those ways have a warning, it will not end up deprecated when imported in another module.
+
+    For example: ::
+        
+        module A (x) where
+    
+        x :: Int
+        x = 2
+
+        module M (
+            {-# WARNING x "deprecated" #-} x
+            module A
+          )
+        import A
+
+     When :ghc-flag:`-Wincomplete-export-warnings` is enabled, GHC warns about exports 
+     that are not deprecating a name that is deprecated with another export in that module.
\ No newline at end of file
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/Makefile b/testsuite/tests/backpack/cabal/bkpcabal08/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..4932f7272f0bdb091f911c199a417136b005a9cc
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/Makefile
@@ -0,0 +1,21 @@
+TOP=../../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+SETUP=./Setup -v0
+CONFIGURE=$(SETUP) configure $(CABAL_MINIMAL_BUILD) --with-ghc='$(TEST_HC)' --ghc-options='$(TEST_HC_OPTS)' --package-db=tmp.d --prefix='$(PWD)/inst'
+
+bkpcabal08: clean
+	$(MAKE) -s --no-print-directory clean
+	'$(GHC_PKG)' init tmp.d
+	'$(TEST_HC)' $(TEST_HC_OPTS) -v0 --make Setup
+	# typecheck
+	$(CONFIGURE)
+	$(SETUP) build
+	$(SETUP) -v1 build
+ifneq "$(CLEANUP)" ""
+	$(MAKE) -s --no-print-directory clean
+endif
+
+clean :
+	$(RM) -r tmp.d inst dist Setup$(exeext)
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/R.hs b/testsuite/tests/backpack/cabal/bkpcabal08/R.hs
new file mode 100644
index 0000000000000000000000000000000000000000..95d1891d4cf475a804858acecec96b413e613a68
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/R.hs
@@ -0,0 +1,4 @@
+module R(y) where
+import A (x)
+import B (z)
+y = x && z
\ No newline at end of file
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/Setup.hs b/testsuite/tests/backpack/cabal/bkpcabal08/Setup.hs
new file mode 100644
index 0000000000000000000000000000000000000000..9a994af677b0dfd41b4e3b76b3e7e604003d64e1
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/all.T b/testsuite/tests/backpack/cabal/bkpcabal08/all.T
new file mode 100644
index 0000000000000000000000000000000000000000..08454185c1b38f7fce5cb0f3615f64fee5238d87
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/all.T
@@ -0,0 +1,12 @@
+if config.cleanup:
+   cleanup = 'CLEANUP=1'
+else:
+   cleanup = 'CLEANUP=0'
+
+test('bkpcabal08',
+     [extra_files(['p', 'q', 'impl', 'bkpcabal08.cabal', 'Setup.hs', 'R.hs']),
+      js_broken(22351), 
+      normalise_slashes,
+      normalise_version('bkpcabal08')],
+     run_command,
+     ['$MAKE -s --no-print-directory bkpcabal08 ' + cleanup])
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/bkpcabal08.cabal b/testsuite/tests/backpack/cabal/bkpcabal08/bkpcabal08.cabal
new file mode 100644
index 0000000000000000000000000000000000000000..0a75b0f41174c25b69821ebb0d5f43914e1a5be1
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/bkpcabal08.cabal
@@ -0,0 +1,30 @@
+cabal-version:       2.2
+name:                bkpcabal08
+version:             0.1.0.0
+license:             BSD-3-Clause
+author:              Bartłomiej Cieślar
+build-type:          Simple
+
+library impl
+  exposed-modules: A, B
+  hs-source-dirs: impl
+  build-depends: base
+  default-language:    Haskell2010
+
+library p
+  signatures: A, B
+  hs-source-dirs: p
+  build-depends: base
+  default-language:    Haskell2010
+
+library q
+  signatures: A, B
+  exposed-modules: M
+  hs-source-dirs: q
+  build-depends: base, p
+  default-language:    Haskell2010
+
+library r
+  exposed-modules: R
+  build-depends: base, q, impl
+  default-language:    Haskell2010
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/bkpcabal08.stdout b/testsuite/tests/backpack/cabal/bkpcabal08/bkpcabal08.stdout
new file mode 100644
index 0000000000000000000000000000000000000000..e0d3325475e53e471beb0c89e077578097ab6625
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/bkpcabal08.stdout
@@ -0,0 +1,25 @@
+Preprocessing library 'p' for bkpcabal08-0.1.0.0..
+Building library 'p' instantiated with
+  A = <A>
+  B = <B>
+for bkpcabal08-0.1.0.0..
+[2 of 2] Compiling B[sig]           ( p/B.hsig, nothing )
+Preprocessing library 'q' for bkpcabal08-0.1.0.0..
+Building library 'q' instantiated with
+  A = <A>
+  B = <B>
+for bkpcabal08-0.1.0.0..
+[2 of 4] Compiling B[sig]           ( q/B.hsig, nothing )
+[3 of 4] Compiling M                ( q/M.hs, nothing ) [A changed]
+[4 of 4] Instantiating bkpcabal08-0.1.0.0-EyPgBicvfbiC7dE1n4Leie-p
+Preprocessing library 'impl' for bkpcabal08-0.1.0.0..
+Building library 'impl' for bkpcabal08-0.1.0.0..
+Preprocessing library 'q' for bkpcabal08-0.1.0.0..
+Building library 'q' instantiated with
+  A = bkpcabal08-0.1.0.0-7fVENJzzGcJGpTFnmRtPuV-impl:A
+  B = bkpcabal08-0.1.0.0-7fVENJzzGcJGpTFnmRtPuV-impl:B
+for bkpcabal08-0.1.0.0..
+[1 of 3] Compiling A[sig]           ( q/A.hsig, dist/build/bkpcabal08-0.1.0.0-ECOfUnn43H71QBN16LasXC-q+GMGlyMx4Le5H1wfFVpXzYJ/A.o ) [Prelude package changed]
+[2 of 3] Compiling B[sig]           ( q/B.hsig, dist/build/bkpcabal08-0.1.0.0-ECOfUnn43H71QBN16LasXC-q+GMGlyMx4Le5H1wfFVpXzYJ/B.o ) [Prelude package changed]
+Preprocessing library 'r' for bkpcabal08-0.1.0.0..
+Building library 'r' for bkpcabal08-0.1.0.0..
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/impl/A.hs b/testsuite/tests/backpack/cabal/bkpcabal08/impl/A.hs
new file mode 100644
index 0000000000000000000000000000000000000000..405cf98c057b23c26dafbd5e64e780f63252e423
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/impl/A.hs
@@ -0,0 +1,2 @@
+module A where
+x = True
\ No newline at end of file
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/impl/B.hs b/testsuite/tests/backpack/cabal/bkpcabal08/impl/B.hs
new file mode 100644
index 0000000000000000000000000000000000000000..7e111444f5f7f8667c0f5942efbddaa8f242c35e
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/impl/B.hs
@@ -0,0 +1,2 @@
+module B where
+z = False
\ No newline at end of file
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/p/A.hsig b/testsuite/tests/backpack/cabal/bkpcabal08/p/A.hsig
new file mode 100644
index 0000000000000000000000000000000000000000..13da166454ad90529f3f61ae2d85ac132842b10e
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/p/A.hsig
@@ -0,0 +1,3 @@
+signature A where
+data T
+x :: Bool
\ No newline at end of file
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/p/B.hsig b/testsuite/tests/backpack/cabal/bkpcabal08/p/B.hsig
new file mode 100644
index 0000000000000000000000000000000000000000..9282cdcc4af262ac4b21b079c25ea6c2fe152ea8
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/p/B.hsig
@@ -0,0 +1,4 @@
+signature B where
+import A
+y :: T
+z :: Bool
\ No newline at end of file
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/q/A.hsig b/testsuite/tests/backpack/cabal/bkpcabal08/q/A.hsig
new file mode 100644
index 0000000000000000000000000000000000000000..b58fdb4b3e5b3a32721eb469874d43bd08242fcb
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/q/A.hsig
@@ -0,0 +1,2 @@
+signature A (x) where
+x :: Bool
\ No newline at end of file
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/q/B.hsig b/testsuite/tests/backpack/cabal/bkpcabal08/q/B.hsig
new file mode 100644
index 0000000000000000000000000000000000000000..beff211567d3e3a94ca1ff900304c3aa78d37a56
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/q/B.hsig
@@ -0,0 +1,2 @@
+signature B (z) where
+z :: Bool
\ No newline at end of file
diff --git a/testsuite/tests/backpack/cabal/bkpcabal08/q/M.hs b/testsuite/tests/backpack/cabal/bkpcabal08/q/M.hs
new file mode 100644
index 0000000000000000000000000000000000000000..769d2cdb14ea92100cdec52be5485940546b95a8
--- /dev/null
+++ b/testsuite/tests/backpack/cabal/bkpcabal08/q/M.hs
@@ -0,0 +1,4 @@
+module M(y) where
+import A (x)
+import B (z)
+y = x && z
\ No newline at end of file
diff --git a/testsuite/tests/backpack/should_compile/all.T b/testsuite/tests/backpack/should_compile/all.T
index d9534d713086b4d4527c13ebd4ee6506e3bf9144..9144fbb5cd63e2b24ada7103a7f49f44ddd0332d 100644
--- a/testsuite/tests/backpack/should_compile/all.T
+++ b/testsuite/tests/backpack/should_compile/all.T
@@ -35,7 +35,7 @@ test('bkp40', normal, backpack_compile, [''])
 test('bkp41', normal, backpack_compile, [''])
 test('bkp42', normal, backpack_compile, [''])
 test('bkp43', normal, backpack_compile, [''])
-test('bkp44', normal, backpack_compile, [''])
+# bkp44 moved to bkpcabal08
 test('bkp45', normal, backpack_compile, [''])
 test('bkp46', normal, backpack_compile, [''])
 test('bkp47', normal, backpack_compile, [''])
diff --git a/testsuite/tests/backpack/should_compile/bkp44.bkp b/testsuite/tests/backpack/should_compile/bkp44.bkp
deleted file mode 100644
index 06134b70863c5dd33b00896e289df1c17dbb0bcb..0000000000000000000000000000000000000000
--- a/testsuite/tests/backpack/should_compile/bkp44.bkp
+++ /dev/null
@@ -1,23 +0,0 @@
-unit p where
-    signature A where
-        data T
-        x :: Bool
-    signature B where
-        import A
-        y :: T
-        z :: Bool
-unit q where
-    dependency signature p[A=<A>,B=<B>]
-    signature A (x) where
-    signature B (z) where
-    module M(y) where
-        import A
-        import B
-        y = x && z
-unit pimpl where
-    module A where
-        x = True
-    module B where
-        z = False
-unit r where
-    dependency q[A=pimpl:A,B=pimpl:B]
diff --git a/testsuite/tests/backpack/should_compile/bkp44.stderr b/testsuite/tests/backpack/should_compile/bkp44.stderr
deleted file mode 100644
index 83a8578dcd6caf5aaf2d10f66dd2c68c4a51aee8..0000000000000000000000000000000000000000
--- a/testsuite/tests/backpack/should_compile/bkp44.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-[1 of 4] Processing p
-  [1 of 2] Compiling A[sig]           ( p/A.hsig, nothing )
-  [2 of 2] Compiling B[sig]           ( p/B.hsig, nothing )
-[2 of 4] Processing q
-  [1 of 4] Compiling A[sig]           ( q/A.hsig, nothing )
-  [2 of 4] Compiling B[sig]           ( q/B.hsig, nothing )
-  [3 of 4] Compiling M                ( q/M.hs, nothing )
-  [4 of 4] Instantiating p
-[3 of 4] Processing pimpl
-  Instantiating pimpl
-  [1 of 2] Compiling A                ( pimpl/A.hs, bkp44.out/pimpl/A.o )
-  [2 of 2] Compiling B                ( pimpl/B.hs, bkp44.out/pimpl/B.o )
-[4 of 4] Processing r
-  Instantiating r
-  [1 of 1] Including q[A=pimpl:A,B=pimpl:B]
-    Instantiating q[A=pimpl:A,B=pimpl:B]
-    [1 of 3] Compiling A[sig]           ( q/A.hsig, bkp44.out/q/q-BxPafal3NcFHV8AOBzU3fg/A.o )
-    [2 of 3] Compiling B[sig]           ( q/B.hsig, bkp44.out/q/q-BxPafal3NcFHV8AOBzU3fg/B.o )
-    [3 of 3] Compiling M                ( q/M.hs, bkp44.out/q/q-BxPafal3NcFHV8AOBzU3fg/M.o )
-  [1 of 1] Instantiating q
diff --git a/testsuite/tests/parser/should_compile/DumpRenamedAst.stderr b/testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
index 31f8d36bb35cde2bf574626780be7ad3b786b2d6..cd3455b92a8887934e74e5db1fc46e6582571028 100644
--- a/testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
+++ b/testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
@@ -1373,7 +1373,9 @@
         [(L
           (SrcSpanAnn (EpAnnNotUsed) { DumpRenamedAst.hs:8:19-22 })
           (IEThingAbs
-           (EpAnnNotUsed)
+           ((,)
+            (Nothing)
+            (EpAnnNotUsed))
            (L
             (SrcSpanAnn (EpAnnNotUsed) { DumpRenamedAst.hs:8:19-22 })
             (IEName
diff --git a/testsuite/tests/parser/should_compile/T14189.stderr b/testsuite/tests/parser/should_compile/T14189.stderr
index 1bd38be52a19045ca956b2ce5ee081ad74581b98..5fd2724f165014f6cb34b2704703e3857bcaeba1 100644
--- a/testsuite/tests/parser/should_compile/T14189.stderr
+++ b/testsuite/tests/parser/should_compile/T14189.stderr
@@ -186,14 +186,16 @@
      (L
       (SrcSpanAnn (EpAnnNotUsed) { T14189.hs:3:3-15 })
       (IEThingWith
-       (EpAnn
-        (Anchor
-         { T14189.hs:3:3-8 }
-         (UnchangedAnchor))
-        [(AddEpAnn AnnOpenP (EpaSpan { T14189.hs:3:10 }))
-        ,(AddEpAnn AnnCloseP (EpaSpan { T14189.hs:3:15 }))]
-        (EpaComments
-         []))
+       ((,)
+        (Nothing)
+        (EpAnn
+         (Anchor
+          { T14189.hs:3:3-8 }
+          (UnchangedAnchor))
+         [(AddEpAnn AnnOpenP (EpaSpan { T14189.hs:3:10 }))
+         ,(AddEpAnn AnnCloseP (EpaSpan { T14189.hs:3:15 }))]
+         (EpaComments
+          [])))
        (L
         (SrcSpanAnn (EpAnnNotUsed) { T14189.hs:3:3-8 })
         (IEName
diff --git a/testsuite/tests/printer/Makefile b/testsuite/tests/printer/Makefile
index de88dea3f050a65310220f7959a9a54298601261..cab3e0631344f4586c74414a1eac58cf75342bfd 100644
--- a/testsuite/tests/printer/Makefile
+++ b/testsuite/tests/printer/Makefile
@@ -729,6 +729,11 @@ PprCommentPlacement2:
 	$(CHECK_PPR)   $(LIBDIR) PprCommentPlacement2.hs
 	$(CHECK_EXACT) $(LIBDIR) PprCommentPlacement2.hs
 
+.PHONY: PprExportWarn
+PprExportWarn:
+	$(CHECK_PPR)   $(LIBDIR) PprExportWarn.hs
+	$(CHECK_EXACT) $(LIBDIR) PprExportWarn.hs
+
 .PHONY: Test20243
 Test20243:
 	$(CHECK_PPR)   $(LIBDIR) Test20243.hs
diff --git a/testsuite/tests/printer/PprExportWarn.hs b/testsuite/tests/printer/PprExportWarn.hs
new file mode 100644
index 0000000000000000000000000000000000000000..d68cc06060233b68dcb2307b63e0dfbb8248d645
--- /dev/null
+++ b/testsuite/tests/printer/PprExportWarn.hs
@@ -0,0 +1,31 @@
+{-# LANGUAGE PatternSynonyms #-}
+module PprExportWarning (
+        {-# WARNING "Just because I can but a really long message" #-}
+        Foo(..),
+        {-# DEPRECATED "Just because" #-}
+        reallyreallyreallyreallyreallyreallyreallyreallylongname,
+        {-# DEPRECATED "Just because" #-} Bar(Bar1, Bar2),
+        {-# WARNING "Just because" #-} name,
+        {-# DEPRECATED ["Reason", 
+                        "Another reason"] #-} 
+        Baz,
+        {-# DEPRECATED [ ] #-} module GHC,
+        {-# WARNING "Dummy Pattern" #-} pattern Dummy,
+        Foo'(..), 
+        reallyreallyreallyreallyreallyreallyreallyreallylongname',
+        Bar'(Bar1, Bar2), name', Baz', module Data.List, pattern Dummy'
+    ) where
+import GHC
+import Data.List
+data Foo = Foo1 | Foo2 | Foo3
+reallyreallyreallyreallyreallyreallyreallyreallylongname = undefined
+data Bar = Bar1 | Bar2 | Bar3
+name = undefined
+data Baz
+pattern Dummy = Foo1
+data Foo' = Foo1 | Foo2 | Foo3
+reallyreallyreallyreallyreallyreallyreallyreallylongname' = undefined
+data Bar' = Bar1 | Bar2 | Bar3
+name' = undefined
+data Baz'
+pattern Dummy' = Foo1
diff --git a/testsuite/tests/printer/all.T b/testsuite/tests/printer/all.T
index e9de8ea590d1187c58a756345bf33e6f3430dc15..b401556590ed96d2b1794e9ef096695385afcdf9 100644
--- a/testsuite/tests/printer/all.T
+++ b/testsuite/tests/printer/all.T
@@ -171,6 +171,7 @@ test('PprT13747', [ignore_stderr, req_ppr_deps], makefile_test, ['PprT13747'])
 test('PprBracesSemiDataDecl', [ignore_stderr, req_ppr_deps], makefile_test, ['PprBracesSemiDataDecl'])
 test('PprUnicodeSyntax', [ignore_stderr, req_ppr_deps], makefile_test, ['PprUnicodeSyntax'])
 test('PprCommentPlacement2', [ignore_stderr, req_ppr_deps], makefile_test, ['PprCommentPlacement2'])
+test('PprExportWarn', [ignore_stderr, req_ppr_deps], makefile_test, ['PprExportWarn'])
 
 test('Test20243', [ignore_stderr, req_ppr_deps], makefile_test, ['Test20243'])
 test('Test20247', [ignore_stderr, req_ppr_deps], makefile_test, ['Test20247'])
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings1.hs b/testsuite/tests/rename/should_compile/ExportWarnings1.hs
new file mode 100644
index 0000000000000000000000000000000000000000..c78a2cff7ca139d60bfc2f4e9d9616e07cb59547
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings1.hs
@@ -0,0 +1,5 @@
+-- Case for explicit mentions of imports
+module ExportWarnings1 () where
+
+import ExportWarnings_aux (x, S(S1))
+import ExportWarnings_base (x, T(T1), V, B)
\ No newline at end of file
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings1.stderr b/testsuite/tests/rename/should_compile/ExportWarnings1.stderr
new file mode 100644
index 0000000000000000000000000000000000000000..7870a128f1afc71529d91f31ea0d5a2a5886cb1d
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings1.stderr
@@ -0,0 +1,30 @@
+
+ExportWarnings1.hs:4:28: warning: [GHC-63394] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of ‘x’ (imported from ExportWarnings_aux): "warn"
+
+ExportWarnings1.hs:4:31: warning: [GHC-63394] [-Wx-custom (in -Wextended-warnings)]
+    In the use of data constructor ‘S1’
+    (imported from ExportWarnings_aux):
+    "is
+     deprecated"
+
+ExportWarnings1.hs:4:31: warning: [GHC-63394] [-Wx-custom (in -Wextended-warnings)]
+    In the use of type constructor or class ‘S’
+    (imported from ExportWarnings_aux):
+    "is
+     deprecated"
+
+ExportWarnings1.hs:5:32: warning: [GHC-68441] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of data constructor ‘T1’
+    (imported from ExportWarnings_base):
+    Deprecated: "warn"
+
+ExportWarnings1.hs:5:32: warning: [GHC-68441] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of type constructor or class ‘T’
+    (imported from ExportWarnings_base):
+    Deprecated: "warn"
+
+ExportWarnings1.hs:5:39: warning: [GHC-68441] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of type constructor or class ‘V’
+    (imported from ExportWarnings_base):
+    Deprecated: ""
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings2.hs b/testsuite/tests/rename/should_compile/ExportWarnings2.hs
new file mode 100644
index 0000000000000000000000000000000000000000..4ad6d88ae9c46817e841a31a4e2963032550d012
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings2.hs
@@ -0,0 +1,7 @@
+-- Case for no explicit mention but usage
+module ExportWarnings2 () where
+
+import ExportWarnings_aux
+import ExportWarnings_aux2
+foo = x
+type U = V
\ No newline at end of file
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings2.stderr b/testsuite/tests/rename/should_compile/ExportWarnings2.stderr
new file mode 100644
index 0000000000000000000000000000000000000000..5891b1ec085f310ffe20ed24852f5088e4e38d28
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings2.stderr
@@ -0,0 +1,12 @@
+
+ExportWarnings_aux2.hs:3:5: warning: [GHC-68441] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of type constructor or class ‘V’
+    (imported from ExportWarnings_base):
+    Deprecated: ""
+
+ExportWarnings2.hs:6:7: warning: [GHC-63394] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of ‘x’ (imported from ExportWarnings_aux): "warn"
+
+ExportWarnings2.hs:6:7: warning: [GHC-63394] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of ‘x’ (imported from ExportWarnings_aux2):
+    "different warn"
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings3.hs b/testsuite/tests/rename/should_compile/ExportWarnings3.hs
new file mode 100644
index 0000000000000000000000000000000000000000..3be7e924abc7b3f59befacb5fd6e495262bd22b4
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings3.hs
@@ -0,0 +1,14 @@
+-- Case for explicit usage of imports + usage when not all import paths are deprecated
+module ExportWarnings3 () where
+
+import ExportWarnings_base
+import ExportWarnings_aux
+foo = x
+
+bar :: S -> Int -> T
+bar S1 v = T1 v
+bar _ v  = T2 v
+
+
+baz :: V -> V
+baz = id
\ No newline at end of file
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings3.stderr b/testsuite/tests/rename/should_compile/ExportWarnings3.stderr
new file mode 100644
index 0000000000000000000000000000000000000000..230a4832c302b620e74ef4f4e93acb13ab37bbd0
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings3.stderr
@@ -0,0 +1,37 @@
+
+ExportWarnings3.hs:8:8: warning: [GHC-63394] [-Wx-custom (in -Wextended-warnings)]
+    In the use of type constructor or class ‘S’
+    (imported from ExportWarnings_aux):
+    "is
+     deprecated"
+
+ExportWarnings3.hs:8:20: warning: [GHC-68441] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of type constructor or class ‘T’
+    (imported from ExportWarnings_base):
+    Deprecated: "warn"
+
+ExportWarnings3.hs:9:5: warning: [GHC-63394] [-Wx-custom (in -Wextended-warnings)]
+    In the use of data constructor ‘S1’
+    (imported from ExportWarnings_aux):
+    "is
+     deprecated"
+
+ExportWarnings3.hs:9:12: warning: [GHC-68441] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of data constructor ‘T1’
+    (imported from ExportWarnings_base):
+    Deprecated: "warn"
+
+ExportWarnings3.hs:10:12: warning: [GHC-68441] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of data constructor ‘T2’
+    (imported from ExportWarnings_base):
+    Deprecated: "warn"
+
+ExportWarnings3.hs:13:8: warning: [GHC-68441] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of type constructor or class ‘V’
+    (imported from ExportWarnings_base):
+    Deprecated: ""
+
+ExportWarnings3.hs:13:13: warning: [GHC-68441] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of type constructor or class ‘V’
+    (imported from ExportWarnings_base):
+    Deprecated: ""
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings4.hs b/testsuite/tests/rename/should_compile/ExportWarnings4.hs
new file mode 100644
index 0000000000000000000000000000000000000000..c1b8f9cee8ed5b458512bce78e9f23c338b61449
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings4.hs
@@ -0,0 +1,6 @@
+-- Case for when not all import paths are deprecated but the name is qualified
+module ExportWarnings4 () where
+
+import ExportWarnings_base
+import ExportWarnings_aux
+foo = ExportWarnings_aux.x
\ No newline at end of file
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings4.stderr b/testsuite/tests/rename/should_compile/ExportWarnings4.stderr
new file mode 100644
index 0000000000000000000000000000000000000000..892ff8192e639058111f7bc46b105f651f8d5f98
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings4.stderr
@@ -0,0 +1,3 @@
+
+ExportWarnings4.hs:6:7: warning: [GHC-63394] [-Wdeprecations (in -Wextended-warnings)]
+    In the use of ‘x’ (imported from ExportWarnings_aux): "warn"
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings5.hs b/testsuite/tests/rename/should_compile/ExportWarnings5.hs
new file mode 100644
index 0000000000000000000000000000000000000000..d4aedd9d6f2c651536a74ed985543dc2919c3772
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings5.hs
@@ -0,0 +1,5 @@
+-- Case for when names are mentioned in the hiding clauses
+module ExportWarnings5 () where
+
+import ExportWarnings_aux hiding (x, S(..))
+import ExportWarnings_base hiding (x, T(T2, y), V)
\ No newline at end of file
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings6.hs b/testsuite/tests/rename/should_compile/ExportWarnings6.hs
new file mode 100644
index 0000000000000000000000000000000000000000..bc18b37346c03a2d824d0a1e43ef02229795d22b
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings6.hs
@@ -0,0 +1,2 @@
+module ExportWarnings6 ({-# WARNING "warn" #-} x, x) where
+x = 1
\ No newline at end of file
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings6.stderr b/testsuite/tests/rename/should_compile/ExportWarnings6.stderr
new file mode 100644
index 0000000000000000000000000000000000000000..0893d927471cac3489e11a7554e274f529843dfb
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings6.stderr
@@ -0,0 +1,7 @@
+
+ExportWarnings6.hs:1:25: warning: [GHC-94721] [-Wincomplete-export-warnings (in -Wall)]
+    ‘x’ will not have its export warned about
+    missing export warning at ExportWarnings6.hs:1:51
+
+ExportWarnings6.hs:1:51: warning: [GHC-47854] [-Wduplicate-exports (in -Wdefault)]
+    ‘x’ is exported by ‘x’ and ‘{-# WARNING "warn" #-} x’
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings_aux.hs b/testsuite/tests/rename/should_compile/ExportWarnings_aux.hs
new file mode 100644
index 0000000000000000000000000000000000000000..c8f38debe51d3e0fe68964b973bc97b88687031b
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings_aux.hs
@@ -0,0 +1,7 @@
+module ExportWarnings_aux (
+    {-# WARNING "warn" #-} x, 
+    {-# WARNING in "x-custom" ["is", "deprecated"] #-} S(S1), 
+  ) where
+import ExportWarnings_base (x)
+
+data S = S1 | S2
\ No newline at end of file
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings_aux2.hs b/testsuite/tests/rename/should_compile/ExportWarnings_aux2.hs
new file mode 100644
index 0000000000000000000000000000000000000000..c9327b20a0ca55204179f2c0078f76ecf6ac6993
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings_aux2.hs
@@ -0,0 +1,5 @@
+module ExportWarnings_aux2 (
+    {-# WARNING "different warn" #-} x,
+    V
+  ) where
+import ExportWarnings_base
\ No newline at end of file
diff --git a/testsuite/tests/rename/should_compile/ExportWarnings_base.hs b/testsuite/tests/rename/should_compile/ExportWarnings_base.hs
new file mode 100644
index 0000000000000000000000000000000000000000..cb4a0971c8b6aa184fd363f6eff62063b381c1b7
--- /dev/null
+++ b/testsuite/tests/rename/should_compile/ExportWarnings_base.hs
@@ -0,0 +1,14 @@
+module ExportWarnings_base (
+    x, 
+    {-# DEPRECATED "warn" #-} T(..), 
+    {-# WARNING "no warn" #-} B(B1), 
+    B(B2), 
+    {-# DEPRECATED [] #-} V
+  ) where
+
+x :: Bool
+x = True
+
+data T = T1 {y :: Int} | T2 {y :: Int}
+data B = B1 | B2
+newtype V = V ()
\ No newline at end of file
diff --git a/testsuite/tests/rename/should_compile/all.T b/testsuite/tests/rename/should_compile/all.T
index ad9301b273a17aa37e753e359d857679bdff9973..1eefe0b0806db8448242d99df562e532e2673aa6 100644
--- a/testsuite/tests/rename/should_compile/all.T
+++ b/testsuite/tests/rename/should_compile/all.T
@@ -214,3 +214,9 @@ test('T23318', normal, compile, ['-Wduplicate-exports'])
 test('T23434', normal, compile, [''])
 test('T23510b', normal, compile, [''])
 test('T23512b', normal, compile, [''])
+test('ExportWarnings1', extra_files(['ExportWarnings_base.hs', 'ExportWarnings_aux.hs']), multimod_compile, ['ExportWarnings1', '-v0 -Wno-duplicate-exports -Wx-custom'])
+test('ExportWarnings2', extra_files(['ExportWarnings_base.hs', 'ExportWarnings_aux.hs', 'ExportWarnings_aux2.hs']), multimod_compile, ['ExportWarnings2', '-v0 -Wno-duplicate-exports -Wx-custom'])
+test('ExportWarnings3', extra_files(['ExportWarnings_base.hs', 'ExportWarnings_aux.hs']), multimod_compile, ['ExportWarnings3', '-v0 -Wno-duplicate-exports -Wx-custom'])
+test('ExportWarnings4', extra_files(['ExportWarnings_base.hs', 'ExportWarnings_aux.hs']), multimod_compile, ['ExportWarnings4', '-v0 -Wno-duplicate-exports -Wx-custom'])
+test('ExportWarnings5', extra_files(['ExportWarnings_base.hs', 'ExportWarnings_aux.hs']), multimod_compile, ['ExportWarnings5', '-v0 -Wno-duplicate-exports -Wx-custom'])
+test('ExportWarnings6', normal, compile, ['-Wincomplete-export-warnings'])
diff --git a/testsuite/tests/rename/should_fail/DifferentExportWarnings.hs b/testsuite/tests/rename/should_fail/DifferentExportWarnings.hs
new file mode 100644
index 0000000000000000000000000000000000000000..a9ae815f3d18e56d30dc1a7d29cc0d96c556d483
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/DifferentExportWarnings.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE PatternSynonyms #-}
+module DifferentExportWarnings (
+    {-# DEPRECATED "test" #-} Foo(..),
+    {-# DEPRECATED "test" #-} Foo(Foo1),
+    {-# WARNING "test" #-} Foo(Foo2),
+    {-# WARNING in "x-cat" "test2" #-} Bar(Dummy),
+    {-# WARNING in "x-cat2" "test2" #-} Bar,
+    {-# WARNING "test3-a" #-} module DifferentExportWarningsA,
+    {-# WARNING "test3-b" #-} module DifferentExportWarningsA,
+    {-# WARNING "test3-b" #-} x
+  ) where
+
+import DifferentExportWarningsA (x, y)
+
+data Foo = Foo1 | Foo2
+data Bar = Bar1 | Bar2
+pattern Dummy = Bar1
\ No newline at end of file
diff --git a/testsuite/tests/rename/should_fail/DifferentExportWarnings.stderr b/testsuite/tests/rename/should_fail/DifferentExportWarnings.stderr
new file mode 100644
index 0000000000000000000000000000000000000000..4385f9a9c209f2ace7fab2f33c91d74da5061c73
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/DifferentExportWarnings.stderr
@@ -0,0 +1,21 @@
+
+DifferentExportWarnings.hs:5:5: error: [GHC-92878]
+    ‘Foo2’ exported with different error messages
+    at DifferentExportWarnings.hs:3:5-37
+
+DifferentExportWarnings.hs:5:5: error: [GHC-92878]
+    ‘Foo’ exported with different error messages
+    at DifferentExportWarnings.hs:3:5-37
+       DifferentExportWarnings.hs:4:5-39
+
+DifferentExportWarnings.hs:7:5: error: [GHC-92878]
+    ‘Bar’ exported with different error messages
+    at DifferentExportWarnings.hs:6:5-49
+
+DifferentExportWarnings.hs:9:5: error: [GHC-92878]
+    ‘y’ exported with different error messages
+    at DifferentExportWarnings.hs:8:5-61
+
+DifferentExportWarnings.hs:10:5: error: [GHC-92878]
+    ‘x’ exported with different error messages
+    at DifferentExportWarnings.hs:8:5-61
diff --git a/testsuite/tests/rename/should_fail/DifferentExportWarningsA.hs b/testsuite/tests/rename/should_fail/DifferentExportWarningsA.hs
new file mode 100644
index 0000000000000000000000000000000000000000..1e7d7385033e51171dbbb5d7cb8d3998ae91c923
--- /dev/null
+++ b/testsuite/tests/rename/should_fail/DifferentExportWarningsA.hs
@@ -0,0 +1,6 @@
+{-# LANGUAGE PatternSynonyms #-}
+module DifferentExportWarningsA (x, y, z) where
+
+x = undefined
+y = undefined
+z = undefined
\ No newline at end of file
diff --git a/testsuite/tests/rename/should_fail/all.T b/testsuite/tests/rename/should_fail/all.T
index 4e97f45cfdf44f3a3f9ab45517c150580e3ff5c1..2eccda4e9e610a5567f21f854f34aa6f99747134 100644
--- a/testsuite/tests/rename/should_fail/all.T
+++ b/testsuite/tests/rename/should_fail/all.T
@@ -204,3 +204,4 @@ test('T16635a', normal, compile_fail, [''])
 test('T16635b', normal, compile_fail, [''])
 test('T16635c', normal, compile_fail, [''])
 test('T23512a', normal, compile_fail, [''])
+test('DifferentExportWarnings', normal, multimod_compile_fail, ['DifferentExportWarnings', '-v0'])
diff --git a/testsuite/tests/showIface/PragmaDocs.hs b/testsuite/tests/showIface/PragmaDocs.hs
index 3e7a068d71a85c74eeff9d5aa97b0564600d7665..e3b3ecf6174c72a4b35c46973bb90b8bf7e4febe 100644
--- a/testsuite/tests/showIface/PragmaDocs.hs
+++ b/testsuite/tests/showIface/PragmaDocs.hs
@@ -1,4 +1,4 @@
-module PragmaDocs where
+module PragmaDocs ({-# DEPRECATED "Do not use" #-} contains) where
 
 {-# DEPRECATED contains "Use `elem` instead." #-}
 contains :: (Eq a, Foldable f) => f a -> a -> Bool
diff --git a/testsuite/tests/showIface/PragmaDocs.stdout b/testsuite/tests/showIface/PragmaDocs.stdout
index b2a9c929c6d477e110d386d4fbb8cd4c6a08e1f7..e905057dd8253b6712aa6593263789f68a038f58 100644
--- a/testsuite/tests/showIface/PragmaDocs.stdout
+++ b/testsuite/tests/showIface/PragmaDocs.stdout
@@ -1,6 +1,8 @@
-Warnings: x "These are useless"
-          y "These are useless"
-          contains "Use `elem` instead."
+Warnings:
+  Deprecated names: x "These are useless"
+                    y "These are useless"
+                    contains "Use `elem` instead."
+  Deprecated exports: contains "Do not use"
 trusted: none
 require own pkg trusted: False
 docs:
@@ -13,10 +15,6 @@ docs:
        documentation structure:
          avails:
            [contains]
-         avails:
-           [x]
-         avails:
-           [y]
        named chunks:
        haddock options:
        language:
diff --git a/utils/check-exact/ExactPrint.hs b/utils/check-exact/ExactPrint.hs
index 30a8831ddfec71b7ab548c912797adbaad461b92..0bca517507186e35c205a4522e2f478f2e456f47 100644
--- a/utils/check-exact/ExactPrint.hs
+++ b/utils/check-exact/ExactPrint.hs
@@ -4467,37 +4467,41 @@ instance ExactPrint (LocatedL (BF.BooleanFormula (LocatedN RdrName))) where
 
 instance ExactPrint (IE GhcPs) where
   getAnnotationEntry (IEVar _ _)            = NoEntryVal
-  getAnnotationEntry (IEThingAbs an _)      = fromAnn an
-  getAnnotationEntry (IEThingAll an _)      = fromAnn an
-  getAnnotationEntry (IEThingWith an _ _ _) = fromAnn an
-  getAnnotationEntry (IEModuleContents an _)= fromAnn an
+  getAnnotationEntry (IEThingAbs (_, an) _)      = fromAnn an
+  getAnnotationEntry (IEThingAll (_, an) _)      = fromAnn an
+  getAnnotationEntry (IEThingWith (_, an) _ _ _) = fromAnn an
+  getAnnotationEntry (IEModuleContents (_, an) _)= fromAnn an
   getAnnotationEntry (IEGroup _ _ _)        = NoEntryVal
   getAnnotationEntry (IEDoc _ _)            = NoEntryVal
   getAnnotationEntry (IEDocNamed _ _)       = NoEntryVal
 
   setAnnotationAnchor a@(IEVar _ _)             _ _s = a
-  setAnnotationAnchor (IEThingAbs an a)       anc cs = (IEThingAbs (setAnchorEpa an anc cs) a)
-  setAnnotationAnchor (IEThingAll an a)       anc cs = (IEThingAll (setAnchorEpa an anc cs) a)
-  setAnnotationAnchor (IEThingWith an a b c)  anc cs = (IEThingWith (setAnchorEpa an anc cs) a b c)
-  setAnnotationAnchor (IEModuleContents an a) anc cs = (IEModuleContents (setAnchorEpa an anc cs) a)
+  setAnnotationAnchor (IEThingAbs (depr, an) a)       anc cs = (IEThingAbs (depr, setAnchorEpa an anc cs) a)
+  setAnnotationAnchor (IEThingAll (depr, an) a)       anc cs = (IEThingAll (depr, setAnchorEpa an anc cs) a)
+  setAnnotationAnchor (IEThingWith (depr, an) a b c)  anc cs = (IEThingWith (depr, setAnchorEpa an anc cs) a b c)
+  setAnnotationAnchor (IEModuleContents (depr, an) a) anc cs = (IEModuleContents (depr, setAnchorEpa an anc cs) a)
   setAnnotationAnchor a@(IEGroup _ _ _)         _ _s = a
   setAnnotationAnchor a@(IEDoc _ _)             _ _s = a
   setAnnotationAnchor a@(IEDocNamed _ _)        _ _s = a
 
-  exact (IEVar x ln) = do
+  exact (IEVar depr ln) = do
+    depr' <- markAnnotated depr
     ln' <- markAnnotated ln
-    return (IEVar x ln')
-  exact (IEThingAbs x thing) = do
+    return (IEVar depr' ln')
+  exact (IEThingAbs (depr, an) thing) = do
+    depr' <- markAnnotated depr
     thing' <- markAnnotated thing
-    return (IEThingAbs x thing')
-  exact (IEThingAll an thing) = do
+    return (IEThingAbs (depr', an) thing')
+  exact (IEThingAll (depr, an) thing) = do
+    depr' <- markAnnotated depr
     thing' <- markAnnotated thing
     an0 <- markEpAnnL an  lidl AnnOpenP
     an1 <- markEpAnnL an0 lidl AnnDotdot
     an2 <- markEpAnnL an1 lidl AnnCloseP
-    return (IEThingAll an2 thing')
+    return (IEThingAll (depr', an2) thing')
 
-  exact (IEThingWith an thing wc withs) = do
+  exact (IEThingWith (depr, an) thing wc withs) = do
+    depr' <- markAnnotated depr
     thing' <- markAnnotated thing
     an0 <- markEpAnnL an lidl AnnOpenP
     (an1, wc', withs') <-
@@ -4513,12 +4517,13 @@ instance ExactPrint (IE GhcPs) where
           as' <- markAnnotated as
           return (an2, wc, bs'++as')
     an2 <- markEpAnnL an1 lidl AnnCloseP
-    return (IEThingWith an2 thing' wc' withs')
+    return (IEThingWith (depr', an2) thing' wc' withs')
 
-  exact (IEModuleContents an m) = do
+  exact (IEModuleContents (depr, an) m) = do
+    depr' <- markAnnotated depr
     an0 <- markEpAnnL an lidl AnnModule
     m' <- markAnnotated m
-    return (IEModuleContents an0 m')
+    return (IEModuleContents (depr', an0) m')
 
   exact x = error $ "missing match for IE:" ++ showAst x
 
@@ -4849,7 +4854,7 @@ getPosP = gets epPos
 
 setPosP :: (Monad m, Monoid w) => Pos -> EP w m ()
 setPosP l = do
-  -- debugM $ "setPosP:" ++ show l
+  debugM $ "setPosP:" ++ show l
   modify (\s -> s {epPos = l})
 
 getExtraDP :: (Monad m, Monoid w) => EP w m (Maybe Anchor)
diff --git a/utils/check-exact/Main.hs b/utils/check-exact/Main.hs
index 74525dd5f9cd4792d2f08a354323c47155813388..b498f6cc48af03c50fa8a25e2a1bb06d54a11f26 100644
--- a/utils/check-exact/Main.hs
+++ b/utils/check-exact/Main.hs
@@ -896,8 +896,8 @@ addHiding1 _libdir (L l p) = do
           [L li imp1,imp2] = hsmodImports p
           n1 = L (noAnnSrcSpanDP0 l1) (mkVarUnqual (mkFastString "n1"))
           n2 = L (noAnnSrcSpanDP0 l2) (mkVarUnqual (mkFastString "n2"))
-          v1 = L (addComma $ noAnnSrcSpanDP0 l1) (IEVar noExtField (L (noAnnSrcSpanDP0 l1) (IEName noExtField n1)))
-          v2 = L (           noAnnSrcSpanDP0 l2) (IEVar noExtField (L (noAnnSrcSpanDP0 l2) (IEName noExtField n2)))
+          v1 = L (addComma $ noAnnSrcSpanDP0 l1) (IEVar Nothing (L (noAnnSrcSpanDP0 l1) (IEName noExtField n1)))
+          v2 = L (           noAnnSrcSpanDP0 l2) (IEVar Nothing (L (noAnnSrcSpanDP0 l2) (IEName noExtField n2)))
           impHiding = L (SrcSpanAnn (EpAnn (Anchor (realSrcSpan l0) m0)
                                      (AnnList Nothing
                                               (Just (AddEpAnn AnnOpenP  d1))
@@ -933,8 +933,8 @@ addHiding2 _libdir top = do
                                        emptyComments) (locA lh))
           n1 = L (noAnnSrcSpanDP0 l1) (mkVarUnqual (mkFastString "n1"))
           n2 = L (noAnnSrcSpanDP0 l2) (mkVarUnqual (mkFastString "n2"))
-          v1 = L (addComma $ noAnnSrcSpanDP0 l1) (IEVar noExtField (L (noAnnSrcSpanDP0 l1) (IEName noExtField n1)))
-          v2 = L (           noAnnSrcSpanDP0 l2) (IEVar noExtField (L (noAnnSrcSpanDP0 l2) (IEName noExtField n2)))
+          v1 = L (addComma $ noAnnSrcSpanDP0 l1) (IEVar Nothing (L (noAnnSrcSpanDP0 l1) (IEName noExtField n1)))
+          v2 = L (           noAnnSrcSpanDP0 l2) (IEVar Nothing (L (noAnnSrcSpanDP0 l2) (IEName noExtField n2)))
           L ln n = last ns
           n' = L (addComma ln) n
           imp1' = imp1 { ideclImportList = Just (EverythingBut, L lh' (init ns ++ [n',v1,v2]))}
diff --git a/utils/haddock b/utils/haddock
index bfb52adefa028f541672623321eb1b3d21dd2547..081aa819f292323387c84bbc2192215e88df6efe 160000
--- a/utils/haddock
+++ b/utils/haddock
@@ -1 +1 @@
-Subproject commit bfb52adefa028f541672623321eb1b3d21dd2547
+Subproject commit 081aa819f292323387c84bbc2192215e88df6efe