Index: llvm/include/llvm/Support/YAMLTraits.h =================================================================== --- llvm/include/llvm/Support/YAMLTraits.h +++ llvm/include/llvm/Support/YAMLTraits.h @@ -902,24 +902,7 @@ template void processKeyWithDefault(const char *Key, Optional &Val, const Optional &DefaultValue, bool Required, - Context &Ctx) { - assert(DefaultValue.hasValue() == false && - "Optional shouldn't have a value!"); - void *SaveInfo; - bool UseDefault = true; - const bool sameAsDefault = outputting() && !Val.hasValue(); - if (!outputting() && !Val.hasValue()) - Val = T(); - if (Val.hasValue() && - this->preflightKey(Key, Required, sameAsDefault, UseDefault, - SaveInfo)) { - yamlize(*this, Val.getValue(), Required, Ctx); - this->postflightKey(SaveInfo); - } else { - if (UseDefault) - Val = DefaultValue; - } - } + Context &Ctx); template void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue, @@ -1625,6 +1608,40 @@ StringRef PaddingBeforeContainer; }; +template +void IO::processKeyWithDefault(const char *Key, Optional &Val, + const Optional &DefaultValue, bool Required, + Context &Ctx) { + assert(DefaultValue.hasValue() == false && + "Optional shouldn't have a value!"); + void *SaveInfo; + bool UseDefault = true; + const bool sameAsDefault = outputting() && !Val.hasValue(); + if (!outputting() && !Val.hasValue()) + Val = T(); + if (Val.hasValue() && + this->preflightKey(Key, Required, sameAsDefault, UseDefault, SaveInfo)) { + + // When reading an Optional key from a YAML description, we allow the + // special "" value, which can be used to specify that no value was + // requested, i.e. the DefaultValue will be assigned. The DefaultValue is + // usually None. + bool IsNone = false; + if (!outputting()) + if (auto *Node = dyn_cast(((Input *)this)->getCurrentNode())) + IsNone = Node->getRawValue() == ""; + + if (IsNone) + Val = DefaultValue; + else + yamlize(*this, Val.getValue(), Required, Ctx); + this->postflightKey(SaveInfo); + } else { + if (UseDefault) + Val = DefaultValue; + } +} + /// YAML I/O does conversion based on types. But often native data types /// are just a typedef of built in intergral types (e.g. int). But the C++ /// type matching system sees through the typedef and all the typedefed types Index: llvm/test/tools/yaml2obj/ELF/none-value.yaml =================================================================== --- /dev/null +++ llvm/test/tools/yaml2obj/ELF/none-value.yaml @@ -0,0 +1,262 @@ +## We have a special "" value for all keys that are implemented +## as Optional<> in the code. Setting a key to "" means no-op and +## works in the same way as when a value was not set at all. + +# RUN: yaml2obj %s --docnum=1 -o %t-none +# RUN: yaml2obj %s --docnum=2 -o %t-base +# RUN: cmp %t-none %t-base + +## Test all keys for which the "" value is supported. + +## We do not use the TEST macro. It is exist to +## demonstrate the expected use case for the word. +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 + EShEntSize: [[TEST=]] + EShOff: [[TEST=]] + EShNum: [[TEST=]] + EShStrNdx: [[TEST=]] + EPhOff: [[TEST=]] + EPhEntSize: [[TEST=]] + EPhNum: [[TEST=]] +Sections: + - Name: .bar + Type: SHT_PROGBITS + Offset: [[TEST=]] + Address: [[TEST=]] + Content: [[TEST=]] + Size: [[TEST=]] + ContentArray: [[TEST=]] + Info: [[TEST=]] + EntSize: [[TEST=]] + ShName: [[TEST=]] + ShOffset: [[TEST=]] + ShSize: [[TEST=]] + ShFlags: [[TEST=]] + - Type: Fill + Pattern: [[TEST=]] + Size: 0x3 + - Name: .cgp + Type: SHT_LLVM_CALL_GRAPH_PROFILE + Content: [[TEST=]] + Entries: [[TEST=]] + - Name: .dynamic + Type: SHT_DYNAMIC + Content: [[TEST=]] +## Note: for SHT_NOTE sections, one of "Content", "Size" or "Notes" must be specified. + - Name: .note.1 + Type: SHT_NOTE + Content: [[TEST=]] + Size: 1 + Notes: [[TEST=]] + - Name: .note.2 + Type: SHT_NOTE + Content: "1122" + Size: [[TEST=]] +## Note: for SHT_HASH sections, one of "Content", "Size", "Bucket" or "Chain" must be specified. + - Name: .hash.1 + Type: SHT_HASH + Content: [[TEST=]] + Size: 1 + Bucket: [[TEST=]] + Chain: [[TEST=]] + NBucket: [[TEST=]] + NChain: [[TEST=]] + - Name: .hash.2 + Type: SHT_HASH + Content: "1122" + Size: [[TEST=]] +## Note: for SHT_GNU_HASH sections either "Content" or "Header", "BloomFilter", "HashBuckets" and +## "HashBuckets" must be specified. + - Name: .gnu.hash.1 + Type: SHT_GNU_HASH + Content: "00" + Header: [[TEST=]] + BloomFilter: [[TEST=]] + HashBuckets: [[TEST=]] + HashValues: [[TEST=]] + - Name: .gnu.hash.2 + Type: SHT_GNU_HASH + Content: [[TEST=]] + BloomFilter: [] + HashBuckets: [] + HashValues: [] + Header: + SymNdx: 0x0 + Shift2: 0x0 + - Name: .gnu.version_r + Type: SHT_GNU_verneed + Info: 0x0 + Dependencies: [[TEST=]] + Content: [[TEST=]] + - Name: .gnu.version_d + Info: 0x0 + Type: SHT_GNU_verdef + Entries: [[TEST=]] + Content: [[TEST=]] +## Note: for SHT_LLVM_ADDRSIG sections one of "Content", "Size" or "Symbols" must be specified. + - Name: .llvm_addrsig.1 + Type: SHT_LLVM_ADDRSIG + Content: "1122" + Size: [[TEST=]] + Symbols: [[TEST=]] + - Name: .llvm_addrsig.2 + Type: SHT_LLVM_ADDRSIG + Content: [[TEST=]] + Size: 1 + - Name: .linker-options + Type: SHT_LLVM_LINKER_OPTIONS + Content: [[TEST=]] + Options: [[TEST=]] + - Name: .deplibs + Type: SHT_LLVM_DEPENDENT_LIBRARIES + Libraries: [[TEST=]] + Content: [[TEST=]] + - Name: .group + Type: SHT_GROUP + Info: [[TEST=]] + Members: [] + - Name: .rela + Type: SHT_RELA + Relocations: + - Type: R_X86_64_NONE + Symbol: [[TEST=]] + - Name: .relr + Type: SHT_RELR + Entries: [[TEST=]] + Content: [[TEST=]] +ProgramHeaders: + - Type: PT_LOAD + Align: [[TEST=]] + FileSize: [[TEST=]] + MemSize: [[TEST=]] + Offset: [[TEST=]] +Symbols: + - Name: foo + Other: [[TEST=]] + StName: [[TEST=]] +SectionHeaderTable: + Sections: + - Name: .bar + - Name: .cgp + - Name: .symtab + - Name: .strtab + - Name: .shstrtab + - Name: .dynamic + - Name: .note.1 + - Name: .note.2 + - Name: .hash.1 + - Name: .hash.2 + - Name: .gnu.hash.1 + - Name: .gnu.hash.2 + - Name: .gnu.version_r + - Name: .gnu.version_d + - Name: .llvm_addrsig.1 + - Name: .llvm_addrsig.2 + - Name: .linker-options + - Name: .deplibs + - Name: .group + - Name: .rela + - Name: .relr + NoHeaders: [[TEST=]] + +## The same document, but all fields that were set to are removed. +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .bar + Type: SHT_PROGBITS + - Type: Fill + Size: 0x3 + - Name: .cgp + Type: SHT_LLVM_CALL_GRAPH_PROFILE + - Name: .dynamic + Type: SHT_DYNAMIC +## Note: for SHT_NOTE sections, one of "Content", "Size" or "Notes" must be specified. + - Name: .note.1 + Type: SHT_NOTE + Size: 1 + - Name: .note.2 + Type: SHT_NOTE + Content: "1122" +## Note: for SHT_HASH sections, one of "Content", "Size", "Bucket" or "Chain" must be specified. + - Name: .hash.1 + Type: SHT_HASH + Size: 1 + - Name: .hash.2 + Type: SHT_HASH + Content: "1122" +## Note: for SHT_GNU_HASH sections either "Content" or "Header", "BloomFilter", "HashBuckets" and +## "HashBuckets" must be specified. + - Name: .gnu.hash.1 + Type: SHT_GNU_HASH + Content: "00" + - Name: .gnu.hash.2 + Type: SHT_GNU_HASH + BloomFilter: [] + HashBuckets: [] + HashValues: [] + Header: + SymNdx: 0x0 + Shift2: 0x0 + - Name: .gnu.version_r + Type: SHT_GNU_verneed + Info: 0x0 + - Name: .gnu.version_d + Info: 0x0 + Type: SHT_GNU_verdef +## Note: for SHT_LLVM_ADDRSIG sections one of "Content", "Size" or "Symbols" must be specified. + - Name: .llvm_addrsig.1 + Type: SHT_LLVM_ADDRSIG + Content: "1122" + - Name: .llvm_addrsig.2 + Type: SHT_LLVM_ADDRSIG + Size: 1 + - Name: .linker-options + Type: SHT_LLVM_LINKER_OPTIONS + - Name: .deplibs + Type: SHT_LLVM_DEPENDENT_LIBRARIES + - Name: .group + Type: SHT_GROUP + Members: [] + - Name: .rela + Type: SHT_RELA + Relocations: + - Type: R_X86_64_NONE + - Name: .relr + Type: SHT_RELR +ProgramHeaders: + - Type: PT_LOAD +Symbols: + - Name: foo +SectionHeaderTable: + Sections: + - Name: .bar + - Name: .cgp + - Name: .symtab + - Name: .strtab + - Name: .shstrtab + - Name: .dynamic + - Name: .note.1 + - Name: .note.2 + - Name: .hash.1 + - Name: .hash.2 + - Name: .gnu.hash.1 + - Name: .gnu.hash.2 + - Name: .gnu.version_r + - Name: .gnu.version_d + - Name: .llvm_addrsig.1 + - Name: .llvm_addrsig.2 + - Name: .linker-options + - Name: .deplibs + - Name: .group + - Name: .rela + - Name: .relr