]> granicus.if.org Git - clang/commitdiff
[modules] Incrementally compute the list of overridden module macros based on
authorRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 27 Apr 2015 23:21:38 +0000 (23:21 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 27 Apr 2015 23:21:38 +0000 (23:21 +0000)
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

include/clang/Lex/Preprocessor.h
lib/Lex/PPDirectives.cpp
lib/Lex/PPLexerChange.cpp
lib/Lex/PPMacroExpansion.cpp
lib/Lex/Preprocessor.cpp

index aef950da05a13c9916ae0d1143666ebd3e335ee1..4d1d4486d91c86fe7add94671956d8a75a6e0f0b 100644 (file)
@@ -364,57 +364,104 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
   };
   SmallVector<MacroExpandsInfo, 2> 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<ModuleMacro*, 4> OverriddenMacros;
-    };
-
-    llvm::PointerUnion<MacroDirective *, ExtInfo *> State;
+    /// The most recent macro directive for this identifier.
+    MacroDirective *MD;
+    /// The active module macros for this identifier.
+    llvm::TinyPtrVector<ModuleMacro*> 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<ModuleMacro*> OverriddenMacros;
+  };
 
-    ExtInfo &getExtInfo(Preprocessor &PP) {
-      auto *Ext = State.dyn_cast<ExtInfo*>();
-      if (!Ext) {
-        Ext = new (PP.getPreprocessorAllocator())
-            ExtInfo(State.get<MacroDirective *>());
-        State = Ext;
+  /// The state of a macro for an identifier.
+  class MacroState {
+    mutable llvm::PointerUnion<MacroDirective *, ModuleMacroInfo *> 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<ModuleMacroInfo*>();
+      if (!Info) {
+        Info = new (PP.getPreprocessorAllocator())
+            ModuleMacroInfo(State.get<MacroDirective *>());
+        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<ExtInfo*>())
-        return Ext->MD;
+      if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
+        return Info->MD;
       return State.get<MacroDirective*>();
     }
     void setLatest(MacroDirective *MD) {
-      if (auto *Ext = State.dyn_cast<ExtInfo*>())
-        Ext->MD = MD;
+      if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
+        Info->MD = MD;
       else
         State = MD;
     }
 
+    bool isAmbiguous(Preprocessor &PP, IdentifierInfo *II) const {
+      auto *Info = getModuleInfo(PP, II);
+      return Info ? Info->IsAmbiguous : false;
+    }
+    ArrayRef<ModuleMacro *> 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<ModuleMacro*> getOverriddenMacros() const {
-      if (auto *Ext = State.dyn_cast<ExtInfo*>())
-        return Ext->OverriddenMacros;
+      if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
+        return Info->OverriddenMacros;
       return None;
     }
+    void setOverriddenMacros(ArrayRef<ModuleMacro*> Overrides) {
+      auto *Info = State.dyn_cast<ModuleMacroInfo*>();
+      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<const IdentifierInfo *, MacroState> MacroMap;
@@ -435,8 +482,13 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
     Module *M;
     /// The location at which the module was included.
     SourceLocation ImportLoc;
+
+    struct SavedMacroInfo {
+      MacroDirective *Latest;
+      llvm::TinyPtrVector<ModuleMacro*> Overridden;
+    };
     /// The macros that were visible before we entered the module.
-    MacroMap Macros;
+    llvm::DenseMap<const IdentifierInfo*, SavedMacroInfo> Macros;
 
     // FIXME: VisibleModules?
     // FIXME: CounterValue?
@@ -447,6 +499,10 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
   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<ModuleMacro> ModuleMacros;
 
@@ -455,6 +511,10 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
   llvm::DenseMap<const IdentifierInfo *, llvm::TinyPtrVector<ModuleMacro*>>
       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.
   ///
index 7c0edfc876d45f966007934cc924f34b96578cb1..718bb5cb89ccb837f50dc53301187186cf325d61 100644 (file)
@@ -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");
 
index a57cba4183550aac72b6010e9113d565c04a5f11..57110aa246fe42ba035fc049a9edf4d34f3101cb 100644 (file)
@@ -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<IdentifierInfo*>(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();
index 174718f4385a9416b817e2b9c3fe3e8100f150b6..438758c36f6a7a6b593c84b866df4da253eb2697 100644 (file)
@@ -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<ModuleMacro *, int> NumHiddenOverrides;
+  for (auto *O : Info.OverriddenMacros)
+    NumHiddenOverrides[O] = -1;
+
+  // Collect all macros that are not overridden by a visible macro.
+  llvm::SmallVector<ModuleMacro *, 16> 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<DefMacroDirective>(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){
index 6f2e390fc0336779fc39dbcd46e0b8110e34ca5c..92ab2af19216bfd347b6a9566a419fa1170186ac 100644 (file)
@@ -73,7 +73,8 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> 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);
   }