[cfe-commits] r165682 - in /cfe/trunk: include/clang/Lex/ExternalPreprocessorSource.h include/clang/Lex/MacroInfo.h include/clang/Lex/Preprocessor.h include/clang/Serialization/ASTReader.h lib/Lex/MacroInfo.cpp lib/Lex/PPMacroExpansion.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/Modules/Inputs/macros_left.h test/Modules/Inputs/macros_right.h test/Modules/Inputs/module.map test/Modules/macros.c

Douglas Gregor dgregor at apple.com
Wed Oct 10 17:46:50 PDT 2012


Author: dgregor
Date: Wed Oct 10 19:46:49 2012
New Revision: 165682

URL: http://llvm.org/viewvc/llvm-project?rev=165682&view=rev
Log:
Deserialize macro history when we deserialize an identifier that has
macro history.

When deserializing macro history, we arrange history such that the
macros that have definitions (that haven't been #undef'd) and are
visible come at the beginning of the list, which is what the
preprocessor and other clients of Preprocessor::getMacroInfo()
expect. If additional macro definitions become visible later, they'll
be moved toward the front of the list. Note that it's possible to have
ambiguities, but we don't diagnose them yet.

There is a partially-implemented design decision here that, if a
particular identifier has been defined or #undef'd within the
translation unit, that definition (or #undef) hides any macro
definitions that come from imported modules. There's still a little
work to do to ensure that the right #undef'ing happens.

Additionally, we'll need to scope the update records for #undefs, so
they only kick in when the submodule containing that update record
becomes visible.


Modified:
    cfe/trunk/include/clang/Lex/ExternalPreprocessorSource.h
    cfe/trunk/include/clang/Lex/MacroInfo.h
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/lib/Lex/MacroInfo.cpp
    cfe/trunk/lib/Lex/PPMacroExpansion.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/Modules/Inputs/macros_left.h
    cfe/trunk/test/Modules/Inputs/macros_right.h
    cfe/trunk/test/Modules/Inputs/module.map
    cfe/trunk/test/Modules/macros.c

Modified: cfe/trunk/include/clang/Lex/ExternalPreprocessorSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ExternalPreprocessorSource.h?rev=165682&r1=165681&r2=165682&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ExternalPreprocessorSource.h (original)
+++ cfe/trunk/include/clang/Lex/ExternalPreprocessorSource.h Wed Oct 10 19:46:49 2012
@@ -28,9 +28,6 @@
   /// \brief Read the set of macros defined by this external macro source.
   virtual void ReadDefinedMacros() = 0;
   
-  /// \brief Read the definition for the given macro.
-  virtual void LoadMacroDefinition(IdentifierInfo *II) = 0;
-  
   /// \brief Update an out-of-date identifier.
   virtual void updateOutOfDateIdentifier(IdentifierInfo &II) = 0;
 };

Modified: cfe/trunk/include/clang/Lex/MacroInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/MacroInfo.h?rev=165682&r1=165681&r2=165682&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/MacroInfo.h (original)
+++ cfe/trunk/include/clang/Lex/MacroInfo.h Wed Oct 10 19:46:49 2012
@@ -105,7 +105,12 @@
    
   /// \brief Whether the macro has public (when described in a module).
   bool IsPublic : 1;
-  
+
+  /// \brief Whether the macro definition is currently "hidden".
+  /// Note that this is transient state that is never serialized to the AST
+  /// file.
+  bool IsHidden : 1;
+
    ~MacroInfo() {
     assert(ArgumentList == 0 && "Didn't call destroy before dtor!");
   }
@@ -149,10 +154,8 @@
   /// \brief Get the location where macro was undefined.
   SourceLocation getUndefLoc() const { return UndefLocation; }
 
-  /// \brief Set previous definition of the macro with the same name. Can only
-  /// be set once.
+  /// \brief Set previous definition of the macro with the same name.
   void setPreviousDefinition(MacroInfo *PreviousDef) {
-    assert(!PreviousDefinition && "PreviousDefiniton is already set!");
     PreviousDefinition = PreviousDef;
   }
 
