[Preprocessor/Modules] Separate the macro directives kinds into their own MacroDirective's subclasses.

For each macro directive (define, undefine, visibility) have a separate object that gets chained
to the macro directive history. This has several benefits:

-No need to mutate a MacroDirective when there is a undefine/visibility directive. Stuff like
 PPMutationListener become unnecessary.
-No need to keep extra source locations for the undef/visibility locations for the define directive object
 (which is the majority of the directives)
-Much easier to hide/unhide a section in the macro directive history.
-Easier to track the effects of the directives across different submodules.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178037 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index c6dbfe1..837524d 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1476,8 +1476,8 @@
 
   MacroInfo *MI = getMacro(GMacID);
   SubmoduleID SubModID = MI->getOwningModuleID();
-  MacroDirective *MD = PP.AllocateMacroDirective(MI, ImportLoc,
-                                                 /*isImported=*/true);
+  MacroDirective *MD = PP.AllocateDefMacroDirective(MI, ImportLoc,
+                                                    /*isImported=*/true);
 
   // Determine whether this macro definition is visible.
   bool Hidden = false;
@@ -1494,7 +1494,6 @@
       }
     }
   }
-  MD->setHidden(Hidden);
 
   if (!Hidden)
     installImportedMacro(II, MD);
@@ -1527,22 +1526,30 @@
   MacroDirective *Latest = 0, *Earliest = 0;
   unsigned Idx = 0, N = Record.size();
   while (Idx < N) {
-    GlobalMacroID GMacID = getGlobalMacroID(M, Record[Idx++]);
-    MacroInfo *MI = getMacro(GMacID);
+    MacroDirective *MD = 0;
     SourceLocation Loc = ReadSourceLocation(M, Record, Idx);
-    SourceLocation UndefLoc = ReadSourceLocation(M, Record, Idx);
-    SourceLocation VisibilityLoc = ReadSourceLocation(M, Record, Idx);
-    bool isImported = Record[Idx++];
-    bool isPublic = Record[Idx++];
-    bool isAmbiguous = Record[Idx++];
-
-    MacroDirective *MD = PP.AllocateMacroDirective(MI, Loc, isImported);
-    if (UndefLoc.isValid())
-      MD->setUndefLoc(UndefLoc);
-    if (VisibilityLoc.isValid())
-      MD->setVisibility(isPublic, VisibilityLoc);
-    MD->setAmbiguous(isAmbiguous);
-    MD->setIsFromPCH();
+    MacroDirective::Kind K = (MacroDirective::Kind)Record[Idx++];
+    switch (K) {
+    case MacroDirective::MD_Define: {
+      GlobalMacroID GMacID = getGlobalMacroID(M, Record[Idx++]);
+      MacroInfo *MI = getMacro(GMacID);
+      bool isImported = Record[Idx++];
+      bool isAmbiguous = Record[Idx++];
+      DefMacroDirective *DefMD =
+          PP.AllocateDefMacroDirective(MI, Loc, isImported);
+      DefMD->setAmbiguous(isAmbiguous);
+      MD = DefMD;
+      break;
+    }
+    case MacroDirective::MD_Undefine:
+      MD = PP.AllocateUndefMacroDirective(Loc);
+      break;
+    case MacroDirective::MD_Visibility: {
+      bool isPublic = Record[Idx++];
+      MD = PP.AllocateVisibilityMacroDirective(Loc, isPublic);
+      break;
+    }
+    }
 
     if (!Latest)
       Latest = MD;
@@ -1557,13 +1564,18 @@
 void ASTReader::installImportedMacro(IdentifierInfo *II, MacroDirective *MD) {
   assert(II && MD);
 
+  DefMacroDirective *DefMD = cast<DefMacroDirective>(MD);
   MacroDirective *Prev = PP.getMacroDirective(II);
-  if (Prev && !Prev->getInfo()->isIdenticalTo(*MD->getInfo(), PP)) {
-    Prev->setAmbiguous(true);
-    MD->setAmbiguous(true);
+  if (Prev) {
+    MacroDirective::DefInfo PrevDef = Prev->getDefinition();
+    if (DefMD->getInfo() != PrevDef.getMacroInfo() &&
+        !PrevDef.getMacroInfo()->isIdenticalTo(*DefMD->getInfo(), PP)) {
+      PrevDef.getDirective()->setAmbiguous(true);
+      DefMD->setAmbiguous(true);
+    }
   }
   
-  PP.setMacroDirective(II, MD);
+  PP.appendMacroDirective(II, MD);
 }
 
 InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
@@ -2723,21 +2735,12 @@
     }
     case HiddenName::MacroVisibility: {
       std::pair<IdentifierInfo *, MacroDirective *> Macro = Names[I].getMacro();
-      Macro.second->setHidden(!Macro.second->isPublic());
-      if (Macro.second->isDefined()) {
-        installImportedMacro(Macro.first, Macro.second);
-      }
+      installImportedMacro(Macro.first, Macro.second);
       break;
     }
 
     case HiddenName::MacroUndef: {
-      std::pair<IdentifierInfo *, MacroDirective *> Macro = Names[I].getMacro();
-      if (Macro.second->isDefined()) {
-        Macro.second->setUndefLoc(Names[I].getMacroUndefLoc());
-        if (PPMutationListener *Listener = PP.getPPMutationListener())
-          Listener->UndefinedMacro(Macro.second);
-        PP.makeLoadedMacroInfoVisible(Macro.first, Macro.second);
-      }
+      // FIXME: Remove HiddenName::MacroUndef and PPMutationListener.
       break;
     }
     }
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 7258963..95e32a3 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1833,8 +1833,9 @@
 
 static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule,
                               const Preprocessor &PP) {
-  if (MD->getInfo()->isBuiltinMacro())
-    return true;
+  if (MacroInfo *MI = MD->getMacroInfo())
+    if (MI->isBuiltinMacro())
+      return true;
 
   if (IsModule) {
     SourceLocation Loc = MD->getLocation();
@@ -1902,25 +1903,30 @@
 
     // If the macro or identifier need no updates, don't write the macro history
     // for this one.
-    if (MD->isFromPCH() && !MD->hasChangedAfterLoad() &&
+    // FIXME: Chain the macro history instead of re-writing it.
+    if (MD->isFromPCH() &&
         Name->isFromAST() && !Name->hasChangedSinceDeserialization())
       continue;
 
     // Emit the macro directives in reverse source order.
     for (; MD; MD = MD->getPrevious()) {
+      if (MD->isHidden())
+        continue;
       if (shouldIgnoreMacro(MD, IsModule, PP))
         continue;
-      MacroID InfoID = getMacroRef(MD->getInfo(), Name);
-      if (InfoID == 0)
-        continue;
 
-      Record.push_back(InfoID);
       AddSourceLocation(MD->getLocation(), Record);
-      AddSourceLocation(MD->getUndefLoc(), Record);
-      AddSourceLocation(MD->getVisibilityLocation(), Record);
-      Record.push_back(MD->isImported());
-      Record.push_back(MD->isPublic());
-      Record.push_back(MD->isAmbiguous());
+      Record.push_back(MD->getKind());
+      if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
+        MacroID InfoID = getMacroRef(DefMD->getInfo(), Name);
+        Record.push_back(InfoID);
+        Record.push_back(DefMD->isImported());
+        Record.push_back(DefMD->isAmbiguous());
+
+      } else if (VisibilityMacroDirective *
+                   VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
+        Record.push_back(VisMD->isPublic());
+      }
     }
     if (Record.empty())
       continue;
@@ -2898,48 +2904,78 @@
     return false;
   }
 
-  MacroDirective *getFirstPublicSubmoduleMacro(MacroDirective *MD,
-                                               SubmoduleID &ModID) {
-    if (shouldIgnoreMacro(MD, IsModule, PP))
-      return 0;
-    ModID = getSubmoduleID(MD);
-    if (ModID == 0)
-      return 0;
-    if (MD->isDefined() && MD->isPublic())
-      return MD;
-    return getNextPublicSubmoduleMacro(MD, ModID);
-  }
-
-  MacroDirective *getNextPublicSubmoduleMacro(MacroDirective *MD,
-                                              SubmoduleID &ModID) {
-    while (MD) {
-      MD = getNextSubmoduleMacro(MD, ModID);
-      if (MD && MD->isDefined() && MD->isPublic())
-        return MD;
-    }
+  DefMacroDirective *getFirstPublicSubmoduleMacro(MacroDirective *MD,
+                                                  SubmoduleID &ModID) {
+    ModID = 0;
+    if (DefMacroDirective *DefMD = getPublicSubmoduleMacro(MD, ModID))
+      if (!shouldIgnoreMacro(DefMD, IsModule, PP))
+        return DefMD;
     return 0;
   }
 
-  MacroDirective *getNextSubmoduleMacro(MacroDirective *CurrMD,
-                                        SubmoduleID &CurrModID) {
-    SubmoduleID OrigID = CurrModID;
-    while ((CurrMD = CurrMD->getPrevious())) {
-      if (shouldIgnoreMacro(CurrMD, IsModule, PP))
-        return 0;
-      CurrModID = getSubmoduleID(CurrMD);
-      if (CurrModID == 0)
-        return 0;
-      if (CurrModID != OrigID)
-        return CurrMD;
+  DefMacroDirective *getNextPublicSubmoduleMacro(DefMacroDirective *MD,
+                                                 SubmoduleID &ModID) {
+    if (DefMacroDirective *
+          DefMD = getPublicSubmoduleMacro(MD->getPrevious(), ModID))
+      if (!shouldIgnoreMacro(DefMD, IsModule, PP))
+        return DefMD;
+    return 0;
+  }
+
+  /// \brief Traverses the macro directives history and returns the latest
+  /// macro that is public and not undefined in the same submodule.
+  /// A macro that is defined in submodule A and undefined in submodule B,
+  /// will still be considered as defined/exported from submodule A.
+  DefMacroDirective *getPublicSubmoduleMacro(MacroDirective *MD,
+                                             SubmoduleID &ModID) {
+    if (!MD)
+      return 0;
+
+    bool isUndefined = false;
+    Optional<bool> isPublic;
+    for (; MD; MD = MD->getPrevious()) {
+      if (MD->isHidden())
+        continue;
+
+      SubmoduleID ThisModID = getSubmoduleID(MD);
+      if (ThisModID == 0) {
+        isUndefined = false;
+        isPublic = Optional<bool>();
+        continue;
+      }
+      if (ThisModID != ModID){
+        ModID = ThisModID;
+        isUndefined = false;
+        isPublic = Optional<bool>();
+      }
+
+      if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
+        if (!isUndefined && (!isPublic.hasValue() || isPublic.getValue()))
+          return DefMD;
+        continue;
+      }
+
+      if (isa<UndefMacroDirective>(MD)) {
+        isUndefined = true;
+        continue;
+      }
+
+      VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD);
+      if (!isPublic.hasValue())
+        isPublic = VisMD->isPublic();
     }
+
     return 0;
   }
 
   SubmoduleID getSubmoduleID(MacroDirective *MD) {
-    MacroInfo *MI = MD->getInfo();
-    if (unsigned ID = MI->getOwningModuleID())
-      return ID;
-    return Writer.inferSubmoduleIDFromLocation(MI->getDefinitionLoc());
+    if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD)) {
+      MacroInfo *MI = DefMD->getInfo();
+      if (unsigned ID = MI->getOwningModuleID())
+        return ID;
+      return Writer.inferSubmoduleIDFromLocation(MI->getDefinitionLoc());
+    }
+    return Writer.inferSubmoduleIDFromLocation(MD->getLocation());
   }
 
 public:
