diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-05-01 21:22:17 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-05-01 21:22:17 +0000 |
commit | c9e137359d69ba06ab347da130bbc5046452cb69 (patch) | |
tree | 0ec7829ffc2d7772b720f2085142cdbd681d7fc5 /lib/Lex/PPLexerChange.cpp | |
parent | 8189e1138317c86d9648594b32a7a747358bb6bf (diff) |
[modules] Add -fmodules-local-submodule-visibility flag.
This flag specifies that the normal visibility rules should be used even for
local submodules (submodules of the currently-being-built module). Thus names
will only be visible if a header / module that declares them has actually been
included / imported, and not merely because a submodule that happened to be
built earlier declared those names. This also removes the need to modularize
bottom-up: textually-included headers will be included into every submodule
that includes them, since their include guards will not leak between modules.
So far, this only governs visibility of macros, not of declarations, so is not
ready for real use yet.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@236350 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Lex/PPLexerChange.cpp')
-rw-r--r-- | lib/Lex/PPLexerChange.cpp | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index 6766fdfcd0..c506aa7f6f 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -612,16 +612,25 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) { void Preprocessor::EnterSubmodule(Module *M, SourceLocation ImportLoc) { // Save the current state for future imports. BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo(M, ImportLoc)); - auto &Info = BuildingSubmoduleStack.back(); - // Copy across our macros and start the submodule with the current state. - // FIXME: We should start each submodule with just the predefined macros. - for (auto &M : Macros) { - BuildingSubmoduleInfo::SavedMacroInfo SMI; - SMI.Latest = M.second.getLatest(); - auto O = M.second.getOverriddenMacros(); - SMI.Overridden.insert(SMI.Overridden.end(), O.begin(), O.end()); - Info.Macros.insert(std::make_pair(M.first, SMI)); + Info.Macros.swap(Macros); + // Save our visible modules set. This is guaranteed to clear the set. + if (getLangOpts().ModulesLocalVisibility) + Info.VisibleModules = std::move(VisibleModules); + + // Determine the set of starting macros for this submodule. + // FIXME: If we re-enter a submodule, should we restore its MacroDirectives? + auto &StartingMacros = (getLangOpts().ModulesLocalVisibility && + BuildingSubmoduleStack.size() > 1) + ? BuildingSubmoduleStack[0].Macros + : Info.Macros; + + // Restore to the starting state. + // FIXME: Do this lazily, when each macro name is first referenced. + for (auto &Macro : StartingMacros) { + MacroState MS(Macro.second.getLatest()); + MS.setOverriddenMacros(*this, MS.getOverriddenMacros()); + Macros.insert(std::make_pair(Macro.first, std::move(MS))); } } @@ -631,19 +640,35 @@ void Preprocessor::LeaveSubmodule() { // Create ModuleMacros for any macros defined in this submodule. for (auto &Macro : Macros) { auto *II = const_cast<IdentifierInfo*>(Macro.first); - auto SavedInfo = Info.Macros.lookup(II); + auto &OuterInfo = Info.Macros[II]; + + // Find the starting point for the MacroDirective chain in this submodule. + auto *OldMD = OuterInfo.getLatest(); + if (getLangOpts().ModulesLocalVisibility && + BuildingSubmoduleStack.size() > 1) { + auto &PredefMacros = BuildingSubmoduleStack[0].Macros; + auto PredefMacroIt = PredefMacros.find(Macro.first); + if (PredefMacroIt == PredefMacros.end()) + OldMD = nullptr; + else + OldMD = PredefMacroIt->second.getLatest(); + } // This module may have exported a new macro. If so, create a ModuleMacro // representing that fact. bool ExplicitlyPublic = false; - for (auto *MD = Macro.second.getLatest(); MD != SavedInfo.Latest; + for (auto *MD = Macro.second.getLatest(); MD != OldMD; MD = MD->getPrevious()) { assert(MD && "broken macro directive chain"); // Skip macros defined in other submodules we #included along the way. - Module *Mod = getModuleContainingLocation(MD->getLocation()); - if (Mod != Info.M) - continue; + // There's no point doing this if we're tracking local submodule + // visibiltiy, since there can be no such directives in our list. + if (!getLangOpts().ModulesLocalVisibility) { + Module *Mod = getModuleContainingLocation(MD->getLocation()); + if (Mod != Info.M) + continue; + } if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) { // The latest visibility directive for a name in a submodule affects @@ -667,11 +692,21 @@ void Preprocessor::LeaveSubmodule() { } } - // Restore the macro's overrides list. - Macro.second.setOverriddenMacros(SavedInfo.Overridden); + // Maintain a single macro directive chain if we're not tracking + // per-submodule macro visibility. + if (!getLangOpts().ModulesLocalVisibility) + OuterInfo.setLatest(Macro.second.getLatest()); } - makeModuleVisible(Info.M, Info.ImportLoc); + // Put back the old macros. + std::swap(Info.Macros, Macros); + + if (getLangOpts().ModulesLocalVisibility) + VisibleModules = std::move(Info.VisibleModules); + + // A nested #include makes the included submodule visible. + if (BuildingSubmoduleStack.size() > 1) + makeModuleVisible(Info.M, Info.ImportLoc); BuildingSubmoduleStack.pop_back(); } |