Rework how YAMLReader is layered on top of YAMLParser. Turn hand written

recursive descent functions into one table driven parser.  Add proper
error recovery and reporting.  Add lots of test cases with semantics errors
and verify error messages.

llvm-svn: 156136
This commit is contained in:
Nick Kledzik 2012-05-03 23:55:34 +00:00
parent 6ccfcf346d
commit 3011259a85
14 changed files with 1027 additions and 628 deletions

View File

@ -1,4 +1,4 @@
//===- Core/InputFiles.cpp - Manages list of Files -----------------------===//
//===- Core/InputFiles.cpp - Manages list of Files ------------------------===//
//
// The LLVM Linker
//

View File

@ -18,35 +18,6 @@ namespace lld {
namespace yaml {
const char* const KeyValues::nameKeyword = "name";
const char* const KeyValues::refNameKeyword = "ref-name";
const char* const KeyValues::definitionKeyword = "definition";
const char* const KeyValues::scopeKeyword = "scope";
const char* const KeyValues::contentTypeKeyword = "type";
const char* const KeyValues::deadStripKindKeyword = "dead-strip";
const char* const KeyValues::sectionChoiceKeyword = "section-choice";
const char* const KeyValues::interposableKeyword = "interposable";
const char* const KeyValues::mergeKeyword = "merge";
const char* const KeyValues::isThumbKeyword = "is-thumb";
const char* const KeyValues::isAliasKeyword = "is-alias";
const char* const KeyValues::sectionNameKeyword = "section-name";
const char* const KeyValues::contentKeyword = "content";
const char* const KeyValues::loadNameKeyword = "load-name";
const char* const KeyValues::sizeKeyword = "size";
const char* const KeyValues::valueKeyword = "value";
const char* const KeyValues::fixupsKeyword = "fixups";
const char* const KeyValues::permissionsKeyword = "permissions";
const char* const KeyValues::canBeNullKeyword = "can-be-null";
const char* const KeyValues::fixupsKindKeyword = "kind";
const char* const KeyValues::fixupsOffsetKeyword = "offset";
const char* const KeyValues::fixupsTargetKeyword = "target";
const char* const KeyValues::fixupsAddendKeyword = "addend";
const char* const KeyValues::fileAtomsKeyword = "atoms";
const char* const KeyValues::fileKindKeyword = "kind";
const char* const KeyValues::fileMembersKeyword = "members";
const DefinedAtom::Definition KeyValues::definitionDefault = Atom::definitionRegular;
const DefinedAtom::Scope KeyValues::scopeDefault = DefinedAtom::scopeTranslationUnit;
const DefinedAtom::ContentType KeyValues::contentTypeDefault = DefinedAtom::typeData;
@ -58,36 +29,8 @@ const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAto
const bool KeyValues::isThumbDefault = false;
const bool KeyValues::isAliasDefault = false;
const UndefinedAtom::CanBeNull KeyValues::canBeNullDefault = UndefinedAtom::canBeNullNever;
const File::Kind KeyValues::fileKindDefault = File::kindObject;
struct FileKindMapping {
const char* string;
File::Kind value;
};
static const FileKindMapping fileKindMappings[] = {
{ "object", File::kindObject },
{ "archive", File::kindArchiveLibrary },
{ "shared-library", File::kindSharedLibrary },
{ nullptr, File::kindObject }
};
File::Kind KeyValues::fileKind(StringRef str) {
for (const FileKindMapping* p = fileKindMappings; p->string != nullptr; ++p) {
if (str == p->string)
return p->value;
}
llvm::report_fatal_error("bad file kind value");
}
const char* KeyValues::fileKind(File::Kind k) {
for (const FileKindMapping* p = fileKindMappings; p->string != nullptr; ++p) {
if ( p->value == k )
return p->string;
}
llvm::report_fatal_error("bad file kind value");
}
struct DefinitionMapping {
@ -103,13 +46,15 @@ static const DefinitionMapping defMappings[] = {
{ nullptr, Atom::definitionRegular }
};
Atom::Definition KeyValues::definition(StringRef s)
bool KeyValues::definition(StringRef s, Atom::Definition &out)
{
for (const DefinitionMapping* p = defMappings; p->string != nullptr; ++p) {
if (s == p->string)
return p->value;
if (s == p->string) {
out = p->value;
return false;
}
}
llvm::report_fatal_error("bad definition value");
return true;
}
const char* KeyValues::definition(Atom::Definition s) {
@ -136,13 +81,15 @@ static const ScopeMapping scopeMappings[] = {
{ nullptr, DefinedAtom::scopeGlobal }
};
DefinedAtom::Scope KeyValues::scope(StringRef s)
bool KeyValues::scope(StringRef s, DefinedAtom::Scope &out)
{
for (const ScopeMapping* p = scopeMappings; p->string != nullptr; ++p) {
if (s == p->string)
return p->value;
if (s == p->string) {
out = p->value;
return false;
}
}
llvm::report_fatal_error("bad scope value");
return true;
}
const char* KeyValues::scope(DefinedAtom::Scope s) {
@ -197,13 +144,15 @@ static const ContentTypeMapping typeMappings[] = {
{ nullptr, DefinedAtom::typeUnknown }
};
DefinedAtom::ContentType KeyValues::contentType(StringRef s)
bool KeyValues::contentType(StringRef s, DefinedAtom::ContentType &out)
{
for (const ContentTypeMapping* p = typeMappings; p->string != nullptr; ++p) {
if (s == p->string)
return p->value;
if (s == p->string) {
out = p->value;
return false;
}
}
llvm::report_fatal_error("bad content type value");
return true;
}
const char* KeyValues::contentType(DefinedAtom::ContentType s) {
@ -225,26 +174,26 @@ struct DeadStripMapping {
DefinedAtom::DeadStripKind value;
};
static const DeadStripMapping deadStripMappings[] = {
static const DeadStripMapping dsMappings[] = {
{ "normal", DefinedAtom::deadStripNormal },
{ "never", DefinedAtom::deadStripNever },
{ "always", DefinedAtom::deadStripAlways },
{ nullptr, DefinedAtom::deadStripNormal }
};
DefinedAtom::DeadStripKind KeyValues::deadStripKind(StringRef s)
bool KeyValues::deadStripKind(StringRef s, DefinedAtom::DeadStripKind &out)
{
for (const DeadStripMapping* p = deadStripMappings; p->string != nullptr; ++p)
{
if (s == p->string)
return p->value;
for (const DeadStripMapping* p = dsMappings; p->string != nullptr; ++p) {
if (s == p->string) {
out = p->value;
return false;
}
}
llvm::report_fatal_error("bad dead strip value");
return true;
}
const char* KeyValues::deadStripKind(DefinedAtom::DeadStripKind dsk) {
for (const DeadStripMapping* p = deadStripMappings; p->string != nullptr; ++p)
{
for (const DeadStripMapping* p = dsMappings; p->string != nullptr; ++p) {
if ( p->value == dsk )
return p->string;
}
@ -267,13 +216,15 @@ static const InterposableMapping interMappings[] = {
{ nullptr, DefinedAtom::interposeNo }
};
DefinedAtom::Interposable KeyValues::interposable(StringRef s)
bool KeyValues::interposable(StringRef s, DefinedAtom::Interposable &out)
{
for (const InterposableMapping* p = interMappings; p->string != nullptr; ++p){
if (s == p->string)
return p->value;
if (s == p->string) {
out = p->value;
return false;
}
}
llvm::report_fatal_error("bad interposable value");
return true;
}
const char* KeyValues::interposable(DefinedAtom::Interposable in) {
@ -302,13 +253,15 @@ static const MergeMapping mergeMappings[] = {
{ nullptr, DefinedAtom::mergeNo }
};
DefinedAtom::Merge KeyValues::merge(StringRef s)
bool KeyValues::merge(StringRef s, DefinedAtom::Merge& out)
{
for (const MergeMapping* p = mergeMappings; p->string != nullptr; ++p) {
if (s == p->string)
return p->value;
if (s == p->string) {
out = p->value;
return false;
}
}
llvm::report_fatal_error("bad merge value");
return true;
}
const char* KeyValues::merge(DefinedAtom::Merge in) {
@ -336,13 +289,15 @@ static const SectionChoiceMapping sectMappings[] = {
{ nullptr, DefinedAtom::sectionBasedOnContent }
};
DefinedAtom::SectionChoice KeyValues::sectionChoice(StringRef s)
bool KeyValues::sectionChoice(StringRef s, DefinedAtom::SectionChoice &out)
{
for (const SectionChoiceMapping* p = sectMappings; p->string != nullptr; ++p){
if (s == p->string)
return p->value;
if (s == p->string) {
out = p->value;
return false;
}
}
llvm::report_fatal_error("bad dead strip value");
return true;
}
const char* KeyValues::sectionChoice(DefinedAtom::SectionChoice s) {
@ -365,21 +320,23 @@ struct PermissionsMapping {
};
static const PermissionsMapping permMappings[] = {
{ "content", DefinedAtom::perm___ },
{ "custom", DefinedAtom::permR__ },
{ "custom-required", DefinedAtom::permR_X },
{ "custom-required", DefinedAtom::permRW_ },
{ "custom-required", DefinedAtom::permRW_L },
{ nullptr, DefinedAtom::perm___ }
{ "---", DefinedAtom::perm___ },
{ "r--", DefinedAtom::permR__ },
{ "r-x", DefinedAtom::permR_X },
{ "rw-", DefinedAtom::permRW_ },
{ "rw-l", DefinedAtom::permRW_L },
{ nullptr, DefinedAtom::perm___ }
};
DefinedAtom::ContentPermissions KeyValues::permissions(StringRef s)
bool KeyValues::permissions(StringRef s, DefinedAtom::ContentPermissions &out)
{
for (const PermissionsMapping* p = permMappings; p->string != nullptr; ++p) {
if (s == p->string)
return p->value;
if (s == p->string) {
out = p->value;
return false;
}
}
llvm::report_fatal_error("bad permissions value");
return true;
}
const char* KeyValues::permissions(DefinedAtom::ContentPermissions s) {
@ -390,10 +347,42 @@ const char* KeyValues::permissions(DefinedAtom::ContentPermissions s) {
llvm::report_fatal_error("bad permissions value");
}
bool KeyValues::isThumb(StringRef s, bool &out)
{
if ( s.equals("true") ) {
out = true;
return false;
}
if ( s.equals("false") ) {
out = false;
return false;
}
return true;
}
const char* KeyValues::isThumb(bool b) {
return b ? "true" : "false";
}
bool KeyValues::isAlias(StringRef s, bool &out)
{
if ( s.equals("true") ) {
out = true;
return false;
}
if ( s.equals("false") ) {
out = false;
return false;
}
return true;
}
const char* KeyValues::isAlias(bool b) {
return b ? "true" : "false";
}
@ -414,13 +403,15 @@ static const CanBeNullMapping cbnMappings[] = {
};
UndefinedAtom::CanBeNull KeyValues::canBeNull(StringRef s)
bool KeyValues::canBeNull(StringRef s, UndefinedAtom::CanBeNull &out)
{
for (const CanBeNullMapping* p = cbnMappings; p->string != nullptr; ++p) {
if (s == p->string)
return p->value;
if (s == p->string) {
out = p->value;
return false;
}
}
llvm::report_fatal_error("bad can-be-null value");
return true;
}
const char* KeyValues::canBeNull(UndefinedAtom::CanBeNull c) {

View File

@ -20,81 +20,62 @@ namespace yaml {
class KeyValues {
public:
static const char* const nameKeyword;
static const char* const refNameKeyword;
static const char* const sectionNameKeyword;
static const char* const contentKeyword;
static const char* const sizeKeyword;
static const char* const loadNameKeyword;
static const char* const valueKeyword;
static const char* const fixupsKeyword;
static const char* const fileAtomsKeyword;
static const char* const fileMembersKeyword;
static const char* const fileKindKeyword;
static const File::Kind fileKindDefault;
static File::Kind fileKind(StringRef);
static const char* fileKind(File::Kind);
static const char* const definitionKeyword;
static const Atom::Definition definitionDefault;
static Atom::Definition definition(StringRef);
static bool definition(StringRef, Atom::Definition&);
static const char* definition(Atom::Definition);
static const char* const scopeKeyword;
static const DefinedAtom::Scope scopeDefault;
static DefinedAtom::Scope scope(StringRef);
static bool scope(StringRef, DefinedAtom::Scope&);
static const char* scope(DefinedAtom::Scope);
static const char* const contentTypeKeyword;
static const DefinedAtom::ContentType contentTypeDefault;
static DefinedAtom::ContentType contentType(StringRef);
static bool contentType(StringRef, DefinedAtom::ContentType&);
static const char* contentType(DefinedAtom::ContentType);
static const char* const deadStripKindKeyword;
static const DefinedAtom::DeadStripKind deadStripKindDefault;
static DefinedAtom::DeadStripKind deadStripKind(StringRef);
static bool deadStripKind(StringRef, DefinedAtom::DeadStripKind&);
static const char* deadStripKind(DefinedAtom::DeadStripKind);
static const char* const sectionChoiceKeyword;
static const DefinedAtom::SectionChoice sectionChoiceDefault;
static DefinedAtom::SectionChoice sectionChoice(StringRef);
static bool sectionChoice(StringRef, DefinedAtom::SectionChoice&);
static const char* sectionChoice(DefinedAtom::SectionChoice);
static const char* const interposableKeyword;
static const DefinedAtom::Interposable interposableDefault;
static DefinedAtom::Interposable interposable(StringRef);
static bool interposable(StringRef, DefinedAtom::Interposable&);
static const char* interposable(DefinedAtom::Interposable);
static const char* const mergeKeyword;
static const DefinedAtom::Merge mergeDefault;
static DefinedAtom::Merge merge(StringRef);
static bool merge(StringRef, DefinedAtom::Merge&);
static const char* merge(DefinedAtom::Merge);
static const char* const permissionsKeyword;
static const DefinedAtom::ContentPermissions permissionsDefault;
static DefinedAtom::ContentPermissions permissions(StringRef);
static bool permissions(StringRef, DefinedAtom::ContentPermissions&);
static const char* permissions(DefinedAtom::ContentPermissions);
static const char* const isThumbKeyword;
static const bool isThumbDefault;
static bool isThumb(StringRef, bool&);
static const char* isThumb(bool);
static const char* const isAliasKeyword;
static const bool isAliasDefault;
static bool isAlias(StringRef, bool&);
static const char* isAlias(bool);
static const char* const canBeNullKeyword;
static const UndefinedAtom::CanBeNull canBeNullDefault;
static UndefinedAtom::CanBeNull canBeNull(StringRef);
static bool canBeNull(StringRef, UndefinedAtom::CanBeNull&);
static const char* canBeNull(UndefinedAtom::CanBeNull);
static const char* const fixupsKindKeyword;
static const char* const fixupsOffsetKeyword;
static const char* const fixupsTargetKeyword;
static const char* const fixupsAddendKeyword;
};
} // namespace yaml

File diff suppressed because it is too large Load Diff

View File

@ -164,9 +164,8 @@ public:
bool hasDash = false;
if ( !atom.name().empty() ) {
out << " - "
<< KeyValues::nameKeyword
<< ":"
<< spacePadding(KeyValues::nameKeyword)
<< "name:"
<< spacePadding(strlen("name"))
<< atom.name()
<< "\n";
hasDash = true;
@ -174,9 +173,8 @@ public:
if ( _rnb.hasRefName(&atom) ) {
out << (hasDash ? " " : " - ")
<< KeyValues::refNameKeyword
<< ":"
<< spacePadding(KeyValues::refNameKeyword)
<< "ref-name:"
<< spacePadding(strlen("ref-name"))
<< _rnb.refName(&atom)
<< "\n";
hasDash = true;
@ -184,9 +182,8 @@ public:
if ( atom.definition() != KeyValues::definitionDefault ) {
out << (hasDash ? " " : " - ")
<< KeyValues::definitionKeyword
<< ":"
<< spacePadding(KeyValues::definitionKeyword)
<< "definition:"
<< spacePadding(strlen("definition"))
<< KeyValues::definition(atom.definition())
<< "\n";
hasDash = true;
@ -194,9 +191,8 @@ public:
if ( atom.scope() != KeyValues::scopeDefault ) {
out << (hasDash ? " " : " - ")
<< KeyValues::scopeKeyword
<< ":"
<< spacePadding(KeyValues::scopeKeyword)
<< "scope:"
<< spacePadding(strlen("scope"))
<< KeyValues::scope(atom.scope())
<< "\n";
hasDash = true;
@ -204,70 +200,62 @@ public:
if ( atom.interposable() != KeyValues::interposableDefault ) {
out << " "
<< KeyValues::interposableKeyword
<< ":"
<< spacePadding(KeyValues::interposableKeyword)
<< "interposable:"
<< spacePadding(strlen("interposable"))
<< KeyValues::interposable(atom.interposable())
<< "\n";
}
if ( atom.merge() != KeyValues::mergeDefault ) {
out << " "
<< KeyValues::mergeKeyword
<< ":"
<< spacePadding(KeyValues::mergeKeyword)
<< "merge:"
<< spacePadding(strlen("merge"))
<< KeyValues::merge(atom.merge())
<< "\n";
}
if ( atom.contentType() != KeyValues::contentTypeDefault ) {
out << " "
<< KeyValues::contentTypeKeyword
<< ":"
<< spacePadding(KeyValues::contentTypeKeyword)
<< "type:"
<< spacePadding(strlen("type"))
<< KeyValues::contentType(atom.contentType())
<< "\n";
}
if ( atom.deadStrip() != KeyValues::deadStripKindDefault ) {
out << " "
<< KeyValues::deadStripKindKeyword
<< ":"
<< spacePadding(KeyValues::deadStripKindKeyword)
<< "dead-strip:"
<< spacePadding(strlen("dead-strip"))
<< KeyValues::deadStripKind(atom.deadStrip())
<< "\n";
}
if ( atom.sectionChoice() != KeyValues::sectionChoiceDefault ) {
out << " "
<< KeyValues::sectionChoiceKeyword
<< ":"
<< spacePadding(KeyValues::sectionChoiceKeyword)
<< "section-choice:"
<< spacePadding(strlen("section-choice"))
<< KeyValues::sectionChoice(atom.sectionChoice())
<< "\n";
assert( ! atom.customSectionName().empty() );
out << " "
<< KeyValues::sectionNameKeyword
<< ":"
<< spacePadding(KeyValues::sectionNameKeyword)
<< "section-name:"
<< spacePadding(strlen("section-name"))
<< atom.customSectionName()
<< "\n";
}
if ( atom.isThumb() != KeyValues::isThumbDefault ) {
out << " "
<< KeyValues::isThumbKeyword
<< ":"
<< spacePadding(KeyValues::isThumbKeyword)
<< "is-thumb:"
<< spacePadding(strlen("is-thumb"))
<< KeyValues::isThumb(atom.isThumb())
<< "\n";
}
if ( atom.isAlias() != KeyValues::isAliasDefault ) {
out << " "
<< KeyValues::isAliasKeyword
<< ":"
<< spacePadding(KeyValues::isAliasKeyword)
<< "is-alias:"
<< spacePadding(strlen("is-alias"))
<< KeyValues::isAlias(atom.isAlias())
<< "\n";
}
@ -275,9 +263,8 @@ public:
if ( (atom.contentType() != DefinedAtom::typeZeroFill)
&& (atom.size() != 0) ) {
out << " "
<< KeyValues::contentKeyword
<< ":"
<< spacePadding(KeyValues::contentKeyword)
<< "content:"
<< spacePadding(strlen("content"))
<< "[ ";
ArrayRef<uint8_t> arr = atom.rawContent();
bool needComma = false;
@ -301,15 +288,13 @@ public:
wroteFirstFixup = true;
}
out << " - "
<< KeyValues::fixupsOffsetKeyword
<< ":"
<< spacePadding(KeyValues::fixupsOffsetKeyword)
<< "offset:"
<< spacePadding(strlen("offset"))
<< ref->offsetInAtom()
<< "\n";
out << " "
<< KeyValues::fixupsKindKeyword
<< ":"
<< spacePadding(KeyValues::fixupsKindKeyword)
<< "kind:"
<< spacePadding(strlen("kind"))
<< _platform.kindToString(ref->kind())
<< "\n";
const Atom* target = ref->target();
@ -319,17 +304,15 @@ public:
refName = _rnb.refName(target);
assert(!refName.empty());
out << " "
<< KeyValues::fixupsTargetKeyword
<< ":"
<< spacePadding(KeyValues::fixupsTargetKeyword)
<< "target:"
<< spacePadding(strlen("target"))
<< refName
<< "\n";
}
if ( ref->addend() != 0 ) {
out << " "
<< KeyValues::fixupsAddendKeyword
<< ":"
<< spacePadding(KeyValues::fixupsAddendKeyword)
<< "addend:"
<< spacePadding(strlen("addend"))
<< ref->addend()
<< "\n";
}
@ -348,24 +331,21 @@ public:
}
out << " - "
<< KeyValues::nameKeyword
<< ":"
<< spacePadding(KeyValues::nameKeyword)
<< "name:"
<< spacePadding(strlen("name"))
<< atom.name()
<< "\n";
out << " "
<< KeyValues::definitionKeyword
<< ":"
<< spacePadding(KeyValues::definitionKeyword)
<< "definition:"
<< spacePadding(strlen("definition"))
<< KeyValues::definition(atom.definition())
<< "\n";
if ( atom.canBeNull() != KeyValues::canBeNullDefault ) {
out << " "
<< KeyValues::canBeNullKeyword
<< ":"
<< spacePadding(KeyValues::canBeNullKeyword)
<< "can-be-null:"
<< spacePadding(strlen("can-be-null"))
<< KeyValues::canBeNull(atom.canBeNull())
<< "\n";
}
@ -382,33 +362,29 @@ public:
}
out << " - "
<< KeyValues::nameKeyword
<< ":"
<< spacePadding(KeyValues::nameKeyword)
<< "name:"
<< spacePadding(strlen("name"))
<< atom.name()
<< "\n";
out << " "
<< KeyValues::definitionKeyword
<< ":"
<< spacePadding(KeyValues::definitionKeyword)
<< "definition:"
<< spacePadding(strlen("definition"))
<< KeyValues::definition(atom.definition())
<< "\n";
if ( !atom.loadName().empty() ) {
out << " "
<< KeyValues::loadNameKeyword
<< ":"
<< spacePadding(KeyValues::loadNameKeyword)
<< "load-name:"
<< spacePadding(strlen("load-name"))
<< atom.loadName()
<< "\n";
}
if ( atom.canBeNullAtRuntime() ) {
out << " "
<< KeyValues::canBeNullKeyword
<< ":"
<< spacePadding(KeyValues::canBeNullKeyword)
<< "can-be-null:"
<< spacePadding(strlen("can-be-null"))
<< KeyValues::canBeNull(UndefinedAtom::canBeNullAtRuntime)
<< "\n";
}
@ -425,23 +401,20 @@ public:
}
out << " - "
<< KeyValues::nameKeyword
<< ":"
<< spacePadding(KeyValues::nameKeyword)
<< "name:"
<< spacePadding(strlen("name"))
<< atom.name()
<< "\n";
out << " "
<< KeyValues::definitionKeyword
<< ":"
<< spacePadding(KeyValues::definitionKeyword)
<< "definition:"
<< spacePadding(strlen("definition"))
<< KeyValues::definition(atom.definition())
<< "\n";
out << " "
<< KeyValues::valueKeyword
<< ":"
<< spacePadding(KeyValues::valueKeyword)
<< "value:"
<< spacePadding(strlen("value"))
<< "0x";
out.write_hex(atom.value());
out << "\n";
@ -450,10 +423,10 @@ public:
private:
// return a string of the correct number of spaces to align value
const char* spacePadding(const char* key) {
const char* spacePadding(int keyLen) {
const char* spaces = " ";
assert(strlen(spaces) > strlen(key));
return &spaces[strlen(key)];
assert(strlen(spaces) > keyLen);
return &spaces[keyLen];
}
char hexdigit(uint8_t nibble) {

View File

@ -14,7 +14,7 @@ atoms:
- name: bar
scope: global
content: zero-fill
type: zero-fill
merge: asTentative
---

View File

@ -0,0 +1,19 @@
# RUN: not lld-core %s 2> %t.err
# RUN: FileCheck < %t.err %s
#
# Test that unknown atom attribute produces a readable error.
#
---
atoms:
- name: entry
scope: hidden
foobar: true
dead-strip: never
...
# CHECK: error: Unknown atom attribute
# CHECK: foobar

View File

@ -0,0 +1,18 @@
# RUN: not lld-core %s 2> %t.err
# RUN: FileCheck < %t.err %s
#
# Test that an invalid hex byte produces a readable error.
#
---
atoms:
- name: entry
scope: hidden
content: [ A5, 00, 4G, 1F ]
...
# CHECK: error: Invalid content hex byte
# CHECK: 4G

View File

@ -0,0 +1,19 @@
# RUN: not lld-core %s 2> %t.err
# RUN: FileCheck < %t.err %s
#
# Test that an out of range byte value produces a readable error.
#
---
atoms:
- name: entry
scope: hidden
content: [ A5, 1234, 00, 4F ]
...
# CHECK: error: Content hex byte out of range
# CHECK: 1234

View File

@ -0,0 +1,19 @@
# RUN: not lld-core %s 2> %t.err
# RUN: FileCheck < %t.err %s
#
# Test that an unknown content type produces a readable error.
#
---
atoms:
- name: entry
scope: hidden
type: superluminal
dead-strip: never
...
# CHECK: error: Invalid value for 'type:'
# CHECK: superluminal

View File

@ -0,0 +1,18 @@
# RUN: not lld-core %s 2> %t.err
# RUN: FileCheck < %t.err %s
#
# Test that a defined attribute on an undefined atom produces a readable error.
#
---
atoms:
- name: foo
type: code
definition: undefined
...
# CHECK: error: Undefined atom 'foo' has attributes only allowed on defined atoms

View File

@ -0,0 +1,18 @@
# RUN: not lld-core %s 2> %t.err
# RUN: FileCheck < %t.err %s
#
# Test that unknown file attribute produces a readable error.
#
---
aardvark: true
atoms:
- name: entry
scope: hidden
...
# CHECK: error: Unknown file attribute
# CHECK: aardvark

View File

@ -0,0 +1,22 @@
# RUN: not lld-core %s 2> %t.err
# RUN: FileCheck < %t.err %s
#
# Test that unknown fixup attribute produces a readable error.
#
---
atoms:
- name: entry
scope: hidden
fixups:
- offset: 3
kind: 3
weasel: bar
addend: 100
...
# CHECK: error: Unknown fixup attribute
# CHECK: weasel

View File

@ -0,0 +1,27 @@
# RUN: not lld-core %s 2> %t.err
# RUN: FileCheck < %t.err %s
#
# Test that unbindable target name produces a readable error.
#
---
atoms:
- name: entry
scope: hidden
fixups:
- offset: 3
kind: 3
target: bar
- offset: 5
kind: 3
target: baz
- name: bar
definition: undefined
...
# CHECK: error: Fixup has target 'baz' which does not exist
# CHECK: baz