r306075 - PR33552: Distinguish between declarations that are owned by no module and

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 22 18:04:36 PDT 2017


Author: rsmith
Date: Thu Jun 22 20:04:34 2017
New Revision: 306075

URL: http://llvm.org/viewvc/llvm-project?rev=306075&view=rev
Log:
PR33552: Distinguish between declarations that are owned by no module and
declarations that are owned but unconditionally visible.

This allows us to set declarations as visible even if they have a local owning
module, without losing information. In turn, that means that our Objective-C
support can keep on incorrectly assuming the "hidden" bit on the declaration is
the whole story with regard to name visibility. This will also be useful once
we support the C++ Modules TS export semantics.

Objective-C name visibility is still incorrect in any case where the "hidden"
bit is not the complete story: for instance, in Objective-C++ the set of
visible categories will be wrong during template instantiation, and with local
submodule visibility enabled it will be wrong when building modules. Fixing that
will require a major overhaul of how visibility is handled for Objective-C (and
particularly for categories).

Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/test/Misc/ast-dump-decl.c
    cfe/trunk/test/Misc/ast-dump-decl.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=306075&r1=306074&r2=306075&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Thu Jun 22 20:04:34 2017
@@ -202,26 +202,33 @@ public:
     OBJC_TQ_CSNullability = 0x40
   };
 
-protected:
-  // Enumeration values used in the bits stored in NextInContextAndBits.
-  enum {
-    /// \brief Whether this declaration is a top-level declaration (function,
-    /// global variable, etc.) that is lexically inside an objc container
-    /// definition.
-    TopLevelDeclInObjCContainerFlag = 0x01,
-    
-    /// \brief Whether this declaration is private to the module in which it was
-    /// defined.
-    ModulePrivateFlag = 0x02
+  /// The kind of ownership a declaration has, for visibility purposes.
+  /// This enumeration is designed such that higher values represent higher
+  /// levels of name hiding.
+  enum class ModuleOwnershipKind : unsigned {
+    /// This declaration is not owned by a module.
+    Unowned,
+    /// This declaration has an owning module, but is globally visible
+    /// (typically because its owning module is visible and we know that
+    /// modules cannot later become hidden in this compilation).
+    /// After serialization and deserialization, this will be converted
+    /// to VisibleWhenImported.
+    Visible,
+    /// This declaration has an owning module, and is visible when that
+    /// module is imported.
+    VisibleWhenImported,
+    /// This declaration has an owning module, but is only visible to
+    /// lookups that occur within that module.
+    ModulePrivate
   };
-  
+
+protected:
   /// \brief The next declaration within the same lexical
   /// DeclContext. These pointers form the linked list that is
   /// traversed via DeclContext's decls_begin()/decls_end().
   ///
-  /// The extra two bits are used for the TopLevelDeclInObjCContainer and
-  /// ModulePrivate bits.
-  llvm::PointerIntPair<Decl *, 2, unsigned> NextInContextAndBits;
+  /// The extra two bits are used for the ModuleOwnershipKind.
+  llvm::PointerIntPair<Decl *, 2, ModuleOwnershipKind> NextInContextAndBits;
 
 private:
   friend class DeclContext;
@@ -282,6 +289,11 @@ private:
   /// are regarded as "referenced" but not "used".
   unsigned Referenced : 1;
 
+  /// \brief Whether this declaration is a top-level declaration (function,
+  /// global variable, etc.) that is lexically inside an objc container
+  /// definition.
+  unsigned TopLevelDeclInObjCContainer : 1;
+  
   /// \brief Whether statistic collection is enabled.
   static bool StatisticsEnabled;
 
@@ -294,11 +306,6 @@ protected:
   /// \brief Whether this declaration was loaded from an AST file.
   unsigned FromASTFile : 1;
 
-  /// \brief Whether this declaration is hidden from normal name lookup, e.g.,
-  /// because it is was loaded from an AST file is either module-private or
-  /// because its submodule has not been made visible.
-  unsigned Hidden : 1;
-  
   /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
   unsigned IdentifierNamespace : 13;
 
@@ -332,26 +339,38 @@ protected:
 private:
   bool AccessDeclContextSanity() const;
 
+  /// Get the module ownership kind to use for a local lexical child of \p DC,
+  /// which may be either a local or (rarely) an imported declaration.
+  static ModuleOwnershipKind getModuleOwnershipKindForChildOf(DeclContext *DC) {
+    if (DC) {
+      auto *D = cast<Decl>(DC);
+      auto MOK = D->getModuleOwnershipKind();
+      if (MOK != ModuleOwnershipKind::Unowned &&
+          (!D->isFromASTFile() || D->hasLocalOwningModuleStorage()))
+        return MOK;
+      // If D is not local and we have no local module storage, then we don't
+      // need to track module ownership at all.
+    }
+    return ModuleOwnershipKind::Unowned;
+  }
+
 protected:
   Decl(Kind DK, DeclContext *DC, SourceLocation L)
-      : NextInContextAndBits(), DeclCtx(DC), Loc(L), DeclKind(DK),
-        InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false),
-        Referenced(false), Access(AS_none), FromASTFile(0),
-        Hidden(DC && cast<Decl>(DC)->Hidden &&
-               (!cast<Decl>(DC)->isFromASTFile() ||
-                hasLocalOwningModuleStorage())),
+      : NextInContextAndBits(nullptr, getModuleOwnershipKindForChildOf(DC)),
+        DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false),
+        Implicit(false), Used(false), Referenced(false),
+        TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
         IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
         CacheValidAndLinkage(0) {
     if (StatisticsEnabled) add(DK);
   }
 
   Decl(Kind DK, EmptyShell Empty)
