[llvm] f9e2a62 - [FileCheck] Add support for hex alternate form in FileCheck

Thomas Preud'homme via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 12 10:14:13 PST 2021


Author: Thomas Preud'homme
Date: 2021-03-12T18:14:17Z
New Revision: f9e2a62cc594c96194908a3ac4804caa07f86ba6

URL: https://github.com/llvm/llvm-project/commit/f9e2a62cc594c96194908a3ac4804caa07f86ba6
DIFF: https://github.com/llvm/llvm-project/commit/f9e2a62cc594c96194908a3ac4804caa07f86ba6.diff

LOG: [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

Added: 
    

Modified: 
    llvm/docs/CommandGuide/FileCheck.rst
    llvm/lib/FileCheck/FileCheck.cpp
    llvm/lib/FileCheck/FileCheckImpl.h
    llvm/test/FileCheck/numeric-expression.txt
    llvm/unittests/FileCheck/FileCheckTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/docs/CommandGuide/FileCheck.rst b/llvm/docs/CommandGuide/FileCheck.rst
index 398cce1f8a8c..a4e3e069a05a 100644
--- a/llvm/docs/CommandGuide/FileCheck.rst
+++ b/llvm/docs/CommandGuide/FileCheck.rst
@@ -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.

diff  --git a/llvm/lib/FileCheck/FileCheck.cpp b/llvm/lib/FileCheck/FileCheck.cpp
index 9a4c86682739..462f50788663 100644
--- a/llvm/lib/FileCheck/FileCheck.cpp
+++ b/llvm/lib/FileCheck/FileCheck.cpp
@@ -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(

diff  --git a/llvm/lib/FileCheck/FileCheckImpl.h b/llvm/lib/FileCheck/FileCheckImpl.h
index 05b2a529002f..1966b0e7831c 100644
--- a/llvm/lib/FileCheck/FileCheckImpl.h
+++ b/llvm/lib/FileCheck/FileCheckImpl.h
@@ -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 @@ struct ExpressionFormat {
   /// 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 @@ struct ExpressionFormat {
   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

diff  --git a/llvm/test/FileCheck/numeric-expression.txt b/llvm/test/FileCheck/numeric-expression.txt
index b55cc16c6e63..0a7f2f3d2255 100644
--- a/llvm/test/FileCheck/numeric-expression.txt
+++ b/llvm/test/FileCheck/numeric-expression.txt
@@ -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

diff  --git a/llvm/unittests/FileCheck/FileCheckTest.cpp b/llvm/unittests/FileCheck/FileCheckTest.cpp
index c5eaa5fb04d2..3ed514339439 100644
--- a/llvm/unittests/FileCheck/FileCheckTest.cpp
+++ b/llvm/unittests/FileCheck/FileCheckTest.cpp
@@ -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),
-
-                      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_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_pair(ExpressionFormat::Kind::Unsigned, 20),
-                      std::make_pair(ExpressionFormat::Kind::Signed, 20)), );
+    ::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_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_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_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());
 


        


More information about the llvm-commits mailing list