[clang] 7a54140 - Revert "[C++20] [Modules] Implement Reachable initiallly"

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 28 21:44:15 PDT 2022


Author: Chuanqi Xu
Date: 2022-06-29T12:43:26+08:00
New Revision: 7a541406b5a23a811a4f37432292a6de3307b0f1

URL: https://github.com/llvm/llvm-project/commit/7a541406b5a23a811a4f37432292a6de3307b0f1
DIFF: https://github.com/llvm/llvm-project/commit/7a541406b5a23a811a4f37432292a6de3307b0f1.diff

LOG: Revert "[C++20] [Modules] Implement Reachable initiallly"

This reverts commit a223ba0a697c1598b434cf2495c9cd9ec5640fc7.

The previous commit don't contain additional information, which is bad.

Added: 
    

Modified: 
    clang/include/clang/AST/DeclBase.h
    clang/include/clang/Basic/Module.h
    clang/include/clang/Sema/Lookup.h
    clang/include/clang/Sema/Sema.h
    clang/lib/AST/Decl.cpp
    clang/lib/Sema/SemaCXXScopeSpec.cpp
    clang/lib/Sema/SemaDeclCXX.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/lib/Sema/SemaLookup.cpp
    clang/lib/Sema/SemaModule.cpp
    clang/lib/Sema/SemaTemplate.cpp
    clang/lib/Sema/SemaType.cpp
    clang/lib/Serialization/ASTReaderDecl.cpp
    clang/lib/Serialization/ASTWriterDecl.cpp
    clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp
    clang/test/CXX/module/module.import/p2.cpp
    clang/test/CXX/module/module.interface/p2.cpp
    clang/test/CXX/module/module.unit/p7/t6.cpp
    clang/test/CXX/modules-ts/basic/basic.link/p2/other.cpp
    clang/test/Modules/cxx20-10-1-ex2.cpp
    clang/test/Modules/module-private.cpp

Removed: 
    clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp
    clang/test/CXX/module/module.context/p7.cpp
    clang/test/CXX/module/module.interface/p7.cpp
    clang/test/CXX/module/module.reach/ex1.cpp
    clang/test/CXX/module/module.reach/p2.cpp
    clang/test/CXX/module/module.reach/p4/TransitiveImport.cpp
    clang/test/CXX/module/module.reach/p5.cpp
    clang/test/Modules/Reachability-Private.cpp
    clang/test/Modules/Reachability-func-default-arg.cpp
    clang/test/Modules/Reachability-func-ret.cpp
    clang/test/Modules/Reachability-template-default-arg.cpp
    clang/test/Modules/Reachability-template-instantiation.cpp
    clang/test/Modules/Reachability-using-templates.cpp
    clang/test/Modules/Reachability-using.cpp
    clang/test/Modules/derived_class.cpp
    clang/test/Modules/explicitly-specialized-template.cpp
    clang/test/Modules/template-function-specialization.cpp
    clang/test/Modules/template_default_argument.cpp


################################################################################
diff  --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 52fe8dd6b1e57..0611cf5ccb000 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -225,15 +225,8 @@ class alignas(8) Decl {
     /// module is imported.
     VisibleWhenImported,
 
-    /// This declaration has an owning module, and is visible to lookups
-    /// that occurs within that module. And it is reachable in other module
-    /// when the owning module is transitively imported.
-    ReachableWhenImported,
-
     /// This declaration has an owning module, but is only visible to
     /// lookups that occur within that module.
-    /// The discarded declarations in global module fragment belongs
-    /// to this group too.
     ModulePrivate
   };
 
