diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-04-23 18:18:26 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-04-23 18:18:26 +0000 |
commit | eacc7339437e06b76df1f8b653c5a4dfb2566eda (patch) | |
tree | 58fe5177235e26c8049d04f5910eb1b219acaa50 /lib/Lex/PPLexerChange.cpp | |
parent | 9e7eb7e6324af09ffac26146a8dc9c792f49c0e3 (diff) |
[modules] Determine the set of macros exported by a submodule at the end of that submodule.
Previously we'd defer this determination until writing the AST, which doesn't
allow us to use this information when building other submodules of the same
module. This change also allows us to use a uniform mechanism for writing
module macro records, independent of whether they are local or imported.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@235614 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Lex/PPLexerChange.cpp')
-rw-r--r-- | lib/Lex/PPLexerChange.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index fb5e2b0580..33f5ff07f0 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -400,6 +400,9 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { CurLexer->FormTokenWithChars(Result, EndPos, tok::annot_module_end); Result.setAnnotationEndLoc(Result.getLocation()); Result.setAnnotationValue(CurSubmodule); + + // We're done with this submodule. + LeaveSubmodule(); } // We're done with the #included file. @@ -605,3 +608,63 @@ void Preprocessor::HandleMicrosoftCommentPaste(Token &Tok) { // preprocessor directive mode), so just return EOF as our token. assert(!FoundLexer && "Lexer should return EOD before EOF in PP mode"); } + +void Preprocessor::EnterSubmodule(Module *M) { + // Save the current state for future imports. + BuildingSubmoduleStack.push_back(BuildingSubmoduleInfo(M)); + + 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. + Info.Macros = Macros; +} + +void Preprocessor::LeaveSubmodule() { + auto &Info = BuildingSubmoduleStack.back(); + + // Create ModuleMacros for any macros defined in this submodule. + for (auto &Macro : Macros) { + auto *II = const_cast<IdentifierInfo*>(Macro.first); + MacroState State = Info.Macros.lookup(II); + + // 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 != State.getLatest(); + MD = MD->getPrevious()) { + // Skip macros defined in other submodules we #included along the way. + Module *Mod = getModuleForLocation(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 + // all the directives that come before it. + if (VisMD->isPublic()) + ExplicitlyPublic = true; + else if (!ExplicitlyPublic) + // Private with no following public directive: not exported. + break; + } else { + MacroInfo *Def = nullptr; + if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) + Def = DefMD->getInfo(); + + // FIXME: Issue a warning if multiple headers for the same submodule + // define a macro, rather than silently ignoring all but the first. + bool IsNew; + addModuleMacro(Info.M, II, Def, Macro.second.getOverriddenMacros(), + IsNew); + break; + } + } + + // Update the macro to refer to the latest directive in the chain. + State.setLatest(Macro.second.getLatest()); + + // Restore the old macro state. + Macro.second = State; + } + + BuildingSubmoduleStack.pop_back(); +} |