@@ -326,7 +329,17 @@
   /// \brief Determine the location where this macro was explicitly made
   /// public or private within its module.
   SourceLocation getVisibilityLocation() { return VisibilityLocation; }
-  
+
+  /// \brief Determine whether this macro is currently defined (and has not
+  /// been #undef'd) or has been hidden.
+  bool isDefined() const { return UndefLocation.isInvalid() && !IsHidden; }
+
+  /// \brief Determine whether this macro definition is hidden.
+  bool isHidden() const { return IsHidden; }
+
+  /// \brief Set whether this macro definition is hidden.
+  void setHidden(bool Val) { IsHidden = Val; }
+
 private:
   unsigned getDefinitionLengthSlow(SourceManager &SM) const;
 };

Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=165682&r1=165681&r2=165682&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Wed Oct 10 19:46:49 2012
@@ -517,8 +517,12 @@
   MacroInfo *getMacroInfoHistory(IdentifierInfo *II) const;
 
   /// \brief Specify a macro for this identifier.
-  void setMacroInfo(IdentifierInfo *II, MacroInfo *MI,
-                    bool LoadedFromAST = false);
+  void setMacroInfo(IdentifierInfo *II, MacroInfo *MI);
+  /// \brief Add a MacroInfo that was loaded from an AST file.
+  void addLoadedMacroInfo(IdentifierInfo *II, MacroInfo *MI);
+  /// \brief Make the given MacroInfo, that was loaded from an AST file and
+  /// previously hidden, visible.
+  void makeLoadedMacroInfoVisible(IdentifierInfo *II, MacroInfo *MI);
   /// \brief Undefine a macro for this identifier.
   void clearMacroInfo(IdentifierInfo *II);
 

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=165682&r1=165681&r2=165682&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Wed Oct 10 19:46:49 2012
@@ -415,8 +415,35 @@
   /// global submodule ID to produce a local ID.
   GlobalSubmoduleMapType GlobalSubmoduleMap;
 
+  /// \brief An entity that has been hidden.
+  class HiddenName {
+    /// \brief The hidden declaration or macro.
+    llvm::PointerUnion<Decl *, MacroInfo *> DeclOrMacro;
+
+    /// \brief The name being defined to a macro, for the macro case.
+    IdentifierInfo *Identifier;
+
+  public:
+    HiddenName(Decl *D) : DeclOrMacro(D), Identifier() { }
+    HiddenName(IdentifierInfo *II, MacroInfo *MI)
+      : DeclOrMacro(MI), Identifier(II) { }
+
+    bool isDecl() const { return DeclOrMacro.is<Decl*>(); }
+    bool isMacro() const { return !isDecl(); }
+
+    Decl *getDecl() const {
+      assert(isDecl() && "Hidden name is not a declaration");
+      return DeclOrMacro.get<Decl *>();
+    }
+
+    std::pair<IdentifierInfo *, MacroInfo *> getMacro() const {
+      assert(isMacro() && "Hidden name is not a macro!");
+      return std::make_pair(Identifier, DeclOrMacro.get<MacroInfo *>());
+    }
+  };
+
   /// \brief A set of hidden declarations.
-  typedef llvm::SmallVector<llvm::PointerUnion<Decl *, IdentifierInfo *>, 2>
+  typedef llvm::SmallVector<HiddenName, 2>
     HiddenNames;
   
   typedef llvm::DenseMap<Module *, HiddenNames> HiddenNamesMapType;
@@ -468,9 +495,13 @@
   /// global method pool for this selector.
   llvm::DenseMap<Selector, unsigned> SelectorGeneration;
 
-  /// \brief Mapping from identifiers that represent macros whose definitions
-  /// have not yet been deserialized to the global ID of the macro.
-  llvm::DenseMap<IdentifierInfo *, serialization::MacroID> UnreadMacroIDs;
+  typedef llvm::DenseMap<IdentifierInfo *,
+                         llvm::SmallVector<serialization::MacroID, 2> >
+    PendingMacroIDsMap;
+
+  /// \brief Mapping from identifiers that have a macro history to the global
+  /// IDs have not yet been deserialized to the global IDs of those macros.
+  PendingMacroIDsMap PendingMacroIDs;
 
   typedef ContinuousRangeMap<unsigned, ModuleFile *, 4>
     GlobalPreprocessedEntityMapType;
