Index: include/clang/Lex/Preprocessor.h =================================================================== --- include/clang/Lex/Preprocessor.h +++ include/clang/Lex/Preprocessor.h @@ -522,10 +522,13 @@ /// \brief Information about a submodule's preprocessor state. struct SubmoduleState { + SubmoduleState() : NumCompiledHeaders(0) {} /// The macros for the submodule. MacroMap Macros; /// The set of modules that are visible within the submodule. VisibleModuleSet VisibleModules; + /// Number of module headers compiled so far. + unsigned NumCompiledHeaders; // FIXME: CounterValue? // FIXME: PragmaPushMacroInfo? }; Index: lib/Lex/PPLexerChange.cpp =================================================================== --- lib/Lex/PPLexerChange.cpp +++ lib/Lex/PPLexerChange.cpp @@ -404,6 +404,8 @@ bool LeavingSubmodule = CurSubmodule && CurLexer; if (LeavingSubmodule) { + ++CurSubmoduleState->NumCompiledHeaders; + // Notify the parser that we've left the module. const char *EndPos = getCurLexerEndPos(); Result.startToken(); @@ -701,42 +703,47 @@ // 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 != OldMD; - MD = MD->getPrevious()) { - assert(MD && "broken macro directive chain"); - - // Stop on macros defined in other submodules we #included along the way. - // There's no point doing this if we're tracking local submodule - // visibility, since there can be no such directives in our list. - if (!getLangOpts().ModulesLocalVisibility) { - Module *Mod = getModuleContainingLocation(MD->getLocation()); - if (Mod != LeavingMod) - break; - } + // We do this only if when the last module header is compiled, to avoid + // repeating updates of macro set. + if (CurSubmoduleState->NumCompiledHeaders >= + LeavingMod->Headers[Module::HK_Normal].size()) { + bool ExplicitlyPublic = false; + for (auto *MD = Macro.second.getLatest(); MD != OldMD; + MD = MD->getPrevious()) { + assert(MD && "broken macro directive chain"); + + // Stop on macros defined in other submodules we #included along the + // way. There's no point doing this if we're tracking local submodule + // visibility, since there can be no such directives in our list. + if (!getLangOpts().ModulesLocalVisibility) { + Module *Mod = getModuleContainingLocation(MD->getLocation()); + if (Mod != LeavingMod) + break; + } - if (auto *VisMD = dyn_cast(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. + if (auto *VisMD = dyn_cast(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(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; + // Don't bother creating a module macro if it would represent a #undef + // that doesn't override anything. + if (Def || !Macro.second.getOverriddenMacros().empty()) + addModuleMacro(LeavingMod, II, Def, + Macro.second.getOverriddenMacros(), IsNew); break; - } else { - MacroInfo *Def = nullptr; - if (DefMacroDirective *DefMD = dyn_cast(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; - // Don't bother creating a module macro if it would represent a #undef - // that doesn't override anything. - if (Def || !Macro.second.getOverriddenMacros().empty()) - addModuleMacro(LeavingMod, II, Def, - Macro.second.getOverriddenMacros(), IsNew); - break; + } } } }