@@ -2969,8 +3005,9 @@
         DataLen += 4; // MacroDirectives offset.
         if (IsModule) {
           SubmoduleID ModID;
-          for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, ModID);
-                 MD; MD = getNextPublicSubmoduleMacro(MD, ModID)) {
+          for (DefMacroDirective *
+                 DefMD = getFirstPublicSubmoduleMacro(Macro, ModID);
+                 DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) {
             DataLen += 4; // MacroInfo ID.
           }
           DataLen += 4;
@@ -3025,9 +3062,10 @@
       if (IsModule) {
         // Write the IDs of macros coming from different submodules.
         SubmoduleID ModID;
-        for (MacroDirective *MD = getFirstPublicSubmoduleMacro(Macro, ModID);
-               MD; MD = getNextPublicSubmoduleMacro(MD, ModID)) {
-          MacroID InfoID = Writer.getMacroID(MD->getInfo());
+        for (DefMacroDirective *
+               DefMD = getFirstPublicSubmoduleMacro(Macro, ModID);
+               DefMD; DefMD = getNextPublicSubmoduleMacro(DefMD, ModID)) {
+          MacroID InfoID = Writer.getMacroID(DefMD->getInfo());
           assert(InfoID);
           clang::io::Emit32(Out, InfoID);
         }