@@ -1390,6 +1421,9 @@
   }
 
   virtual IdentifierInfo *GetIdentifier(serialization::IdentifierID ID) {
+    // Note that we are loading an identifier.
+    Deserializing AnIdentifier(this);
+
     return DecodeIdentifierInfo(ID);
   }
 
@@ -1555,23 +1589,17 @@
   serialization::PreprocessedEntityID
   getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const;
 
-  /// \brief Note that the identifier is a macro whose record will be loaded
-  /// from the given AST file at the given (file-local) offset.
+  /// \brief Note that the identifier has a macro history.
   ///
   /// \param II The name of the macro.
   ///
-  /// \param ID The global macro ID.
-  ///
-  /// \param Visible Whether the macro should be made visible.
-  void setIdentifierIsMacro(IdentifierInfo *II, serialization::MacroID ID,
-                            bool Visible);
+  /// \param IDs The global macro IDs that are associated with this identifier.
+  void setIdentifierIsMacro(IdentifierInfo *II,
+                            ArrayRef<serialization::MacroID> IDs);
 
   /// \brief Read the set of macros defined by this external macro source.
   virtual void ReadDefinedMacros();
 
-  /// \brief Read the macro definition for this identifier.
-  virtual void LoadMacroDefinition(IdentifierInfo *II);
-
   /// \brief Update an out-of-date identifier.
   virtual void updateOutOfDateIdentifier(IdentifierInfo &II);
 
@@ -1580,8 +1608,7 @@
 
   /// \brief Read the macro definition corresponding to this iterator
   /// into the unread macro record offsets table.
-  void LoadMacroDefinition(
-         llvm::DenseMap<IdentifierInfo *,serialization::MacroID>::iterator Pos);
+  void LoadMacroDefinition(PendingMacroIDsMap::iterator Pos);
 
   /// \brief Load all external visible decls in the given DeclContext.
   void completeVisibleDeclsMap(const DeclContext *DC);

Modified: cfe/trunk/lib/Lex/MacroInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/MacroInfo.cpp?rev=165682&r1=165681&r2=165682&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/MacroInfo.cpp (original)
+++ cfe/trunk/lib/Lex/MacroInfo.cpp Wed Oct 10 19:46:49 2012
@@ -31,7 +31,8 @@
     IsUsed(false),
     IsAllowRedefinitionsWithoutWarning(false),
     IsWarnIfUnused(false),
-    IsPublic(true) {
+    IsPublic(true),
+    IsHidden(false) {
 }
 
 MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator)
@@ -54,7 +55,8 @@
     IsUsed(MI.IsUsed),
     IsAllowRedefinitionsWithoutWarning(MI.IsAllowRedefinitionsWithoutWarning),
     IsWarnIfUnused(MI.IsWarnIfUnused),
-    IsPublic(MI.IsPublic) {
+    IsPublic(MI.IsPublic),
+    IsHidden(MI.IsHidden) {
   setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator);
 }
 

Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=165682&r1=165681&r2=165682&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Wed Oct 10 19:46:49 2012
@@ -36,29 +36,106 @@
   assert(II->hadMacroDefinition() && "Identifier has not been not a macro!");
 
   macro_iterator Pos = Macros.find(II);
-  if (Pos == Macros.end()) {
-    // Load this macro from the external source.
-    getExternalSource()->LoadMacroDefinition(II);
-    Pos = Macros.find(II);
-  }
   assert(Pos != Macros.end() && "Identifier macro info is missing!");
   return Pos->second;
 }
 
 /// setMacroInfo - Specify a macro for this identifier.
 ///
-void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI,
-                                bool LoadedFromAST) {
+void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI) {
   assert(MI && "MacroInfo should be non-zero!");
-  assert((LoadedFromAST || MI->getUndefLoc().isInvalid()) &&
-         "Undefined macros can only be registered when just LoadedFromAST");
-  MI->setPreviousDefinition(Macros[II]);
-  Macros[II] = MI;
+  assert(MI->getUndefLoc().isInvalid() &&
+         "Undefined macros cannot be registered");
+
+  MacroInfo *&StoredMI = Macros[II];
+  MI->setPreviousDefinition(StoredMI);
+  StoredMI = MI;
   II->setHasMacroDefinition(MI->getUndefLoc().isInvalid());
-  if (II->isFromAST() && !LoadedFromAST)
+  if (II->isFromAST())
     II->setChangedSinceDeserialization();
 }
 
