summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp2
-rw-r--r--clang/lib/Lex/PPLexerChange.cpp69
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp45
3 files changed, 71 insertions, 45 deletions
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index a91e31e36c1..79f80d0df74 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1508,6 +1508,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse);
Opts.ModulesDeclUse =
Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse;
+ Opts.ModulesLocalVisibility =
+ Args.hasArg(OPT_fmodules_local_submodule_visibility);
Opts.ModulesSearchAll = Opts.Modules &&
!Args.hasArg(OPT_fno_modules_search_all) &&
Args.hasArg(OPT_fmodules_search_all);
diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp
index 6766fdfcd07..c506aa7f6f0 100644
--- a/clang/lib/Lex/PPLexerChange.cpp
+++ b/clang/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();
}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 8a3b9d5163f..7ea50e5003f 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -2019,37 +2019,23 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
// Loop over all the macro directives that are live at the end of the file,
// emitting each to the PP section.
- // Construct the list of macro directives that need to be serialized.
- typedef std::pair<const IdentifierInfo *, MacroDirective *> MacroChain;
- SmallVector<MacroChain, 2> MacroDirectives;
- for (Preprocessor::macro_iterator
- I = PP.macro_begin(/*IncludeExternalMacros=*/false),
- E = PP.macro_end(/*IncludeExternalMacros=*/false);
- I != E; ++I) {
- MacroDirectives.push_back(std::make_pair(I->first, I->second.getLatest()));
- }
-
+ // Construct the list of identifiers with macro directives that need to be
+ // serialized.
+ SmallVector<const IdentifierInfo *, 128> MacroIdentifiers;
+ for (auto &Id : PP.getIdentifierTable())
+ if (Id.second->hadMacroDefinition() &&
+ (!Id.second->isFromAST() ||
+ Id.second->hasChangedSinceDeserialization()))
+ MacroIdentifiers.push_back(Id.second);
// Sort the set of macro definitions that need to be serialized by the
// name of the macro, to provide a stable ordering.
- int (*Cmp)(const MacroChain*, const MacroChain*) =
- [](const MacroChain *A, const MacroChain *B) -> int {
- return A->first->getName().compare(B->first->getName());
- };
- llvm::array_pod_sort(MacroDirectives.begin(), MacroDirectives.end(), Cmp);
+ std::sort(MacroIdentifiers.begin(), MacroIdentifiers.end(),
+ llvm::less_ptr<IdentifierInfo>());
// Emit the macro directives as a list and associate the offset with the
// identifier they belong to.
- for (auto &Chain : MacroDirectives) {
- const IdentifierInfo *Name = Chain.first;
- MacroDirective *MD = Chain.second;
-
- // If the macro or identifier need no updates, don't write the macro history
- // for this one.
- // FIXME: Chain the macro history instead of re-writing it.
- if (MD && MD->isFromPCH() &&
- Name->isFromAST() && !Name->hasChangedSinceDeserialization())
- continue;
-
+ for (const IdentifierInfo *Name : MacroIdentifiers) {
+ MacroDirective *MD = PP.getLocalMacroDirectiveHistory(Name);
auto StartOffset = Stream.GetCurrentBitNo();
// Emit the macro directives in reverse source order.
@@ -2069,6 +2055,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
}
// Write out any exported module macros.
+ bool EmittedModuleMacros = false;
if (IsModule) {
auto Leafs = PP.getLeafModuleMacros(Name);
SmallVector<ModuleMacro*, 8> Worklist(Leafs.begin(), Leafs.end());
@@ -2079,7 +2066,7 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
// Emit a record indicating this submodule exports this macro.
ModuleMacroRecord.push_back(
getSubmoduleID(Macro->getOwningModule()));
- ModuleMacroRecord.push_back(getMacroID(Macro->getMacroInfo()));
+ ModuleMacroRecord.push_back(getMacroRef(Macro->getMacroInfo(), Name));
for (auto *M : Macro->overrides())
ModuleMacroRecord.push_back(getSubmoduleID(M->getOwningModule()));
@@ -2090,10 +2077,12 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
for (auto *M : Macro->overrides())
if (++Visits[M] == M->getNumOverridingMacros())
Worklist.push_back(M);
+
+ EmittedModuleMacros = true;
}
}
- if (Record.empty())
+ if (Record.empty() && !EmittedModuleMacros)
continue;
IdentMacroDirectivesOffsetMap[Name] = StartOffset;
OpenPOWER on IntegriCloud