From: Richard Smith Date: Mon, 27 Apr 2015 23:21:38 +0000 (+0000) Subject: [modules] Incrementally compute the list of overridden module macros based on X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2f2e0b923aa3e906018ab044878d5ffb0557aed8;p=clang [modules] Incrementally compute the list of overridden module macros based on the active module macros at the point of definition, rather than reconstructing it from the macro history. No functionality change intended. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@235941 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index aef950da05..4d1d4486d9 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -364,57 +364,104 @@ class Preprocessor : public RefCountedBase { }; SmallVector DelayedMacroExpandsCallbacks; - /// The state of a macro for an identifier. - class MacroState { - struct ExtInfo { - ExtInfo(MacroDirective *MD) : MD(MD) {} + /// Information about a name that has been used to define a module macro. + struct ModuleMacroInfo { + ModuleMacroInfo(MacroDirective *MD) + : MD(MD), ActiveModuleMacrosGeneration(0) {} - // The most recent macro directive for this identifier. - MacroDirective *MD; - // The module macros that are overridden by this macro. - SmallVector OverriddenMacros; - }; - - llvm::PointerUnion State; + /// The most recent macro directive for this identifier. + MacroDirective *MD; + /// The active module macros for this identifier. + llvm::TinyPtrVector ActiveModuleMacros; + /// The generation number at which we last updated ActiveModuleMacros. + /// \see Preprocessor::MacroVisibilityGeneration. + unsigned ActiveModuleMacrosGeneration; + /// Whether this macro name is ambiguous. + bool IsAmbiguous; + /// The module macros that are overridden by this macro. + llvm::TinyPtrVector OverriddenMacros; + }; - ExtInfo &getExtInfo(Preprocessor &PP) { - auto *Ext = State.dyn_cast(); - if (!Ext) { - Ext = new (PP.getPreprocessorAllocator()) - ExtInfo(State.get()); - State = Ext; + /// The state of a macro for an identifier. + class MacroState { + mutable llvm::PointerUnion State; + + ModuleMacroInfo *getModuleInfo(Preprocessor &PP, IdentifierInfo *II) const { + // FIXME: Find a spare bit on IdentifierInfo and store a + // HasModuleMacros flag. + if (!II->hasMacroDefinition() || !PP.getLangOpts().Modules || + !PP.MacroVisibilityGeneration) + return nullptr; + + auto *Info = State.dyn_cast(); + if (!Info) { + Info = new (PP.getPreprocessorAllocator()) + ModuleMacroInfo(State.get()); + State = Info; } - return *Ext; + + if (PP.MacroVisibilityGeneration != Info->ActiveModuleMacrosGeneration) + PP.updateModuleMacroInfo(II, *Info); + return Info; } public: MacroState() : MacroState(nullptr) {} MacroState(MacroDirective *MD) : State(MD) {} MacroDirective *getLatest() const { - if (auto *Ext = State.dyn_cast()) - return Ext->MD; + if (auto *Info = State.dyn_cast()) + return Info->MD; return State.get(); } void setLatest(MacroDirective *MD) { - if (auto *Ext = State.dyn_cast()) - Ext->MD = MD; + if (auto *Info = State.dyn_cast()) + Info->MD = MD; else State = MD; } + bool isAmbiguous(Preprocessor &PP, IdentifierInfo *II) const { + auto *Info = getModuleInfo(PP, II); + return Info ? Info->IsAmbiguous : false; + } + ArrayRef getActiveModuleMacros(Preprocessor &PP, + IdentifierInfo *II) const { + if (auto *Info = getModuleInfo(PP, II)) + return Info->ActiveModuleMacros; + return None; + } + MacroDirective::DefInfo findDirectiveAtLoc(SourceLocation Loc, SourceManager &SourceMgr) const { + // FIXME: Incorporate module macros into the result of this. return getLatest()->findDirectiveAtLoc(Loc, SourceMgr); } - void addOverriddenMacro(Preprocessor &PP, ModuleMacro *MM) { - getExtInfo(PP).OverriddenMacros.push_back(MM); + void overrideActiveModuleMacros(Preprocessor &PP, IdentifierInfo *II) { + if (auto *Info = getModuleInfo(PP, II)) { + for (auto *Active : Info->ActiveModuleMacros) + Info->OverriddenMacros.push_back(Active); + Info->ActiveModuleMacros.clear(); + Info->IsAmbiguous = false; + } } ArrayRef getOverriddenMacros() const { - if (auto *Ext = State.dyn_cast()) - return Ext->OverriddenMacros; + if (auto *Info = State.dyn_cast()) + return Info->OverriddenMacros; return None; } + void setOverriddenMacros(ArrayRef Overrides) { + auto *Info = State.dyn_cast(); + if (!Info) { + assert(Overrides.empty() && + "have overrides but never had module macro"); + return; + } + Info->OverriddenMacros.clear(); + Info->OverriddenMacros.insert(Info->OverriddenMacros.end(), + Overrides.begin(), Overrides.end()); + Info->ActiveModuleMacrosGeneration = 0; + } }; typedef llvm::DenseMap MacroMap; @@ -435,8 +482,13 @@ class Preprocessor : public RefCountedBase { Module *M; /// The location at which the module was included. SourceLocation ImportLoc; + + struct SavedMacroInfo { + MacroDirective *Latest; + llvm::TinyPtrVector Overridden; + }; /// The macros that were visible before we entered the module. - MacroMap Macros; + llvm::DenseMap Macros; // FIXME: VisibleModules? // FIXME: CounterValue? @@ -447,6 +499,10 @@ class Preprocessor : public RefCountedBase { void EnterSubmodule(Module *M, SourceLocation ImportLoc); void LeaveSubmodule(); + /// Update the set of active module macros and ambiguity flag for a module + /// macro name. + void updateModuleMacroInfo(IdentifierInfo *II, ModuleMacroInfo &Info); + /// The set of known macros exported from modules. llvm::FoldingSet ModuleMacros; @@ -455,6 +511,10 @@ class Preprocessor : public RefCountedBase { llvm::DenseMap> LeafModuleMacros; + /// The generation number for module macros. Incremented each time the set + /// of modules with visible macros changes. + unsigned MacroVisibilityGeneration; + /// \brief Macros that we want to warn because they are not used at the end /// of the translation unit. /// diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 7c0edfc876..718bb5cb89 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -1693,6 +1693,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, ModuleLoadResult Imported = TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility, /*IsIncludeDirective=*/true); + ++MacroVisibilityGeneration; assert((Imported == nullptr || Imported == SuggestedModule.getModule()) && "the imported module is different than the suggested one"); diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index a57cba4183..57110aa246 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -616,7 +616,13 @@ void Preprocessor::EnterSubmodule(Module *M, SourceLocation 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. - Info.Macros = 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)); + } } void Preprocessor::LeaveSubmodule() { @@ -625,12 +631,12 @@ void Preprocessor::LeaveSubmodule() { // Create ModuleMacros for any macros defined in this submodule. for (auto &Macro : Macros) { auto *II = const_cast(Macro.first); - MacroState State = Info.Macros.lookup(II); + auto SavedInfo = 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(); + for (auto *MD = Macro.second.getLatest(); MD != SavedInfo.Latest; MD = MD->getPrevious()) { // Skip macros defined in other submodules we #included along the way. Module *Mod = getModuleContainingLocation(MD->getLocation()); @@ -659,11 +665,15 @@ void Preprocessor::LeaveSubmodule() { } } - // Update the macro to refer to the latest directive in the chain. - State.setLatest(Macro.second.getLatest()); + // Restore the macro's overrides list. + Macro.second.setOverriddenMacros(SavedInfo.Overridden); + } - // Restore the old macro state. - Macro.second = State; + if (Info.M->NameVisibility < Module::MacrosVisible) { + Info.M->NameVisibility = Module::MacrosVisible; + Info.M->MacroVisibilityLoc = Info.ImportLoc; + ++MacroVisibilityGeneration; + // FIXME: Also mark any exported macros as visible, and check for conflicts. } BuildingSubmoduleStack.pop_back(); diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 174718f438..438758c36f 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -50,6 +50,7 @@ void Preprocessor::appendMacroDirective(IdentifierInfo *II, MacroDirective *MD){ auto *OldMD = StoredMD.getLatest(); MD->setPrevious(OldMD); StoredMD.setLatest(MD); + StoredMD.overrideActiveModuleMacros(*this, II); // Set up the identifier as having associated macro history. II->setHasMacroDefinition(true); @@ -57,43 +58,6 @@ void Preprocessor::appendMacroDirective(IdentifierInfo *II, MacroDirective *MD){ II->setHasMacroDefinition(false); if (II->isFromAST() && !MD->isImported()) II->setChangedSinceDeserialization(); - - // Accumulate any overridden imported macros. - if (!MD->isImported() && getCurrentModule()) { - Module *OwningMod = getModuleContainingLocation(MD->getLocation()); - if (!OwningMod) - return; - - for (auto *PrevMD = OldMD; PrevMD; PrevMD = PrevMD->getPrevious()) { - Module *DirectiveMod = getModuleContainingLocation(PrevMD->getLocation()); - if (ModuleMacro *PrevMM = PrevMD->getOwningModuleMacro()) - StoredMD.addOverriddenMacro(*this, PrevMM); - else if (ModuleMacro *PrevMM = getModuleMacro(DirectiveMod, II)) - // The previous macro was from another submodule that we #included. - // FIXME: Create an import directive when importing a macro from a local - // submodule. - StoredMD.addOverriddenMacro(*this, PrevMM); - else - // We're still within the module defining the previous macro. We don't - // override it. - break; - - // Stop once we leave the original macro's submodule. - // - // Either this submodule #included another submodule of the same - // module or it just happened to be built after the other module. - // In the former case, we override the submodule's macro. - // - // FIXME: In the latter case, we shouldn't do so, but we can't tell - // these cases apart. - // - // FIXME: We can leave this submodule and re-enter it if it #includes a - // header within a different submodule of the same module. In such cases - // the overrides list will be incomplete. - if (DirectiveMod != OwningMod || !PrevMD->isImported()) - break; - } - } } void Preprocessor::setLoadedMacroDirective(IdentifierInfo *II, @@ -157,6 +121,71 @@ ModuleMacro *Preprocessor::getModuleMacro(Module *Mod, IdentifierInfo *II) { return ModuleMacros.FindNodeOrInsertPos(ID, InsertPos); } +void Preprocessor::updateModuleMacroInfo(IdentifierInfo *II, + ModuleMacroInfo &Info) { + assert(Info.ActiveModuleMacrosGeneration != MacroVisibilityGeneration && + "don't need to update this macro name info"); + Info.ActiveModuleMacrosGeneration = MacroVisibilityGeneration; + + auto Leaf = LeafModuleMacros.find(II); + if (Leaf == LeafModuleMacros.end()) { + // No imported macros at all: nothing to do. + return; + } + + Info.ActiveModuleMacros.clear(); + + // Every macro that's locally overridden is overridden by a visible macro. + llvm::DenseMap NumHiddenOverrides; + for (auto *O : Info.OverriddenMacros) + NumHiddenOverrides[O] = -1; + + // Collect all macros that are not overridden by a visible macro. + llvm::SmallVector Worklist(Leaf->second.begin(), + Leaf->second.end()); + while (!Worklist.empty()) { + auto *MM = Worklist.pop_back_val(); + if (MM->getOwningModule()->NameVisibility >= Module::MacrosVisible) { + // We only care about collecting definitions; undefinitions only act + // to override other definitions. + if (MM->getMacroInfo()) + Info.ActiveModuleMacros.push_back(MM); + } else { + for (auto *O : MM->overrides()) + if ((unsigned)++NumHiddenOverrides[O] == O->getNumOverridingMacros()) + Worklist.push_back(O); + } + } + + // Determine whether the macro name is ambiguous. + Info.IsAmbiguous = false; + MacroInfo *MI = nullptr; + bool IsSystemMacro = false; + if (auto *DMD = dyn_cast(Info.MD)) { + MI = DMD->getInfo(); + IsSystemMacro = SourceMgr.isInSystemHeader(DMD->getLocation()); + } + for (auto *Active : Info.ActiveModuleMacros) { + auto *NewMI = Active->getMacroInfo(); + + // Before marking the macro as ambiguous, check if this is a case where + // both macros are in system headers. If so, we trust that the system + // did not get it wrong. This also handles cases where Clang's own + // headers have a different spelling of certain system macros: + // #define LONG_MAX __LONG_MAX__ (clang's limits.h) + // #define LONG_MAX 0x7fffffffffffffffL (system's limits.h) + // + // FIXME: Remove the defined-in-system-headers check. clang's limits.h + // overrides the system limits.h's macros, so there's no conflict here. + IsSystemMacro &= Active->getOwningModule()->IsSystem; + if (MI && NewMI != MI && !IsSystemMacro && + !MI->isIdenticalTo(*NewMI, *this, /*Syntactically=*/true)) { + Info.IsAmbiguous = true; + break; + } + } +} + /// RegisterBuiltinMacro - Register the specified identifier in the identifier /// table and mark it as a builtin macro to be expanded. static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){ diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 6f2e390fc0..92ab2af192 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -73,7 +73,8 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr PPOpts, ModuleImportExpectsIdentifier(false), CodeCompletionReached(0), MainFileDir(nullptr), SkipMainFilePreamble(0, true), CurPPLexer(nullptr), CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), CurSubmodule(nullptr), - Callbacks(nullptr), MacroArgCache(nullptr), Record(nullptr), + Callbacks(nullptr), MacroVisibilityGeneration(0), + MacroArgCache(nullptr), Record(nullptr), MIChainHead(nullptr), DeserialMIChainHead(nullptr) { OwnsHeaderSearch = OwnsHeaders; @@ -748,11 +749,13 @@ void Preprocessor::LexAfterModuleImport(Token &Result) { // If we have a non-empty module path, load the named module. if (!ModuleImportPath.empty()) { Module *Imported = nullptr; - if (getLangOpts().Modules) + if (getLangOpts().Modules) { Imported = TheModuleLoader.loadModule(ModuleImportLoc, ModuleImportPath, Module::MacrosVisible, /*IsIncludeDirective=*/false); + ++MacroVisibilityGeneration; + } if (Callbacks && (getLangOpts().Modules || getLangOpts().DebuggerSupport)) Callbacks->moduleImport(ModuleImportLoc, ModuleImportPath, Imported); }