+void Preprocessor::addLoadedMacroInfo(IdentifierInfo *II, MacroInfo *MI) {
+  assert(MI && "Missing macro?");
+  assert(MI->isFromAST() && "Macro is not from an AST?");
+  assert(!MI->getPreviousDefinition() && "Macro already in chain?");
+  
+  MacroInfo *&StoredMI = Macros[II];
+
+  // Easy case: this is the first macro definition for this macro.
+  if (!StoredMI) {
+    StoredMI = MI;
+
+    if (MI->isDefined())
+      II->setHasMacroDefinition(true);
+    return;
+  }
+
+  // If this macro is a definition and this identifier has been neither
+  // defined nor undef'd in the current translation unit, add this macro
+  // to the end of the chain of definitions.
+  if (MI->isDefined() && StoredMI->isFromAST()) {
+    // Simple case: if this is the first actual definition, just put it at
+    // th beginning.
+    if (!StoredMI->isDefined()) {
+      MI->setPreviousDefinition(StoredMI);
+      StoredMI = MI;
+
+      II->setHasMacroDefinition(true);
+      return;
+    }
+
+    // Find the end of the definition chain.
+    MacroInfo *Prev = StoredMI;
+    MacroInfo *PrevPrev;
+    bool Ambiguous = false;
+    do {
+      // If the macros are not identical, we have an ambiguity.
+      if (!Prev->isIdenticalTo(*MI, *this))
+        Ambiguous = true;
+    } while ((PrevPrev = Prev->getPreviousDefinition()) &&
+             PrevPrev->isDefined());
+
+    // FIXME: Actually use the ambiguity information for something.
+    
+    // Wire this macro information into the chain.
+    MI->setPreviousDefinition(Prev->getPreviousDefinition());
+    Prev->setPreviousDefinition(MI);
+    return;
+  }
+
+  // The macro is not a definition; put it at the end of the list.
+  // FIXME: Adding macro history is quadratic, but a hint could fix this.
+  MacroInfo *Prev = StoredMI;
+  while (Prev->getPreviousDefinition())
+    Prev = Prev->getPreviousDefinition();
+  Prev->setPreviousDefinition(MI);
+}
+
+void Preprocessor::makeLoadedMacroInfoVisible(IdentifierInfo *II,
+                                              MacroInfo *MI) {
+  assert(MI->isFromAST() && "Macro must be from the AST");
+  assert(MI->isDefined() && "Macro is not visible");
+
+  MacroInfo *&StoredMI = Macros[II];
+  if (StoredMI == MI) {
+    // Easy case: this is the first macro anyway.
+    II->setHasMacroDefinition(true);
+    return;
+  }
+
+  // Go find the macro and pull it out of the list.
+  // FIXME: Yes, this is O(N), and making a pile of macros visible would be
+  // quadratic.
+  MacroInfo *Prev = StoredMI;
+  while (Prev->getPreviousDefinition() != MI)
+    Prev = Prev->getPreviousDefinition();
+  Prev->setPreviousDefinition(MI->getPreviousDefinition());
+
+  // Add the macro back to the list.
+  addLoadedMacroInfo(II, MI);
+}
+
 /// \brief Undefine a macro for this identifier.
 void Preprocessor::clearMacroInfo(IdentifierInfo *II) {
   assert(II->hasMacroDefinition() && "Macro is not defined!");

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=165682&r1=165681&r2=165682&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Wed Oct 10 19:46:49 2012
@@ -573,31 +573,13 @@
   // If this identifier is a macro, deserialize the macro
   // definition.
   if (hadMacroDefinition) {
-    // FIXME: Check for conflicts?
-    uint32_t LocalID = ReadUnalignedLE32(d);
-    unsigned LocalSubmoduleID = ReadUnalignedLE32(d);
-    
-    // Determine whether this macro definition should be visible now, or
-    // whether it is in a hidden submodule.
-    bool Visible = true;
-    if (SubmoduleID GlobalSubmoduleID
-          = Reader.getGlobalSubmoduleID(F, LocalSubmoduleID)) {
-      if (Module *Owner = Reader.getSubmodule(GlobalSubmoduleID)) {
-        if (Owner->NameVisibility == Module::Hidden) {
-          // The owning module is not visible, and this macro definition should
-          // not be, either.
-          Visible = false;
-          
-          // Note that this macro definition was hidden because its owning 
-          // module is not yet visible.
-          Reader.HiddenNamesMap[Owner].push_back(II);
-        }
-      }
+    SmallVector<MacroID, 4> MacroIDs;
+    while (uint32_t LocalID = ReadUnalignedLE32(d)) {
+      MacroIDs.push_back(Reader.getGlobalMacroID(F, LocalID));
+      DataLen -= 4;
     }
-
-    Reader.setIdentifierIsMacro(II, Reader.getGlobalMacroID(F, LocalID),
-                                Visible && hasMacroDefinition);
-    DataLen -= 8;
+    DataLen -= 4;
+    Reader.setIdentifierIsMacro(II, MacroIDs);
   }
 
   Reader.SetIdentifierInfo(ID, II);
@@ -1322,7 +1304,8 @@
       if (MacrosLoaded[GlobalID - NUM_PREDEF_MACRO_IDS])
         return;
 
-      unsigned NextIndex = 2;
+      SubmoduleID GlobalSubmoduleID = getGlobalSubmoduleID(F, Record[2]);
+      unsigned NextIndex = 3;
       SourceLocation Loc = ReadSourceLocation(F, Record, NextIndex);
       MacroInfo *MI = PP.AllocateMacroInfo(Loc);
 
@@ -1360,6 +1343,7 @@
         DeserializationListener->MacroRead(GlobalID, MI);
 
       // If an update record marked this as undefined, do so now.
+      // FIXME: Only if the submodule this update came from is visible?
       MacroUpdatesMap::iterator Update = MacroUpdates.find(GlobalID);
       if (Update != MacroUpdates.end()) {
         if (MI->getUndefLoc().isInvalid()) {
@@ -1370,8 +1354,25 @@
         MacroUpdates.erase(Update);
       }
 
+      // Determine whether this macro definition is visible.
+      bool Hidden = !MI->isPublic();
+      if (!Hidden && GlobalSubmoduleID) {
+        if (Module *Owner = getSubmodule(GlobalSubmoduleID)) {
+          if (Owner->NameVisibility == Module::Hidden) {
+            // The owning module is not visible, and this macro definition
+            // should not be, either.
+            Hidden = true;
+
+            // Note that this macro definition was hidden because its owning
+            // module is not yet visible.
+            HiddenNamesMap[Owner].push_back(HiddenName(II, MI));
+          }
+        }
+      }
+      MI->setHidden(Hidden);
+
       // Finally, install the macro.
-      PP.setMacroInfo(II, MI, /*LoadedFromAST=*/true);
+      PP.addLoadedMacroInfo(II, MI);
 
       // Remember that we saw this macro last so that we add the tokens that
       // form its body to it.
@@ -1480,21 +1481,16 @@
   return HFI;
 }
 
-void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, MacroID ID,
-                                     bool Visible) {
-  if (Visible) {
-    // Note that this identifier has a macro definition.
-    II->setHasMacroDefinition(true);
-  } else {
-    II->setHadMacroDefinition(true);
-  }
-
-  // FIXME: This could end up overwriting a previously recording macro
-  // definition here, which is not cool at all.
-  UnreadMacroIDs[II] = ID;
+void ASTReader::setIdentifierIsMacro(IdentifierInfo *II, ArrayRef<MacroID> IDs){
+  II->setHadMacroDefinition(true);
+  assert(NumCurrentElementsDeserializing > 0 &&"Missing deserialization guard");
+  PendingMacroIDs[II].append(IDs.begin(), IDs.end());
 }
 
 void ASTReader::ReadDefinedMacros() {
+  // Note that we are loading defined macros.
+  Deserializing Macros(this);
+
   for (ModuleReverseIterator I = ModuleMgr.rbegin(),
       E = ModuleMgr.rend(); I != E; ++I) {
     llvm::BitstreamCursor &MacroCursor = (*I)->MacroCursor;
@@ -1546,24 +1542,14 @@
       }
     }
   }
-  
-  // Drain the unread macro-record offsets map.
-  while (!UnreadMacroIDs.empty())
-    LoadMacroDefinition(UnreadMacroIDs.begin());
-}
-
-void ASTReader::LoadMacroDefinition(
-                    llvm::DenseMap<IdentifierInfo *, MacroID>::iterator Pos) {
-  assert(Pos != UnreadMacroIDs.end() && "Unknown macro definition");
-  uint64_t GlobalID = Pos->second;
-  UnreadMacroIDs.erase(Pos);
-  getMacro(GlobalID);
-}
-
-void ASTReader::LoadMacroDefinition(IdentifierInfo *II) {
-  llvm::DenseMap<IdentifierInfo *, MacroID>::iterator Pos
-    = UnreadMacroIDs.find(II);
-  LoadMacroDefinition(Pos);
+}
+
+void ASTReader::LoadMacroDefinition(PendingMacroIDsMap::iterator Pos) {
+  assert(Pos != PendingMacroIDs.end() && "Unknown macro definition");
+  SmallVector<MacroID, 2> GlobalIDs = Pos->second;
+  PendingMacroIDs.erase(Pos);
+  for (unsigned I = 0, N = GlobalIDs.size(); I != N; ++I)
+    getMacro(GlobalIDs[I]);
 }
 
 namespace {
@@ -1612,6 +1598,9 @@
 }
 
 void ASTReader::updateOutOfDateIdentifier(IdentifierInfo &II) {
+  // Note that we are loading an identifier.
+  Deserializing AnIdentifier(this);
+
   unsigned PriorGeneration = 0;
   if (getContext().getLangOpts().Modules)
     PriorGeneration = IdentifierGeneration[&II];
@@ -2620,22 +2609,17 @@
 
 void ASTReader::makeNamesVisible(const HiddenNames &Names) {
   for (unsigned I = 0, N = Names.size(); I != N; ++I) {
-    if (Decl *D = Names[I].dyn_cast<Decl *>())
-      D->Hidden = false;
-    else {
-      IdentifierInfo *II = Names[I].get<IdentifierInfo *>();
-      // FIXME: Check if this works correctly with macro history.
-      if (!II->hasMacroDefinition()) {
-        // Make sure that this macro hasn't been #undef'd in the mean-time.
-        llvm::DenseMap<IdentifierInfo*, MacroInfo*>::iterator Known
-          = PP.Macros.find(II);
-        if (Known == PP.Macros.end() ||
-            Known->second->getUndefLoc().isInvalid()) {
-          II->setHasMacroDefinition(true);
-          if (DeserializationListener)
-            DeserializationListener->MacroVisible(II);
-        }
-      }
+    if (Names[I].isDecl()) {
+      Names[I].getDecl()->Hidden = false;
+      continue;
+    }
+
+    std::pair<IdentifierInfo *, MacroInfo *> Macro = Names[I].getMacro();
+    Macro.second->setHidden(!Macro.second->isPublic());
+    if (Macro.second->isDefined()) {
+      PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
+      if (DeserializationListener)
+        DeserializationListener->MacroVisible(Macro.first);
     }
   }
 }
@@ -5418,6 +5402,9 @@
 }
 
 IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
+  // Note that we are loading an identifier.
+  Deserializing AnIdentifier(this);
+  
   IdentifierLookupVisitor Visitor(StringRef(NameStart, NameEnd - NameStart),
                                   /*PriorGeneration=*/0);
   ModuleMgr.visit(IdentifierLookupVisitor::visit, &Visitor);
@@ -6516,7 +6503,8 @@
 }
 
 void ASTReader::finishPendingActions() {
-  while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty()) {
+  while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() ||
+         !PendingMacroIDs.empty()) {
     // If any identifiers with corresponding top-level declarations have
     // been loaded, load those declarations now.
     while (!PendingIdentifierInfos.empty()) {
@@ -6531,6 +6519,11 @@
       PendingDeclChainsKnown.erase(PendingDeclChains[I]);
     }
     PendingDeclChains.clear();
+
+    // Load any pending macro definitions.
+    // FIXME: Non-determinism here.
+    while (!PendingMacroIDs.empty())
+      LoadMacroDefinition(PendingMacroIDs.begin());
   }
   
   // If we deserialized any C++ or Objective-C class definitions, any

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=165682&r1=165681&r2=165682&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed Oct 10 19:46:49 2012
@@ -1744,6 +1744,7 @@
 
       AddIdentifierRef(Name, Record);
       addMacroRef(MI, Record);