-    : NextInContextAndBits(), DeclKind(DK), InvalidDecl(0),
-      HasAttrs(false), Implicit(false), Used(false), Referenced(false),
-      Access(AS_none), FromASTFile(0), Hidden(0),
-      IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
-      CacheValidAndLinkage(0)
-  {
+      : NextInContextAndBits(), DeclKind(DK), InvalidDecl(0), HasAttrs(false),
+        Implicit(false), Used(false), Referenced(false),
+        TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
+        IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
+        CacheValidAndLinkage(0) {
     if (StatisticsEnabled) add(DK);
   }
 
@@ -551,16 +570,11 @@ public:
   /// global variable, etc.) that is lexically inside an objc container
   /// definition.
   bool isTopLevelDeclInObjCContainer() const {
-    return NextInContextAndBits.getInt() & TopLevelDeclInObjCContainerFlag;
+    return TopLevelDeclInObjCContainer;
   }
 
   void setTopLevelDeclInObjCContainer(bool V = true) {
-    unsigned Bits = NextInContextAndBits.getInt();
-    if (V)
-      Bits |= TopLevelDeclInObjCContainerFlag;
-    else
-      Bits &= ~TopLevelDeclInObjCContainerFlag;
-    NextInContextAndBits.setInt(Bits);
+    TopLevelDeclInObjCContainer = V;
   }
 
   /// \brief Looks on this and related declarations for an applicable
@@ -570,7 +584,7 @@ public:
   /// \brief Whether this declaration was marked as being private to the
   /// module in which it was defined.
   bool isModulePrivate() const {
-    return NextInContextAndBits.getInt() & ModulePrivateFlag;
+    return getModuleOwnershipKind() == ModuleOwnershipKind::ModulePrivate;
   }
 
   /// \brief Whether this declaration is exported (by virtue of being lexically
@@ -585,15 +599,14 @@ public:
   const Attr *getDefiningAttr() const;
 
 protected:
-  /// \brief Specify whether this declaration was marked as being private
+  /// \brief Specify that this declaration was marked as being private
   /// to the module in which it was defined.
-  void setModulePrivate(bool MP = true) {
-    unsigned Bits = NextInContextAndBits.getInt();
-    if (MP)
-      Bits |= ModulePrivateFlag;
-    else
-      Bits &= ~ModulePrivateFlag;
-    NextInContextAndBits.setInt(Bits);
+  void setModulePrivate() {
+    // The module-private specifier has no effect on unowned declarations.
+    // FIXME: We should track this in some way for source fidelity.
+    if (getModuleOwnershipKind() == ModuleOwnershipKind::Unowned)
+      return;
+    setModuleOwnershipKind(ModuleOwnershipKind::ModulePrivate);
   }
 
   /// \brief Set the owning module ID.
@@ -692,7 +705,7 @@ public:
   /// \brief Get the imported owning module, if this decl is from an imported
   /// (non-local) module.
   Module *getImportedOwningModule() const {
-    if (!isFromASTFile())
+    if (!isFromASTFile() || !hasOwningModule())
       return nullptr;
 
     return getOwningModuleSlow();
@@ -701,31 +714,57 @@ public:
   /// \brief Get the local owning module, if known. Returns nullptr if owner is
   /// not yet known or declaration is not from a module.
   Module *getLocalOwningModule() const {
-    if (isFromASTFile() || !Hidden)
+    if (isFromASTFile() || !hasOwningModule())
       return nullptr;
 
     assert(hasLocalOwningModuleStorage() &&
-           "hidden local decl but no local module storage");
+           "owned local decl but no local module storage");
     return reinterpret_cast<Module *const *>(this)[-1];
   }
   void setLocalOwningModule(Module *M) {
-    assert(!isFromASTFile() && Hidden && hasLocalOwningModuleStorage() &&
+    assert(!isFromASTFile() && hasOwningModule() &&
+           hasLocalOwningModuleStorage() &&
            "should not have a cached owning module");
     reinterpret_cast<Module **>(this)[-1] = M;
   }
 
+  /// Is this declaration owned by some module?
+  bool hasOwningModule() const {
+    return getModuleOwnershipKind() != ModuleOwnershipKind::Unowned;
+  }
+
+  /// Get the module that owns this declaration.
   Module *getOwningModule() const {
     return isFromASTFile() ? getImportedOwningModule() : getLocalOwningModule();
   }
 
-  /// \brief Determine whether this declaration is hidden from name lookup.
-  bool isHidden() const { return Hidden; }
+  /// \brief Determine whether this declaration might be hidden from name
+  /// lookup. Note that the declaration might be visible even if this returns
+  /// \c false, if the owning module is visible within the query context.
+  // FIXME: Rename this to make it clearer what it does.
+  bool isHidden() const {
+    return (int)getModuleOwnershipKind() > (int)ModuleOwnershipKind::Visible;
+  }
+
+  /// Set that this declaration is globally visible, even if it came from a
+  /// module that is not visible.
+  void setVisibleDespiteOwningModule() {
+    if (hasOwningModule())
+      setModuleOwnershipKind(ModuleOwnershipKind::Visible);
+  }
+
+  /// \brief Get the kind of module ownership for this declaration.
+  ModuleOwnershipKind getModuleOwnershipKind() const {
+    return NextInContextAndBits.getInt();
+  }
 
   /// \brief Set whether this declaration is hidden from name lookup.
-  void setHidden(bool Hide) {
-    assert((!Hide || isFromASTFile() || hasLocalOwningModuleStorage()) &&
-           "declaration with no owning module can't be hidden");
-    Hidden = Hide;
+  void setModuleOwnershipKind(ModuleOwnershipKind MOK) {
+    assert(!(getModuleOwnershipKind() == ModuleOwnershipKind::Unowned &&
+             MOK != ModuleOwnershipKind::Unowned && !isFromASTFile() &&
+             !hasLocalOwningModuleStorage()) &&
+           "no storage available for owning module for this declaration");
+    NextInContextAndBits.setInt(MOK);
   }
 
   unsigned getIdentifierNamespace() const {

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=306075&r1=306074&r2=306075&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Jun 22 20:04:34 2017
@@ -894,7 +894,7 @@ void ASTContext::mergeDefinitionIntoModu
   if (getLangOpts().ModulesLocalVisibility)
     MergedDefModules[ND].push_back(M);
   else
-    ND->setHidden(false);
+    ND->setVisibleDespiteOwningModule();
 }
 
 void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) {

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=306075&r1=306074&r2=306075&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Thu Jun 22 20:04:34 2017
@@ -278,12 +278,12 @@ void Decl::setLexicalDeclContext(DeclCon
   // FIXME: We shouldn't be changing the lexical context of declarations
   // imported from AST files.
   if (!isFromASTFile()) {
-    Hidden = cast<Decl>(DC)->Hidden && hasLocalOwningModuleStorage();
-    if (Hidden)
+    setModuleOwnershipKind(getModuleOwnershipKindForChildOf(DC));
+    if (hasOwningModule())
       setLocalOwningModule(cast<Decl>(DC)->getOwningModule());
   }
 
-  assert((!Hidden || getOwningModule()) &&
+  assert((!hasOwningModule() || getOwningModule()) &&
          "hidden declaration has no owning module");
 }
 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=306075&r1=306074&r2=306075&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jun 22 20:04:34 2017
@@ -16104,7 +16104,10 @@ void Sema::ActOnModuleBegin(SourceLocati
   // lexically within the module.
   if (getLangOpts().trackLocalOwningModule()) {
     for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) {
-      cast<Decl>(DC)->setHidden(true);
+      cast<Decl>(DC)->setModuleOwnershipKind(
+          getLangOpts().ModulesLocalVisibility
+              ? Decl::ModuleOwnershipKind::VisibleWhenImported
+              : Decl::ModuleOwnershipKind::Visible);
       cast<Decl>(DC)->setLocalOwningModule(Mod);
     }
   }
@@ -16144,7 +16147,8 @@ void Sema::ActOnModuleEnd(SourceLocation
     for (auto *DC = CurContext; DC; DC = DC->getLexicalParent()) {
       cast<Decl>(DC)->setLocalOwningModule(getCurrentModule());
       if (!getCurrentModule())
-        cast<Decl>(DC)->setHidden(false);
+        cast<Decl>(DC)->setModuleOwnershipKind(
+            Decl::ModuleOwnershipKind::Unowned);
     }
   }
 }

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=306075&r1=306074&r2=306075&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Jun 22 20:04:34 2017
@@ -2630,7 +2630,7 @@ void Sema::DeclareGlobalAllocationFuncti
           // Make the function visible to name lookup, even if we found it in
           // an unimported module. It either is an implicitly-declared global
           // allocation function, or is suppressing that function.
-          Func->setHidden(false);
+          Func->setVisibleDespiteOwningModule();
           return;
         }
       }
@@ -2662,7 +2662,7 @@ void Sema::DeclareGlobalAllocationFuncti
         FnType, /*TInfo=*/nullptr, SC_None, false, true);
     Alloc->setImplicit();
     // Global allocation functions should always be visible.
-    Alloc->setHidden(false);
+    Alloc->setVisibleDespiteOwningModule();
 
     // Implicit sized deallocation functions always have default visibility.
     Alloc->addAttr(

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=306075&r1=306074&r2=306075&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Jun 22 20:04:34 2017
@@ -1341,7 +1341,7 @@ void Sema::makeMergedDefinitionVisible(N
     Context.mergeDefinitionIntoModule(ND, M);
   else
     // We're not building a module; just make the definition visible.
-    ND->setHidden(false);
+    ND->setVisibleDespiteOwningModule();
 
   // If ND is a template declaration, make the template parameters
   // visible too. They're not (necessarily) within a mergeable DeclContext.
@@ -1528,7 +1528,7 @@ bool LookupResult::isVisibleSlow(Sema &S
           !SemaRef.getLangOpts().ModulesLocalVisibility) {
         // Cache the fact that this declaration is implicitly visible because
         // its parent has a visible definition.
-        D->setHidden(false);
+        D->setVisibleDespiteOwningModule();
       }
       return true;
     }

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=306075&r1=306074&r2=306075&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Jun 22 20:04:34 2017
@@ -2045,7 +2045,7 @@ Sema::InstantiateClass(SourceLocation Po
 
   // The instantiation is visible here, even if it was first declared in an
   // unimported module.
-  Instantiation->setHidden(false);
+  Instantiation->setVisibleDespiteOwningModule();
 
   // FIXME: This loses the as-written tag kind for an explicit instantiation.
   Instantiation->setTagKind(Pattern->getTagKind());
@@ -2247,7 +2247,7 @@ bool Sema::InstantiateEnum(SourceLocatio
 
   // The instantiation is visible here, even if it was first declared in an
   // unimported module.
-  Instantiation->setHidden(false);
+  Instantiation->setVisibleDespiteOwningModule();
 
   // Enter the scope of this instantiation. We don't use
   // PushDeclContext because we don't have a scope.

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=306075&r1=306074&r2=306075&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Jun 22 20:04:34 2017
@@ -3868,7 +3868,7 @@ void Sema::InstantiateFunctionDefinition
 
   // The instantiation is visible here, even if it was first declared in an
   // unimported module.
-  Function->setHidden(false);
+  Function->setVisibleDespiteOwningModule();
 
   // Copy the inner loc start from the pattern.
   Function->setInnerLocStart(PatternDecl->getInnerLocStart());
@@ -4274,7 +4274,7 @@ void Sema::InstantiateVariableDefinition
 
       // The instantiation is visible here, even if it was first declared in an
       // unimported module.
-      Var->setHidden(false);
+      Var->setVisibleDespiteOwningModule();
 
       // If we're performing recursive template instantiation, create our own
       // queue of pending implicit instantiations that we will instantiate

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=306075&r1=306074&r2=306075&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Jun 22 20:04:34 2017
@@ -3580,8 +3580,8 @@ static void moveMethodToBackOfGlobalList
 void ASTReader::makeNamesVisible(const HiddenNames &Names, Module *Owner) {
   assert(Owner->NameVisibility != Module::Hidden && "nothing to make visible?");
   for (Decl *D : Names) {
-    bool wasHidden = D->Hidden;
-    D->Hidden = false;
+    bool wasHidden = D->isHidden();
+    D->setVisibleDespiteOwningModule();
 
     if (wasHidden && SemaObj) {
       if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) {
@@ -3648,7 +3648,7 @@ void ASTReader::mergeDefinitionVisibilit
   if (Def->isHidden()) {
     // If MergedDef is visible or becomes visible, make the definition visible.
     if (!MergedDef->isHidden())
-      Def->Hidden = false;
+      Def->setVisibleDespiteOwningModule();
     else if (getContext().getLangOpts().ModulesLocalVisibility) {
       getContext().mergeDefinitionIntoModule(
           Def, MergedDef->getImportedOwningModule(),

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=306075&r1=306074&r2=306075&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Jun 22 20:04:34 2017
@@ -522,31 +522,29 @@ void ASTDeclReader::VisitDecl(Decl *D) {
   D->setTopLevelDeclInObjCContainer(Record.readInt());
   D->setAccess((AccessSpecifier)Record.readInt());
   D->FromASTFile = true;
-  D->setModulePrivate(Record.readInt());
-  D->Hidden = D->isModulePrivate();
+  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()) {
     // Store the owning submodule ID in the declaration.
+    D->setModuleOwnershipKind(
+        ModulePrivate ? Decl::ModuleOwnershipKind::ModulePrivate
+                      : Decl::ModuleOwnershipKind::VisibleWhenImported);
     D->setOwningModuleID(SubmoduleID);
 
-    if (D->Hidden) {
-      // Module-private declarations are never visible, so there is no work to do.
+    if (ModulePrivate) {
+      // Module-private declarations are never visible, so there is no work to
+      // do.
     } else if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
       // If local visibility is being tracked, this declaration will become
-      // hidden and visible as the owning module does. Inform Sema that this
-      // declaration might not be visible.
-      D->Hidden = true;
+      // hidden and visible as the owning module does.
     } else if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
-      if (Owner->NameVisibility != Module::AllVisible) {
-        // The owning module is not visible. Mark this declaration as hidden.
-        D->Hidden = true;
-
-        // Note that this declaration was hidden because its owning module is 
-        // not yet visible.
+      // Mark the declaration as visible when its owning module becomes visible.
+      if (Owner->NameVisibility == Module::AllVisible)
+        D->setVisibleDespiteOwningModule();
+      else
         Reader.HiddenNamesMap[Owner].push_back(D);
-      }
     }
   }
 }
@@ -4144,7 +4142,7 @@ void ASTDeclReader::UpdateDecl(Decl *D)
         Reader.HiddenNamesMap[Owner].push_back(Exported);
       } else {
         // The declaration is now visible.
-        Exported->Hidden = false;
+        Exported->setVisibleDespiteOwningModule();
       }
       break;
     }

Modified: cfe/trunk/test/Misc/ast-dump-decl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-decl.c?rev=306075&r1=306074&r2=306075&view=diff
==============================================================================
--- cfe/trunk/test/Misc/ast-dump-decl.c (original)
+++ cfe/trunk/test/Misc/ast-dump-decl.c Thu Jun 22 20:04:34 2017
@@ -1,8 +1,13 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix CHECK -strict-whitespace %s
 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -ast-dump %s | FileCheck -check-prefix CHECK-TU -strict-whitespace %s
+// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-name=X -triple x86_64-unknown-unknown -fmodule-map-file=%S/Inputs/module.modulemap -ast-dump -ast-dump-filter Test %s -DMODULES | FileCheck -check-prefix CHECK -check-prefix CHECK-MODULES -strict-whitespace %s
 
 int TestLocation;
-// CHECK: VarDecl 0x{{[^ ]*}} <{{.*}}:4:1, col:5> col:5 TestLocation
+// CHECK: VarDecl 0x{{[^ ]*}} <{{.*}}:[[@LINE-1]]:1, col:5> col:5 TestLocation
+
+#ifdef MODULES
+#pragma clang module begin X
+#endif
 
 struct TestIndent {
   int x;
@@ -33,7 +38,7 @@ typedef int TestTypedefDecl;
 // CHECK:      TypedefDecl{{.*}} TestTypedefDecl 'int'
 
 __module_private__ typedef int TestTypedefDeclPrivate;
-// CHECK:      TypedefDecl{{.*}} TestTypedefDeclPrivate 'int' __module_private__
+// CHECK-MODULE:      TypedefDecl{{.*}} TestTypedefDeclPrivate 'int' __module_private__
 
 enum TestEnumDecl {
   testEnumDecl
@@ -53,7 +58,7 @@ enum TestEnumDeclForward;
 // CHECK:      EnumDecl{{.*}} TestEnumDeclForward
 
 __module_private__ enum TestEnumDeclPrivate;
-// CHECK:      EnumDecl{{.*}} TestEnumDeclPrivate __module_private__
+// CHECK-MODULE:      EnumDecl{{.*}} TestEnumDeclPrivate __module_private__
 
 struct TestRecordDecl {
   int i;
@@ -83,7 +88,7 @@ struct TestRecordDeclForward;
 // CHECK:      RecordDecl{{.*}} struct TestRecordDeclForward
 
 __module_private__ struct TestRecordDeclPrivate;
-// CHECK:      RecordDecl{{.*}} struct TestRecordDeclPrivate __module_private__
+// CHECK-MODULE:      RecordDecl{{.*}} struct TestRecordDeclPrivate __module_private__
 
 enum testEnumConstantDecl {
   TestEnumConstantDecl,
@@ -136,7 +141,7 @@ struct testFieldDecl {
 // CHECK:      FieldDecl{{.*}} TestFieldDecl 'int'
 // CHECK:      FieldDecl{{.*}} TestFieldDeclWidth 'int'
 // CHECK-NEXT:   IntegerLiteral
-// CHECK:      FieldDecl{{.*}} TestFieldDeclPrivate 'int' __module_private__
+// CHECK-MODULE:      FieldDecl{{.*}} TestFieldDeclPrivate 'int' __module_private__
 
 int TestVarDecl;
 // CHECK:      VarDecl{{.*}} TestVarDecl 'int'
@@ -148,7 +153,7 @@ __thread int TestVarDeclThread;
 // CHECK:      VarDecl{{.*}} TestVarDeclThread 'int' tls{{$}}
 
 __module_private__ int TestVarDeclPrivate;
-// CHECK:      VarDecl{{.*}} TestVarDeclPrivate 'int' __module_private__
+// CHECK-MODULE:      VarDecl{{.*}} TestVarDeclPrivate 'int' __module_private__
 
 int TestVarDeclInit = 0;
 // CHECK:      VarDecl{{.*}} TestVarDeclInit 'int'
@@ -156,3 +161,8 @@ int TestVarDeclInit = 0;
 
 void testParmVarDecl(int TestParmVarDecl);
 // CHECK: ParmVarDecl{{.*}} TestParmVarDecl 'int'
+
+#ifdef MODULES
+#pragma clang module end
+#endif
+

Modified: cfe/trunk/test/Misc/ast-dump-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-decl.cpp?rev=306075&r1=306074&r2=306075&view=diff
==============================================================================
--- cfe/trunk/test/Misc/ast-dump-decl.cpp (original)
+++ cfe/trunk/test/Misc/ast-dump-decl.cpp Thu Jun 22 20:04:34 2017
@@ -95,17 +95,12 @@ class TestCXXRecordDeclPack : public T..
 thread_local int TestThreadLocalInt;
 // CHECK: TestThreadLocalInt {{.*}} tls_dynamic
 
-__module_private__ class TestCXXRecordDeclPrivate;
-// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDeclPrivate __module_private__
-
 class testCXXMethodDecl {
-  __module_private__ void TestCXXMethodDeclPrivate();
   virtual void TestCXXMethodDeclPure() = 0;
   void TestCXXMethodDeclDelete() = delete;
   void TestCXXMethodDeclThrow() throw();
   void TestCXXMethodDeclThrowType() throw(int);
 };
-// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclPrivate 'void (void)' __module_private__
 // CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclPure 'void (void)' virtual pure
 // CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclDelete 'void (void)' delete
 // CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrow 'void (void) throw()'




More information about the cfe-commits mailing list