Index: test/tools/llvm-rc/tag-dialog.test =================================================================== --- test/tools/llvm-rc/tag-dialog.test +++ test/tools/llvm-rc/tag-dialog.test @@ -579,6 +579,62 @@ ; HEADERS-NEXT: 0010: 05000000 FFFF2A00 0000 |......*...| ; HEADERS-NEXT: ) +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 29 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 32 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 67452301 00008880 |........gE#.....| +; HEADERS-NEXT: 0010: 00000000 01000000 09000000 00000000 |................| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 30 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 24 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 00008880 67452301 00000000 01000000 |....gE#.........| +; HEADERS-NEXT: 0010: 09000000 00000000 |........| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 31 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 32 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 0100FFFF 00000000 67452301 10325476 |........gE#..2Tv| +; HEADERS-NEXT: 0010: 00000000 01000000 09000000 00000000 |................| +; HEADERS-NEXT: ) + +; HEADERS-DAG: Resource type (int): 5 +; HEADERS-NEXT: Resource name (int): 32 +; HEADERS-NEXT: Data version: 0 +; HEADERS-NEXT: Memory flags: 0x1030 +; HEADERS-NEXT: Language ID: 1033 +; HEADERS-NEXT: Version (major): 0 +; HEADERS-NEXT: Version (minor): 0 +; HEADERS-NEXT: Characteristics: 0 +; HEADERS-NEXT: Data size: 24 +; HEADERS-NEXT: Data: ( +; HEADERS-NEXT: 0000: 10325476 56341200 00000000 01000000 |.2TvV4..........| +; HEADERS-NEXT: 0010: 09000000 00000000 |........| +; HEADERS-NEXT: ) + ; RUN: not llvm-rc /FO %t %p/Inputs/tag-dialog-large-coord.rc 2>&1 | FileCheck %s --check-prefix COORD1 Index: tools/llvm-rc/ResourceFileWriter.h =================================================================== --- tools/llvm-rc/ResourceFileWriter.h +++ tools/llvm-rc/ResourceFileWriter.h @@ -66,6 +66,7 @@ Error visitFontStmt(const FontStmt *) override; Error visitLanguageStmt(const LanguageResource *) override; Error visitStyleStmt(const StyleStmt *) override; + Error visitExtStyleStmt(const ExtStyleStmt *) override; Error visitVersionStmt(const VersionStmt *) override; // Stringtables are output at the end of .res file. We need a separate @@ -80,6 +81,7 @@ uint32_t VersionInfo; Optional Style; + Optional ExtStyle; StringRef Caption; struct FontInfo { uint32_t Size; Index: tools/llvm-rc/ResourceFileWriter.cpp =================================================================== --- tools/llvm-rc/ResourceFileWriter.cpp +++ tools/llvm-rc/ResourceFileWriter.cpp @@ -536,6 +536,11 @@ return Error::success(); } +Error ResourceFileWriter::visitExtStyleStmt(const ExtStyleStmt *Stmt) { + ObjectData.ExtStyle = Stmt->Value; + return Error::success(); +} + Error ResourceFileWriter::visitVersionStmt(const VersionStmt *Stmt) { ObjectData.VersionInfo = Stmt->Value; return Error::success(); @@ -1065,6 +1070,7 @@ UsedStyle |= StyleCaptionFlag; const uint16_t DialogExMagic = 0xFFFF; + uint32_t ExtStyle = ObjectData.ExtStyle.getValueOr(0); // Write DIALOG(EX) header prefix. These are pretty different. if (!Res->IsExtended) { @@ -1083,7 +1089,7 @@ ulittle32_t Style; ulittle32_t ExtStyle; } Prefix{ulittle32_t(UsedStyle), - ulittle32_t(0)}; // As of now, we don't keep EXSTYLE. + ulittle32_t(ExtStyle)}; writeObject(Prefix); } else { @@ -1094,7 +1100,7 @@ ulittle32_t ExtStyle; ulittle32_t Style; } Prefix{ulittle16_t(1), ulittle16_t(DialogExMagic), - ulittle32_t(Res->HelpID), ulittle32_t(0), ulittle32_t(UsedStyle)}; + ulittle32_t(Res->HelpID), ulittle32_t(ExtStyle), ulittle32_t(UsedStyle)}; writeObject(Prefix); } Index: tools/llvm-rc/ResourceScriptParser.h =================================================================== --- tools/llvm-rc/ResourceScriptParser.h +++ tools/llvm-rc/ResourceScriptParser.h @@ -174,6 +174,7 @@ ParseOptionType parseClassStmt(); ParseOptionType parseFontStmt(OptStmtType DialogType); ParseOptionType parseStyleStmt(); + ParseOptionType parseExtStyleStmt(); // Raises an error. If IsAlreadyRead = false (default), this complains about // the token that couldn't be parsed. If the flag is on, this complains about Index: tools/llvm-rc/ResourceScriptParser.cpp =================================================================== --- tools/llvm-rc/ResourceScriptParser.cpp +++ tools/llvm-rc/ResourceScriptParser.cpp @@ -392,6 +392,8 @@ return parseFontStmt(StmtsType); if (TypeToken->equals_lower("STYLE")) return parseStyleStmt(); + if (TypeToken->equals_lower("EXSTYLE")) + return parseExtStyleStmt(); } return getExpectedError("optional statement type, BEGIN or '{'", @@ -817,6 +819,11 @@ return llvm::make_unique(*Arg); } +RCParser::ParseOptionType RCParser::parseExtStyleStmt() { + ASSIGN_OR_RETURN(Arg, readInt()); + return llvm::make_unique(*Arg); +} + Error RCParser::getExpectedError(const Twine &Message, bool IsAlreadyRead) { return make_error( Message, IsAlreadyRead ? std::prev(CurLoc) : CurLoc, End); Index: tools/llvm-rc/ResourceScriptStmt.h =================================================================== --- tools/llvm-rc/ResourceScriptStmt.h +++ tools/llvm-rc/ResourceScriptStmt.h @@ -866,6 +866,19 @@ Error visit(Visitor *V) const override { return V->visitStyleStmt(this); } }; +// EXSTYLE optional statement. +// +// Ref: docs.microsoft.com/en-us/windows/desktop/menurc/exstyle-statement +class ExtStyleStmt : public OptionalStmt { +public: + uint32_t Value; + + ExtStyleStmt(uint32_t ExtStyle) : Value(ExtStyle) {} + raw_ostream &log(raw_ostream &) const override; + Twine getResourceTypeName() const override { return "EXSTYLE"; } + Error visit(Visitor *V) const override { return V->visitExtStyleStmt(this); } +}; + // CLASS optional statement. // // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa380883(v=vs.85).aspx Index: tools/llvm-rc/ResourceScriptStmt.cpp =================================================================== --- tools/llvm-rc/ResourceScriptStmt.cpp +++ tools/llvm-rc/ResourceScriptStmt.cpp @@ -283,5 +283,9 @@ return OS << "Style: " << Value << "\n"; } +raw_ostream &ExtStyleStmt::log(raw_ostream &OS) const { + return OS << "ExtStyle: " << Value << "\n"; +} + } // namespace rc } // namespace llvm Index: tools/llvm-rc/ResourceVisitor.h =================================================================== --- tools/llvm-rc/ResourceVisitor.h +++ tools/llvm-rc/ResourceVisitor.h @@ -27,6 +27,7 @@ class FontStmt; class LanguageResource; class StyleStmt; +class ExtStyleStmt; class VersionStmt; class Visitor { @@ -49,6 +50,7 @@ virtual Error visitFontStmt(const FontStmt *) = 0; virtual Error visitLanguageStmt(const LanguageResource *) = 0; virtual Error visitStyleStmt(const StyleStmt *) = 0; + virtual Error visitExtStyleStmt(const ExtStyleStmt *) = 0; virtual Error visitVersionStmt(const VersionStmt *) = 0; virtual ~Visitor() {}