+      Record.push_back(inferSubmoduleIDFromLocation(MI->getDefinitionLoc()));
       AddSourceLocation(MI->getDefinitionLoc(), Record);
       AddSourceLocation(MI->getUndefLoc(), Record);
       Record.push_back(MI->isUsed());
@@ -2587,8 +2588,14 @@
     if (isInterestingIdentifier(II, Macro)) {
       DataLen += 2; // 2 bytes for builtin ID
       DataLen += 2; // 2 bytes for flags
-      if (hadMacroDefinition(II, Macro))
-        DataLen += 8;
+      if (hadMacroDefinition(II, Macro)) {
+        for (MacroInfo *M = Macro; M; M = M->getPreviousDefinition()) {
+          if (Writer.getMacroRef(M) != 0)
+            DataLen += 4;
+        }
+
+        DataLen += 4;
+      }
 
       for (IdentifierResolver::iterator D = IdResolver.begin(II),
                                      DEnd = IdResolver.end();
@@ -2635,9 +2642,13 @@
     clang::io::Emit16(Out, Bits);
 
     if (HadMacroDefinition) {
-      clang::io::Emit32(Out, Writer.getMacroRef(Macro));
-      clang::io::Emit32(Out,
-        Writer.inferSubmoduleIDFromLocation(Macro->getDefinitionLoc()));
+      // Write all of the macro IDs associated with this identifier.
+      for (MacroInfo *M = Macro; M; M = M->getPreviousDefinition()) {
+        if (MacroID ID = Writer.getMacroRef(M))
+          clang::io::Emit32(Out, ID);
+      }
+
+      clang::io::Emit32(Out, 0);
     }
 
     // Emit the declaration IDs in reverse order, because the

Modified: cfe/trunk/test/Modules/Inputs/macros_left.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/macros_left.h?rev=165682&r1=165681&r2=165682&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/macros_left.h (original)
+++ cfe/trunk/test/Modules/Inputs/macros_left.h Wed Oct 10 19:46:49 2012
@@ -3,3 +3,10 @@
 
 #undef TOP_LEFT_UNDEF
 
+
+
+
+#define LEFT_RIGHT_IDENTICAL int
+#define LEFT_RIGHT_DIFFERENT float
+#define LEFT_RIGHT_DIFFERENT2 float
+#define LEFT_RIGHT_DIFFERENT3 float

Modified: cfe/trunk/test/Modules/Inputs/macros_right.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/macros_right.h?rev=165682&r1=165681&r2=165682&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/macros_right.h (original)
+++ cfe/trunk/test/Modules/Inputs/macros_right.h Wed Oct 10 19:46:49 2012
@@ -4,3 +4,12 @@
 #undef TOP_RIGHT_REDEF
 #define TOP_RIGHT_REDEF float
 
+
+
+
+
+#define LEFT_RIGHT_IDENTICAL int
+#define LEFT_RIGHT_DIFFERENT int
+#define LEFT_RIGHT_DIFFERENT2 int
+#define LEFT_RIGHT_DIFFERENT3 int
+

Modified: cfe/trunk/test/Modules/Inputs/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/module.map?rev=165682&r1=165681&r2=165682&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/module.map (original)
+++ cfe/trunk/test/Modules/Inputs/module.map Wed Oct 10 19:46:49 2012
@@ -18,6 +18,17 @@
 module lookup_right_cxx { header "lookup_right.hpp" }
 module module_private_left { header "module_private_left.h" }
 module module_private_right { header "module_private_right.h" }
+module macros_top { 
+  header "macros_top.h" 
+}
+module macros_left { 
+  header "macros_left.h" 
+  export *
+}
+module macros_right { 
+  header "macros_right.h" 
+  export *
+}
 module macros { header "macros.h" }
 module category_top { header "category_top.h" }
 module category_left { 

Modified: cfe/trunk/test/Modules/macros.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/macros.c?rev=165682&r1=165681&r2=165682&view=diff
==============================================================================
--- cfe/trunk/test/Modules/macros.c (original)
+++ cfe/trunk/test/Modules/macros.c Wed Oct 10 19:46:49 2012
@@ -1,8 +1,14 @@
 // RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodule-cache-path %t -fmodule-name=macros_top %S/Inputs/module.map
+// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodule-cache-path %t -fmodule-name=macros_left %S/Inputs/module.map
+// RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodule-cache-path %t -fmodule-name=macros_right %S/Inputs/module.map
 // RUN: %clang_cc1 -fmodules -x objective-c -emit-module -fmodule-cache-path %t -fmodule-name=macros %S/Inputs/module.map
 // RUN: %clang_cc1 -fmodules -x objective-c -verify -fmodule-cache-path %t %s
 // RUN: %clang_cc1 -E -fmodules -x objective-c -fmodule-cache-path %t %s | FileCheck -check-prefix CHECK-PREPROCESSED %s
 // FIXME: When we have a syntax for modules in C, use that.
+// These notes come from headers in modules, and are bogus.
+// FIXME: expected-note{{previous definition is here}}
+// FIXME: expected-note{{previous definition is here}}
 
 @__experimental_modules_import macros;
 
@@ -37,3 +43,83 @@
 #if __building_module(macros)
 # error Not building a module
 #endif
+
+// None of the modules we depend on have been imported, and therefore
+// their macros should not be visible.
+#ifdef LEFT
+#  error LEFT should not be visible
+#endif
+
+#ifdef RIGHT
+#  error RIGHT should not be visible
+#endif
+
+#ifdef TOP
+#  error TOP should not be visible
+#endif
+
+// Import left module (which also imports top)
+ at __experimental_modules_import macros_left;
+
+#ifndef LEFT
+#  error LEFT should be visible
+#endif
+
+#ifdef RIGHT
+#  error RIGHT should not be visible
+#endif
+
+#ifndef TOP
+#  error TOP should be visible
+#endif
+
+#ifdef TOP_LEFT_UNDEF
+#  error TOP_LEFT_UNDEF should not be visible
+#endif
+
+void test1() {
+  int i;
+  TOP_RIGHT_REDEF *ip = &i;
+}
+
+#define LEFT_RIGHT_DIFFERENT2 double // FIXME: expected-warning{{'LEFT_RIGHT_DIFFERENT2' macro redefined}}
+
+// Import right module (which also imports top)
+ at __experimental_modules_import macros_right;
+
+#undef LEFT_RIGHT_DIFFERENT3
+
+#ifndef LEFT
+#  error LEFT should be visible
+#endif
+
+#ifndef RIGHT
+#  error RIGHT should be visible
+#endif
+
+#ifndef TOP
+#  error TOP should be visible
+#endif
+
+#ifndef TOP_LEFT_UNDEF
+#  error TOP_LEFT_UNDEF should be visible
+#endif
+
+void test2() {
+  int i;
+  float f;
+  double d;
+  TOP_RIGHT_REDEF *ip = &i; // FIXME: warning
+  
+  LEFT_RIGHT_IDENTICAL *ip2 = &i;
+  LEFT_RIGHT_DIFFERENT *fp = &f; // FIXME: warning
+  LEFT_RIGHT_DIFFERENT2 *dp = &d; // okay
+  int LEFT_RIGHT_DIFFERENT3;
+}
+
+#define LEFT_RIGHT_DIFFERENT double // FIXME: expected-warning{{'LEFT_RIGHT_DIFFERENT' macro redefined}}
+
+void test3() {
+  double d;
+  LEFT_RIGHT_DIFFERENT *dp = &d; // okay
+}





More information about the cfe-commits mailing list