[llvm-rc] Serialize MENU resources to .res files (serialization, pt 3).

This allows MENU resources to be serialized.

MENU resource statement doc:
msdn.microsoft.com/en-us/library/windows/desktop/aa381025.aspx
POPUP sub-statement doc:
msdn.microsoft.com/en-us/library/windows/desktop/aa381030.aspx
MENUITEM sub-statement doc:
msdn.microsoft.com/en-us/library/windows/desktop/aa381024.aspx
MENUHEADER structure:
msdn.microsoft.com/en-us/library/windows/desktop/ms648018.aspx (and
NORMALMENUITEM, POPUPMENUITEM structs).

Thanks for Nico Weber for his original work in this area.

Differential Revision: https://reviews.llvm.org/D37828

llvm-svn: 314562
diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.h b/llvm/tools/llvm-rc/ResourceScriptStmt.h
index 6f83d72..d00e1784 100644
--- a/llvm/tools/llvm-rc/ResourceScriptStmt.h
+++ b/llvm/tools/llvm-rc/ResourceScriptStmt.h
@@ -315,6 +315,8 @@
     MENUBREAK = 0x0040
   };
 
+  enum MenuDefKind { MkBase, MkSeparator, MkMenuItem, MkPopup };
+
   static constexpr size_t NumFlags = 6;
   static StringRef OptionsStr[NumFlags];
   static uint32_t OptionsFlags[NumFlags];
@@ -323,13 +325,16 @@
     return OS << "Base menu definition\n";
   }
   virtual ~MenuDefinition() {}
+
+  virtual uint16_t getResFlags() const { return 0; }
+  virtual MenuDefKind getKind() const { return MkBase; }
 };
 
 // Recursive description of a whole submenu.
 class MenuDefinitionList : public MenuDefinition {
+public:
   std::vector<std::unique_ptr<MenuDefinition>> Definitions;
 
-public:
   void addDefinition(std::unique_ptr<MenuDefinition> Def) {
     Definitions.push_back(std::move(Def));
   }
@@ -342,46 +347,73 @@
 class MenuSeparator : public MenuDefinition {
 public:
   raw_ostream &log(raw_ostream &) const override;
+
+  MenuDefKind getKind() const override { return MkSeparator; }
+  static bool classof(const MenuDefinition *D) {
+    return D->getKind() == MkSeparator;
+  }
 };
 
 // MENUITEM statement definition.
 //
 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381024(v=vs.85).aspx
 class MenuItem : public MenuDefinition {
+public:
   StringRef Name;
   uint32_t Id;
   uint16_t Flags;
 
-public:
   MenuItem(StringRef Caption, uint32_t ItemId, uint16_t ItemFlags)
       : Name(Caption), Id(ItemId), Flags(ItemFlags) {}
   raw_ostream &log(raw_ostream &) const override;
+
+  uint16_t getResFlags() const override { return Flags; }
+  MenuDefKind getKind() const override { return MkMenuItem; }
+  static bool classof(const MenuDefinition *D) {
+    return D->getKind() == MkMenuItem;
+  }
 };
 
 // POPUP statement definition.
 //
 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx
 class PopupItem : public MenuDefinition {
+public:
   StringRef Name;
   uint16_t Flags;
   MenuDefinitionList SubItems;
 
-public:
   PopupItem(StringRef Caption, uint16_t ItemFlags,
             MenuDefinitionList &&SubItemsList)
       : Name(Caption), Flags(ItemFlags), SubItems(std::move(SubItemsList)) {}
   raw_ostream &log(raw_ostream &) const override;
+
+  // This has an additional (0x10) flag. It doesn't match with documented
+  // 0x01 flag, though.
+  uint16_t getResFlags() const override { return Flags | 0x10; }
+  MenuDefKind getKind() const override { return MkPopup; }
+  static bool classof(const MenuDefinition *D) {
+    return D->getKind() == MkPopup;
+  }
 };
 
 // Menu resource definition.
 class MenuResource : public OptStatementsRCResource {
+public:
   MenuDefinitionList Elements;
 
-public:
   MenuResource(OptionalStmtList &&OptStmts, MenuDefinitionList &&Items)
       : OptStatementsRCResource(std::move(OptStmts)),
         Elements(std::move(Items)) {}
   raw_ostream &log(raw_ostream &) const override;
+
+  IntOrString getResourceType() const override { return RkMenu; }
+  Twine getResourceTypeName() const override { return "MENU"; }
+  Error visit(Visitor *V) const override { return V->visitMenuResource(this); }
+  ResourceKind getKind() const override { return RkMenu; }
+  static bool classof(const RCResource *Res) {
+    return Res->getKind() == RkMenu;
+  }
 };
 
 // STRINGTABLE resource. Contains a list of strings, each having its unique ID.