@@ -242,8 +235,8 @@ class alignas(8) Decl {
   /// DeclContext. These pointers form the linked list that is
   /// traversed via DeclContext's decls_begin()/decls_end().
   ///
-  /// The extra three bits are used for the ModuleOwnershipKind.
-  llvm::PointerIntPair<Decl *, 3, ModuleOwnershipKind> NextInContextAndBits;
+  /// The extra two bits are used for the ModuleOwnershipKind.
+  llvm::PointerIntPair<Decl *, 2, ModuleOwnershipKind> NextInContextAndBits;
 
 private:
   friend class DeclContext;
@@ -629,14 +622,6 @@ class alignas(8) Decl {
   ///   export void B::f2(); // isInExportDeclContext() == true
   bool isInExportDeclContext() const;
 
-  bool isInvisibleOutsideTheOwningModule() const {
-    return getModuleOwnershipKind() > ModuleOwnershipKind::VisibleWhenImported;
-  }
-
-  /// FIXME: Implement discarding declarations actually in global module
-  /// fragment. See [module.global.frag]p3,4 for details.
-  bool isDiscardedInGlobalModuleFragment() const { return false; }
-
   /// Return true if this declaration has an attribute which acts as
   /// definition of the entity, such as 'alias' or 'ifunc'.
   bool hasDefiningAttr() const;
@@ -814,11 +799,6 @@ class alignas(8) Decl {
     return (int)getModuleOwnershipKind() <= (int)ModuleOwnershipKind::Visible;
   }
 
-  bool isReachable() const {
-    return (int)getModuleOwnershipKind() <=
-           (int)ModuleOwnershipKind::ReachableWhenImported;
-  }
-
   /// Set that this declaration is globally visible, even if it came from a
   /// module that is not visible.
   void setVisibleDespiteOwningModule() {

diff  --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h
index a1778baa04530..5ce5fea45c670 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -170,8 +170,6 @@ class Module {
 
   bool isPrivateModule() const { return Kind == PrivateModuleFragment; }
 
-  bool isModuleMapModule() const { return Kind == ModuleMapModule; }
-
 private:
   /// The submodules of this module, indexed by name.
   std::vector<Module *> SubModules;
@@ -538,10 +536,6 @@ class Module {
     return Kind == ModuleInterfaceUnit || isModulePartition();
   }
 
-  bool isModuleInterfaceUnit() const {
-    return Kind == ModuleInterfaceUnit || Kind == ModulePartitionInterface;
-  }
-
   /// Get the primary module interface name from a partition.
   StringRef getPrimaryModuleInterfaceName() const {
     // Technically, global module fragment belongs to global module. And global

diff  --git a/clang/include/clang/Sema/Lookup.h b/clang/include/clang/Sema/Lookup.h
index 8b11273416c55..1f43ff0b5aaf6 100644
--- a/clang/include/clang/Sema/Lookup.h
+++ b/clang/include/clang/Sema/Lookup.h
@@ -346,56 +346,30 @@ class LookupResult {
 
   /// Determine whether the given declaration is visible to the
   /// program.
-  static bool isVisible(Sema &SemaRef, NamedDecl *D);
+  static bool isVisible(Sema &SemaRef, NamedDecl *D) {
+    // If this declaration is not hidden, it's visible.
+    if (D->isUnconditionallyVisible())
+      return true;
 
-  static bool isReachable(Sema &SemaRef, NamedDecl *D);
-
-  static bool isAcceptable(Sema &SemaRef, NamedDecl *D,
-                           Sema::AcceptableKind Kind) {
-    return Kind == Sema::AcceptableKind::Visible ? isVisible(SemaRef, D)
-                                                 : isReachable(SemaRef, D);
+    // During template instantiation, we can refer to hidden declarations, if
+    // they were visible in any module along the path of instantiation.
+    return isVisibleSlow(SemaRef, D);
   }
 
-  /// Determine whether this lookup is permitted to see the declaration.
-  /// Note that a reachable but not visible declaration inhabiting a namespace
-  /// is not allowed to be seen during name lookup.
-  ///
-  /// For example:
-  /// ```
-  /// // m.cppm
-  /// export module m;
-  /// struct reachable { int v; }
-  /// export auto func() { return reachable{43}; }
-  /// // Use.cpp
-  /// import m;
-  /// auto Use() {
-  ///   // Not valid. We couldn't see reachable here.
-  ///   // So isAvailableForLookup would return false when we look
-  ///   up 'reachable' here.
-  ///   // return reachable(43).v;
-  ///   // Valid. The field name 'v' is allowed during name lookup.
-  ///   // So isAvailableForLookup would return true when we look up 'v' here.
-  ///   return func().v;
-  /// }
-  /// ```
-  static bool isAvailableForLookup(Sema &SemaRef, NamedDecl *ND);
-
   /// Retrieve the accepted (re)declaration of the given declaration,
   /// if there is one.
   NamedDecl *getAcceptableDecl(NamedDecl *D) const {
     if (!D->isInIdentifierNamespace(IDNS))
       return nullptr;
 
-    if (isAvailableForLookup(getSema(), D) || isHiddenDeclarationVisible(D))
+    if (isVisible(getSema(), D) || isHiddenDeclarationVisible(D))
       return D;
 
     return getAcceptableDeclSlow(D);
   }
 
 private:
-  static bool isAcceptableSlow(Sema &SemaRef, NamedDecl *D,
-                               Sema::AcceptableKind Kind);
-  static bool isReachableSlow(Sema &SemaRef, NamedDecl *D);
+  static bool isVisibleSlow(Sema &SemaRef, NamedDecl *D);
   NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const;
 
 public:

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 07f3d2c654c1b..f3b134953d400 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -363,6 +363,8 @@ class Sema final {
 
   static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD);
 
+  bool isVisibleSlow(const NamedDecl *D);
+
   /// Determine whether two declarations should be linked together, given that
   /// the old declaration might not be visible and the new declaration might
   /// not have external linkage.
@@ -2216,8 +2218,6 @@ class Sema final {
     Default = AcceptSizeless
   };
 
-  enum class AcceptableKind { Visible, Reachable };
-
 private:
   /// Methods for marking which expressions involve dereferencing a pointer
   /// marked with the 'noderef' attribute. Expressions are checked bottom up as
@@ -2252,6 +2252,11 @@ class Sema final {
   /// Namespace definitions that we will export when they finish.
   llvm::SmallPtrSet<const NamespaceDecl*, 8> DeferredExportedNamespaces;
 
+  /// Get the module unit whose scope we are currently within.
+  Module *getCurrentModule() const {
+    return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
+  }
+
   /// Helper function to judge if we are in module purview.
   /// Return false if we are not in a module.
   bool isCurrentModulePurview() const {
@@ -2270,14 +2275,7 @@ class Sema final {
 
   bool isUsableModule(const Module *M);
 
-  bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind);
-
 public:
-  /// Get the module unit whose scope we are currently within.
-  Module *getCurrentModule() const {
-    return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
-  }
-
   /// Get the module owning an entity.
   Module *getOwningModule(const Decl *Entity) {
     return Entity->getOwningModule();
@@ -2301,20 +2299,7 @@ class Sema final {
 
   /// Determine whether a declaration is visible to name lookup.
   bool isVisible(const NamedDecl *D) {
-    return D->isUnconditionallyVisible() ||
-           isAcceptableSlow(D, AcceptableKind::Visible);
-  }
-
-  /// Determine whether a declaration is reachable.
-  bool isReachable(const NamedDecl *D) {
-    // All visible declarations are reachable.
-    return D->isUnconditionallyVisible() ||
-           isAcceptableSlow(D, AcceptableKind::Reachable);
-  }
-
-  /// Determine whether a declaration is acceptable (visible/reachable).
-  bool isAcceptable(const NamedDecl *D, AcceptableKind Kind) {
-    return Kind == AcceptableKind::Visible ? isVisible(D) : isReachable(D);
+    return D->isUnconditionallyVisible() || isVisibleSlow(D);
   }
 
   /// Determine whether any declaration of an entity is visible.
@@ -2323,17 +2308,8 @@ class Sema final {
                         llvm::SmallVectorImpl<Module *> *Modules = nullptr) {
     return isVisible(D) || hasVisibleDeclarationSlow(D, Modules);
   }
-
   bool hasVisibleDeclarationSlow(const NamedDecl *D,
                                  llvm::SmallVectorImpl<Module *> *Modules);
-  /// Determine whether any declaration of an entity is reachable.
-  bool
-  hasReachableDeclaration(const NamedDecl *D,
-                          llvm::SmallVectorImpl<Module *> *Modules = nullptr) {
-    return isReachable(D) || hasReachableDeclarationSlow(D, Modules);
-  }
-  bool hasReachableDeclarationSlow(
-      const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr);
 
   bool hasVisibleMergedDefinition(NamedDecl *Def);
   bool hasMergedDefinitionInCurrentModule(NamedDecl *Def);
@@ -2351,54 +2327,21 @@ class Sema final {
     return hasVisibleDefinition(const_cast<NamedDecl*>(D), &Hidden);
   }
 
-  /// Determine if \p D has a reachable definition. If not, suggest a
-  /// declaration that should be made reachable to expose the definition.
-  bool hasReachableDefinition(NamedDecl *D, NamedDecl **Suggested,
-                              bool OnlyNeedComplete = false);
-  bool hasReachableDefinition(NamedDecl *D) {
-    NamedDecl *Hidden;
-    return hasReachableDefinition(D, &Hidden);
-  }
-
-  bool hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested,
-                               AcceptableKind Kind,
-                               bool OnlyNeedComplete = false);
-  bool hasAcceptableDefinition(NamedDecl *D, AcceptableKind Kind) {
-    NamedDecl *Hidden;
-    return hasAcceptableDefinition(D, &Hidden, Kind);
-  }
-
   /// Determine if the template parameter \p D has a visible default argument.
   bool
   hasVisibleDefaultArgument(const NamedDecl *D,
                             llvm::SmallVectorImpl<Module *> *Modules = nullptr);
-  /// Determine if the template parameter \p D has a reachable default argument.
-  bool hasReachableDefaultArgument(
-      const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr);
-  /// Determine if the template parameter \p D has a reachable default argument.
-  bool hasAcceptableDefaultArgument(const NamedDecl *D,
-                                    llvm::SmallVectorImpl<Module *> *Modules,
-                                    Sema::AcceptableKind Kind);
 
   /// Determine if there is a visible declaration of \p D that is an explicit
   /// specialization declaration for a specialization of a template. (For a
   /// member specialization, use hasVisibleMemberSpecialization.)
   bool hasVisibleExplicitSpecialization(
       const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr);
-  /// Determine if there is a reachable declaration of \p D that is an explicit
-  /// specialization declaration for a specialization of a template. (For a
-  /// member specialization, use hasReachableMemberSpecialization.)
-  bool hasReachableExplicitSpecialization(
-      const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr);
 
   /// Determine if there is a visible declaration of \p D that is a member
   /// specialization declaration (as opposed to an instantiated declaration).
   bool hasVisibleMemberSpecialization(
       const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr);
-  /// Determine if there is a reachable declaration of \p D that is a member
-  /// specialization declaration (as opposed to an instantiated declaration).
-  bool hasReachableMemberSpecialization(
-      const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr);
 
   /// Determine if \p A and \p B are equivalent internal linkage declarations
   /// from 
diff erent modules, and thus an ambiguity error can be downgraded to
@@ -3157,9 +3100,8 @@ class Sema final {
 
   /// We've found a use of a templated declaration that would trigger an
   /// implicit instantiation. Check that any relevant explicit specializations
-  /// and partial specializations are visible/reachable, and diagnose if not.
+  /// and partial specializations are visible, and diagnose if not.
   void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec);
-  void checkSpecializationReachability(SourceLocation Loc, NamedDecl *Spec);
 
   /// Retrieve a suitable printing policy for diagnostics.
   PrintingPolicy getPrintingPolicy() const {

diff  --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 5e5101203e6cf..94f5d5cb89a24 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -588,7 +588,6 @@ static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
   // FIXME: Handle isModulePrivate.
   switch (D->getModuleOwnershipKind()) {
   case Decl::ModuleOwnershipKind::Unowned:
-  case Decl::ModuleOwnershipKind::ReachableWhenImported:
   case Decl::ModuleOwnershipKind::ModulePrivate:
     return false;
   case Decl::ModuleOwnershipKind::Visible:

diff  --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 3f8fedda7174e..97783ebd6b530 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -121,7 +121,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
             // entering the context, and that can't happen in a SFINAE context.
             assert(!isSFINAEContext() &&
                    "partial specialization scope specifier in SFINAE context?");
-            if (!hasReachableDefinition(PartialSpec))
+            if (!hasVisibleDeclaration(PartialSpec))
               diagnoseMissingImport(SS.getLastQualifierNameLoc(), PartialSpec,
                                     MissingImportKind::PartialSpecialization,
                                     /*Recover*/true);
@@ -243,8 +243,8 @@ bool Sema::RequireCompleteEnumDecl(EnumDecl *EnumD, SourceLocation L,
   if (EnumD->isCompleteDefinition()) {
     // If we know about the definition but it is not visible, complain.
     NamedDecl *SuggestedDef = nullptr;
-    if (!hasReachableDefinition(EnumD, &SuggestedDef,
-                                /*OnlyNeedComplete*/ false)) {
+    if (!hasVisibleDefinition(EnumD, &SuggestedDef,
+                              /*OnlyNeedComplete*/false)) {
       // If the user is going to see an error here, recover by making the
       // definition visible.
       bool TreatAsComplete = !isSFINAEContext();

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 7ed338d49a869..99dfebd603ffc 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -16310,12 +16310,7 @@ Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
   if (getLangOpts().CPlusPlusModules && isCurrentModulePurview()) {
     Module *GlobalModule =
         PushGlobalModuleFragment(ExternLoc, /*IsImplicit=*/true);
-    /// According to [module.reach]p3.2,
-    /// The declaration in global module fragment is reachable if it is not
-    /// discarded. And the discarded declaration should be deleted. So it
-    /// doesn't matter mark the declaration in global module fragment as
-    /// reachable here.
-    D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported);
+    D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate);
     D->setLocalOwningModule(GlobalModule);
   }
 

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 40fb60c729bc6..ce7706ab96cac 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -17943,7 +17943,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
   if (NeedDefinition &&
       (Func->getTemplateSpecializationKind() != TSK_Undeclared ||
        Func->getMemberSpecializationInfo()))
-    checkSpecializationReachability(Loc, Func);
+    checkSpecializationVisibility(Loc, Func);
 
   if (getLangOpts().CUDA)
     CheckCUDACall(Loc, Func);

diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 47c7a61f8072f..9f2e1eac41be6 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1607,17 +1607,16 @@ bool Sema::hasMergedDefinitionInCurrentModule(NamedDecl *Def) {
   return false;
 }
 
-template <typename ParmDecl>
+template<typename ParmDecl>
 static bool
-hasAcceptableDefaultArgument(Sema &S, const ParmDecl *D,
-                             llvm::SmallVectorImpl<Module *> *Modules,
-                             Sema::AcceptableKind Kind) {
+hasVisibleDefaultArgument(Sema &S, const ParmDecl *D,
+                          llvm::SmallVectorImpl<Module *> *Modules) {
   if (!D->hasDefaultArgument())
     return false;
 
   while (D) {
     auto &DefaultArg = D->getDefaultArgStorage();
-    if (!DefaultArg.isInherited() && S.isAcceptable(D, Kind))
+    if (!DefaultArg.isInherited() && S.isVisible(D))
       return true;
 
     if (!DefaultArg.isInherited() && Modules) {
@@ -1631,36 +1630,20 @@ hasAcceptableDefaultArgument(Sema &S, const ParmDecl *D,
   return false;
 }
 
-bool Sema::hasAcceptableDefaultArgument(
-    const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules,
-    Sema::AcceptableKind Kind) {
-  if (auto *P = dyn_cast<TemplateTypeParmDecl>(D))
-    return ::hasAcceptableDefaultArgument(*this, P, Modules, Kind);
-
-  if (auto *P = dyn_cast<NonTypeTemplateParmDecl>(D))
-    return ::hasAcceptableDefaultArgument(*this, P, Modules, Kind);
-
-  return ::hasAcceptableDefaultArgument(
-      *this, cast<TemplateTemplateParmDecl>(D), Modules, Kind);
-}
-
 bool Sema::hasVisibleDefaultArgument(const NamedDecl *D,
                                      llvm::SmallVectorImpl<Module *> *Modules) {
-  return hasAcceptableDefaultArgument(D, Modules,
-                                      Sema::AcceptableKind::Visible);
-}
-
-bool Sema::hasReachableDefaultArgument(
-    const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) {
-  return hasAcceptableDefaultArgument(D, Modules,
-                                      Sema::AcceptableKind::Reachable);
+  if (auto *P = dyn_cast<TemplateTypeParmDecl>(D))
+    return ::hasVisibleDefaultArgument(*this, P, Modules);
+  if (auto *P = dyn_cast<NonTypeTemplateParmDecl>(D))
+    return ::hasVisibleDefaultArgument(*this, P, Modules);
+  return ::hasVisibleDefaultArgument(*this, cast<TemplateTemplateParmDecl>(D),
+                                     Modules);
 }
 
-template <typename Filter>
-static bool
-hasAcceptableDeclarationImpl(Sema &S, const NamedDecl *D,
-                             llvm::SmallVectorImpl<Module *> *Modules, Filter F,
-                             Sema::AcceptableKind Kind) {
+template<typename Filter>
+static bool hasVisibleDeclarationImpl(Sema &S, const NamedDecl *D,
+                                      llvm::SmallVectorImpl<Module *> *Modules,
+                                      Filter F) {
   bool HasFilteredRedecls = false;
 
   for (auto *Redecl : D->redecls()) {
@@ -1668,7 +1651,7 @@ hasAcceptableDeclarationImpl(Sema &S, const NamedDecl *D,
     if (!F(R))
       continue;
 
-    if (S.isAcceptable(R, Kind))
+    if (S.isVisible(R))
       return true;
 
     HasFilteredRedecls = true;
@@ -1684,115 +1667,74 @@ hasAcceptableDeclarationImpl(Sema &S, const NamedDecl *D,
   return true;
 }
 
-static bool
-hasAcceptableExplicitSpecialization(Sema &S, const NamedDecl *D,
-                                    llvm::SmallVectorImpl<Module *> *Modules,
-                                    Sema::AcceptableKind Kind) {
-  return hasAcceptableDeclarationImpl(
-      S, D, Modules,
-      [](const NamedDecl *D) {
-        if (auto *RD = dyn_cast<CXXRecordDecl>(D))
-          return RD->getTemplateSpecializationKind() ==
-                 TSK_ExplicitSpecialization;
-        if (auto *FD = dyn_cast<FunctionDecl>(D))
-          return FD->getTemplateSpecializationKind() ==
-                 TSK_ExplicitSpecialization;
-        if (auto *VD = dyn_cast<VarDecl>(D))
-          return VD->getTemplateSpecializationKind() ==
-                 TSK_ExplicitSpecialization;
-        llvm_unreachable("unknown explicit specialization kind");
-      },
-      Kind);
-}
-
 bool Sema::hasVisibleExplicitSpecialization(
     const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) {
-  return ::hasAcceptableExplicitSpecialization(*this, D, Modules,
-                                               Sema::AcceptableKind::Visible);
+  return hasVisibleDeclarationImpl(*this, D, Modules, [](const NamedDecl *D) {
+    if (auto *RD = dyn_cast<CXXRecordDecl>(D))
+      return RD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
+    if (auto *FD = dyn_cast<FunctionDecl>(D))
+      return FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
+    if (auto *VD = dyn_cast<VarDecl>(D))
+      return VD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
+    llvm_unreachable("unknown explicit specialization kind");
+  });
 }
 
-bool Sema::hasReachableExplicitSpecialization(
+bool Sema::hasVisibleMemberSpecialization(
     const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) {
-  return ::hasAcceptableExplicitSpecialization(*this, D, Modules,
-                                               Sema::AcceptableKind::Reachable);
-}
-
-static bool
-hasAcceptableMemberSpecialization(Sema &S, const NamedDecl *D,
-                                  llvm::SmallVectorImpl<Module *> *Modules,
-                                  Sema::AcceptableKind Kind) {
   assert(isa<CXXRecordDecl>(D->getDeclContext()) &&
          "not a member specialization");
-  return hasAcceptableDeclarationImpl(
-      S, D, Modules,
-      [](const NamedDecl *D) {
-        // If the specialization is declared at namespace scope, then it's a
-        // member specialization declaration. If it's lexically inside the class
-        // definition then it was instantiated.
-        //
-        // FIXME: This is a hack. There should be a better way to determine
-        // this.
-        // FIXME: What about MS-style explicit specializations declared within a
-        //        class definition?
-        return D->getLexicalDeclContext()->isFileContext();
-      },
-      Kind);
-}
-
-bool Sema::hasVisibleMemberSpecialization(
-    const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) {
-  return hasAcceptableMemberSpecialization(*this, D, Modules,
-                                           Sema::AcceptableKind::Visible);
-}
-
-bool Sema::hasReachableMemberSpecialization(
-    const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) {
-  return hasAcceptableMemberSpecialization(*this, D, Modules,
-                                           Sema::AcceptableKind::Reachable);
+  return hasVisibleDeclarationImpl(*this, D, Modules, [](const NamedDecl *D) {
+    // If the specialization is declared at namespace scope, then it's a member
+    // specialization declaration. If it's lexically inside the class
+    // definition then it was instantiated.
+    //
+    // FIXME: This is a hack. There should be a better way to determine this.
+    // FIXME: What about MS-style explicit specializations declared within a
+    //        class definition?
+    return D->getLexicalDeclContext()->isFileContext();
+  });
 }
 
-/// Determine whether a declaration is acceptable to name lookup.
+/// Determine whether a declaration is visible to name lookup.
 ///
-/// This routine determines whether the declaration D is acceptable in the
-/// current lookup context, taking into account the current template
-/// instantiation stack. During template instantiation, a declaration is
-/// acceptable if it is acceptable from a module containing any entity on the
-/// template instantiation path (by instantiating a template, you allow it to
-/// see the declarations that your module can see, including those later on in
-/// your module).
-bool LookupResult::isAcceptableSlow(Sema &SemaRef, NamedDecl *D,
-                                    Sema::AcceptableKind Kind) {
+/// This routine determines whether the declaration D is visible in the current
+/// lookup context, taking into account the current template instantiation
+/// stack. During template instantiation, a declaration is visible if it is
+/// visible from a module containing any entity on the template instantiation
+/// path (by instantiating a template, you allow it to see the declarations that
+/// your module can see, including those later on in your module).
+bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {
   assert(!D->isUnconditionallyVisible() &&
          "should not call this: not in slow case");
 
   Module *DeclModule = SemaRef.getOwningModule(D);
   assert(DeclModule && "hidden decl has no owning module");
 
-  // If the owning module is visible, the decl is acceptable.
-  if (SemaRef.isModuleVisible(DeclModule,
-                              D->isInvisibleOutsideTheOwningModule()))
+  if (SemaRef.isModuleVisible(DeclModule, D->isModulePrivate()))
+    // If the owning module is visible, the decl is visible.
     return true;
 
   // Determine whether a decl context is a file context for the purpose of
-  // visibility/reachability. This looks through some (export and linkage spec)
-  // transparent contexts, but not others (enums).
+  // visibility. This looks through some (export and linkage spec) transparent
+  // contexts, but not others (enums).
   auto IsEffectivelyFileContext = [](const DeclContext *DC) {
     return DC->isFileContext() || isa<LinkageSpecDecl>(DC) ||
            isa<ExportDecl>(DC);
   };
 
   // If this declaration is not at namespace scope
-  // then it is acceptable if its lexical parent has a acceptable definition.
+  // then it is visible if its lexical parent has a visible definition.
   DeclContext *DC = D->getLexicalDeclContext();
   if (DC && !IsEffectivelyFileContext(DC)) {
     // For a parameter, check whether our current template declaration's
-    // lexical context is acceptable, not whether there's some other acceptable
+    // lexical context is visible, not whether there's some other visible
     // definition of it, because parameters aren't "within" the definition.
     //
-    // In C++ we need to check for a acceptable definition due to ODR merging,
+    // In C++ we need to check for a visible definition due to ODR merging,
     // and in C we must not because each declaration of a function gets its own
     // set of declarations for tags in prototype scope.
-    bool AcceptableWithinParent;
+    bool VisibleWithinParent;
     if (D->isTemplateParameter()) {
       bool SearchDefinitions = true;
       if (const auto *DCD = dyn_cast<Decl>(DC)) {
@@ -1803,63 +1745,41 @@ bool LookupResult::isAcceptableSlow(Sema &SemaRef, NamedDecl *D,
         }
       }
       if (SearchDefinitions)
-        AcceptableWithinParent =
-            SemaRef.hasAcceptableDefinition(cast<NamedDecl>(DC), Kind);
+        VisibleWithinParent = SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC));
       else
-        AcceptableWithinParent =
-            isAcceptable(SemaRef, cast<NamedDecl>(DC), Kind);
+        VisibleWithinParent = isVisible(SemaRef, cast<NamedDecl>(DC));
     } else if (isa<ParmVarDecl>(D) ||
                (isa<FunctionDecl>(DC) && !SemaRef.getLangOpts().CPlusPlus))
-      AcceptableWithinParent = isAcceptable(SemaRef, cast<NamedDecl>(DC), Kind);
+      VisibleWithinParent = isVisible(SemaRef, cast<NamedDecl>(DC));
     else if (D->isModulePrivate()) {
-      // A module-private declaration is only acceptable if an enclosing lexical
+      // A module-private declaration is only visible if an enclosing lexical
       // parent was merged with another definition in the current module.
-      AcceptableWithinParent = false;
+      VisibleWithinParent = false;
       do {
         if (SemaRef.hasMergedDefinitionInCurrentModule(cast<NamedDecl>(DC))) {
-          AcceptableWithinParent = true;
+          VisibleWithinParent = true;
           break;
         }
         DC = DC->getLexicalParent();
       } while (!IsEffectivelyFileContext(DC));
     } else {
-      AcceptableWithinParent =
-          SemaRef.hasAcceptableDefinition(cast<NamedDecl>(DC), Kind);
+      VisibleWithinParent = SemaRef.hasVisibleDefinition(cast<NamedDecl>(DC));
     }
 
-    if (AcceptableWithinParent && SemaRef.CodeSynthesisContexts.empty() &&
-        Kind == Sema::AcceptableKind::Visible &&
+    if (VisibleWithinParent && SemaRef.CodeSynthesisContexts.empty() &&
         // FIXME: Do something better in this case.
         !SemaRef.getLangOpts().ModulesLocalVisibility) {
       // Cache the fact that this declaration is implicitly visible because
       // its parent has a visible definition.
       D->setVisibleDespiteOwningModule();
     }
-    return AcceptableWithinParent;
+    return VisibleWithinParent;
   }
 
-  if (Kind == Sema::AcceptableKind::Visible)
-    return false;
-
-  assert(Kind == Sema::AcceptableKind::Reachable &&
-         "Additional Sema::AcceptableKind?");
-  return isReachableSlow(SemaRef, D);
+  return false;
 }
 
 bool Sema::isModuleVisible(const Module *M, bool ModulePrivate) {
-  // [module.global.frag]p2:
-  // A global-module-fragment specifies the contents of the global module
-  // fragment for a module unit. The global module fragment can be used to
-  // provide declarations that are attached to the global module and usable
-  // within the module unit.
-  //
-  // Global module fragment is special. Global Module fragment is only usable
-  // within the module unit it got defined [module.global.frag]p2. So here we
-  // check if the Module is the global module fragment in current translation
-  // unit.
-  if (M->isGlobalModule() && M != this->GlobalModuleFragment)
-    return false;
-
   // The module might be ordinarily visible. For a module-private query, that
   // means it is part of the current module.
   if (ModulePrivate && isUsableModule(M))
@@ -1892,74 +1812,8 @@ bool Sema::isModuleVisible(const Module *M, bool ModulePrivate) {
   });
 }
 
-// FIXME: Return false directly if we don't have an interface dependency on the
-// translation unit containing D.
-bool LookupResult::isReachableSlow(Sema &SemaRef, NamedDecl *D) {
-  assert(!isVisible(SemaRef, D) && "Shouldn't call the slow case.\n");
-
-  Module *DeclModule = SemaRef.getOwningModule(D);
-  assert(DeclModule && "hidden decl has no owning module");
-
-  // Entities in module map modules are reachable only if they're visible.
-  if (DeclModule->isModuleMapModule())
-    return false;
-
-  // If D comes from a module and SemaRef doesn't own a module, it implies D
-  // comes from another TU. In case SemaRef owns a module, we could judge if D
-  // comes from another TU by comparing the module unit.
-  //
-  // FIXME: It would look better if we have direct method to judge whether D is
-  // in another TU.
-  if (SemaRef.getCurrentModule() &&
-      SemaRef.getCurrentModule()->getTopLevelModule() ==
-          DeclModule->getTopLevelModule())
-    return true;
-
-  // [module.reach]/p3:
-  // A declaration D is reachable from a point P if:
-  // ...
-  // - D is not discarded ([module.global.frag]), appears in a translation unit
-  //   that is reachable from P, and does not appear within a private module
-  //   fragment.
-  //
-  // A declaration that's discarded in the GMF should be module-private.
-  if (D->isModulePrivate())
-    return false;
-
-  // [module.reach]/p1
-  //   A translation unit U is necessarily reachable from a point P if U is a
-  //   module interface unit on which the translation unit containing P has an
-  //   interface dependency, or the translation unit containing P imports U, in
-  //   either case prior to P ([module.import]).
-  //
-  // [module.import]/p10
-  //   A translation unit has an interface dependency on a translation unit U if
-  //   it contains a declaration (possibly a module-declaration) that imports U
-  //   or if it has an interface dependency on a translation unit that has an
-  //   interface dependency on U.
-  //
-  // So we could conclude the module unit U is necessarily reachable if:
-  // (1) The module unit U is module interface unit.
-  // (2) The current unit has an interface dependency on the module unit U.
-  //
-  // Here we only check for the first condition. Since we couldn't see
-  // DeclModule if it isn't (transitively) imported.
-  if (DeclModule->getTopLevelModule()->isModuleInterfaceUnit())
-    return true;
-
-  // [module.reach]/p2
-  //   Additional translation units on
-  //   which the point within the program has an interface dependency may be
-  //   considered reachable, but it is unspecified which are and under what
-  //   circumstances.
-  //
-  // The decision here is to treat all additional tranditional units as
-  // unreachable.
-  return false;
-}
-
-bool Sema::isAcceptableSlow(const NamedDecl *D, Sema::AcceptableKind Kind) {
-  return LookupResult::isAcceptable(*this, const_cast<NamedDecl *>(D), Kind);
+bool Sema::isVisibleSlow(const NamedDecl *D) {
+  return LookupResult::isVisible(*this, const_cast<NamedDecl*>(D));
 }
 
 bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) {
@@ -2008,7 +1862,7 @@ bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) {
 /// and visible. If no declaration of D is visible, returns null.
 static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D,
                                      unsigned IDNS) {
-  assert(!LookupResult::isAvailableForLookup(SemaRef, D) && "not in slow case");
+  assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
 
   for (auto RD : D->redecls()) {
     // Don't bother with extra checks if we already know this one isn't visible.
@@ -2020,7 +1874,7 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D,
     // visible in the same scope as D. This needs to be done much more
     // carefully.
     if (ND->isInIdentifierNamespace(IDNS) &&
-        LookupResult::isAvailableForLookup(SemaRef, ND))
+        LookupResult::isVisible(SemaRef, ND))
       return ND;
   }
 
@@ -2030,17 +1884,8 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D,
 bool Sema::hasVisibleDeclarationSlow(const NamedDecl *D,
                                      llvm::SmallVectorImpl<Module *> *Modules) {
   assert(!isVisible(D) && "not in slow case");
-  return hasAcceptableDeclarationImpl(
-      *this, D, Modules, [](const NamedDecl *) { return true; },
-      Sema::AcceptableKind::Visible);
-}
-
-bool Sema::hasReachableDeclarationSlow(
-    const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules) {
-  assert(!isReachable(D) && "not in slow case");
-  return hasAcceptableDeclarationImpl(
-      *this, D, Modules, [](const NamedDecl *) { return true; },
-      Sema::AcceptableKind::Reachable);
+  return hasVisibleDeclarationImpl(*this, D, Modules,
+                                   [](const NamedDecl *) { return true; });
 }
 
 NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
@@ -2065,60 +1910,6 @@ NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
   return findAcceptableDecl(getSema(), D, IDNS);
 }
 
-bool LookupResult::isVisible(Sema &SemaRef, NamedDecl *D) {
-  // If this declaration is already visible, return it directly.
-  if (D->isUnconditionallyVisible())
-    return true;
-
-  // During template instantiation, we can refer to hidden declarations, if
-  // they were visible in any module along the path of instantiation.
-  return isAcceptableSlow(SemaRef, D, Sema::AcceptableKind::Visible);
-}
-
-bool LookupResult::isReachable(Sema &SemaRef, NamedDecl *D) {
-  if (D->isUnconditionallyVisible())
-    return true;
-
-  return isAcceptableSlow(SemaRef, D, Sema::AcceptableKind::Reachable);
-}
-
-bool LookupResult::isAvailableForLookup(Sema &SemaRef, NamedDecl *ND) {
-  // We should check the visibility at the callsite already.
-  if (isVisible(SemaRef, ND))
-    return true;
-
-  auto *DC = ND->getDeclContext();
-  // If ND is not visible and it is at namespace scope, it shouldn't be found
-  // by name lookup.
-  if (DC->isFileContext())
-    return false;
-
-  // [module.interface]p7
-  // Class and enumeration member names can be found by name lookup in any
-  // context in which a definition of the type is reachable.
-  //
-  // FIXME: The current implementation didn't consider about scope. For example,
-  // ```
-  // // m.cppm
-  // export module m;
-  // enum E1 { e1 };
-  // // Use.cpp
-  // import m;
-  // void test() {
-  //   auto a = E1::e1; // Error as expected.
-  //   auto b = e1; // Should be error. namespace-scope name e1 is not visible
-  // }
-  // ```
-  // For the above example, the current implementation would emit error for `a`
-  // correctly. However, the implementation wouldn't diagnose about `b` now.
-  // Since we only check the reachability for the parent only.
-  // See clang/test/CXX/module/module.interface/p7.cpp for example.
-  if (auto *TD = dyn_cast<TagDecl>(DC))
-    return SemaRef.hasReachableDefinition(TD);
-
-  return false;
-}
-
 /// Perform unqualified name lookup starting from a given
 /// scope.
 ///
@@ -3850,16 +3641,7 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
           }
         } else if (D->getFriendObjectKind()) {
           auto *RD = cast<CXXRecordDecl>(D->getLexicalDeclContext());
-          // [basic.lookup.argdep]p4:
-          //   Argument-dependent lookup finds all declarations of functions and
-          //   function templates that
-          //  - ...
-          //  - are declared as a friend ([class.friend]) of any class with a
-          //  reachable definition in the set of associated entities,
-          //
-          // FIXME: If there's a merged definition of D that is reachable, then
-          // the friend declaration should be considered.
-          if (AssociatedClasses.count(RD) && isReachable(D)) {
+          if (AssociatedClasses.count(RD) && isVisible(D)) {
             Visible = true;
             break;
           }

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 3aa124d457b03..b0e7d30526a3c 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -90,14 +90,7 @@ Sema::ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc) {
 
   // All declarations created from now on are owned by the global module.
   auto *TU = Context.getTranslationUnitDecl();
-  // [module.global.frag]p2
-  // A global-module-fragment specifies the contents of the global module
-  // fragment for a module unit. The global module fragment can be used to
-  // provide declarations that are attached to the global module and usable
-  // within the module unit.
-  //
-  // So the declations in the global module shouldn't be visible by default.
-  TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported);
+  TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::Visible);
   TU->setLocalOwningModule(GlobalModule);
 
   // FIXME: Consider creating an explicit representation of this declaration.
@@ -332,12 +325,10 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
   VisibleModules.setVisible(Mod, ModuleLoc);
 
   // From now on, we have an owning module for all declarations we see.
-  // In C++20 modules, those declaration would be reachable when imported
-  // unless explicitily exported.
-  // Otherwise, those declarations are module-private unless explicitly
+  // However, those declarations are module-private unless explicitly
   // exported.
   auto *TU = Context.getTranslationUnitDecl();
-  TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported);
+  TU->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate);
   TU->setLocalOwningModule(Mod);
 
   // We are in the module purview, but before any other (non import)

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index dbfe6164bda2c..250dbcd4aba63 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -799,9 +799,8 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
 
   if (PatternDef && !IsEntityBeingDefined) {
     NamedDecl *SuggestedDef = nullptr;
-    if (!hasReachableDefinition(const_cast<NamedDecl *>(PatternDef),
-                                &SuggestedDef,
-                                /*OnlyNeedComplete*/ false)) {
+    if (!hasVisibleDefinition(const_cast<NamedDecl*>(PatternDef), &SuggestedDef,
+                              /*OnlyNeedComplete*/false)) {
       // If we're allowed to diagnose this and recover, do so.
       bool Recover = Complain && !isSFINAEContext();
       if (Complain)
@@ -5256,7 +5255,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
   HasDefaultArg = false;
 
   if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) {
-    if (!hasReachableDefaultArgument(TypeParm))
+    if (!hasVisibleDefaultArgument(TypeParm))
       return TemplateArgumentLoc();
 
     HasDefaultArg = true;
@@ -5273,7 +5272,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
 
   if (NonTypeTemplateParmDecl *NonTypeParm
         = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
-    if (!hasReachableDefaultArgument(NonTypeParm))
+    if (!hasVisibleDefaultArgument(NonTypeParm))
       return TemplateArgumentLoc();
 
     HasDefaultArg = true;
@@ -5291,7 +5290,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
 
   TemplateTemplateParmDecl *TempTempParm
     = cast<TemplateTemplateParmDecl>(Param);
-  if (!hasReachableDefaultArgument(TempTempParm))
+  if (!hasVisibleDefaultArgument(TempTempParm))
     return TemplateArgumentLoc();
 
   HasDefaultArg = true;
@@ -5629,10 +5628,10 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc,
                                  ->getTemplateParameters()
                                  ->getParam(D->getIndex()));
 
-  // If there's a default argument that's not reachable, diagnose that we're
+  // If there's a default argument that's not visible, diagnose that we're
   // missing a module import.
   llvm::SmallVector<Module*, 8> Modules;
-  if (D->hasDefaultArgument() && !S.hasReachableDefaultArgument(D, &Modules)) {
+  if (D->hasDefaultArgument() && !S.hasVisibleDefaultArgument(D, &Modules)) {
     S.diagnoseMissingImport(Loc, cast<NamedDecl>(TD),
                             D->getDefaultArgumentLoc(), Modules,
                             Sema::MissingImportKind::DefaultArgument,
@@ -5815,7 +5814,7 @@ bool Sema::CheckTemplateArgumentList(
     // (when the template parameter was part of a nested template) into
     // the default argument.
     if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
-      if (!hasReachableDefaultArgument(TTP))
+      if (!hasVisibleDefaultArgument(TTP))
         return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP,
                                        NewArgs);
 
@@ -5832,7 +5831,7 @@ bool Sema::CheckTemplateArgumentList(
                                 ArgType);
     } else if (NonTypeTemplateParmDecl *NTTP
                  = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
-      if (!hasReachableDefaultArgument(NTTP))
+      if (!hasVisibleDefaultArgument(NTTP))
         return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP,
                                        NewArgs);
 
@@ -5850,7 +5849,7 @@ bool Sema::CheckTemplateArgumentList(
       TemplateTemplateParmDecl *TempParm
         = cast<TemplateTemplateParmDecl>(*Param);
 
-      if (!hasReachableDefaultArgument(TempParm))
+      if (!hasVisibleDefaultArgument(TempParm))
         return diagnoseMissingArgument(*this, TemplateLoc, Template, TempParm,
                                        NewArgs);
 
@@ -11007,12 +11006,10 @@ class ExplicitSpecializationVisibilityChecker {
   Sema &S;
   SourceLocation Loc;
   llvm::SmallVector<Module *, 8> Modules;
-  Sema::AcceptableKind Kind;
 
 public:
-  ExplicitSpecializationVisibilityChecker(Sema &S, SourceLocation Loc,
-                                          Sema::AcceptableKind Kind)
-      : S(S), Loc(Loc), Kind(Kind) {}
+  ExplicitSpecializationVisibilityChecker(Sema &S, SourceLocation Loc)
+      : S(S), Loc(Loc) {}
 
   void check(NamedDecl *ND) {
     if (auto *FD = dyn_cast<FunctionDecl>(ND))
@@ -11040,23 +11037,6 @@ class ExplicitSpecializationVisibilityChecker {
       S.diagnoseMissingImport(Loc, D, D->getLocation(), Modules, Kind, Recover);
   }
 
-  bool CheckMemberSpecialization(const NamedDecl *D) {
-    return Kind == Sema::AcceptableKind::Visible
-               ? S.hasVisibleMemberSpecialization(D)
-               : S.hasReachableMemberSpecialization(D);
-  }
-
-  bool CheckExplicitSpecialization(const NamedDecl *D) {
-    return Kind == Sema::AcceptableKind::Visible
-               ? S.hasVisibleExplicitSpecialization(D)
-               : S.hasReachableExplicitSpecialization(D);
-  }
-
-  bool CheckDeclaration(const NamedDecl *D) {
-    return Kind == Sema::AcceptableKind::Visible ? S.hasVisibleDeclaration(D)
-                                                 : S.hasReachableDeclaration(D);
-  }
-
   // Check a specific declaration. There are three problematic cases:
   //
   //  1) The declaration is an explicit specialization of a template
@@ -11073,9 +11053,10 @@ class ExplicitSpecializationVisibilityChecker {
   void checkImpl(SpecDecl *Spec) {
     bool IsHiddenExplicitSpecialization = false;
     if (Spec->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
-      IsHiddenExplicitSpecialization = Spec->getMemberSpecializationInfo()
-                                           ? !CheckMemberSpecialization(Spec)
-                                           : !CheckExplicitSpecialization(Spec);
+      IsHiddenExplicitSpecialization =
+          Spec->getMemberSpecializationInfo()
+              ? !S.hasVisibleMemberSpecialization(Spec, &Modules)
+              : !S.hasVisibleExplicitSpecialization(Spec, &Modules);
     } else {
       checkInstantiated(Spec);
     }
@@ -11099,7 +11080,7 @@ class ExplicitSpecializationVisibilityChecker {
       checkTemplate(TD);
     else if (auto *TD =
                  From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
-      if (!CheckDeclaration(TD))
+      if (!S.hasVisibleDeclaration(TD))
         diagnose(TD, true);
       checkTemplate(TD);
     }
@@ -11115,7 +11096,7 @@ class ExplicitSpecializationVisibilityChecker {
       checkTemplate(TD);
     else if (auto *TD =
                  From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
-      if (!CheckDeclaration(TD))
+      if (!S.hasVisibleDeclaration(TD))
         diagnose(TD, true);
       checkTemplate(TD);
     }
@@ -11126,7 +11107,7 @@ class ExplicitSpecializationVisibilityChecker {
   template<typename TemplDecl>
   void checkTemplate(TemplDecl *TD) {
     if (TD->isMemberSpecialization()) {
-      if (!CheckMemberSpecialization(TD))
+      if (!S.hasVisibleMemberSpecialization(TD, &Modules))
         diagnose(TD->getMostRecentDecl(), false);
     }
   }
@@ -11137,17 +11118,5 @@ void Sema::checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec) {
   if (!getLangOpts().Modules)
     return;
 
-  ExplicitSpecializationVisibilityChecker(*this, Loc,
-                                          Sema::AcceptableKind::Visible)
-      .check(Spec);
-}
-
-void Sema::checkSpecializationReachability(SourceLocation Loc,
-                                           NamedDecl *Spec) {
-  if (!getLangOpts().CPlusPlusModules)
-    return checkSpecializationVisibility(Loc, Spec);
-
-  ExplicitSpecializationVisibilityChecker(*this, Loc,
-                                          Sema::AcceptableKind::Reachable)
-      .check(Spec);
+  ExplicitSpecializationVisibilityChecker(*this, Loc).check(Spec);
 }

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 3edce941c3817..0015d6a870b98 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -8642,8 +8642,17 @@ bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) {
   return Ctx.IsEquivalent(D, Suggested);
 }
 
-bool Sema::hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested,
-                                   AcceptableKind Kind, bool OnlyNeedComplete) {
+/// Determine whether there is any declaration of \p D that was ever a
+///        definition (perhaps before module merging) and is currently visible.
+/// \param D The definition of the entity.
+/// \param Suggested Filled in with the declaration that should be made visible
+///        in order to provide a definition of this entity.
+/// \param OnlyNeedComplete If \c true, we only need the type to be complete,
+///        not defined. This only matters for enums with a fixed underlying
+///        type, since in all other cases, a type is complete if and only if it
+///        is defined.
+bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
+                                bool OnlyNeedComplete) {
   // Easy case: if we don't have modules, all declarations are visible.
   if (!getLangOpts().Modules && !getLangOpts().ModulesLocalVisibility)
     return true;
@@ -8687,14 +8696,13 @@ bool Sema::hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested,
       VD = Pattern;
     D = VD->getDefinition();
   }
-
   assert(D && "missing definition for pattern of instantiated definition");
 
   *Suggested = D;
 
-  auto DefinitionIsAcceptable = [&] {
+  auto DefinitionIsVisible = [&] {
     // The (primary) definition might be in a visible module.
-    if (isAcceptable(D, Kind))
+    if (isVisible(D))
       return true;
 
     // A visible module might have a merged definition instead.
@@ -8712,51 +8720,19 @@ bool Sema::hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested,
     return false;
   };
 
-  if (DefinitionIsAcceptable())
+  if (DefinitionIsVisible())
     return true;
 
   // The external source may have additional definitions of this entity that are
   // visible, so complete the redeclaration chain now and ask again.
   if (auto *Source = Context.getExternalSource()) {
     Source->CompleteRedeclChain(D);
-    return DefinitionIsAcceptable();
+    return DefinitionIsVisible();
   }
 
   return false;
 }
 
-/// Determine whether there is any declaration of \p D that was ever a
-///        definition (perhaps before module merging) and is currently visible.
-/// \param D The definition of the entity.
-/// \param Suggested Filled in with the declaration that should be made visible
-///        in order to provide a definition of this entity.
-/// \param OnlyNeedComplete If \c true, we only need the type to be complete,
-///        not defined. This only matters for enums with a fixed underlying
-///        type, since in all other cases, a type is complete if and only if it
-///        is defined.
-bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
-                                bool OnlyNeedComplete) {
-  return hasAcceptableDefinition(D, Suggested, Sema::AcceptableKind::Visible,
-                                 OnlyNeedComplete);
-}
-
-/// Determine whether there is any declaration of \p D that was ever a
-///        definition (perhaps before module merging) and is currently
-///        reachable.
-/// \param D The definition of the entity.
-/// \param Suggested Filled in with the declaration that should be made
-/// reachable
-///        in order to provide a definition of this entity.
-/// \param OnlyNeedComplete If \c true, we only need the type to be complete,
-///        not defined. This only matters for enums with a fixed underlying
-///        type, since in all other cases, a type is complete if and only if it
-///        is defined.
-bool Sema::hasReachableDefinition(NamedDecl *D, NamedDecl **Suggested,
-                                  bool OnlyNeedComplete) {
-  return hasAcceptableDefinition(D, Suggested, Sema::AcceptableKind::Reachable,
-                                 OnlyNeedComplete);
-}
-
 /// Locks in the inheritance model for the given class and all of its bases.
 static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
   RD = RD->getMostRecentNonInjectedDecl();
@@ -8826,19 +8802,20 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
   // Check that any necessary explicit specializations are visible. For an
   // enum, we just need the declaration, so don't check this.
   if (Def && !isa<EnumDecl>(Def))
-    checkSpecializationReachability(Loc, Def);
+    checkSpecializationVisibility(Loc, Def);
 
   // If we have a complete type, we're done.
   if (!Incomplete) {
-    NamedDecl *Suggested = nullptr;
+    // If we know about the definition but it is not visible, complain.
+    NamedDecl *SuggestedDef = nullptr;
     if (Def &&
-        !hasReachableDefinition(Def, &Suggested, /*OnlyNeedComplete=*/true)) {
+        !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true)) {
       // If the user is going to see an error here, recover by making the
       // definition visible.
       bool TreatAsComplete = Diagnoser && !isSFINAEContext();
-      if (Diagnoser && Suggested)
-        diagnoseMissingImport(Loc, Suggested, MissingImportKind::Definition,
-                              /*Recover*/ TreatAsComplete);
+      if (Diagnoser && SuggestedDef)
+        diagnoseMissingImport(Loc, SuggestedDef, MissingImportKind::Definition,
+                              /*Recover*/TreatAsComplete);
       return !TreatAsComplete;
     } else if (Def && !TemplateInstCallbacks.empty()) {
       CodeSynthesisContext TempInst;

diff  --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index b4506da2bb2ba..ae298557ee49c 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -605,27 +605,15 @@ void ASTDeclReader::VisitDecl(Decl *D) {
   D->setTopLevelDeclInObjCContainer(Record.readInt());
   D->setAccess((AccessSpecifier)Record.readInt());
   D->FromASTFile = true;
-  auto ModuleOwnership = (Decl::ModuleOwnershipKind)Record.readInt();
-  bool ModulePrivate =
-      (ModuleOwnership == Decl::ModuleOwnershipKind::ModulePrivate);
+  bool ModulePrivate = Record.readInt();
 
   // Determine whether this declaration is part of a (sub)module. If so, it
   // may not yet be visible.
   if (unsigned SubmoduleID = readSubmoduleID()) {
-
-    switch (ModuleOwnership) {
-    case Decl::ModuleOwnershipKind::Visible:
-      ModuleOwnership = Decl::ModuleOwnershipKind::VisibleWhenImported;
-      break;
-    case Decl::ModuleOwnershipKind::Unowned:
-    case Decl::ModuleOwnershipKind::VisibleWhenImported:
-    case Decl::ModuleOwnershipKind::ReachableWhenImported:
-    case Decl::ModuleOwnershipKind::ModulePrivate:
-      break;
-    }
-
-    D->setModuleOwnershipKind(ModuleOwnership);
     // Store the owning submodule ID in the declaration.
+    D->setModuleOwnershipKind(
+        ModulePrivate ? Decl::ModuleOwnershipKind::ModulePrivate
+                      : Decl::ModuleOwnershipKind::VisibleWhenImported);
     D->setOwningModuleID(SubmoduleID);
 
     if (ModulePrivate) {

diff  --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 01f692c9611b7..3666d5a6daab8 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -311,7 +311,7 @@ void ASTDeclWriter::VisitDecl(Decl *D) {
   Record.push_back(D->isReferenced());
   Record.push_back(D->isTopLevelDeclInObjCContainer());
   Record.push_back(D->getAccess());
-  Record.push_back((uint64_t)D->getModuleOwnershipKind());
+  Record.push_back(D->isModulePrivate());
   Record.push_back(Writer.getSubmoduleID(D->getOwningModule()));
 
   // If this declaration injected a name into a context 
diff erent from its
@@ -1928,7 +1928,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced
   Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2));  // AccessSpecifier
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3));  // ModuleOwnershipKind
+  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
@@ -1961,7 +1961,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced
   Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2));  // AccessSpecifier
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3));  // ModuleOwnershipKind
+  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
@@ -1999,7 +1999,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced
   Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer
   Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind
+  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
@@ -2049,7 +2049,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced
   Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer
   Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind
+  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
@@ -2111,7 +2111,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced
   Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer
   Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind
+  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
@@ -2159,7 +2159,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isReferenced
   Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // C++ AccessSpecifier
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind
+  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
@@ -2188,7 +2188,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   Abv->Add(BitCodeAbbrevOp(0));                       // isReferenced
   Abv->Add(BitCodeAbbrevOp(0));                   // TopLevelDeclInObjCContainer
   Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind
+  Abv->Add(BitCodeAbbrevOp(0));                       // ModulePrivate
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
@@ -2240,7 +2240,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Referenced
   Abv->Add(BitCodeAbbrevOp(0));                         // InObjCContainer
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Access
-  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // ModuleOwnershipKind
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModulePrivate
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // SubmoduleID
   // NamedDecl
   Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind

diff  --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp
deleted file mode 100644
index 638057cbd681f..0000000000000
--- a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-// This tests for [basic.lookup.argdep]/p4.2:
-//   Argument-dependent lookup finds all declarations of functions and function templates that
-// - ...
-// - are declared as a friend ([class.friend]) of any class with a reachable definition in the set of associated entities,
-//
-// RUN: rm -fr %t
-// RUN: mkdir %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Friend-in-reachable-class.cppm -o %t/X.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
-//
-//--- Friend-in-reachable-class.cppm
-module;
-# 3 __FILE__ 1
-struct A {
-  friend int operator+(const A &lhs, const A &rhs) {
-    return 0;
-  }
-};
-# 6 "" 2
-export module X;
-export using ::A;
-
-//--- Use.cpp
-// expected-no-diagnostics
-import X;
-int use() {
-  A a, b;
-  return a + b;
-}

diff  --git a/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp b/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp
index d4b425b22fd6a..79529c6c0fc0a 100644
--- a/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp
+++ b/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp
@@ -30,20 +30,17 @@ module;
 
 void test_early() {
   in_header = 1; // expected-error {{missing '#include "foo.h"'; 'in_header' must be declared before it is used}}
-  // expected-note@* {{not visible}}
+  // expected-note@*{{not visible}}
 
   global_module_fragment = 1; // expected-error {{missing '#include'; 'global_module_fragment' must be declared before it is used}}
-                              // expected-note at p2.cpp:16 {{not visible}}
+  // expected-note at p2.cpp:16 {{not visible}}
 
   exported = 1; // expected-error {{must be imported from module 'A'}}
-                // expected-note at p2.cpp:18 {{declaration here is not visible}}
+  // expected-note at p2.cpp:18 {{not visible}}
 
-  not_exported = 1; // expected-error {{declaration of 'not_exported' must be imported from module 'A' before it is required}}
-                    // expected-note at p2.cpp:19 {{declaration here is not visible}}
+  not_exported = 1; // expected-error {{undeclared identifier}}
 
-  // FIXME: We need better diagnostic message for static variable.
-  internal = 1; // expected-error {{declaration of 'internal' must be imported from module 'A' before it is required}}
-                // expected-note at p2.cpp:20 {{declaration here is not visible}}
+  internal = 1; // expected-error {{undeclared identifier}}
 
   not_exported_private = 1; // expected-error {{undeclared identifier}}
 
@@ -58,7 +55,7 @@ import A;
 
 void test_late() {
   in_header = 1; // expected-error {{missing '#include "foo.h"'; 'in_header' must be declared before it is used}}
-  // expected-note@* {{not visible}}
+  // expected-note@*{{not visible}}
 
   global_module_fragment = 1; // expected-error {{missing '#include'; 'global_module_fragment' must be declared before it is used}}
   // expected-note at p2.cpp:16 {{not visible}}
@@ -67,14 +64,14 @@ void test_late() {
 
   not_exported = 1;
 #ifndef IMPLEMENTATION
-  // expected-error at -2 {{declaration of 'not_exported' must be imported from module 'A' before it is required}}
-  // expected-note at p2.cpp:19 {{declaration here is not visible}}
+  // expected-error at -2 {{undeclared identifier 'not_exported'; did you mean 'exported'}}
+  // expected-note at p2.cpp:18 {{declared here}}
 #endif
 
   internal = 1;
 #ifndef IMPLEMENTATION
-  // expected-error at -2 {{declaration of 'internal' must be imported from module 'A' before it is required}}
-  // expected-note at p2.cpp:20 {{declaration here is not visible}}
+  // FIXME: should not be visible here
+  // expected-error at -3 {{undeclared identifier}}
 #endif
 
   not_exported_private = 1;

diff  --git a/clang/test/CXX/module/module.context/p7.cpp b/clang/test/CXX/module/module.context/p7.cpp
deleted file mode 100644
index 6a63e3e15aac4..0000000000000
--- a/clang/test/CXX/module/module.context/p7.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-// RUN: rm -rf %t
-// RUN: split-file %s %t
-// RUN: cd %t
-
-// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-header-unit-header std-10-6-ex1-decl.h \
-// RUN: -o decl.pcm
-
-// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-header-unit-header std-10-6-ex1-defn.h \
-// RUN: -o defn.pcm
-
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface std-10-6-ex1-stuff.cpp \
-// RUN: -o stuff.pcm
-
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface std-10-6-ex1-M1.cpp \
-// RUN: -fmodule-file=stuff.pcm -o M1.pcm  -fmodule-file=defn.pcm
-
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface std-10-6-ex1-M2.cpp \
-// RUN: -fmodule-file=stuff.pcm -o M2.pcm  -fmodule-file=decl.pcm
-
-// RUN: %clang_cc1 -std=c++20 std-10-6-ex1-use.cpp \
-// RUN: -fmodule-file=M1.pcm -fmodule-file=M2.pcm  -fsyntax-only -verify
-
-//--- std-10-6-ex1-decl.h
-struct X;
-
-//--- std-10-6-ex1-defn.h
-struct X {};
-
-//--- std-10-6-ex1-stuff.cpp
-export module stuff;
-export template <typename T, typename U> void foo(T, U u) { auto v = u; }
-export template <typename T, typename U> void bar(T, U u) { auto v = *u; }
-
-//--- std-10-6-ex1-M1.cpp
-export module M1;
-import "std-10-6-ex1-defn.h"; // provides struct X {};
-import stuff;
-
-export template <typename T> void f(T t) {
-  X x;
-  foo(t, x);
-}
-
-//--- std-10-6-ex1-M2.cpp
-export module M2;
-import "std-10-6-ex1-decl.h"; // provides struct X; (not a definition)
-
-import stuff;
-export template <typename T> void g(T t) {
-  X *x;
-  bar(t, x);
-}
-
-//--- std-10-6-ex1-use.cpp
-import M1;
-import M2;
-
-void test() {
-  f(0);
-  // It is unspecified whether the instantiation of g(0) is valid here.
-  // We choose to make it invalid here.
-  g(0); // expected-error@* {{definition of 'X' must be imported from module}}
-        // expected-note@* {{in instantiation of function template specialization 'bar<int, X *>'}}
-        // expected-note@* {{in instantiation of function template specialization}}
-        // expected-note@* {{definition here is not reachable}}
-}

diff  --git a/clang/test/CXX/module/module.import/p2.cpp b/clang/test/CXX/module/module.import/p2.cpp
index 0c02d253f3a89..7aa54e38f8c3f 100644
--- a/clang/test/CXX/module/module.import/p2.cpp
+++ b/clang/test/CXX/module/module.import/p2.cpp
@@ -23,10 +23,7 @@ export A f();
 //--- Use.cpp
 import M;
 void test() {
-  A a; // expected-error {{declaration of 'A' must be imported from module 'M:impl'}}
-       // expected-error at -1 {{definition of 'A' must be imported from module 'M:impl'}} expected-error at -1 {{}}
-       // expected-note at impl.cppm:2 {{declaration here is not visible}}
-       // expected-note at impl.cppm:2 {{definition here is not reachable}} expected-note at impl.cppm:2 {{}}
+  A a; // expected-error {{unknown type name 'A'}}
 }
 
 //--- UseInPartA.cppm
@@ -41,10 +38,7 @@ void test() {
 export module B;
 import M;
 void test() {
-  A a; // expected-error {{declaration of 'A' must be imported from module 'M:impl'}}
-       // expected-error at -1 {{definition of 'A' must be imported from module 'M:impl'}} expected-error at -1 {{}}
-       // expected-note at impl.cppm:2 {{declaration here is not visible}}
-       // expected-note at impl.cppm:2 {{definition here is not reachable}} expected-note at impl.cppm:2 {{}}
+  A a; // expected-error {{unknown type name 'A'}}
 }
 
 //--- Private.cppm

diff  --git a/clang/test/CXX/module/module.interface/p2.cpp b/clang/test/CXX/module/module.interface/p2.cpp
index 804b0363ffa31..0a6f8c2aad567 100644
--- a/clang/test/CXX/module/module.interface/p2.cpp
+++ b/clang/test/CXX/module/module.interface/p2.cpp
@@ -69,29 +69,22 @@ import "header.h";
 
 void use() {
   // namespace A is implicitly exported by the export of A::g.
-  A::f(); // expected-error {{declaration of 'f' must be imported from module 'p2' before it is required}}
-          // expected-note@* {{declaration here is not visible}}
+  A::f(); // expected-error {{no member named 'f' in namespace 'A'}}
   A::g();
-  A::h();                   // expected-error {{declaration of 'h' must be imported from module 'p2' before it is required}}
-                            // expected-note@* {{declaration here is not visible}}
-  using namespace A::inner; // expected-error {{declaration of 'inner' must be imported from module 'p2' before it is required}}
-                            // expected-note@* {{declaration here is not visible}}
+  A::h(); // expected-error {{no member named 'h' in namespace 'A'}}
+  using namespace A::inner; // expected-error {{expected namespace name}}
 
   // namespace B and B::inner are explicitly exported
   using namespace B;
   using namespace B::inner;
-  B::f(); // expected-error {{declaration of 'f' must be imported from module 'p2' before it is required}}
-          // expected-note@* {{declaration here is not visible}}
-  f();    // expected-error {{declaration of 'f' must be imported from module 'p2' before it is required}}
-          // expected-note@* {{declaration here is not visible}}
+  B::f(); // expected-error {{no member named 'f' in namespace 'B'}}
+  f(); // expected-error {{undeclared identifier 'f'}}
 
   // namespace C is not exported
-  using namespace C; // expected-error {{declaration of 'C' must be imported from module 'p2' before it is required}}
-                     // expected-note@* {{declaration here is not visible}}
+  using namespace C; // expected-error {{expected namespace name}}
 
   // namespace D is exported, but D::f is not
-  D::f(); // expected-error {{declaration of 'f' must be imported from module 'p2' before it is required}}
-          // expected-note@* {{declaration here is not visible}}
+  D::f(); // expected-error {{no member named 'f' in namespace 'D'}}
 }
 
 int use_header() { return foo + bar::baz(); }

diff  --git a/clang/test/CXX/module/module.interface/p7.cpp b/clang/test/CXX/module/module.interface/p7.cpp
deleted file mode 100644
index 1572390f0d289..0000000000000
--- a/clang/test/CXX/module/module.interface/p7.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/p7.cppm -emit-module-interface -o %t/p7.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify
-
-//--- p7.cppm
-export module p7;
-struct reachable {
-  constexpr static int sv = 43;
-  int value = 44;
-
-  static int getValue() { return 43; }
-  int get() { return 44; }
-
-  template <typename T>
-  static bool templ_get(T t) { return false; }
-  typedef int typedef_type;
-  using using_type = int;
-  template <typename T>
-  using templ_using_type = int;
-  bool operator()() {
-    return false;
-  }
-
-  enum E { a,
-           b };
-};
-
-export auto getReachable() {
-  return reachable{};
-}
-
-export enum E1 { e1 };
-enum E2 { e2 };
-export using E2U = E2;
-enum E3 { e3 };
-export E3 func();
-
-//--- Use.cpp
-import p7;
-void test() {
-  auto reachable = getReachable();
-  int a = decltype(reachable)::sv;
-  int b = decltype(reachable)::getValue();
-  int c = reachable.value;
-  int d = reachable.get();
-  int e = decltype(reachable)::a;
-  int f = reachable.templ_get(a);
-  typename decltype(reachable)::typedef_type g;
-  typename decltype(reachable)::using_type h;
-  typename decltype(reachable)::template templ_using_type<int> j;
-  auto value = reachable();
-}
-
-void test2() {
-  auto a = E1::e1;               // OK, namespace-scope name E1 is visible and e1 is reachable
-  auto b = e1;                   // OK, namespace-scope name e1 is visible
-  auto c = E2::e2;               // expected-error {{declaration of 'E2' must be imported from module}}
-                                 // expected-note@* {{declaration here is not visible}}
-  auto d = e2;                   // should be error, namespace-scope name e2 is not visible
-  auto e = E2U::e2;              // OK, namespace-scope name E2U is visible and E2::e2 is reachable
-  auto f = E3::e3;               // expected-error {{declaration of 'E3' must be imported from module 'p7' before it is required}}
-                                 // expected-note@* {{declaration here is not visible}}
-  auto g = e3;                   // should be error, namespace-scope name e3 is not visible
-  auto h = decltype(func())::e3; // OK, namespace-scope name f is visible and E3::e3 is reachable
-}

diff  --git a/clang/test/CXX/module/module.reach/ex1.cpp b/clang/test/CXX/module/module.reach/ex1.cpp
deleted file mode 100644
index 00f87607dc1d8..0000000000000
--- a/clang/test/CXX/module/module.reach/ex1.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// From [module.reach]p4, example 1
-//
-// RUN: rm -fr %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/M-A.cppm -o %t/M-A.pcm
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface -fprebuilt-module-path=%t %t/M-B-impl.cppm -o %t/M-B.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/M-C.cppm -fsyntax-only -verify
-//
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface -fprebuilt-module-path=%t %t/M.cppm -o %t/M.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/X.cppm -fsyntax-only -verify
-//
-//--- M-A.cppm
-export module M:A;
-export struct B;
-
-//--- M-B-impl.cppm
-module M:B;
-struct B {
-  operator int();
-};
-
-//--- M-C.cppm
-module M:C;
-import :A;
-B b1; // expected-error {{variable has incomplete type 'B'}}
-      // expected-note@* {{forward declaration of 'B'}}
-
-//--- M.cppm
-export module M;
-export import :A;
-import :B;
-B b2;
-export void f(B b = B());
-
-//--- X.cppm
-export module X;
-import M;
-B b3; // expected-error {{definition of 'B' must be imported from module 'M:B' before it is required}} expected-error {{}}
-      // expected-note@* {{definition here is not reachable}} expected-note@* {{}}
-// FIXME: We should emit an error for unreachable definition of B.
-void g() { f(); }

diff  --git a/clang/test/CXX/module/module.reach/p2.cpp b/clang/test/CXX/module/module.reach/p2.cpp
deleted file mode 100644
index 6ccf6ee6d0566..0000000000000
--- a/clang/test/CXX/module/module.reach/p2.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-// RUN: %clang_cc1 -std=c++20 %t/impl.cppm -emit-module-interface -o %t/M-impl.pcm
-// RUN: %clang_cc1 -std=c++20 %t/M.cppm -emit-module-interface -fprebuilt-module-path=%t -o %t/M.pcm
-// RUN: %clang_cc1 -std=c++20 %t/UseStrict.cpp -fprebuilt-module-path=%t -verify -fsyntax-only
-
-//--- impl.cppm
-module M:impl;
-class A {};
-
-//--- M.cppm
-export module M;
-import :impl;
-export A f();
-
-//--- UseStrict.cpp
-import M;
-void test() {
-  auto a = f(); // expected-error {{definition of 'A' must be imported from module 'M:impl' before it is required}} expected-error{{}}
-                // expected-note@* {{definition here is not reachable}} expected-note@* {{}}
-}

diff  --git a/clang/test/CXX/module/module.reach/p4/TransitiveImport.cpp b/clang/test/CXX/module/module.reach/p4/TransitiveImport.cpp
deleted file mode 100644
index 96f80a209d266..0000000000000
--- a/clang/test/CXX/module/module.reach/p4/TransitiveImport.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-// RUN: rm -fr %t
-// RUN: mkdir %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/foo.cppm -emit-module-interface -o %t/foo.pcm
-// RUN: %clang_cc1 -std=c++20 %t/bar.cppm -emit-module-interface -fprebuilt-module-path=%t -o %t/bar.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -verify %t/Use.cpp -fsyntax-only
-//
-//--- foo.cppm
-export module foo;
-export class foo {
-};
-
-//--- bar.cppm
-export module bar;
-import foo;
-export auto bar() {
-  return foo{};
-}
-
-//--- Use.cpp
-// expected-no-diagnostics
-import bar;
-auto foo() {
-  // [module.reach]Note1:
-  // While module interface units are reachable even when they
-  // are only transitively imported via a non-exported import declaration,
-  // namespace-scope names from such module interface units are not found
-  // by name lookup ([basic.lookup]).
-  auto b = bar(); // foo should be reachable here.
-}

diff  --git a/clang/test/CXX/module/module.reach/p5.cpp b/clang/test/CXX/module/module.reach/p5.cpp
deleted file mode 100644
index 9c498a260530f..0000000000000
--- a/clang/test/CXX/module/module.reach/p5.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/B.cppm -fsyntax-only -verify
-//
-//--- A.cppm
-export module A;
-struct X {};
-export using Y = X;
-
-//--- B.cppm
-export module B;
-import A;
-Y y; // OK, definition of X is reachable
-X x; // expected-error {{declaration of 'X' must be imported from module 'A' before it is required}}
-     // expected-note@* {{declaration here is not visible}}

diff  --git a/clang/test/CXX/module/module.unit/p7/t6.cpp b/clang/test/CXX/module/module.unit/p7/t6.cpp
index bcc29d9ba25e0..8bd05c298d95d 100644
--- a/clang/test/CXX/module/module.unit/p7/t6.cpp
+++ b/clang/test/CXX/module/module.unit/p7/t6.cpp
@@ -2,11 +2,14 @@
 // RUN: mkdir %t
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %S/Inputs/CPP.cppm -I%S/Inputs -o %t/X.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %s -verify
-// expected-no-diagnostics
 module;
 #include "Inputs/h2.h"
 export module use;
 import X;
 void printX(CPP *cpp) {
-  cpp->print();
+  cpp->print(); // expected-error {{'CPP' must be defined before it is used}}
+                // expected-error at -1 {{'CPP' must be defined before it is used}}
+                // expected-error at -2 {{no member named 'print' in 'CPP'}}
+                // expected-note at Inputs/CPP.cppm:5 {{definition here is not reachable}}
+                // expected-note at Inputs/CPP.cppm:5 {{definition here is not reachable}}
 }

diff  --git a/clang/test/CXX/modules-ts/basic/basic.link/p2/other.cpp b/clang/test/CXX/modules-ts/basic/basic.link/p2/other.cpp
index efac3f892ab79..8370777e7ed47 100644
--- a/clang/test/CXX/modules-ts/basic/basic.link/p2/other.cpp
+++ b/clang/test/CXX/modules-ts/basic/basic.link/p2/other.cpp
@@ -4,13 +4,12 @@ import M;
 
 void use_from_module_impl() {
   external_linkage_fn();
-  module_linkage_fn();   // expected-error {{declaration of 'module_linkage_fn' must be imported}}
-  internal_linkage_fn(); // expected-error {{declaration of 'internal_linkage_fn' must be imported}}
+  module_linkage_fn(); // expected-error {{undeclared identifier}}
+  internal_linkage_fn(); // expected-error {{undeclared identifier}}
   (void)external_linkage_class{};
   (void)module_linkage_class{}; // expected-error {{undeclared identifier}} expected-error 0+{{}}
   (void)internal_linkage_class{}; // expected-error {{undeclared identifier}} expected-error 0+{{}}
-  // expected-note at module.cppm:10 {{declaration here is not visible}}
-  // expected-note at module.cppm:11 {{declaration here is not visible}}
+  // expected-note at module.cppm:9 {{here}}
   (void)external_linkage_var;
   (void)module_linkage_var; // expected-error {{undeclared identifier}}
   (void)internal_linkage_var; // expected-error {{undeclared identifier}}

diff  --git a/clang/test/Modules/Reachability-Private.cpp b/clang/test/Modules/Reachability-Private.cpp
deleted file mode 100644
index fdaf5c349f8ae..0000000000000
--- a/clang/test/Modules/Reachability-Private.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Tests that the definition in private module fragment is not reachable to its users.
-//
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/Private.cppm -emit-module-interface -o %t/Private.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
-
-//--- Private.cppm
-export module Private;
-inline void fn_m(); // OK, module-linkage inline function
-static void fn_s();
-export struct X;
-
-export void g(X *x) {
-  fn_s(); // OK, call to static function in same translation unit
-  fn_m(); // OK, call to module-linkage inline function
-}
-export X *factory(); // OK
-
-module :private;
-struct X {}; // definition not reachable from importers of A
-X *factory() {
-  return new X();
-}
-void fn_m() {}
-void fn_s() {}
-
-//--- Use.cpp
-import Private;
-void foo() {
-  X x; // expected-error {{definition of 'X' must be imported from module 'Private.<private>' before it is required}}
-       // expected-error at -1 {{definition of 'X' must be imported from module 'Private.<private>' before it is required}}
-       // expected-note@* {{definition here is not reachable}}
-       // expected-note@* {{definition here is not reachable}}
-  auto _ = factory();
-  auto *__ = factory();
-  X *___ = factory();
-
-  g(__);
-  g(___);
-  g(factory());
-}

diff  --git a/clang/test/Modules/Reachability-func-default-arg.cpp b/clang/test/Modules/Reachability-func-default-arg.cpp
deleted file mode 100644
index 0d6d8655d5329..0000000000000
--- a/clang/test/Modules/Reachability-func-default-arg.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/func_default_arg.cppm -emit-module-interface -o %t/func_default_arg.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
-//
-//--- func_default_arg.cppm
-export module func_default_arg;
-struct t {};
-export t foo(t t1 = t()) {
-  return t1;
-}
-
-//--- Use.cpp
-// expected-no-diagnostics
-import func_default_arg;
-void bar() {
-  auto ret = foo();
-}

diff  --git a/clang/test/Modules/Reachability-func-ret.cpp b/clang/test/Modules/Reachability-func-ret.cpp
deleted file mode 100644
index ca5bbc68d759f..0000000000000
--- a/clang/test/Modules/Reachability-func-ret.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/func_ret.cppm -emit-module-interface -o %t/func_ret.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
-//
-//--- func_ret.cppm
-export module func_ret;
-struct t {};
-export t foo() {
-  return t{};
-}
-
-//--- Use.cpp
-// expected-no-diagnostics
-import func_ret;
-void bar() {
-  auto ret = foo();
-}

diff  --git a/clang/test/Modules/Reachability-template-default-arg.cpp b/clang/test/Modules/Reachability-template-default-arg.cpp
deleted file mode 100644
index 6fb109e41fcf0..0000000000000
--- a/clang/test/Modules/Reachability-template-default-arg.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/template_default_arg.cppm -emit-module-interface -o %t/template_default_arg.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
-//
-//--- template_default_arg.cppm
-export module template_default_arg;
-struct t {};
-
-export template <typename T = t>
-struct A {
-  T a;
-};
-
-//--- Use.cpp
-import template_default_arg;
-void bar() {
-  A<> a0;
-  A<t> a1; // expected-error {{declaration of 't' must be imported from module 'template_default_arg' before it is required}}
-           // expected-note@* {{declaration here is not visible}}
-}

diff  --git a/clang/test/Modules/Reachability-template-instantiation.cpp b/clang/test/Modules/Reachability-template-instantiation.cpp
deleted file mode 100644
index 2170c7b92a370..0000000000000
--- a/clang/test/Modules/Reachability-template-instantiation.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm
-// RUN: %clang_cc1 -std=c++20 %t/Use.cppm -fprebuilt-module-path=%t -emit-module-interface -o %t/Use.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cpp -verify -fsyntax-only
-//
-//--- Templ.h
-#ifndef TEMPL_H
-#define TEMPL_H
-template <class T>
-class Wrapper {
-public:
-  T value;
-};
-#endif
-
-//--- Templ.cppm
-export module Templ;
-export template <class T>
-class Wrapper2 {
-public:
-  T value;
-};
-
-//--- Use.cppm
-module;
-#include "Templ.h"
-export module Use;
-import Templ;
-
-export template <class T>
-class Use {
-public:
-  Wrapper<T> value;
-  Wrapper2<T> value2;
-};
-
-export template <class T>
-Wrapper<T> wrapper;
-
-//--- Use.cpp
-// expected-no-diagnostics
-module;
-#include "Templ.h"
-export module User;
-
-export template <class T>
-class User {
-public:
-  Wrapper<T> value;
-};

diff  --git a/clang/test/Modules/Reachability-using-templates.cpp b/clang/test/Modules/Reachability-using-templates.cpp
deleted file mode 100644
index f530e15bd4d2b..0000000000000
--- a/clang/test/Modules/Reachability-using-templates.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/mod.templates.cppm -emit-module-interface -o %t/mod.templates.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
-//
-//--- mod.templates.cppm
-export module mod.templates;
-template <class> struct t {};
-export template <class T> using u = t<T>;
-
-//--- Use.cpp
-// expected-no-diagnostics
-import mod.templates;
-void foo() {
-  u<int> v{};
-}

diff  --git a/clang/test/Modules/Reachability-using.cpp b/clang/test/Modules/Reachability-using.cpp
deleted file mode 100644
index 642b97dd8432c..0000000000000
--- a/clang/test/Modules/Reachability-using.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/mod.cppm -emit-module-interface -o %t/mod.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
-//
-//--- mod.cppm
-export module mod;
-struct t {};
-export using u = t;
-
-//--- Use.cpp
-// expected-no-diagnostics
-import mod;
-void foo() {
-  u v{};
-}

diff  --git a/clang/test/Modules/cxx20-10-1-ex2.cpp b/clang/test/Modules/cxx20-10-1-ex2.cpp
index 03e2e26339005..88ec945d6a848 100644
--- a/clang/test/Modules/cxx20-10-1-ex2.cpp
+++ b/clang/test/Modules/cxx20-10-1-ex2.cpp
@@ -53,8 +53,7 @@ int &c = n; // OK
 //--- std10-1-ex2-tu6.cpp
 import B;
 // error, n is module-local and this is not a module.
-int &c = n; // expected-error {{declaration of 'n' must be imported}}
-            // expected-note@* {{declaration here is not visible}}
+int &c = n; // expected-error {{use of undeclared identifier}}
 
 //--- std10-1-ex2-tu7.cpp
 // expected-no-diagnostics

diff  --git a/clang/test/Modules/derived_class.cpp b/clang/test/Modules/derived_class.cpp
deleted file mode 100644
index ee9e0ae4637ec..0000000000000
--- a/clang/test/Modules/derived_class.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/foo.cppm -emit-module-interface -o %t/foo.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
-//
-//--- bar.h
-struct bar_base {
-  enum A {
-    a,
-    b,
-    c,
-    d
-  };
-  constexpr static bool value = false;
-  static bool get() { return false; }
-  bool member_value = false;
-  bool get_func() { return false; }
-};
-
-template <typename T>
-struct bar : public bar_base {
-};
-
-//--- foo.cppm
-module;
-#include "bar.h"
-export module foo;
-export template <typename T>
-int foo() {
-  bool a = bar<T>::value;
-  bar<T>::get();
-  bar<T> b;
-  b.member_value = a;
-  bool c = b.get_func();
-  return bar<T>::a;
-}
-
-//--- Use.cpp
-// expected-no-diagnostics
-import foo;
-void test() {
-  foo<int>();
-}

diff  --git a/clang/test/Modules/explicitly-specialized-template.cpp b/clang/test/Modules/explicitly-specialized-template.cpp
deleted file mode 100644
index 89677254ea739..0000000000000
--- a/clang/test/Modules/explicitly-specialized-template.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/X.cppm -emit-module-interface -o %t/X.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
-//
-//--- foo.h
-#ifndef FOO_H
-#define FOO_H
-template <typename T>
-struct base {};
-
-template <typename T>
-struct foo;
-
-template <typename T>
-struct foo {};
-
-template <>
-struct foo<int> : base<int> {
-  int getInt();
-};
-#endif // FOO_H
-
-//--- X.cppm
-module;
-#include "foo.h"
-export module X;
-export template <class T>
-class X {
-  foo<int> x;
-
-public:
-  int print() {
-    return x.getInt();
-  }
-};
-
-//--- Use.cpp
-import X;
-foo<int> f; // expected-error {{'foo' must be declared before it is used}}
-            // expected-note@* {{declaration here is not visible}}
-int bar() {
-  X<int> x;
-  return x.print();
-}

diff  --git a/clang/test/Modules/module-private.cpp b/clang/test/Modules/module-private.cpp
index 2848226ba067c..a4b3b0fd21d39 100644
--- a/clang/test/Modules/module-private.cpp
+++ b/clang/test/Modules/module-private.cpp
@@ -21,8 +21,8 @@ int test_broken() {
   vector<int> vec; // expected-error{{no template named 'vector'}}
 
   VisibleStruct vs;
-  vs.field = 0;
-  vs.setField(1);
+  vs.field = 0; // expected-error{{no member named 'field' in 'VisibleStruct'}}
+  vs.setField(1); // expected-error{{no member named 'setField' in 'VisibleStruct'}}
 
   return hidden_var; // expected-error{{use of undeclared identifier 'hidden_var'}}
 }

diff  --git a/clang/test/Modules/template-function-specialization.cpp b/clang/test/Modules/template-function-specialization.cpp
deleted file mode 100644
index 3eac92e7edb94..0000000000000
--- a/clang/test/Modules/template-function-specialization.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-// RUN: rm -fr %t
-// RUN: mkdir %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/foo.cppm -o %t/foo.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
-//
-//--- foo.cppm
-module;
-# 3 __FILE__ 1 // use the next physical line number here (and below)
-template <typename T>
-void foo() {
-}
-
-template <>
-void foo<int>() {
-}
-
-template <typename T>
-void foo2() {
-}
-
-template <>
-void foo2<int>() {
-}
-
-template <typename T>
-void foo3() {
-}
-
-template <>
-void foo3<int>();
-
-export module foo;
-export using ::foo;
-export using ::foo3;
-
-export template <typename T>
-void foo4() {
-}
-
-export template <>
-void foo4<int>() {
-}
-
-//--- Use.cpp
-import foo;
-void use() {
-  foo<short>();
-  foo<int>();
-  foo2<short>(); // expected-error {{missing '#include'; 'foo2' must be declared before it is used}}
-                 // expected-note@* {{declaration here is not visible}}
-  foo2<int>();   // expected-error {{missing '#include'; 'foo2' must be declared before it is used}}
-                 // expected-note@* {{declaration here is not visible}}
-  foo3<short>();
-  foo3<int>();
-
-  foo4<short>();
-  foo4<int>();
-}

diff  --git a/clang/test/Modules/template_default_argument.cpp b/clang/test/Modules/template_default_argument.cpp
deleted file mode 100644
index 5a7d1c04cf181..0000000000000
--- a/clang/test/Modules/template_default_argument.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-// RUN: rm -rf %t
-// RUN: mkdir -p %t
-// RUN: split-file %s %t
-//
-// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-module-interface -o %t/B.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
-//
-//--- templ.h
-template <typename T, typename U = T>
-class templ {};
-template <typename T, typename U = void>
-void templ_func() {}
-
-//--- B.cppm
-module;
-#include "templ.h"
-export module B;
-export template <typename G>
-templ<G> bar() {
-  templ_func<G>();
-  return {};
-}
-
-//--- Use.cpp
-// expected-no-diagnostics
-import B;
-auto foo() {
-  return bar<int>();
-}


        


More information about the cfe-commits mailing list