1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 10:32:48 +02:00

[FileCheck] Add support for hex alternate form in FileCheck

Add printf-style alternate form flag to prefix hex number with 0x when
present. This works on both empty numeric expression (e.g. variable
definition from input) and when matching a numeric expression. The
syntax is as follows:

[[#%#<precision specifier><format specifier>, ...]

where <precision specifier> and <format specifier> are optional and ...
can be a variable definition or not with an empty expression or not.

This feature was requested in https://reviews.llvm.org/D81144#2075532
for llvm/test/MC/ELF/gen-dwarf64.s

Reviewed By: jdenny

Differential Revision: https://reviews.llvm.org/D97845
This commit is contained in:
Thomas Preud'homme 2020-06-11 16:14:24 +01:00
parent 8a1cc679e3
commit 0911193c17
5 changed files with 183 additions and 69 deletions

View File

@ -773,8 +773,11 @@ The syntax to capture a numeric value is
* ``<NUMVAR>:`` is an optional definition of variable ``<NUMVAR>`` from the
captured value.
The syntax of ``<fmtspec>`` is: ``.<precision><conversion specifier>`` where:
The syntax of ``<fmtspec>`` is: ``#.<precision><conversion specifier>`` where:
* ``#`` is an optional flag available for hex values (see
``<conversion specifier>`` below) which requires the value matched to be
prefixed by ``0x``.
* ``.<precision>`` is an optional printf-style precision specifier in which
``<precision>`` indicates the minimum number of digits that the value matched
must have, expecting leading zeros if needed.

View File

@ -45,8 +45,12 @@ StringRef ExpressionFormat::toString() const {
}
Expected<std::string> ExpressionFormat::getWildcardRegex() const {
auto CreatePrecisionRegex = [this](StringRef S) {
return (S + Twine('{') + Twine(Precision) + "}").str();
StringRef AlternateFormPrefix = AlternateForm ? StringRef("0x") : StringRef();
auto CreatePrecisionRegex = [&](StringRef S) {
return (Twine(AlternateFormPrefix) + S + Twine('{') + Twine(Precision) +
"}")
.str();
};
switch (Value) {
@ -61,11 +65,11 @@ Expected<std::string> ExpressionFormat::getWildcardRegex() const {
case Kind::HexUpper:
if (Precision)
return CreatePrecisionRegex("([1-9A-F][0-9A-F]*)?[0-9A-F]");
return std::string("[0-9A-F]+");
return (Twine(AlternateFormPrefix) + Twine("[0-9A-F]+")).str();
case Kind::HexLower:
if (Precision)
return CreatePrecisionRegex("([1-9a-f][0-9a-f]*)?[0-9a-f]");
return std::string("[0-9a-f]+");
return (Twine(AlternateFormPrefix) + Twine("[0-9a-f]+")).str();
default:
return createStringError(std::errc::invalid_argument,
"trying to match value with invalid format");
@ -107,14 +111,17 @@ ExpressionFormat::getMatchingString(ExpressionValue IntegerValue) const {
"trying to match value with invalid format");
}
StringRef AlternateFormPrefix = AlternateForm ? StringRef("0x") : StringRef();
if (Precision > AbsoluteValueStr.size()) {
unsigned LeadingZeros = Precision - AbsoluteValueStr.size();
return (Twine(SignPrefix) + std::string(LeadingZeros, '0') +
AbsoluteValueStr)
return (Twine(SignPrefix) + Twine(AlternateFormPrefix) +
std::string(LeadingZeros, '0') + AbsoluteValueStr)
.str();
}
return (Twine(SignPrefix) + AbsoluteValueStr).str();
return (Twine(SignPrefix) + Twine(AlternateFormPrefix) + AbsoluteValueStr)
.str();
}
Expected<ExpressionValue>
@ -138,9 +145,15 @@ ExpressionFormat::valueFromStringRepr(StringRef StrVal,
bool Hex = Value == Kind::HexUpper || Value == Kind::HexLower;
uint64_t UnsignedValue;
bool MissingFormPrefix = AlternateForm && !StrVal.consume_front("0x");
if (StrVal.getAsInteger(Hex ? 16 : 10, UnsignedValue))
return ErrorDiagnostic::get(SM, StrVal, IntegerParseErrorStr);
// Error out for a missing prefix only now that we know we have an otherwise
// valid integer. For example, "-0x18" is reported above instead.
if (MissingFormPrefix)
return ErrorDiagnostic::get(SM, StrVal, "missing alternate form prefix");
return ExpressionValue(UnsignedValue);
}
@ -772,6 +785,10 @@ Expected<std::unique_ptr<Expression>> Pattern::parseNumericSubstitutionBlock(
SM, FormatExpr,
"invalid matching format specification in expression");
// Parse alternate form flag.
SMLoc AlternateFormFlagLoc = SMLoc::getFromPointer(FormatExpr.data());
bool AlternateForm = FormatExpr.consume_front("#");
// Parse precision.
if (FormatExpr.consume_front(".")) {
if (FormatExpr.consumeInteger(10, Precision))
@ -793,12 +810,12 @@ Expected<std::unique_ptr<Expression>> Pattern::parseNumericSubstitutionBlock(
ExpressionFormat(ExpressionFormat::Kind::Signed, Precision);
break;
case 'x':
ExplicitFormat =
ExpressionFormat(ExpressionFormat::Kind::HexLower, Precision);
ExplicitFormat = ExpressionFormat(ExpressionFormat::Kind::HexLower,
Precision, AlternateForm);
break;
case 'X':
ExplicitFormat =
ExpressionFormat(ExpressionFormat::Kind::HexUpper, Precision);
ExplicitFormat = ExpressionFormat(ExpressionFormat::Kind::HexUpper,
Precision, AlternateForm);
break;
default:
return ErrorDiagnostic::get(SM, FmtLoc,
@ -806,6 +823,12 @@ Expected<std::unique_ptr<Expression>> Pattern::parseNumericSubstitutionBlock(
}
}
if (AlternateForm && ExplicitFormat != ExpressionFormat::Kind::HexLower &&
ExplicitFormat != ExpressionFormat::Kind::HexUpper)
return ErrorDiagnostic::get(
SM, AlternateFormFlagLoc,
"alternate form only supported for hex values");
FormatExpr = FormatExpr.ltrim(SpaceChars);
if (!FormatExpr.empty())
return ErrorDiagnostic::get(

View File

@ -54,6 +54,8 @@ struct ExpressionFormat {
private:
Kind Value;
unsigned Precision = 0;
/// printf-like "alternate form" selected.
bool AlternateForm = false;
public:
/// Evaluates a format to true if it can be used in a match.
@ -63,7 +65,7 @@ public:
/// their kinds and precision are the same.
bool operator==(const ExpressionFormat &Other) const {
return Value != Kind::NoFormat && Value == Other.Value &&
Precision == Other.Precision;
Precision == Other.Precision && AlternateForm == Other.AlternateForm;
}
bool operator!=(const ExpressionFormat &Other) const {
@ -81,6 +83,8 @@ public:
explicit ExpressionFormat(Kind Value) : Value(Value), Precision(0){};
explicit ExpressionFormat(Kind Value, unsigned Precision)
: Value(Value), Precision(Precision){};
explicit ExpressionFormat(Kind Value, unsigned Precision, bool AlternateForm)
: Value(Value), Precision(Precision), AlternateForm(AlternateForm){};
/// \returns a wildcard regular expression string that matches any value in
/// the format represented by this instance and no other value, or an error

View File

@ -49,6 +49,37 @@ INVALID-FMT-SPEC-MSG2: numeric-expression.txt:[[#@LINE-4]]:37: error: invalid fo
INVALID-FMT-SPEC-MSG2-NEXT: {{I}}NVALID-FMT-SPEC2-NEXT: INVVAR2={{\[\[#%hhd,INVVAR2:\]\]}}
INVALID-FMT-SPEC-MSG2-NEXT: {{^}} ^{{$}}
; Numeric variable definition of hex value with 0x prefix.
DEF ALT FORM // CHECK-LABEL: DEF ALT FORM
0xf // CHECK-NEXT: {{^}}[[#%#x,PREFIXED_LHEX:]]
0xE // CHECK-NEXT: {{^}}[[#%#X,PREFIXED_UHEX:]]
; Invalid numeric variable definition of non-hex value with 0x prefix.
RUN: %ProtectFileCheckOutput \
RUN: not FileCheck --check-prefixes INVALID-ALT-FORM,INVALID-ALT-FORM1 --input-file %s %s 2>&1 \
RUN: | FileCheck --check-prefix INVALID-ALT-FORM-MSG1 --strict-whitespace %s
RUN: %ProtectFileCheckOutput \
RUN: not FileCheck --check-prefixes INVALID-ALT-FORM,INVALID-ALT-FORM2 --input-file %s %s 2>&1 \
RUN: | FileCheck --check-prefix INVALID-ALT-FORM-MSG2 --strict-whitespace %s
DEF INVALID ALT FORM
PREFIXED_DEC=0x3
INVALID-ALT-FORM-LABEL: DEF INVALID ALT FORM
INVALID-ALT-FORM1-NEXT: PREFIXED_DEC=[[#%#u,PREFIXED_UNSI:]]
INVALID-ALT-FORM2-NEXT: PREFIXED_DEC=[[#%#d,PREFIXED_SIGN:]]
INVALID-ALT-FORM-MSG1: numeric-expression.txt:[[#@LINE-2]]:42: error: alternate form only supported for hex values
INVALID-ALT-FORM-MSG1-NEXT: {{I}}NVALID-ALT-FORM1-NEXT: PREFIXED_DEC={{\[\[#%#u,PREFIXED_UNSI:\]\]}}
INVALID-ALT-FORM-MSG1-NEXT: {{^}} ^{{$}}
INVALID-ALT-FORM-MSG2: numeric-expression.txt:[[#@LINE-4]]:42: error: alternate form only supported for hex values
INVALID-ALT-FORM-MSG2-NEXT: {{I}}NVALID-ALT-FORM2-NEXT: PREFIXED_DEC={{\[\[#%#d,PREFIXED_SIGN:\]\]}}
INVALID-ALT-FORM-MSG2-NEXT: {{^}} ^{{$}}
; Numeric variable definition of hex value with missing 0x prefix.
RUN: FileCheck --check-prefix INVALID-HEX-PREFIX-DEF --input-file %s %s
FAIL DEF ALT FORM // INVALID-HEX-PREFIX-DEF-LABEL: FAIL DEF ALT FORM
INVALID_PREFIXED_LHEX: xf // INVALID-HEX-PREFIX-DEF-NOT: {{^}}INVALID_PREFIXED_LHEX: [[#%#x,INVALID_PREFIXED_LHEX:]]
INVALID_PREFIXED_UHEX: 0E // INVALID-HEX-PREFIX-DEF-NOT: {{^}}INVALID_PREFIXED_UHEX: [[#%#X,INVALID_PREFIXED_UHEX:]]
; Numeric variable definition with precision specifier.
DEF PREC FMT // CHECK-LABEL: DEF PREC FMT
00000022 // CHECK-NEXT: {{^}}[[#%.8,PADDED_UNSI:]]
@ -144,17 +175,21 @@ USE EXPL FMT IMPL MATCH SPC // CHECK-LABEL: USE EXPL FMT IMPL MATCH SPC
13 // CHECK-NEXT: {{^}}[[# %u , add (UNSI,2)]]
104 // CHECK-NEXT: {{^}}[[# %u , UNSI + sub( add (100 , UNSI+ 1 ), 20) +1 ]]
; Numeric expressions with explicit matching format, precision, and default
; matching rule using variables defined on other lines without spaces.
; Numeric expressions with explicit matching format, precision, form and
; default matching rule using variables defined on other lines without spaces.
USE EXPL FMT WITH PREC IMPL MATCH // CHECK-LABEL: USE EXPL FMT WITH PREC IMPL MATCH
11 // CHECK-NEXT: {{^}}[[#%.1u,UNSI]]
00000011 // CHECK-NEXT: {{^}}[[#%.8u,UNSI]]
1c // CHECK-NEXT: {{^}}[[#%.1x,LHEX+16]]
0000000c // CHECK-NEXT: {{^}}[[#%.8x,LHEX]]
1D // CHECK-NEXT: {{^}}[[#%.1X,UHEX+16]]
0000000D // CHECK-NEXT: {{^}}[[#%.8X,UHEX]]
-30 // CHECK-NEXT: {{^}}[[#%.1d,SIGN]]
-00000030 // CHECK-NEXT: {{^}}[[#%.8d,SIGN]]
11 // CHECK-NEXT: {{^}}[[#%.1u,UNSI]]
00000011 // CHECK-NEXT: {{^}}[[#%.8u,UNSI]]
1c // CHECK-NEXT: {{^}}[[#%.1x,LHEX+16]]
0x1c // CHECK-NEXT: {{^}}[[#%#.1x,LHEX+16]]
0000000c // CHECK-NEXT: {{^}}[[#%.8x,LHEX]]
0x0000000c // CHECK-NEXT: {{^}}[[#%#.8x,LHEX]]
1D // CHECK-NEXT: {{^}}[[#%.1X,UHEX+16]]
0x1D // CHECK-NEXT: {{^}}[[#%#.1X,UHEX+16]]
0000000D // CHECK-NEXT: {{^}}[[#%.8X,UHEX]]
0x0000000D // CHECK-NEXT: {{^}}[[#%#.8X,UHEX]]
-30 // CHECK-NEXT: {{^}}[[#%.1d,SIGN]]
-00000030 // CHECK-NEXT: {{^}}[[#%.8d,SIGN]]
; Numeric expressions with explicit matching format, precision and wrong
; padding, and default matching rule using variables defined on other lines

View File

@ -87,7 +87,8 @@ constexpr uint64_t AbsoluteMaxInt64 = static_cast<uint64_t>(MaxInt64);
struct ExpressionFormatParameterisedFixture
: public ::testing::TestWithParam<
std::pair<ExpressionFormat::Kind, unsigned>> {
std::tuple<ExpressionFormat::Kind, unsigned, bool>> {
bool AlternateForm;
unsigned Precision;
bool Signed;
bool AllowHex;
@ -108,12 +109,12 @@ struct ExpressionFormatParameterisedFixture
void SetUp() override {
ExpressionFormat::Kind Kind;
std::tie(Kind, Precision) = GetParam();
std::tie(Kind, Precision, AlternateForm) = GetParam();
AllowHex = Kind == ExpressionFormat::Kind::HexLower ||
Kind == ExpressionFormat::Kind::HexUpper;
AllowUpperHex = Kind == ExpressionFormat::Kind::HexUpper;
Signed = Kind == ExpressionFormat::Kind::Signed;
Format = ExpressionFormat(Kind, Precision);
Format = ExpressionFormat(Kind, Precision, AlternateForm);
if (!AllowHex) {
MaxUint64Str = std::to_string(MaxUint64);
@ -138,10 +139,13 @@ struct ExpressionFormatParameterisedFixture
void checkWildcardRegexMatch(StringRef Input,
unsigned TrailExtendTo = 0) const {
ASSERT_TRUE(TrailExtendTo == 0 || AllowHex);
SmallVector<StringRef, 4> Matches;
std::string ExtendedInput = Input.str();
if (TrailExtendTo > Input.size()) {
ExtendedInput.append(TrailExtendTo - Input.size(), Input[0]);
size_t PrefixSize = AlternateForm ? 2 : 0;
if (TrailExtendTo > Input.size() - PrefixSize) {
size_t ExtensionSize = PrefixSize + TrailExtendTo - Input.size();
ExtendedInput.append(ExtensionSize, Input[PrefixSize]);
}
ASSERT_TRUE(WildcardRegex.match(ExtendedInput, &Matches))
<< "Wildcard regex does not match " << ExtendedInput;
@ -152,9 +156,16 @@ struct ExpressionFormatParameterisedFixture
EXPECT_FALSE(WildcardRegex.match(Input));
}
std::string addBasePrefix(StringRef Num) const {
StringRef Prefix = AlternateForm ? "0x" : "";
return (Twine(Prefix) + Twine(Num)).str();
}
void checkWildcardRegexCharMatchFailure(StringRef Chars) const {
for (auto C : Chars)
EXPECT_FALSE(WildcardRegex.match(StringRef(&C, 1)));
for (auto C : Chars) {
std::string Str = addBasePrefix(StringRef(&C, 1));
EXPECT_FALSE(WildcardRegex.match(Str));
}
}
std::string padWithLeadingZeros(StringRef NumStr) const {
@ -207,10 +218,10 @@ struct ExpressionFormatParameterisedFixture
static_cast<uint64_t>(ExpectedVal));
}
void checkValueFromStringReprFailure(StringRef Str) {
StringRef OverflowErrorStr = "unable to represent numeric value";
void checkValueFromStringReprFailure(
StringRef Str, StringRef ErrorStr = "unable to represent numeric value") {
Expected<ExpressionValue> ResultValue = getValueFromStringReprFailure(Str);
expectDiagnosticError(OverflowErrorStr, ResultValue.takeError());
expectDiagnosticError(ErrorStr, ResultValue.takeError());
}
};
@ -224,9 +235,17 @@ TEST_P(ExpressionFormatParameterisedFixture, FormatGetWildcardRegex) {
// Does not match empty string.
checkWildcardRegexMatchFailure("");
// Matches all decimal digits and matches several of them.
// Matches all decimal digits, matches several of them and match 0x prefix
// if and only if AlternateForm is true.
StringRef LongNumber = "12345678901234567890";
checkWildcardRegexMatch(LongNumber);
StringRef PrefixedLongNumber = "0x12345678901234567890";
if (AlternateForm) {
checkWildcardRegexMatch(PrefixedLongNumber);
checkWildcardRegexMatchFailure(LongNumber);
} else {
checkWildcardRegexMatch(LongNumber);
checkWildcardRegexMatchFailure(PrefixedLongNumber);
}
// Matches negative digits.
LongNumber = "-12345678901234567890";
@ -236,8 +255,10 @@ TEST_P(ExpressionFormatParameterisedFixture, FormatGetWildcardRegex) {
checkWildcardRegexMatchFailure(LongNumber);
// Check non digits or digits with wrong casing are not matched.
std::string LongNumberStr;
if (AllowHex) {
checkWildcardRegexMatch(AcceptedHexOnlyDigits, 16);
LongNumberStr = addBasePrefix(AcceptedHexOnlyDigits);
checkWildcardRegexMatch(LongNumberStr, 16);
checkWildcardRegexCharMatchFailure(RefusedHexOnlyDigits);
}
checkWildcardRegexCharMatchFailure(FirstInvalidCharDigits);
@ -246,17 +267,23 @@ TEST_P(ExpressionFormatParameterisedFixture, FormatGetWildcardRegex) {
// precision.
LongNumber = "01234567890123456789";
if (Precision) {
checkWildcardRegexMatch(LongNumber.take_front(Precision));
checkWildcardRegexMatchFailure(LongNumber.take_front(Precision - 1));
if (Precision < LongNumber.size())
checkWildcardRegexMatchFailure(LongNumber.take_front(Precision + 1));
} else
checkWildcardRegexMatch(LongNumber);
LongNumberStr = addBasePrefix(LongNumber.take_front(Precision));
checkWildcardRegexMatch(LongNumberStr);
LongNumberStr = addBasePrefix(LongNumber.take_front(Precision - 1));
checkWildcardRegexMatchFailure(LongNumberStr);
if (Precision < LongNumber.size()) {
LongNumberStr = addBasePrefix(LongNumber.take_front(Precision + 1));
checkWildcardRegexMatchFailure(LongNumberStr);
}
} else {
LongNumberStr = addBasePrefix(LongNumber);
checkWildcardRegexMatch(LongNumberStr);
}
}
TEST_P(ExpressionFormatParameterisedFixture, FormatGetMatchingString) {
checkMatchingString(0, padWithLeadingZeros("0"));
checkMatchingString(9, padWithLeadingZeros("9"));
checkMatchingString(0, addBasePrefix(padWithLeadingZeros("0")));
checkMatchingString(9, addBasePrefix(padWithLeadingZeros("9")));
if (Signed) {
checkMatchingString(-5, padWithLeadingZeros("-5"));
@ -265,33 +292,38 @@ TEST_P(ExpressionFormatParameterisedFixture, FormatGetMatchingString) {
checkMatchingString(MinInt64, padWithLeadingZeros(MinInt64Str));
} else {
checkMatchingStringFailure(-5);
checkMatchingString(MaxUint64, padWithLeadingZeros(MaxUint64Str));
checkMatchingString(MaxInt64, padWithLeadingZeros(MaxInt64Str));
checkMatchingString(MaxUint64,
addBasePrefix(padWithLeadingZeros(MaxUint64Str)));
checkMatchingString(MaxInt64,
addBasePrefix(padWithLeadingZeros(MaxInt64Str)));
checkMatchingStringFailure(MinInt64);
}
checkMatchingString(10, padWithLeadingZeros(TenStr));
checkMatchingString(15, padWithLeadingZeros(FifteenStr));
checkMatchingString(10, addBasePrefix(padWithLeadingZeros(TenStr)));
checkMatchingString(15, addBasePrefix(padWithLeadingZeros(FifteenStr)));
}
TEST_P(ExpressionFormatParameterisedFixture, FormatValueFromStringRepr) {
checkValueFromStringRepr("0", 0);
checkValueFromStringRepr("9", 9);
checkValueFromStringRepr(addBasePrefix("0"), 0);
checkValueFromStringRepr(addBasePrefix("9"), 9);
if (Signed) {
checkValueFromStringRepr("-5", -5);
checkValueFromStringReprFailure(MaxUint64Str);
} else {
checkValueFromStringReprFailure("-5");
checkValueFromStringRepr(MaxUint64Str, MaxUint64);
checkValueFromStringReprFailure("-" + addBasePrefix("5"));
checkValueFromStringRepr(addBasePrefix(MaxUint64Str), MaxUint64);
}
checkValueFromStringRepr(TenStr, 10);
checkValueFromStringRepr(FifteenStr, 15);
checkValueFromStringRepr(addBasePrefix(TenStr), 10);
checkValueFromStringRepr(addBasePrefix(FifteenStr), 15);
// Wrong casing is not tested because valueFromStringRepr() relies on
// StringRef's getAsInteger() which does not allow to restrict casing.
checkValueFromStringReprFailure("G");
checkValueFromStringReprFailure(addBasePrefix("G"));
if (AlternateForm)
checkValueFromStringReprFailure("9", "missing alternate form prefix");
}
TEST_P(ExpressionFormatParameterisedFixture, FormatBoolOperator) {
@ -300,23 +332,30 @@ TEST_P(ExpressionFormatParameterisedFixture, FormatBoolOperator) {
INSTANTIATE_TEST_CASE_P(
AllowedExplicitExpressionFormat, ExpressionFormatParameterisedFixture,
::testing::Values(std::make_pair(ExpressionFormat::Kind::Unsigned, 0),
std::make_pair(ExpressionFormat::Kind::Signed, 0),
std::make_pair(ExpressionFormat::Kind::HexLower, 0),
std::make_pair(ExpressionFormat::Kind::HexUpper, 0),
::testing::Values(
std::make_tuple(ExpressionFormat::Kind::Unsigned, 0, false),
std::make_tuple(ExpressionFormat::Kind::Signed, 0, false),
std::make_tuple(ExpressionFormat::Kind::HexLower, 0, false),
std::make_tuple(ExpressionFormat::Kind::HexLower, 0, true),
std::make_tuple(ExpressionFormat::Kind::HexUpper, 0, false),
std::make_tuple(ExpressionFormat::Kind::HexUpper, 0, true),
std::make_pair(ExpressionFormat::Kind::Unsigned, 1),
std::make_pair(ExpressionFormat::Kind::Signed, 1),
std::make_pair(ExpressionFormat::Kind::HexLower, 1),
std::make_pair(ExpressionFormat::Kind::HexUpper, 1),
std::make_tuple(ExpressionFormat::Kind::Unsigned, 1, false),
std::make_tuple(ExpressionFormat::Kind::Signed, 1, false),
std::make_tuple(ExpressionFormat::Kind::HexLower, 1, false),
std::make_tuple(ExpressionFormat::Kind::HexLower, 1, true),
std::make_tuple(ExpressionFormat::Kind::HexUpper, 1, false),
std::make_tuple(ExpressionFormat::Kind::HexUpper, 1, true),
std::make_pair(ExpressionFormat::Kind::Unsigned, 16),
std::make_pair(ExpressionFormat::Kind::Signed, 16),
std::make_pair(ExpressionFormat::Kind::HexLower, 16),
std::make_pair(ExpressionFormat::Kind::HexUpper, 16),
std::make_tuple(ExpressionFormat::Kind::Unsigned, 16, false),
std::make_tuple(ExpressionFormat::Kind::Signed, 16, false),
std::make_tuple(ExpressionFormat::Kind::HexLower, 16, false),
std::make_tuple(ExpressionFormat::Kind::HexLower, 16, true),
std::make_tuple(ExpressionFormat::Kind::HexUpper, 16, false),
std::make_tuple(ExpressionFormat::Kind::HexUpper, 16, true),
std::make_pair(ExpressionFormat::Kind::Unsigned, 20),
std::make_pair(ExpressionFormat::Kind::Signed, 20)), );
std::make_tuple(ExpressionFormat::Kind::Unsigned, 20, false),
std::make_tuple(ExpressionFormat::Kind::Signed, 20, false)), );
TEST_F(FileCheckTest, NoFormatProperties) {
ExpressionFormat NoFormat(ExpressionFormat::Kind::NoFormat);
@ -1043,6 +1082,16 @@ TEST_F(FileCheckTest, ParseNumericSubstitutionBlock) {
EXPECT_FALSE(Tester.parsePattern("[[#%.8X, PADDED_ADDR:]]"));
EXPECT_FALSE(Tester.parsePattern("[[#%.8, PADDED_NUM:]]"));
// Acceptable variable definition in alternate form.
EXPECT_THAT_EXPECTED(Tester.parseSubst("%#x, PREFIXED_ADDR:"), Succeeded());
EXPECT_THAT_EXPECTED(Tester.parseSubst("%#X, PREFIXED_ADDR:"), Succeeded());
// Acceptable variable definition in alternate form.
expectDiagnosticError("alternate form only supported for hex values",
Tester.parseSubst("%#u, PREFIXED_UNSI:").takeError());
expectDiagnosticError("alternate form only supported for hex values",
Tester.parseSubst("%#d, PREFIXED_UNSI:").takeError());
// Acceptable variable definition from a numeric expression.
EXPECT_THAT_EXPECTED(Tester.parseSubst("FOOBAR: FOO+1"), Succeeded());