[llvm] d919ae9 - [yaml2obj] - Add a support for "<none>" value for all optional fields.
Georgii Rymar via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 3 02:28:04 PDT 2020
Author: Georgii Rymar
Date: 2020-08-03T12:27:39+03:00
New Revision: d919ae9df8721a56c8457fd5f9cfd50a71c87262
URL: https://github.com/llvm/llvm-project/commit/d919ae9df8721a56c8457fd5f9cfd50a71c87262
DIFF: https://github.com/llvm/llvm-project/commit/d919ae9df8721a56c8457fd5f9cfd50a71c87262.diff
LOG: [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
Added:
llvm/test/tools/yaml2obj/ELF/none-value.yaml
Modified:
llvm/include/llvm/Support/YAMLTraits.h
Removed:
################################################################################
diff --git a/llvm/include/llvm/Support/YAMLTraits.h b/llvm/include/llvm/Support/YAMLTraits.h
index 44e34a4a09b4..e52bf7892d71 100644
--- a/llvm/include/llvm/Support/YAMLTraits.h
+++ b/llvm/include/llvm/Support/YAMLTraits.h
@@ -902,24 +902,7 @@ class IO {
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 @@ class Output : public IO {
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
diff --git a/llvm/test/tools/yaml2obj/ELF/none-value.yaml b/llvm/test/tools/yaml2obj/ELF/none-value.yaml
new file mode 100644
index 000000000000..786a9b53aba7
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/ELF/none-value.yaml
@@ -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
More information about the llvm-commits
mailing list