using Decl::isModulePrivate;
using Decl::setModulePrivate;
+ /// \brief Determine whether this declaration is hidden from name lookup.
+ bool isHidden() const { return Hidden; }
+
+ /// \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;
+ }
+
/// \brief Determine whether this declaration is a C++ class member.
bool isCXXClassMember() const {
const DeclContext *DC = getDeclContext();
reinterpret_cast<Module **>(this)[-1] = M;
}
- Module *getOwningModule() const {
- return isFromASTFile() ? getImportedOwningModule() : getLocalOwningModule();
- }
-
- /// \brief Determine whether this declaration is hidden from name lookup.
- bool isHidden() const { return Hidden; }
-
- /// \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;
- }
-
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}
return getCompilingModule() != CMK_None;
}
- /// Do we need to track the owning module for a local declaration?
- bool trackLocalOwningModule() const {
- return ModulesLocalVisibility;
- }
-
bool isSignedOverflowDefined() const {
return getSignedOverflowBehavior() == SOB_Defined;
}
VisibleModuleSet VisibleModules;
+ Module *CachedFakeTopLevelModule;
+
public:
/// \brief Get the module owning an entity.
- Module *getOwningModule(Decl *Entity) { return Entity->getOwningModule(); }
+ Module *getOwningModule(Decl *Entity);
/// \brief Make a merged definition of an existing hidden definition \p ND
/// visible at the specified location.
dumpSourceRange(D->getSourceRange());
OS << ' ';
dumpLocation(D->getLocation());
- if (D->isFromASTFile())
- OS << " imported";
- if (Module *M = D->getOwningModule())
+ if (Module *M = D->getImportedOwningModule())
OS << " in " << M->getFullModuleName();
+ else if (Module *M = D->getLocalOwningModule())
+ OS << " in (local) " << M->getFullModuleName();
if (auto *ND = dyn_cast<NamedDecl>(D))
for (Module *M : D->getASTContext().getModulesWithMergedDefinition(
const_cast<NamedDecl *>(ND)))
TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
: Decl(TranslationUnit, nullptr, SourceLocation()),
- DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(nullptr) {}
+ DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(nullptr) {
+ Hidden = Ctx.getLangOpts().ModulesLocalVisibility;
+}
//===----------------------------------------------------------------------===//
// NamedDecl Implementation
assert(!Parent || &Parent->getParentASTContext() == &Ctx);
// With local visibility enabled, we track the owning module even for local
// declarations.
- if (Ctx.getLangOpts().trackLocalOwningModule()) {
+ if (Ctx.getLangOpts().ModulesLocalVisibility) {
// Ensure required alignment of the resulting object by adding extra
// padding at the start if required.
size_t ExtraAlign =
char *Buffer = reinterpret_cast<char *>(
::operator new(ExtraAlign + sizeof(Module *) + Size + Extra, Ctx));
Buffer += ExtraAlign;
- auto *ParentModule =
- Parent ? cast<Decl>(Parent)->getOwningModule() : nullptr;
- return new (Buffer) Module*(ParentModule) + 1;
+ return new (Buffer) Module*(nullptr) + 1;
}
return ::operator new(Size + Extra, Ctx);
}
}
bool Decl::hasLocalOwningModuleStorage() const {
- return getASTContext().getLangOpts().trackLocalOwningModule();
+ return getASTContext().getLangOpts().ModulesLocalVisibility;
}
const char *Decl::getDeclKindName() const {
getMultipleDC()->LexicalDC = DC;
}
Hidden = cast<Decl>(DC)->Hidden;
- if (Hidden && !isFromASTFile()) {
- assert(hasLocalOwningModuleStorage() &&
- "hidden local declaration without local submodule visibility?");
- setLocalOwningModule(cast<Decl>(DC)->getOwningModule());
- }
}
void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr),
ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr),
DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false),
- TUKind(TUKind), NumSFINAEErrors(0), AccessCheckingSFINAE(false),
- InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
- ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(nullptr),
- DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this),
+ TUKind(TUKind), NumSFINAEErrors(0), CachedFakeTopLevelModule(nullptr),
+ AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
+ NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
+ CurrentInstantiationScope(nullptr), DisableTypoCorrection(false),
+ TyposCorrected(0), AnalysisWarnings(*this),
ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr),
CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) {
TUScope = nullptr;
ModuleScopes.back().OuterVisibleModules = std::move(VisibleModules);
VisibleModules.setVisible(Mod, DirectiveLoc);
-
- // The enclosing context is now part of this module.
- // FIXME: Consider creating a child DeclContext to hold the entities
- // lexically within the module.
- if (getLangOpts().trackLocalOwningModule()) {
- cast<Decl>(CurContext)->setHidden(true);
- cast<Decl>(CurContext)->setLocalOwningModule(Mod);
- }
}
void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) {
DirectiveLoc = EomLoc;
}
BuildModuleInclude(DirectiveLoc, Mod);
-
- // Any further declarations are in whatever module we returned to.
- if (getLangOpts().trackLocalOwningModule()) {
- cast<Decl>(CurContext)->setLocalOwningModule(getCurrentModule());
- if (!getCurrentModule())
- cast<Decl>(CurContext)->setHidden(false);
- }
}
void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
return !R.empty();
}
+Module *Sema::getOwningModule(Decl *Entity) {
+ // If it's imported, grab its owning module.
+ Module *M = Entity->getImportedOwningModule();
+ if (M || !isa<NamedDecl>(Entity) || !cast<NamedDecl>(Entity)->isHidden())
+ return M;
+ assert(!Entity->isFromASTFile() &&
+ "hidden entity from AST file has no owning module");
+
+ if (!getLangOpts().ModulesLocalVisibility) {
+ // If we're not tracking visibility locally, the only way a declaration
+ // can be hidden and local is if it's hidden because it's parent is (for
+ // instance, maybe this is a lazily-declared special member of an imported
+ // class).
+ auto *Parent = cast<NamedDecl>(Entity->getDeclContext());
+ assert(Parent->isHidden() && "unexpectedly hidden decl");
+ return getOwningModule(Parent);
+ }
+
+ // It's local and hidden; grab or compute its owning module.
+ M = Entity->getLocalOwningModule();
+ if (M)
+ return M;
+
+ if (auto *Containing =
+ PP.getModuleContainingLocation(Entity->getLocation())) {
+ M = Containing;
+ } else if (Entity->isInvalidDecl() || Entity->getLocation().isInvalid()) {
+ // Don't bother tracking visibility for invalid declarations with broken
+ // locations.
+ cast<NamedDecl>(Entity)->setHidden(false);
+ } else {
+ // We need to assign a module to an entity that exists outside of any
+ // module, so that we can hide it from modules that we textually enter.
+ // Invent a fake module for all such entities.
+ if (!CachedFakeTopLevelModule) {
+ CachedFakeTopLevelModule =
+ PP.getHeaderSearchInfo().getModuleMap().findOrCreateModule(
+ "<top-level>", nullptr, false, false).first;
+
+ auto &SrcMgr = PP.getSourceManager();
+ SourceLocation StartLoc =
+ SrcMgr.getLocForStartOfFile(SrcMgr.getMainFileID());
+ auto &TopLevel = ModuleScopes.empty()
+ ? VisibleModules
+ : ModuleScopes[0].OuterVisibleModules;
+ TopLevel.setVisible(CachedFakeTopLevelModule, StartLoc);
+ }
+
+ M = CachedFakeTopLevelModule;
+ }
+
+ if (M)
+ Entity->setLocalOwningModule(M);
+ return M;
+}
+
void Sema::makeMergedDefinitionVisible(NamedDecl *ND) {
if (auto *M = getCurrentModule())
Context.mergeDefinitionIntoModule(ND, M);
if (SemaRef.getLangOpts().ModulesLocalVisibility) {
DeclModule = SemaRef.getOwningModule(D);
if (!DeclModule) {
+ // getOwningModule() may have decided the declaration should not be hidden.
assert(!D->isHidden() && "hidden decl not from a module");
return true;
}