[yaml2obj] - Add a support for "<none>" value for all optional fields.
It implements an approach suggested in the D84398 thread. With it the following: ``` Sections: - Name: .bar Type: SHT_PROGBITS Offset: [[MACRO=<none>]] ``` works just like the `Offset` key was not specified. It is useful for tests that want to have a default value for a field and to have a way to override it at the same time. Differential revision: https://reviews.llvm.org/D84526
This commit is contained in:
parent
6d47431d7e
commit
d919ae9df8
|
@ -902,24 +902,7 @@ private:
|
|||
template <typename T, typename Context>
|
||||
void processKeyWithDefault(const char *Key, Optional<T> &Val,
|
||||
const Optional<T> &DefaultValue, bool Required,
|
||||
Context &Ctx) {
|
||||
assert(DefaultValue.hasValue() == false &&
|
||||
"Optional<T> 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 <typename T, typename Context>
|
||||
void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
|
||||
|
@ -1625,6 +1608,40 @@ private:
|
|||
StringRef PaddingBeforeContainer;
|
||||
};
|
||||
|
||||
template <typename T, typename Context>
|
||||
void IO::processKeyWithDefault(const char *Key, Optional<T> &Val,
|
||||
const Optional<T> &DefaultValue, bool Required,
|
||||
Context &Ctx) {
|
||||
assert(DefaultValue.hasValue() == false &&
|
||||
"Optional<T> 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<X> key from a YAML description, we allow the
|
||||
// special "<none>" 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<ScalarNode>(((Input *)this)->getCurrentNode()))
|
||||
IsNone = Node->getRawValue() == "<none>";
|
||||
|
||||
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
|
||||
|
|
45
llvm/test/tools/yaml2obj/ELF/none-value.yaml
Normal file
45
llvm/test/tools/yaml2obj/ELF/none-value.yaml
Normal file
|
@ -0,0 +1,45 @@
|
|||
## We have a special "<none>" value for all keys that are implemented
|
||||
## as Optional<> in the code. Setting a key to "<none>" means no-op and
|
||||
## works in the same way as when a field was not specified at all.
|
||||
|
||||
## Test a few keys for which the "<none>" value is supported.
|
||||
## We do not test all possible keys, because it would be too verbose.
|
||||
## It reasonable to test all keys for a section, because normally many
|
||||
## of them would conflict or intersect when specified together.
|
||||
# RUN: yaml2obj %s --docnum=1 -o %t-none
|
||||
# RUN: yaml2obj %s --docnum=2 -o %t-base
|
||||
# RUN: cmp %t-none %t-base
|
||||
|
||||
## We do not use the TEST macro. It exists to
|
||||
## demonstrate the expected use case for the <none> word.
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .bar
|
||||
Type: SHT_PROGBITS
|
||||
Offset: [[TEST=<none>]]
|
||||
Address: [[TEST=<none>]]
|
||||
Content: [[TEST=<none>]]
|
||||
Size: [[TEST=<none>]]
|
||||
ContentArray: [[TEST=<none>]]
|
||||
Info: [[TEST=<none>]]
|
||||
EntSize: [[TEST=<none>]]
|
||||
ShName: [[TEST=<none>]]
|
||||
ShOffset: [[TEST=<none>]]
|
||||
ShSize: [[TEST=<none>]]
|
||||
ShFlags: [[TEST=<none>]]
|
||||
|
||||
## The same document, but all fields that were set to <none> are removed.
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .bar
|
||||
Type: SHT_PROGBITS
|
Loading…
Reference in a new issue