15ffd940aSRaphael Isemann //===- llvm/unittest/FileCheck/FileCheckTest.cpp - FileCheck tests --------===//
25ffd940aSRaphael Isemann //
35ffd940aSRaphael Isemann // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd940aSRaphael Isemann // See https://llvm.org/LICENSE.txt for license information.
55ffd940aSRaphael Isemann // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd940aSRaphael Isemann //
75ffd940aSRaphael Isemann //===----------------------------------------------------------------------===//
85ffd940aSRaphael Isemann 
95ffd940aSRaphael Isemann #include "llvm/FileCheck/FileCheck.h"
105ffd940aSRaphael Isemann #include "../lib/FileCheck/FileCheckImpl.h"
115ffd940aSRaphael Isemann #include "llvm/Support/Regex.h"
125ffd940aSRaphael Isemann #include "llvm/Testing/Support/Error.h"
135ffd940aSRaphael Isemann #include "gtest/gtest.h"
145ffd940aSRaphael Isemann #include <tuple>
155ffd940aSRaphael Isemann #include <unordered_set>
165ffd940aSRaphael Isemann 
175ffd940aSRaphael Isemann using namespace llvm;
185ffd940aSRaphael Isemann 
195ffd940aSRaphael Isemann namespace {
205ffd940aSRaphael Isemann 
215ffd940aSRaphael Isemann class FileCheckTest : public ::testing::Test {};
225ffd940aSRaphael Isemann 
bufferize(SourceMgr & SM,StringRef Str)235ffd940aSRaphael Isemann static StringRef bufferize(SourceMgr &SM, StringRef Str) {
245ffd940aSRaphael Isemann   std::unique_ptr<MemoryBuffer> Buffer =
255ffd940aSRaphael Isemann       MemoryBuffer::getMemBufferCopy(Str, "TestBuffer");
265ffd940aSRaphael Isemann   StringRef StrBufferRef = Buffer->getBuffer();
275ffd940aSRaphael Isemann   SM.AddNewSourceBuffer(std::move(Buffer), SMLoc());
285ffd940aSRaphael Isemann   return StrBufferRef;
295ffd940aSRaphael Isemann }
305ffd940aSRaphael Isemann 
toString(const std::unordered_set<std::string> & Set)315ffd940aSRaphael Isemann static std::string toString(const std::unordered_set<std::string> &Set) {
325ffd940aSRaphael Isemann   bool First = true;
335ffd940aSRaphael Isemann   std::string Str;
345ffd940aSRaphael Isemann   for (StringRef S : Set) {
355ffd940aSRaphael Isemann     Str += Twine(First ? "{" + S : ", " + S).str();
365ffd940aSRaphael Isemann     First = false;
375ffd940aSRaphael Isemann   }
385ffd940aSRaphael Isemann   Str += '}';
395ffd940aSRaphael Isemann   return Str;
405ffd940aSRaphael Isemann }
415ffd940aSRaphael Isemann 
425ffd940aSRaphael Isemann template <typename ErrorT>
expectSameErrors(std::unordered_set<std::string> ExpectedMsgs,Error Err)435ffd940aSRaphael Isemann static void expectSameErrors(std::unordered_set<std::string> ExpectedMsgs,
445ffd940aSRaphael Isemann                              Error Err) {
455ffd940aSRaphael Isemann   auto AnyErrorMsgMatch = [&ExpectedMsgs](std::string &&ErrorMsg) -> bool {
465ffd940aSRaphael Isemann     for (auto ExpectedMsgItr = ExpectedMsgs.begin(),
475ffd940aSRaphael Isemann               ExpectedMsgEnd = ExpectedMsgs.end();
485ffd940aSRaphael Isemann          ExpectedMsgItr != ExpectedMsgEnd; ++ExpectedMsgItr) {
495ffd940aSRaphael Isemann       if (ErrorMsg.find(*ExpectedMsgItr) != std::string::npos) {
505ffd940aSRaphael Isemann         ExpectedMsgs.erase(ExpectedMsgItr);
515ffd940aSRaphael Isemann         return true;
525ffd940aSRaphael Isemann       }
535ffd940aSRaphael Isemann     }
545ffd940aSRaphael Isemann     return false;
555ffd940aSRaphael Isemann   };
565ffd940aSRaphael Isemann 
575ffd940aSRaphael Isemann   Error RemainingErrors = std::move(Err);
585ffd940aSRaphael Isemann   do {
595ffd940aSRaphael Isemann     RemainingErrors =
605ffd940aSRaphael Isemann         handleErrors(std::move(RemainingErrors), [&](const ErrorT &E) {
615ffd940aSRaphael Isemann           EXPECT_TRUE(AnyErrorMsgMatch(E.message()))
625ffd940aSRaphael Isemann               << "Unexpected error message:" << std::endl
635ffd940aSRaphael Isemann               << E.message();
645ffd940aSRaphael Isemann         });
655ffd940aSRaphael Isemann   } while (RemainingErrors && !ExpectedMsgs.empty());
665ffd940aSRaphael Isemann   EXPECT_THAT_ERROR(std::move(RemainingErrors), Succeeded());
675ffd940aSRaphael Isemann   EXPECT_TRUE(ExpectedMsgs.empty())
685ffd940aSRaphael Isemann       << "Error message(s) not found:" << std::endl
695ffd940aSRaphael Isemann       << toString(ExpectedMsgs);
705ffd940aSRaphael Isemann }
715ffd940aSRaphael Isemann 
725ffd940aSRaphael Isemann template <typename ErrorT>
expectError(StringRef ExpectedMsg,Error Err)735ffd940aSRaphael Isemann static void expectError(StringRef ExpectedMsg, Error Err) {
745ffd940aSRaphael Isemann   expectSameErrors<ErrorT>({ExpectedMsg.str()}, std::move(Err));
755ffd940aSRaphael Isemann }
765ffd940aSRaphael Isemann 
expectDiagnosticError(StringRef ExpectedMsg,Error Err)775ffd940aSRaphael Isemann static void expectDiagnosticError(StringRef ExpectedMsg, Error Err) {
785ffd940aSRaphael Isemann   expectError<ErrorDiagnostic>(ExpectedMsg, std::move(Err));
795ffd940aSRaphael Isemann }
805ffd940aSRaphael Isemann 
815ffd940aSRaphael Isemann constexpr uint64_t MaxUint64 = std::numeric_limits<uint64_t>::max();
825ffd940aSRaphael Isemann constexpr int64_t MaxInt64 = std::numeric_limits<int64_t>::max();
835ffd940aSRaphael Isemann constexpr int64_t MinInt64 = std::numeric_limits<int64_t>::min();
845ffd940aSRaphael Isemann constexpr uint64_t AbsoluteMinInt64 =
855ffd940aSRaphael Isemann     static_cast<uint64_t>(-(MinInt64 + 1)) + 1;
865ffd940aSRaphael Isemann constexpr uint64_t AbsoluteMaxInt64 = static_cast<uint64_t>(MaxInt64);
875ffd940aSRaphael Isemann 
885ffd940aSRaphael Isemann struct ExpressionFormatParameterisedFixture
895ffd940aSRaphael Isemann     : public ::testing::TestWithParam<
90f9e2a62cSThomas Preud'homme           std::tuple<ExpressionFormat::Kind, unsigned, bool>> {
91f9e2a62cSThomas Preud'homme   bool AlternateForm;
925ffd940aSRaphael Isemann   unsigned Precision;
935ffd940aSRaphael Isemann   bool Signed;
945ffd940aSRaphael Isemann   bool AllowHex;
955ffd940aSRaphael Isemann   bool AllowUpperHex;
965ffd940aSRaphael Isemann   ExpressionFormat Format;
975ffd940aSRaphael Isemann   Regex WildcardRegex;
985ffd940aSRaphael Isemann 
995ffd940aSRaphael Isemann   StringRef TenStr;
1005ffd940aSRaphael Isemann   StringRef FifteenStr;
1015ffd940aSRaphael Isemann   std::string MaxUint64Str;
1025ffd940aSRaphael Isemann   std::string MaxInt64Str;
1035ffd940aSRaphael Isemann   std::string MinInt64Str;
1045ffd940aSRaphael Isemann   StringRef FirstInvalidCharDigits;
1055ffd940aSRaphael Isemann   StringRef AcceptedHexOnlyDigits;
1065ffd940aSRaphael Isemann   StringRef RefusedHexOnlyDigits;
1075ffd940aSRaphael Isemann 
1085ffd940aSRaphael Isemann   SourceMgr SM;
1095ffd940aSRaphael Isemann 
SetUp__anon85dcea870111::ExpressionFormatParameterisedFixture1105ffd940aSRaphael Isemann   void SetUp() override {
1115ffd940aSRaphael Isemann     ExpressionFormat::Kind Kind;
112f9e2a62cSThomas Preud'homme     std::tie(Kind, Precision, AlternateForm) = GetParam();
1135ffd940aSRaphael Isemann     AllowHex = Kind == ExpressionFormat::Kind::HexLower ||
1145ffd940aSRaphael Isemann                Kind == ExpressionFormat::Kind::HexUpper;
1155ffd940aSRaphael Isemann     AllowUpperHex = Kind == ExpressionFormat::Kind::HexUpper;
1165ffd940aSRaphael Isemann     Signed = Kind == ExpressionFormat::Kind::Signed;
117f9e2a62cSThomas Preud'homme     Format = ExpressionFormat(Kind, Precision, AlternateForm);
1185ffd940aSRaphael Isemann 
1195ffd940aSRaphael Isemann     if (!AllowHex) {
1205ffd940aSRaphael Isemann       MaxUint64Str = std::to_string(MaxUint64);
1215ffd940aSRaphael Isemann       MaxInt64Str = std::to_string(MaxInt64);
1225ffd940aSRaphael Isemann       MinInt64Str = std::to_string(MinInt64);
1235ffd940aSRaphael Isemann       TenStr = "10";
1245ffd940aSRaphael Isemann       FifteenStr = "15";
1255ffd940aSRaphael Isemann       FirstInvalidCharDigits = "aA";
1265ffd940aSRaphael Isemann       AcceptedHexOnlyDigits = RefusedHexOnlyDigits = "N/A";
1275ffd940aSRaphael Isemann       return;
1285ffd940aSRaphael Isemann     }
1295ffd940aSRaphael Isemann 
1305ffd940aSRaphael Isemann     MaxUint64Str = AllowUpperHex ? "FFFFFFFFFFFFFFFF" : "ffffffffffffffff";
1315ffd940aSRaphael Isemann     MaxInt64Str = AllowUpperHex ? "7FFFFFFFFFFFFFFF" : "7fffffffffffffff";
1325ffd940aSRaphael Isemann     TenStr = AllowUpperHex ? "A" : "a";
1335ffd940aSRaphael Isemann     FifteenStr = AllowUpperHex ? "F" : "f";
1345ffd940aSRaphael Isemann     AcceptedHexOnlyDigits = AllowUpperHex ? "ABCDEF" : "abcdef";
1355ffd940aSRaphael Isemann     RefusedHexOnlyDigits = AllowUpperHex ? "abcdef" : "ABCDEF";
1365ffd940aSRaphael Isemann     MinInt64Str = "N/A";
1375ffd940aSRaphael Isemann     FirstInvalidCharDigits = "gG";
1385ffd940aSRaphael Isemann   }
1395ffd940aSRaphael Isemann 
checkWildcardRegexMatch__anon85dcea870111::ExpressionFormatParameterisedFixture1405ffd940aSRaphael Isemann   void checkWildcardRegexMatch(StringRef Input,
1415ffd940aSRaphael Isemann                                unsigned TrailExtendTo = 0) const {
142f9e2a62cSThomas Preud'homme     ASSERT_TRUE(TrailExtendTo == 0 || AllowHex);
1435ffd940aSRaphael Isemann     SmallVector<StringRef, 4> Matches;
1445ffd940aSRaphael Isemann     std::string ExtendedInput = Input.str();
145f9e2a62cSThomas Preud'homme     size_t PrefixSize = AlternateForm ? 2 : 0;
146f9e2a62cSThomas Preud'homme     if (TrailExtendTo > Input.size() - PrefixSize) {
147f9e2a62cSThomas Preud'homme       size_t ExtensionSize = PrefixSize + TrailExtendTo - Input.size();
148f9e2a62cSThomas Preud'homme       ExtendedInput.append(ExtensionSize, Input[PrefixSize]);
1495ffd940aSRaphael Isemann     }
1505ffd940aSRaphael Isemann     ASSERT_TRUE(WildcardRegex.match(ExtendedInput, &Matches))
1515ffd940aSRaphael Isemann         << "Wildcard regex does not match " << ExtendedInput;
1525ffd940aSRaphael Isemann     EXPECT_EQ(Matches[0], ExtendedInput);
1535ffd940aSRaphael Isemann   }
1545ffd940aSRaphael Isemann 
checkWildcardRegexMatchFailure__anon85dcea870111::ExpressionFormatParameterisedFixture1555ffd940aSRaphael Isemann   void checkWildcardRegexMatchFailure(StringRef Input) const {
1565ffd940aSRaphael Isemann     EXPECT_FALSE(WildcardRegex.match(Input));
1575ffd940aSRaphael Isemann   }
1585ffd940aSRaphael Isemann 
addBasePrefix__anon85dcea870111::ExpressionFormatParameterisedFixture159f9e2a62cSThomas Preud'homme   std::string addBasePrefix(StringRef Num) const {
160f9e2a62cSThomas Preud'homme     StringRef Prefix = AlternateForm ? "0x" : "";
161f9e2a62cSThomas Preud'homme     return (Twine(Prefix) + Twine(Num)).str();
162f9e2a62cSThomas Preud'homme   }
163f9e2a62cSThomas Preud'homme 
checkPerCharWildcardRegexMatchFailure__anon85dcea870111::ExpressionFormatParameterisedFixture1645ca168b0SThomas Preud'homme   void checkPerCharWildcardRegexMatchFailure(StringRef Chars) const {
165f9e2a62cSThomas Preud'homme     for (auto C : Chars) {
166f9e2a62cSThomas Preud'homme       std::string Str = addBasePrefix(StringRef(&C, 1));
167f9e2a62cSThomas Preud'homme       EXPECT_FALSE(WildcardRegex.match(Str));
168f9e2a62cSThomas Preud'homme     }
1695ffd940aSRaphael Isemann   }
1705ffd940aSRaphael Isemann 
padWithLeadingZeros__anon85dcea870111::ExpressionFormatParameterisedFixture1715ffd940aSRaphael Isemann   std::string padWithLeadingZeros(StringRef NumStr) const {
1725ffd940aSRaphael Isemann     bool Negative = NumStr.startswith("-");
1735ffd940aSRaphael Isemann     if (NumStr.size() - unsigned(Negative) >= Precision)
1745ffd940aSRaphael Isemann       return NumStr.str();
1755ffd940aSRaphael Isemann 
1765ffd940aSRaphael Isemann     std::string PaddedStr;
1775ffd940aSRaphael Isemann     if (Negative) {
1785ffd940aSRaphael Isemann       PaddedStr = "-";
1795ffd940aSRaphael Isemann       NumStr = NumStr.drop_front();
1805ffd940aSRaphael Isemann     }
1815ffd940aSRaphael Isemann     PaddedStr.append(Precision - NumStr.size(), '0');
1825ffd940aSRaphael Isemann     PaddedStr.append(NumStr.str());
1835ffd940aSRaphael Isemann     return PaddedStr;
1845ffd940aSRaphael Isemann   }
1855ffd940aSRaphael Isemann 
checkMatchingString__anon85dcea870111::ExpressionFormatParameterisedFixture1865ffd940aSRaphael Isemann   template <class T> void checkMatchingString(T Val, StringRef ExpectedStr) {
1875ffd940aSRaphael Isemann     Expected<std::string> MatchingString =
1885ffd940aSRaphael Isemann         Format.getMatchingString(ExpressionValue(Val));
1895ffd940aSRaphael Isemann     ASSERT_THAT_EXPECTED(MatchingString, Succeeded())
1905ffd940aSRaphael Isemann         << "No matching string for " << Val;
1915ffd940aSRaphael Isemann     EXPECT_EQ(*MatchingString, ExpectedStr);
1925ffd940aSRaphael Isemann   }
1935ffd940aSRaphael Isemann 
checkMatchingStringFailure__anon85dcea870111::ExpressionFormatParameterisedFixture1945ffd940aSRaphael Isemann   template <class T> void checkMatchingStringFailure(T Val) {
1955ffd940aSRaphael Isemann     Expected<std::string> MatchingString =
1965ffd940aSRaphael Isemann         Format.getMatchingString(ExpressionValue(Val));
1975ffd940aSRaphael Isemann     // Error message tested in ExpressionValue unit tests.
1985ffd940aSRaphael Isemann     EXPECT_THAT_EXPECTED(MatchingString, Failed());
1995ffd940aSRaphael Isemann   }
2005ffd940aSRaphael Isemann 
getValueFromStringReprFailure__anon85dcea870111::ExpressionFormatParameterisedFixture2015ffd940aSRaphael Isemann   Expected<ExpressionValue> getValueFromStringReprFailure(StringRef Str) {
2025ffd940aSRaphael Isemann     StringRef BufferizedStr = bufferize(SM, Str);
2035ffd940aSRaphael Isemann     return Format.valueFromStringRepr(BufferizedStr, SM);
2045ffd940aSRaphael Isemann   }
2055ffd940aSRaphael Isemann 
2065ffd940aSRaphael Isemann   template <class T>
checkValueFromStringRepr__anon85dcea870111::ExpressionFormatParameterisedFixture2075ffd940aSRaphael Isemann   void checkValueFromStringRepr(StringRef Str, T ExpectedVal) {
2085ffd940aSRaphael Isemann     Expected<ExpressionValue> ResultValue = getValueFromStringReprFailure(Str);
2095ffd940aSRaphael Isemann     ASSERT_THAT_EXPECTED(ResultValue, Succeeded())
2105ffd940aSRaphael Isemann         << "Failed to get value from " << Str;
2115ffd940aSRaphael Isemann     ASSERT_EQ(ResultValue->isNegative(), ExpectedVal < 0)
2125ffd940aSRaphael Isemann         << "Value for " << Str << " is not " << ExpectedVal;
2135ffd940aSRaphael Isemann     if (ResultValue->isNegative())
2145ffd940aSRaphael Isemann       EXPECT_EQ(cantFail(ResultValue->getSignedValue()),
2155ffd940aSRaphael Isemann                 static_cast<int64_t>(ExpectedVal));
2165ffd940aSRaphael Isemann     else
2175ffd940aSRaphael Isemann       EXPECT_EQ(cantFail(ResultValue->getUnsignedValue()),
2185ffd940aSRaphael Isemann                 static_cast<uint64_t>(ExpectedVal));
2195ffd940aSRaphael Isemann   }
2205ffd940aSRaphael Isemann 
checkValueFromStringReprFailure__anon85dcea870111::ExpressionFormatParameterisedFixture221f9e2a62cSThomas Preud'homme   void checkValueFromStringReprFailure(
222f9e2a62cSThomas Preud'homme       StringRef Str, StringRef ErrorStr = "unable to represent numeric value") {
2235ffd940aSRaphael Isemann     Expected<ExpressionValue> ResultValue = getValueFromStringReprFailure(Str);
224f9e2a62cSThomas Preud'homme     expectDiagnosticError(ErrorStr, ResultValue.takeError());
2255ffd940aSRaphael Isemann   }
2265ffd940aSRaphael Isemann };
2275ffd940aSRaphael Isemann 
TEST_P(ExpressionFormatParameterisedFixture,FormatGetWildcardRegex)2285ffd940aSRaphael Isemann TEST_P(ExpressionFormatParameterisedFixture, FormatGetWildcardRegex) {
2295ffd940aSRaphael Isemann   // Wildcard regex is valid.
2305ffd940aSRaphael Isemann   Expected<std::string> WildcardPattern = Format.getWildcardRegex();
2315ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(WildcardPattern, Succeeded());
2325ffd940aSRaphael Isemann   WildcardRegex = Regex((Twine("^") + *WildcardPattern + "$").str());
2335ffd940aSRaphael Isemann   ASSERT_TRUE(WildcardRegex.isValid());
2345ffd940aSRaphael Isemann 
2355ffd940aSRaphael Isemann   // Does not match empty string.
2365ffd940aSRaphael Isemann   checkWildcardRegexMatchFailure("");
2375ffd940aSRaphael Isemann 
238f9e2a62cSThomas Preud'homme   // Matches all decimal digits, matches several of them and match 0x prefix
239f9e2a62cSThomas Preud'homme   // if and only if AlternateForm is true.
2405ffd940aSRaphael Isemann   StringRef LongNumber = "12345678901234567890";
241f9e2a62cSThomas Preud'homme   StringRef PrefixedLongNumber = "0x12345678901234567890";
242f9e2a62cSThomas Preud'homme   if (AlternateForm) {
243f9e2a62cSThomas Preud'homme     checkWildcardRegexMatch(PrefixedLongNumber);
244f9e2a62cSThomas Preud'homme     checkWildcardRegexMatchFailure(LongNumber);
245f9e2a62cSThomas Preud'homme   } else {
2465ffd940aSRaphael Isemann     checkWildcardRegexMatch(LongNumber);
247f9e2a62cSThomas Preud'homme     checkWildcardRegexMatchFailure(PrefixedLongNumber);
248f9e2a62cSThomas Preud'homme   }
2495ffd940aSRaphael Isemann 
2505ffd940aSRaphael Isemann   // Matches negative digits.
2515ffd940aSRaphael Isemann   LongNumber = "-12345678901234567890";
2525ffd940aSRaphael Isemann   if (Signed)
2535ffd940aSRaphael Isemann     checkWildcardRegexMatch(LongNumber);
2545ffd940aSRaphael Isemann   else
2555ffd940aSRaphael Isemann     checkWildcardRegexMatchFailure(LongNumber);
2565ffd940aSRaphael Isemann 
2575ffd940aSRaphael Isemann   // Check non digits or digits with wrong casing are not matched.
258f9e2a62cSThomas Preud'homme   std::string LongNumberStr;
2595ffd940aSRaphael Isemann   if (AllowHex) {
260f9e2a62cSThomas Preud'homme     LongNumberStr = addBasePrefix(AcceptedHexOnlyDigits);
261f9e2a62cSThomas Preud'homme     checkWildcardRegexMatch(LongNumberStr, 16);
2625ca168b0SThomas Preud'homme     checkPerCharWildcardRegexMatchFailure(RefusedHexOnlyDigits);
2635ffd940aSRaphael Isemann   }
2645ca168b0SThomas Preud'homme   checkPerCharWildcardRegexMatchFailure(FirstInvalidCharDigits);
2655ffd940aSRaphael Isemann 
2665ffd940aSRaphael Isemann   // Check leading zeros are only accepted if number of digits is less than the
2675ffd940aSRaphael Isemann   // precision.
2685ffd940aSRaphael Isemann   LongNumber = "01234567890123456789";
2695ffd940aSRaphael Isemann   if (Precision) {
270f9e2a62cSThomas Preud'homme     LongNumberStr = addBasePrefix(LongNumber.take_front(Precision));
271f9e2a62cSThomas Preud'homme     checkWildcardRegexMatch(LongNumberStr);
272f9e2a62cSThomas Preud'homme     LongNumberStr = addBasePrefix(LongNumber.take_front(Precision - 1));
273f9e2a62cSThomas Preud'homme     checkWildcardRegexMatchFailure(LongNumberStr);
274f9e2a62cSThomas Preud'homme     if (Precision < LongNumber.size()) {
275f9e2a62cSThomas Preud'homme       LongNumberStr = addBasePrefix(LongNumber.take_front(Precision + 1));
276f9e2a62cSThomas Preud'homme       checkWildcardRegexMatchFailure(LongNumberStr);
277f9e2a62cSThomas Preud'homme     }
278f9e2a62cSThomas Preud'homme   } else {
279f9e2a62cSThomas Preud'homme     LongNumberStr = addBasePrefix(LongNumber);
280f9e2a62cSThomas Preud'homme     checkWildcardRegexMatch(LongNumberStr);
281f9e2a62cSThomas Preud'homme   }
2825ffd940aSRaphael Isemann }
2835ffd940aSRaphael Isemann 
TEST_P(ExpressionFormatParameterisedFixture,FormatGetMatchingString)2845ffd940aSRaphael Isemann TEST_P(ExpressionFormatParameterisedFixture, FormatGetMatchingString) {
285f9e2a62cSThomas Preud'homme   checkMatchingString(0, addBasePrefix(padWithLeadingZeros("0")));
286f9e2a62cSThomas Preud'homme   checkMatchingString(9, addBasePrefix(padWithLeadingZeros("9")));
2875ffd940aSRaphael Isemann 
2885ffd940aSRaphael Isemann   if (Signed) {
2895ffd940aSRaphael Isemann     checkMatchingString(-5, padWithLeadingZeros("-5"));
2905ffd940aSRaphael Isemann     checkMatchingStringFailure(MaxUint64);
2915ffd940aSRaphael Isemann     checkMatchingString(MaxInt64, padWithLeadingZeros(MaxInt64Str));
2925ffd940aSRaphael Isemann     checkMatchingString(MinInt64, padWithLeadingZeros(MinInt64Str));
2935ffd940aSRaphael Isemann   } else {
2945ffd940aSRaphael Isemann     checkMatchingStringFailure(-5);
295f9e2a62cSThomas Preud'homme     checkMatchingString(MaxUint64,
296f9e2a62cSThomas Preud'homme                         addBasePrefix(padWithLeadingZeros(MaxUint64Str)));
297f9e2a62cSThomas Preud'homme     checkMatchingString(MaxInt64,
298f9e2a62cSThomas Preud'homme                         addBasePrefix(padWithLeadingZeros(MaxInt64Str)));
2995ffd940aSRaphael Isemann     checkMatchingStringFailure(MinInt64);
3005ffd940aSRaphael Isemann   }
3015ffd940aSRaphael Isemann 
302f9e2a62cSThomas Preud'homme   checkMatchingString(10, addBasePrefix(padWithLeadingZeros(TenStr)));
303f9e2a62cSThomas Preud'homme   checkMatchingString(15, addBasePrefix(padWithLeadingZeros(FifteenStr)));
3045ffd940aSRaphael Isemann }
3055ffd940aSRaphael Isemann 
TEST_P(ExpressionFormatParameterisedFixture,FormatValueFromStringRepr)3065ffd940aSRaphael Isemann TEST_P(ExpressionFormatParameterisedFixture, FormatValueFromStringRepr) {
307f9e2a62cSThomas Preud'homme   checkValueFromStringRepr(addBasePrefix("0"), 0);
308f9e2a62cSThomas Preud'homme   checkValueFromStringRepr(addBasePrefix("9"), 9);
3095ffd940aSRaphael Isemann 
3105ffd940aSRaphael Isemann   if (Signed) {
3115ffd940aSRaphael Isemann     checkValueFromStringRepr("-5", -5);
3125ffd940aSRaphael Isemann     checkValueFromStringReprFailure(MaxUint64Str);
3135ffd940aSRaphael Isemann   } else {
314f9e2a62cSThomas Preud'homme     checkValueFromStringReprFailure("-" + addBasePrefix("5"));
315f9e2a62cSThomas Preud'homme     checkValueFromStringRepr(addBasePrefix(MaxUint64Str), MaxUint64);
3165ffd940aSRaphael Isemann   }
3175ffd940aSRaphael Isemann 
318f9e2a62cSThomas Preud'homme   checkValueFromStringRepr(addBasePrefix(TenStr), 10);
319f9e2a62cSThomas Preud'homme   checkValueFromStringRepr(addBasePrefix(FifteenStr), 15);
3205ffd940aSRaphael Isemann 
3215ffd940aSRaphael Isemann   // Wrong casing is not tested because valueFromStringRepr() relies on
3225ffd940aSRaphael Isemann   // StringRef's getAsInteger() which does not allow to restrict casing.
323f9e2a62cSThomas Preud'homme   checkValueFromStringReprFailure(addBasePrefix("G"));
324f9e2a62cSThomas Preud'homme 
325f9e2a62cSThomas Preud'homme   if (AlternateForm)
326f9e2a62cSThomas Preud'homme     checkValueFromStringReprFailure("9", "missing alternate form prefix");
3275ffd940aSRaphael Isemann }
3285ffd940aSRaphael Isemann 
TEST_P(ExpressionFormatParameterisedFixture,FormatBoolOperator)3295ffd940aSRaphael Isemann TEST_P(ExpressionFormatParameterisedFixture, FormatBoolOperator) {
3305ffd940aSRaphael Isemann   EXPECT_TRUE(bool(Format));
3315ffd940aSRaphael Isemann }
3325ffd940aSRaphael Isemann 
333d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P(
3345ffd940aSRaphael Isemann     AllowedExplicitExpressionFormat, ExpressionFormatParameterisedFixture,
335f9e2a62cSThomas Preud'homme     ::testing::Values(
336f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::Unsigned, 0, false),
337f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::Signed, 0, false),
338f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::HexLower, 0, false),
339f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::HexLower, 0, true),
340f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::HexUpper, 0, false),
341f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::HexUpper, 0, true),
3425ffd940aSRaphael Isemann 
343f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::Unsigned, 1, false),
344f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::Signed, 1, false),
345f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::HexLower, 1, false),
346f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::HexLower, 1, true),
347f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::HexUpper, 1, false),
348f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::HexUpper, 1, true),
3495ffd940aSRaphael Isemann 
350f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::Unsigned, 16, false),
351f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::Signed, 16, false),
352f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::HexLower, 16, false),
353f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::HexLower, 16, true),
354f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::HexUpper, 16, false),
355f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::HexUpper, 16, true),
3565ffd940aSRaphael Isemann 
357f9e2a62cSThomas Preud'homme         std::make_tuple(ExpressionFormat::Kind::Unsigned, 20, false),
358d4d80a29SBenjamin Kramer         std::make_tuple(ExpressionFormat::Kind::Signed, 20, false)));
3595ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,NoFormatProperties)3605ffd940aSRaphael Isemann TEST_F(FileCheckTest, NoFormatProperties) {
3615ffd940aSRaphael Isemann   ExpressionFormat NoFormat(ExpressionFormat::Kind::NoFormat);
3625ffd940aSRaphael Isemann   expectError<StringError>("trying to match value with invalid format",
3635ffd940aSRaphael Isemann                            NoFormat.getWildcardRegex().takeError());
3645ffd940aSRaphael Isemann   expectError<StringError>(
3655ffd940aSRaphael Isemann       "trying to match value with invalid format",
3665ffd940aSRaphael Isemann       NoFormat.getMatchingString(ExpressionValue(18u)).takeError());
3675ffd940aSRaphael Isemann   EXPECT_FALSE(bool(NoFormat));
3685ffd940aSRaphael Isemann }
3695ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,FormatEqualityOperators)3705ffd940aSRaphael Isemann TEST_F(FileCheckTest, FormatEqualityOperators) {
3715ffd940aSRaphael Isemann   ExpressionFormat UnsignedFormat(ExpressionFormat::Kind::Unsigned);
3725ffd940aSRaphael Isemann   ExpressionFormat UnsignedFormat2(ExpressionFormat::Kind::Unsigned);
3735ffd940aSRaphael Isemann   EXPECT_TRUE(UnsignedFormat == UnsignedFormat2);
3745ffd940aSRaphael Isemann   EXPECT_FALSE(UnsignedFormat != UnsignedFormat2);
3755ffd940aSRaphael Isemann 
3765ffd940aSRaphael Isemann   ExpressionFormat HexLowerFormat(ExpressionFormat::Kind::HexLower);
3775ffd940aSRaphael Isemann   EXPECT_FALSE(UnsignedFormat == HexLowerFormat);
3785ffd940aSRaphael Isemann   EXPECT_TRUE(UnsignedFormat != HexLowerFormat);
3795ffd940aSRaphael Isemann 
3805ffd940aSRaphael Isemann   ExpressionFormat NoFormat(ExpressionFormat::Kind::NoFormat);
3815ffd940aSRaphael Isemann   ExpressionFormat NoFormat2(ExpressionFormat::Kind::NoFormat);
3825ffd940aSRaphael Isemann   EXPECT_FALSE(NoFormat == NoFormat2);
3835ffd940aSRaphael Isemann   EXPECT_TRUE(NoFormat != NoFormat2);
3845ffd940aSRaphael Isemann }
3855ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,FormatKindEqualityOperators)3865ffd940aSRaphael Isemann TEST_F(FileCheckTest, FormatKindEqualityOperators) {
3875ffd940aSRaphael Isemann   ExpressionFormat UnsignedFormat(ExpressionFormat::Kind::Unsigned);
3885ffd940aSRaphael Isemann   EXPECT_TRUE(UnsignedFormat == ExpressionFormat::Kind::Unsigned);
3895ffd940aSRaphael Isemann   EXPECT_FALSE(UnsignedFormat != ExpressionFormat::Kind::Unsigned);
3905ffd940aSRaphael Isemann   EXPECT_FALSE(UnsignedFormat == ExpressionFormat::Kind::HexLower);
3915ffd940aSRaphael Isemann   EXPECT_TRUE(UnsignedFormat != ExpressionFormat::Kind::HexLower);
3925ffd940aSRaphael Isemann   ExpressionFormat NoFormat(ExpressionFormat::Kind::NoFormat);
3935ffd940aSRaphael Isemann   EXPECT_TRUE(NoFormat == ExpressionFormat::Kind::NoFormat);
3945ffd940aSRaphael Isemann   EXPECT_FALSE(NoFormat != ExpressionFormat::Kind::NoFormat);
3955ffd940aSRaphael Isemann }
3965ffd940aSRaphael Isemann 
3975ffd940aSRaphael Isemann template <class T1, class T2>
doValueOperation(binop_eval_t Operation,T1 LeftValue,T2 RightValue)3985ffd940aSRaphael Isemann static Expected<ExpressionValue> doValueOperation(binop_eval_t Operation,
3995ffd940aSRaphael Isemann                                                   T1 LeftValue, T2 RightValue) {
4005ffd940aSRaphael Isemann   ExpressionValue LeftOperand(LeftValue);
4015ffd940aSRaphael Isemann   ExpressionValue RightOperand(RightValue);
4025ffd940aSRaphael Isemann   return Operation(LeftOperand, RightOperand);
4035ffd940aSRaphael Isemann }
4045ffd940aSRaphael Isemann 
4055ffd940aSRaphael Isemann template <class T>
expectValueEqual(ExpressionValue ActualValue,T ExpectedValue)4065ffd940aSRaphael Isemann static void expectValueEqual(ExpressionValue ActualValue, T ExpectedValue) {
4075ffd940aSRaphael Isemann   EXPECT_EQ(ExpectedValue < 0, ActualValue.isNegative());
4085ffd940aSRaphael Isemann   if (ExpectedValue < 0) {
4095ffd940aSRaphael Isemann     Expected<int64_t> SignedActualValue = ActualValue.getSignedValue();
4105ffd940aSRaphael Isemann     ASSERT_THAT_EXPECTED(SignedActualValue, Succeeded());
4115ffd940aSRaphael Isemann     EXPECT_EQ(*SignedActualValue, static_cast<int64_t>(ExpectedValue));
4125ffd940aSRaphael Isemann   } else {
4135ffd940aSRaphael Isemann     Expected<uint64_t> UnsignedActualValue = ActualValue.getUnsignedValue();
4145ffd940aSRaphael Isemann     ASSERT_THAT_EXPECTED(UnsignedActualValue, Succeeded());
4155ffd940aSRaphael Isemann     EXPECT_EQ(*UnsignedActualValue, static_cast<uint64_t>(ExpectedValue));
4165ffd940aSRaphael Isemann   }
4175ffd940aSRaphael Isemann }
4185ffd940aSRaphael Isemann 
4195ffd940aSRaphael Isemann template <class T1, class T2, class TR>
expectOperationValueResult(binop_eval_t Operation,T1 LeftValue,T2 RightValue,TR ResultValue)4205ffd940aSRaphael Isemann static void expectOperationValueResult(binop_eval_t Operation, T1 LeftValue,
4215ffd940aSRaphael Isemann                                        T2 RightValue, TR ResultValue) {
4225ffd940aSRaphael Isemann   Expected<ExpressionValue> OperationResult =
4235ffd940aSRaphael Isemann       doValueOperation(Operation, LeftValue, RightValue);
4245ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(OperationResult, Succeeded());
4255ffd940aSRaphael Isemann   expectValueEqual(*OperationResult, ResultValue);
4265ffd940aSRaphael Isemann }
4275ffd940aSRaphael Isemann 
4285ffd940aSRaphael Isemann template <class T1, class T2>
expectOperationValueResult(binop_eval_t Operation,T1 LeftValue,T2 RightValue)4295ffd940aSRaphael Isemann static void expectOperationValueResult(binop_eval_t Operation, T1 LeftValue,
4305ffd940aSRaphael Isemann                                        T2 RightValue) {
4315ffd940aSRaphael Isemann   expectError<OverflowError>(
4325ffd940aSRaphael Isemann       "overflow error",
4335ffd940aSRaphael Isemann       doValueOperation(Operation, LeftValue, RightValue).takeError());
4345ffd940aSRaphael Isemann }
4355ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,ExpressionValueGetUnsigned)4365ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueGetUnsigned) {
4375ffd940aSRaphael Isemann   // Test positive value.
4385ffd940aSRaphael Isemann   Expected<uint64_t> UnsignedValue = ExpressionValue(10).getUnsignedValue();
4395ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(UnsignedValue, Succeeded());
4405ffd940aSRaphael Isemann   EXPECT_EQ(*UnsignedValue, 10U);
4415ffd940aSRaphael Isemann 
4425ffd940aSRaphael Isemann   // Test 0.
4435ffd940aSRaphael Isemann   UnsignedValue = ExpressionValue(0).getUnsignedValue();
4445ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(UnsignedValue, Succeeded());
4455ffd940aSRaphael Isemann   EXPECT_EQ(*UnsignedValue, 0U);
4465ffd940aSRaphael Isemann 
4475ffd940aSRaphael Isemann   // Test max positive value.
4485ffd940aSRaphael Isemann   UnsignedValue = ExpressionValue(MaxUint64).getUnsignedValue();
4495ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(UnsignedValue, Succeeded());
4505ffd940aSRaphael Isemann   EXPECT_EQ(*UnsignedValue, MaxUint64);
4515ffd940aSRaphael Isemann 
4525ffd940aSRaphael Isemann   // Test failure with negative value.
4535ffd940aSRaphael Isemann   expectError<OverflowError>(
4545ffd940aSRaphael Isemann       "overflow error", ExpressionValue(-1).getUnsignedValue().takeError());
4555ffd940aSRaphael Isemann 
4565ffd940aSRaphael Isemann   // Test failure with min negative value.
4575ffd940aSRaphael Isemann   expectError<OverflowError>(
4585ffd940aSRaphael Isemann       "overflow error",
4595ffd940aSRaphael Isemann       ExpressionValue(MinInt64).getUnsignedValue().takeError());
4605ffd940aSRaphael Isemann }
4615ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,ExpressionValueGetSigned)4625ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueGetSigned) {
4635ffd940aSRaphael Isemann   // Test positive value.
4645ffd940aSRaphael Isemann   Expected<int64_t> SignedValue = ExpressionValue(10).getSignedValue();
4655ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SignedValue, Succeeded());
4665ffd940aSRaphael Isemann   EXPECT_EQ(*SignedValue, 10);
4675ffd940aSRaphael Isemann 
4685ffd940aSRaphael Isemann   // Test 0.
4695ffd940aSRaphael Isemann   SignedValue = ExpressionValue(0).getSignedValue();
4705ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SignedValue, Succeeded());
4715ffd940aSRaphael Isemann   EXPECT_EQ(*SignedValue, 0);
4725ffd940aSRaphael Isemann 
4735ffd940aSRaphael Isemann   // Test max int64_t.
4745ffd940aSRaphael Isemann   SignedValue = ExpressionValue(MaxInt64).getSignedValue();
4755ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SignedValue, Succeeded());
4765ffd940aSRaphael Isemann   EXPECT_EQ(*SignedValue, MaxInt64);
4775ffd940aSRaphael Isemann 
4785ffd940aSRaphael Isemann   // Test failure with too big positive value.
4795ffd940aSRaphael Isemann   expectError<OverflowError>(
4805ffd940aSRaphael Isemann       "overflow error", ExpressionValue(static_cast<uint64_t>(MaxInt64) + 1)
4815ffd940aSRaphael Isemann                             .getSignedValue()
4825ffd940aSRaphael Isemann                             .takeError());
4835ffd940aSRaphael Isemann 
4845ffd940aSRaphael Isemann   // Test failure with max uint64_t.
4855ffd940aSRaphael Isemann   expectError<OverflowError>(
4865ffd940aSRaphael Isemann       "overflow error",
4875ffd940aSRaphael Isemann       ExpressionValue(MaxUint64).getSignedValue().takeError());
4885ffd940aSRaphael Isemann 
4895ffd940aSRaphael Isemann   // Test negative value.
4905ffd940aSRaphael Isemann   SignedValue = ExpressionValue(-10).getSignedValue();
4915ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SignedValue, Succeeded());
4925ffd940aSRaphael Isemann   EXPECT_EQ(*SignedValue, -10);
4935ffd940aSRaphael Isemann 
4945ffd940aSRaphael Isemann   // Test min int64_t.
4955ffd940aSRaphael Isemann   SignedValue = ExpressionValue(MinInt64).getSignedValue();
4965ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SignedValue, Succeeded());
4975ffd940aSRaphael Isemann   EXPECT_EQ(*SignedValue, MinInt64);
4985ffd940aSRaphael Isemann }
4995ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,ExpressionValueAbsolute)5005ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueAbsolute) {
5015ffd940aSRaphael Isemann   // Test positive value.
5025ffd940aSRaphael Isemann   expectValueEqual(ExpressionValue(10).getAbsolute(), 10);
5035ffd940aSRaphael Isemann 
5045ffd940aSRaphael Isemann   // Test 0.
5055ffd940aSRaphael Isemann   expectValueEqual(ExpressionValue(0).getAbsolute(), 0);
5065ffd940aSRaphael Isemann 
5075ffd940aSRaphael Isemann   // Test max uint64_t.
5085ffd940aSRaphael Isemann   expectValueEqual(ExpressionValue(MaxUint64).getAbsolute(), MaxUint64);
5095ffd940aSRaphael Isemann 
5105ffd940aSRaphael Isemann   // Test negative value.
5115ffd940aSRaphael Isemann   expectValueEqual(ExpressionValue(-10).getAbsolute(), 10);
5125ffd940aSRaphael Isemann 
5135ffd940aSRaphael Isemann   // Test absence of overflow on min int64_t.
5145ffd940aSRaphael Isemann   expectValueEqual(ExpressionValue(MinInt64).getAbsolute(),
5155ffd940aSRaphael Isemann                    static_cast<uint64_t>(-(MinInt64 + 10)) + 10);
5165ffd940aSRaphael Isemann }
5175ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,ExpressionValueAddition)5185ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueAddition) {
5195ffd940aSRaphael Isemann   // Test both negative values.
5205ffd940aSRaphael Isemann   expectOperationValueResult(operator+, -10, -10, -20);
5215ffd940aSRaphael Isemann 
5225ffd940aSRaphael Isemann   // Test both negative values with underflow.
5235ffd940aSRaphael Isemann   expectOperationValueResult(operator+, MinInt64, -1);
5245ffd940aSRaphael Isemann   expectOperationValueResult(operator+, MinInt64, MinInt64);
5255ffd940aSRaphael Isemann 
5265ffd940aSRaphael Isemann   // Test negative and positive value.
5275ffd940aSRaphael Isemann   expectOperationValueResult(operator+, -10, 10, 0);
5285ffd940aSRaphael Isemann   expectOperationValueResult(operator+, -10, 11, 1);
5295ffd940aSRaphael Isemann   expectOperationValueResult(operator+, -11, 10, -1);
5305ffd940aSRaphael Isemann 
5315ffd940aSRaphael Isemann   // Test positive and negative value.
5325ffd940aSRaphael Isemann   expectOperationValueResult(operator+, 10, -10, 0);
5335ffd940aSRaphael Isemann   expectOperationValueResult(operator+, 10, -11, -1);
5345ffd940aSRaphael Isemann   expectOperationValueResult(operator+, 11, -10, 1);
5355ffd940aSRaphael Isemann 
5365ffd940aSRaphael Isemann   // Test both positive values.
5375ffd940aSRaphael Isemann   expectOperationValueResult(operator+, 10, 10, 20);
5385ffd940aSRaphael Isemann 
5395ffd940aSRaphael Isemann   // Test both positive values with overflow.
5405ffd940aSRaphael Isemann   expectOperationValueResult(operator+, MaxUint64, 1);
5415ffd940aSRaphael Isemann   expectOperationValueResult(operator+, MaxUint64, MaxUint64);
5425ffd940aSRaphael Isemann }
5435ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,ExpressionValueSubtraction)5445ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueSubtraction) {
5455ffd940aSRaphael Isemann   // Test negative value and value bigger than int64_t max.
5465ffd940aSRaphael Isemann   expectOperationValueResult(operator-, -10, MaxUint64);
5475ffd940aSRaphael Isemann 
5485ffd940aSRaphael Isemann   // Test negative and positive value with underflow.
5495ffd940aSRaphael Isemann   expectOperationValueResult(operator-, MinInt64, 1);
5505ffd940aSRaphael Isemann 
5515ffd940aSRaphael Isemann   // Test negative and positive value.
5525ffd940aSRaphael Isemann   expectOperationValueResult(operator-, -10, 10, -20);
5535ffd940aSRaphael Isemann 
5545ffd940aSRaphael Isemann   // Test both negative values.
5555ffd940aSRaphael Isemann   expectOperationValueResult(operator-, -10, -10, 0);
5565ffd940aSRaphael Isemann   expectOperationValueResult(operator-, -11, -10, -1);
5575ffd940aSRaphael Isemann   expectOperationValueResult(operator-, -10, -11, 1);
5585ffd940aSRaphael Isemann 
5595ffd940aSRaphael Isemann   // Test positive and negative values.
5605ffd940aSRaphael Isemann   expectOperationValueResult(operator-, 10, -10, 20);
5615ffd940aSRaphael Isemann 
5625ffd940aSRaphael Isemann   // Test both positive values with result positive.
5635ffd940aSRaphael Isemann   expectOperationValueResult(operator-, 10, 5, 5);
5645ffd940aSRaphael Isemann 
5655ffd940aSRaphael Isemann   // Test both positive values with underflow.
5665ffd940aSRaphael Isemann   expectOperationValueResult(operator-, 0, MaxUint64);
5675ffd940aSRaphael Isemann   expectOperationValueResult(operator-, 0,
5685ffd940aSRaphael Isemann                              static_cast<uint64_t>(-(MinInt64 + 10)) + 11);
5695ffd940aSRaphael Isemann 
5705ffd940aSRaphael Isemann   // Test both positive values with result < -(max int64_t)
5715ffd940aSRaphael Isemann   expectOperationValueResult(operator-, 10,
5725ffd940aSRaphael Isemann                              static_cast<uint64_t>(MaxInt64) + 11,
5735ffd940aSRaphael Isemann                              -MaxInt64 - 1);
5745ffd940aSRaphael Isemann 
5755ffd940aSRaphael Isemann   // Test both positive values with 0 > result > -(max int64_t)
5765ffd940aSRaphael Isemann   expectOperationValueResult(operator-, 10, 11, -1);
5775ffd940aSRaphael Isemann }
5785ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,ExpressionValueMultiplication)5795ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueMultiplication) {
5805ffd940aSRaphael Isemann   // Test mixed signed values.
5815ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -3, 10, -30);
5825ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 2, -17, -34);
5835ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 0, MinInt64, 0);
5845ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MinInt64, 1, MinInt64);
5855ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 1, MinInt64, MinInt64);
5865ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MaxInt64, -1, -MaxInt64);
5875ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -1, MaxInt64, -MaxInt64);
5885ffd940aSRaphael Isemann 
5895ffd940aSRaphael Isemann   // Test both negative values.
5905ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -3, -10, 30);
5915ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -2, -17, 34);
5925ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MinInt64, -1, AbsoluteMinInt64);
5935ffd940aSRaphael Isemann 
5945ffd940aSRaphael Isemann   // Test both positive values.
5955ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 3, 10, 30);
5965ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 2, 17, 34);
5975ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 0, MaxUint64, 0);
5985ffd940aSRaphael Isemann 
5995ffd940aSRaphael Isemann   // Test negative results that underflow.
6005ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -10, MaxInt64);
6015ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MaxInt64, -10);
6025ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 10, MinInt64);
6035ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MinInt64, 10);
6045ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -1, MaxUint64);
6055ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MaxUint64, -1);
6065ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -1, AbsoluteMaxInt64 + 2);
6075ffd940aSRaphael Isemann   expectOperationValueResult(operator*, AbsoluteMaxInt64 + 2, -1);
6085ffd940aSRaphael Isemann 
6095ffd940aSRaphael Isemann   // Test positive results that overflow.
6105ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 10, MaxUint64);
6115ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MaxUint64, 10);
6125ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MinInt64, -10);
6135ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -10, MinInt64);
6145ffd940aSRaphael Isemann }
6155ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,ExpressionValueDivision)6165ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueDivision) {
6175ffd940aSRaphael Isemann   // Test mixed signed values.
6185ffd940aSRaphael Isemann   expectOperationValueResult(operator/, -30, 10, -3);
6195ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 34, -17, -2);
6205ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 0, -10, 0);
6215ffd940aSRaphael Isemann   expectOperationValueResult(operator/, MinInt64, 1, MinInt64);
6225ffd940aSRaphael Isemann   expectOperationValueResult(operator/, MaxInt64, -1, -MaxInt64);
6235ffd940aSRaphael Isemann   expectOperationValueResult(operator/, -MaxInt64, 1, -MaxInt64);
6245ffd940aSRaphael Isemann 
6255ffd940aSRaphael Isemann   // Test both negative values.
6265ffd940aSRaphael Isemann   expectOperationValueResult(operator/, -30, -10, 3);
6275ffd940aSRaphael Isemann   expectOperationValueResult(operator/, -34, -17, 2);
6285ffd940aSRaphael Isemann 
6295ffd940aSRaphael Isemann   // Test both positive values.
6305ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 30, 10, 3);
6315ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 34, 17, 2);
6325ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 0, 10, 0);
6335ffd940aSRaphael Isemann 
6345ffd940aSRaphael Isemann   // Test divide by zero.
6355ffd940aSRaphael Isemann   expectOperationValueResult(operator/, -10, 0);
6365ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 10, 0);
6375ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 0, 0);
6385ffd940aSRaphael Isemann 
6395ffd940aSRaphael Isemann   // Test negative result that underflows.
6405ffd940aSRaphael Isemann   expectOperationValueResult(operator/, MaxUint64, -1);
6415ffd940aSRaphael Isemann   expectOperationValueResult(operator/, AbsoluteMaxInt64 + 2, -1);
6425ffd940aSRaphael Isemann }
6435ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,ExpressionValueEquality)6445ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueEquality) {
6455ffd940aSRaphael Isemann   // Test negative and positive value.
6465ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(5) == ExpressionValue(-3));
6475ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(5) != ExpressionValue(-3));
6485ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(-2) == ExpressionValue(6));
6495ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(-2) != ExpressionValue(6));
6505ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(-7) == ExpressionValue(7));
6515ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(-7) != ExpressionValue(7));
6525ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(4) == ExpressionValue(-4));
6535ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(4) != ExpressionValue(-4));
6545ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(MaxUint64) == ExpressionValue(-1));
6555ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(MaxUint64) != ExpressionValue(-1));
6565ffd940aSRaphael Isemann 
6575ffd940aSRaphael Isemann   // Test both negative values.
6585ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(-2) == ExpressionValue(-7));
6595ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(-2) != ExpressionValue(-7));
6605ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(-3) == ExpressionValue(-3));
6615ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(-3) != ExpressionValue(-3));
6625ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(MinInt64) == ExpressionValue(-1));
6635ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(MinInt64) != ExpressionValue(-1));
6645ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(MinInt64) == ExpressionValue(-0));
6655ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(MinInt64) != ExpressionValue(-0));
6665ffd940aSRaphael Isemann 
6675ffd940aSRaphael Isemann   // Test both positive values.
6685ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(8) == ExpressionValue(9));
6695ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(8) != ExpressionValue(9));
6705ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(1) == ExpressionValue(1));
6715ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(1) != ExpressionValue(1));
6725ffd940aSRaphael Isemann 
6735ffd940aSRaphael Isemann   // Check the signedness of zero doesn't affect equality.
6745ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(0) == ExpressionValue(0));
6755ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(0) != ExpressionValue(0));
6765ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(0) == ExpressionValue(-0));
6775ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(0) != ExpressionValue(-0));
6785ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(-0) == ExpressionValue(0));
6795ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(-0) != ExpressionValue(0));
6805ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(-0) == ExpressionValue(-0));
6815ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(-0) != ExpressionValue(-0));
6825ffd940aSRaphael Isemann }
6835ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,Literal)6845ffd940aSRaphael Isemann TEST_F(FileCheckTest, Literal) {
6855ffd940aSRaphael Isemann   SourceMgr SM;
6865ffd940aSRaphael Isemann 
6875ffd940aSRaphael Isemann   // Eval returns the literal's value.
6885ffd940aSRaphael Isemann   ExpressionLiteral Ten(bufferize(SM, "10"), 10u);
6895ffd940aSRaphael Isemann   Expected<ExpressionValue> Value = Ten.eval();
6905ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(Value, Succeeded());
6915ffd940aSRaphael Isemann   EXPECT_EQ(10, cantFail(Value->getSignedValue()));
6925ffd940aSRaphael Isemann   Expected<ExpressionFormat> ImplicitFormat = Ten.getImplicitFormat(SM);
6935ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ImplicitFormat, Succeeded());
6945ffd940aSRaphael Isemann   EXPECT_EQ(*ImplicitFormat, ExpressionFormat::Kind::NoFormat);
6955ffd940aSRaphael Isemann 
6965ffd940aSRaphael Isemann   // Min value can be correctly represented.
6975ffd940aSRaphael Isemann   ExpressionLiteral Min(bufferize(SM, std::to_string(MinInt64)), MinInt64);
6985ffd940aSRaphael Isemann   Value = Min.eval();
6995ffd940aSRaphael Isemann   ASSERT_TRUE(bool(Value));
7005ffd940aSRaphael Isemann   EXPECT_EQ(MinInt64, cantFail(Value->getSignedValue()));
7015ffd940aSRaphael Isemann 
7025ffd940aSRaphael Isemann   // Max value can be correctly represented.
7035ffd940aSRaphael Isemann   ExpressionLiteral Max(bufferize(SM, std::to_string(MaxUint64)), MaxUint64);
7045ffd940aSRaphael Isemann   Value = Max.eval();
7055ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(Value, Succeeded());
7065ffd940aSRaphael Isemann   EXPECT_EQ(MaxUint64, cantFail(Value->getUnsignedValue()));
7075ffd940aSRaphael Isemann }
7085ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,Expression)7095ffd940aSRaphael Isemann TEST_F(FileCheckTest, Expression) {
7105ffd940aSRaphael Isemann   SourceMgr SM;
7115ffd940aSRaphael Isemann 
7125ffd940aSRaphael Isemann   std::unique_ptr<ExpressionLiteral> Ten =
7135ffd940aSRaphael Isemann       std::make_unique<ExpressionLiteral>(bufferize(SM, "10"), 10u);
7145ffd940aSRaphael Isemann   ExpressionLiteral *TenPtr = Ten.get();
7155ffd940aSRaphael Isemann   Expression Expr(std::move(Ten),
7165ffd940aSRaphael Isemann                   ExpressionFormat(ExpressionFormat::Kind::HexLower));
7175ffd940aSRaphael Isemann   EXPECT_EQ(Expr.getAST(), TenPtr);
7185ffd940aSRaphael Isemann   EXPECT_EQ(Expr.getFormat(), ExpressionFormat::Kind::HexLower);
7195ffd940aSRaphael Isemann }
7205ffd940aSRaphael Isemann 
7215ffd940aSRaphael Isemann static void
expectUndefErrors(std::unordered_set<std::string> ExpectedUndefVarNames,Error Err)7225ffd940aSRaphael Isemann expectUndefErrors(std::unordered_set<std::string> ExpectedUndefVarNames,
7235ffd940aSRaphael Isemann                   Error Err) {
7245ffd940aSRaphael Isemann   EXPECT_THAT_ERROR(handleErrors(std::move(Err),
7255ffd940aSRaphael Isemann                                  [&](const UndefVarError &E) {
7265ffd940aSRaphael Isemann                                    EXPECT_EQ(ExpectedUndefVarNames.erase(
7275ffd940aSRaphael Isemann                                                  std::string(E.getVarName())),
7285ffd940aSRaphael Isemann                                              1U);
7295ffd940aSRaphael Isemann                                  }),
7305ffd940aSRaphael Isemann                     Succeeded());
7315ffd940aSRaphael Isemann   EXPECT_TRUE(ExpectedUndefVarNames.empty()) << toString(ExpectedUndefVarNames);
7325ffd940aSRaphael Isemann }
7335ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,NumericVariable)7345ffd940aSRaphael Isemann TEST_F(FileCheckTest, NumericVariable) {
7355ffd940aSRaphael Isemann   SourceMgr SM;
7365ffd940aSRaphael Isemann 
7375ffd940aSRaphael Isemann   // Undefined variable: getValue and eval fail, error returned by eval holds
7385ffd940aSRaphael Isemann   // the name of the undefined variable.
7395ffd940aSRaphael Isemann   NumericVariable FooVar("FOO",
7405ffd940aSRaphael Isemann                          ExpressionFormat(ExpressionFormat::Kind::Unsigned), 1);
7415ffd940aSRaphael Isemann   EXPECT_EQ("FOO", FooVar.getName());
7425ffd940aSRaphael Isemann   EXPECT_EQ(FooVar.getImplicitFormat(), ExpressionFormat::Kind::Unsigned);
7435ffd940aSRaphael Isemann   NumericVariableUse FooVarUse("FOO", &FooVar);
7445ffd940aSRaphael Isemann   Expected<ExpressionFormat> ImplicitFormat = FooVarUse.getImplicitFormat(SM);
7455ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ImplicitFormat, Succeeded());
7465ffd940aSRaphael Isemann   EXPECT_EQ(*ImplicitFormat, ExpressionFormat::Kind::Unsigned);
7475ffd940aSRaphael Isemann   EXPECT_FALSE(FooVar.getValue());
7485ffd940aSRaphael Isemann   Expected<ExpressionValue> EvalResult = FooVarUse.eval();
7495ffd940aSRaphael Isemann   expectUndefErrors({"FOO"}, EvalResult.takeError());
7505ffd940aSRaphael Isemann 
7515ffd940aSRaphael Isemann   // Defined variable without string: only getValue and eval return value set.
7525ffd940aSRaphael Isemann   FooVar.setValue(ExpressionValue(42u));
7535ffd940aSRaphael Isemann   Optional<ExpressionValue> Value = FooVar.getValue();
7545ffd940aSRaphael Isemann   ASSERT_TRUE(Value);
7555ffd940aSRaphael Isemann   EXPECT_EQ(42, cantFail(Value->getSignedValue()));
7565ffd940aSRaphael Isemann   EXPECT_FALSE(FooVar.getStringValue());
7575ffd940aSRaphael Isemann   EvalResult = FooVarUse.eval();
7585ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(EvalResult, Succeeded());
7595ffd940aSRaphael Isemann   EXPECT_EQ(42, cantFail(EvalResult->getSignedValue()));
7605ffd940aSRaphael Isemann 
7615ffd940aSRaphael Isemann   // Defined variable with string: getValue, eval, and getStringValue return
7625ffd940aSRaphael Isemann   // value set.
7635ffd940aSRaphael Isemann   StringRef StringValue = "925";
7645ffd940aSRaphael Isemann   FooVar.setValue(ExpressionValue(925u), StringValue);
7655ffd940aSRaphael Isemann   Value = FooVar.getValue();
7665ffd940aSRaphael Isemann   ASSERT_TRUE(Value);
7675ffd940aSRaphael Isemann   EXPECT_EQ(925, cantFail(Value->getSignedValue()));
7685ffd940aSRaphael Isemann   // getStringValue should return the same memory not just the same characters.
769*611ffcf4SKazu Hirata   EXPECT_EQ(StringValue.begin(), FooVar.getStringValue().value().begin());
770*611ffcf4SKazu Hirata   EXPECT_EQ(StringValue.end(), FooVar.getStringValue().value().end());
7715ffd940aSRaphael Isemann   EvalResult = FooVarUse.eval();
7725ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(EvalResult, Succeeded());
7735ffd940aSRaphael Isemann   EXPECT_EQ(925, cantFail(EvalResult->getSignedValue()));
7745ffd940aSRaphael Isemann   EXPECT_EQ(925, cantFail(EvalResult->getSignedValue()));
7755ffd940aSRaphael Isemann 
7765ffd940aSRaphael Isemann   // Clearing variable: getValue and eval fail. Error returned by eval holds
7775ffd940aSRaphael Isemann   // the name of the cleared variable.
7785ffd940aSRaphael Isemann   FooVar.clearValue();
7795ffd940aSRaphael Isemann   EXPECT_FALSE(FooVar.getValue());
7805ffd940aSRaphael Isemann   EXPECT_FALSE(FooVar.getStringValue());
7815ffd940aSRaphael Isemann   EvalResult = FooVarUse.eval();
7825ffd940aSRaphael Isemann   expectUndefErrors({"FOO"}, EvalResult.takeError());
7835ffd940aSRaphael Isemann }
7845ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,Binop)7855ffd940aSRaphael Isemann TEST_F(FileCheckTest, Binop) {
7865ffd940aSRaphael Isemann   SourceMgr SM;
7875ffd940aSRaphael Isemann 
7885ffd940aSRaphael Isemann   StringRef ExprStr = bufferize(SM, "FOO+BAR");
7895ffd940aSRaphael Isemann   StringRef FooStr = ExprStr.take_front(3);
7905ffd940aSRaphael Isemann   NumericVariable FooVar(FooStr,
7915ffd940aSRaphael Isemann                          ExpressionFormat(ExpressionFormat::Kind::Unsigned), 1);
7925ffd940aSRaphael Isemann   FooVar.setValue(ExpressionValue(42u));
7935ffd940aSRaphael Isemann   std::unique_ptr<NumericVariableUse> FooVarUse =
7945ffd940aSRaphael Isemann       std::make_unique<NumericVariableUse>(FooStr, &FooVar);
7955ffd940aSRaphael Isemann   StringRef BarStr = ExprStr.take_back(3);
7965ffd940aSRaphael Isemann   NumericVariable BarVar(BarStr,
7975ffd940aSRaphael Isemann                          ExpressionFormat(ExpressionFormat::Kind::Unsigned), 2);
7985ffd940aSRaphael Isemann   BarVar.setValue(ExpressionValue(18u));
7995ffd940aSRaphael Isemann   std::unique_ptr<NumericVariableUse> BarVarUse =
8005ffd940aSRaphael Isemann       std::make_unique<NumericVariableUse>(BarStr, &BarVar);
8015ffd940aSRaphael Isemann   binop_eval_t doAdd = operator+;
8025ffd940aSRaphael Isemann   BinaryOperation Binop(ExprStr, doAdd, std::move(FooVarUse),
8035ffd940aSRaphael Isemann                         std::move(BarVarUse));
8045ffd940aSRaphael Isemann 
8055ffd940aSRaphael Isemann   // Defined variables: eval returns right value; implicit format is as
8065ffd940aSRaphael Isemann   // expected.
8075ffd940aSRaphael Isemann   Expected<ExpressionValue> Value = Binop.eval();
8085ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(Value, Succeeded());
8095ffd940aSRaphael Isemann   EXPECT_EQ(60, cantFail(Value->getSignedValue()));
8105ffd940aSRaphael Isemann   Expected<ExpressionFormat> ImplicitFormat = Binop.getImplicitFormat(SM);
8115ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ImplicitFormat, Succeeded());
8125ffd940aSRaphael Isemann   EXPECT_EQ(*ImplicitFormat, ExpressionFormat::Kind::Unsigned);
8135ffd940aSRaphael Isemann 
8145ffd940aSRaphael Isemann   // 1 undefined variable: eval fails, error contains name of undefined
8155ffd940aSRaphael Isemann   // variable.
8165ffd940aSRaphael Isemann   FooVar.clearValue();
8175ffd940aSRaphael Isemann   Value = Binop.eval();
8185ffd940aSRaphael Isemann   expectUndefErrors({"FOO"}, Value.takeError());
8195ffd940aSRaphael Isemann 
8205ffd940aSRaphael Isemann   // 2 undefined variables: eval fails, error contains names of all undefined
8215ffd940aSRaphael Isemann   // variables.
8225ffd940aSRaphael Isemann   BarVar.clearValue();
8235ffd940aSRaphael Isemann   Value = Binop.eval();
8245ffd940aSRaphael Isemann   expectUndefErrors({"FOO", "BAR"}, Value.takeError());
8255ffd940aSRaphael Isemann 
8265ffd940aSRaphael Isemann   // Literal + Variable has format of variable.
8275ffd940aSRaphael Isemann   ExprStr = bufferize(SM, "FOO+18");
8285ffd940aSRaphael Isemann   FooStr = ExprStr.take_front(3);
8295ffd940aSRaphael Isemann   StringRef EighteenStr = ExprStr.take_back(2);
8305ffd940aSRaphael Isemann   FooVarUse = std::make_unique<NumericVariableUse>(FooStr, &FooVar);
8315ffd940aSRaphael Isemann   std::unique_ptr<ExpressionLiteral> Eighteen =
8325ffd940aSRaphael Isemann       std::make_unique<ExpressionLiteral>(EighteenStr, 18u);
8335ffd940aSRaphael Isemann   Binop = BinaryOperation(ExprStr, doAdd, std::move(FooVarUse),
8345ffd940aSRaphael Isemann                           std::move(Eighteen));
8355ffd940aSRaphael Isemann   ImplicitFormat = Binop.getImplicitFormat(SM);
8365ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ImplicitFormat, Succeeded());
8375ffd940aSRaphael Isemann   EXPECT_EQ(*ImplicitFormat, ExpressionFormat::Kind::Unsigned);
8385ffd940aSRaphael Isemann   ExprStr = bufferize(SM, "18+FOO");
8395ffd940aSRaphael Isemann   FooStr = ExprStr.take_back(3);
8405ffd940aSRaphael Isemann   EighteenStr = ExprStr.take_front(2);
8415ffd940aSRaphael Isemann   FooVarUse = std::make_unique<NumericVariableUse>(FooStr, &FooVar);
8425ffd940aSRaphael Isemann   Eighteen = std::make_unique<ExpressionLiteral>(EighteenStr, 18u);
8435ffd940aSRaphael Isemann   Binop = BinaryOperation(ExprStr, doAdd, std::move(Eighteen),
8445ffd940aSRaphael Isemann                           std::move(FooVarUse));
8455ffd940aSRaphael Isemann   ImplicitFormat = Binop.getImplicitFormat(SM);
8465ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ImplicitFormat, Succeeded());
8475ffd940aSRaphael Isemann   EXPECT_EQ(*ImplicitFormat, ExpressionFormat::Kind::Unsigned);
8485ffd940aSRaphael Isemann 
8495ffd940aSRaphael Isemann   // Variables with different implicit format conflict.
8505ffd940aSRaphael Isemann   ExprStr = bufferize(SM, "FOO+BAZ");
8515ffd940aSRaphael Isemann   FooStr = ExprStr.take_front(3);
8525ffd940aSRaphael Isemann   StringRef BazStr = ExprStr.take_back(3);
8535ffd940aSRaphael Isemann   NumericVariable BazVar(BazStr,
8545ffd940aSRaphael Isemann                          ExpressionFormat(ExpressionFormat::Kind::HexLower), 3);
8555ffd940aSRaphael Isemann   FooVarUse = std::make_unique<NumericVariableUse>(FooStr, &FooVar);
8565ffd940aSRaphael Isemann   std::unique_ptr<NumericVariableUse> BazVarUse =
8575ffd940aSRaphael Isemann       std::make_unique<NumericVariableUse>(BazStr, &BazVar);
8585ffd940aSRaphael Isemann   Binop = BinaryOperation(ExprStr, doAdd, std::move(FooVarUse),
8595ffd940aSRaphael Isemann                           std::move(BazVarUse));
8605ffd940aSRaphael Isemann   ImplicitFormat = Binop.getImplicitFormat(SM);
8615ffd940aSRaphael Isemann   expectDiagnosticError(
8625ffd940aSRaphael Isemann       "implicit format conflict between 'FOO' (%u) and 'BAZ' (%x), "
8635ffd940aSRaphael Isemann       "need an explicit format specifier",
8645ffd940aSRaphael Isemann       ImplicitFormat.takeError());
8655ffd940aSRaphael Isemann 
8665ffd940aSRaphael Isemann   // All variable conflicts are reported.
8675ffd940aSRaphael Isemann   ExprStr = bufferize(SM, "(FOO+BAZ)+(FOO+QUUX)");
8685ffd940aSRaphael Isemann   StringRef Paren1ExprStr = ExprStr.substr(1, 7);
8695ffd940aSRaphael Isemann   FooStr = Paren1ExprStr.take_front(3);
8705ffd940aSRaphael Isemann   BazStr = Paren1ExprStr.take_back(3);
8715ffd940aSRaphael Isemann   StringRef Paren2ExprStr = ExprStr.substr(ExprStr.rfind('(') + 1, 8);
8725ffd940aSRaphael Isemann   StringRef FooStr2 = Paren2ExprStr.take_front(3);
8735ffd940aSRaphael Isemann   StringRef QuuxStr = Paren2ExprStr.take_back(4);
8745ffd940aSRaphael Isemann   FooVarUse = std::make_unique<NumericVariableUse>(FooStr, &FooVar);
8755ffd940aSRaphael Isemann   BazVarUse = std::make_unique<NumericVariableUse>(BazStr, &BazVar);
8765ffd940aSRaphael Isemann   std::unique_ptr<NumericVariableUse> FooVarUse2 =
8775ffd940aSRaphael Isemann       std::make_unique<NumericVariableUse>(FooStr2, &FooVar);
8785ffd940aSRaphael Isemann   NumericVariable QuuxVar(
8795ffd940aSRaphael Isemann       QuuxStr, ExpressionFormat(ExpressionFormat::Kind::HexLower), 4);
8805ffd940aSRaphael Isemann   std::unique_ptr<NumericVariableUse> QuuxVarUse =
8815ffd940aSRaphael Isemann       std::make_unique<NumericVariableUse>(QuuxStr, &QuuxVar);
8825ffd940aSRaphael Isemann   std::unique_ptr<BinaryOperation> Binop1 = std::make_unique<BinaryOperation>(
8835ffd940aSRaphael Isemann       ExprStr.take_front(9), doAdd, std::move(FooVarUse), std::move(BazVarUse));
8845ffd940aSRaphael Isemann   std::unique_ptr<BinaryOperation> Binop2 = std::make_unique<BinaryOperation>(
8855ffd940aSRaphael Isemann       ExprStr.take_back(10), doAdd, std::move(FooVarUse2),
8865ffd940aSRaphael Isemann       std::move(QuuxVarUse));
8875ffd940aSRaphael Isemann   std::unique_ptr<BinaryOperation> OuterBinop =
8885ffd940aSRaphael Isemann       std::make_unique<BinaryOperation>(ExprStr, doAdd, std::move(Binop1),
8895ffd940aSRaphael Isemann                                         std::move(Binop2));
8905ffd940aSRaphael Isemann   ImplicitFormat = OuterBinop->getImplicitFormat(SM);
8915ffd940aSRaphael Isemann   expectSameErrors<ErrorDiagnostic>(
8925ffd940aSRaphael Isemann       {("implicit format conflict between 'FOO' (%u) and 'BAZ' (%x), need an "
8935ffd940aSRaphael Isemann        "explicit format specifier"),
8945ffd940aSRaphael Isemann        ("implicit format conflict between 'FOO' (%u) and 'QUUX' (%x), need an "
8955ffd940aSRaphael Isemann        "explicit format specifier")},
8965ffd940aSRaphael Isemann       ImplicitFormat.takeError());
8975ffd940aSRaphael Isemann }
8985ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,ValidVarNameStart)8995ffd940aSRaphael Isemann TEST_F(FileCheckTest, ValidVarNameStart) {
9005ffd940aSRaphael Isemann   EXPECT_TRUE(Pattern::isValidVarNameStart('a'));
9015ffd940aSRaphael Isemann   EXPECT_TRUE(Pattern::isValidVarNameStart('G'));
9025ffd940aSRaphael Isemann   EXPECT_TRUE(Pattern::isValidVarNameStart('_'));
9035ffd940aSRaphael Isemann   EXPECT_FALSE(Pattern::isValidVarNameStart('2'));
9045ffd940aSRaphael Isemann   EXPECT_FALSE(Pattern::isValidVarNameStart('$'));
9055ffd940aSRaphael Isemann   EXPECT_FALSE(Pattern::isValidVarNameStart('@'));
9065ffd940aSRaphael Isemann   EXPECT_FALSE(Pattern::isValidVarNameStart('+'));
9075ffd940aSRaphael Isemann   EXPECT_FALSE(Pattern::isValidVarNameStart('-'));
9085ffd940aSRaphael Isemann   EXPECT_FALSE(Pattern::isValidVarNameStart(':'));
9095ffd940aSRaphael Isemann }
9105ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,ParseVar)9115ffd940aSRaphael Isemann TEST_F(FileCheckTest, ParseVar) {
9125ffd940aSRaphael Isemann   SourceMgr SM;
9135ffd940aSRaphael Isemann   StringRef OrigVarName = bufferize(SM, "GoodVar42");
9145ffd940aSRaphael Isemann   StringRef VarName = OrigVarName;
9155ffd940aSRaphael Isemann   Expected<Pattern::VariableProperties> ParsedVarResult =
9165ffd940aSRaphael Isemann       Pattern::parseVariable(VarName, SM);
9175ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
9185ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
9195ffd940aSRaphael Isemann   EXPECT_TRUE(VarName.empty());
9205ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
9215ffd940aSRaphael Isemann 
9225ffd940aSRaphael Isemann   VarName = OrigVarName = bufferize(SM, "$GoodGlobalVar");
9235ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
9245ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
9255ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
9265ffd940aSRaphael Isemann   EXPECT_TRUE(VarName.empty());
9275ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
9285ffd940aSRaphael Isemann 
9295ffd940aSRaphael Isemann   VarName = OrigVarName = bufferize(SM, "@GoodPseudoVar");
9305ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
9315ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
9325ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
9335ffd940aSRaphael Isemann   EXPECT_TRUE(VarName.empty());
9345ffd940aSRaphael Isemann   EXPECT_TRUE(ParsedVarResult->IsPseudo);
9355ffd940aSRaphael Isemann 
9365ffd940aSRaphael Isemann   VarName = bufferize(SM, "42BadVar");
9375ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
9385ffd940aSRaphael Isemann   expectDiagnosticError("invalid variable name", ParsedVarResult.takeError());
9395ffd940aSRaphael Isemann 
9405ffd940aSRaphael Isemann   VarName = bufferize(SM, "$@");
9415ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
9425ffd940aSRaphael Isemann   expectDiagnosticError("invalid variable name", ParsedVarResult.takeError());
9435ffd940aSRaphael Isemann 
9445ffd940aSRaphael Isemann   VarName = OrigVarName = bufferize(SM, "B@dVar");
9455ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
9465ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
9475ffd940aSRaphael Isemann   EXPECT_EQ(VarName, OrigVarName.substr(1));
9485ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, "B");
9495ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
9505ffd940aSRaphael Isemann 
9515ffd940aSRaphael Isemann   VarName = OrigVarName = bufferize(SM, "B$dVar");
9525ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
9535ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
9545ffd940aSRaphael Isemann   EXPECT_EQ(VarName, OrigVarName.substr(1));
9555ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, "B");
9565ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
9575ffd940aSRaphael Isemann 
9585ffd940aSRaphael Isemann   VarName = bufferize(SM, "BadVar+");
9595ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
9605ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
9615ffd940aSRaphael Isemann   EXPECT_EQ(VarName, "+");
9625ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, "BadVar");
9635ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
9645ffd940aSRaphael Isemann 
9655ffd940aSRaphael Isemann   VarName = bufferize(SM, "BadVar-");
9665ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
9675ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
9685ffd940aSRaphael Isemann   EXPECT_EQ(VarName, "-");
9695ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, "BadVar");
9705ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
9715ffd940aSRaphael Isemann 
9725ffd940aSRaphael Isemann   VarName = bufferize(SM, "BadVar:");
9735ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
9745ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
9755ffd940aSRaphael Isemann   EXPECT_EQ(VarName, ":");
9765ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, "BadVar");
9775ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
9785ffd940aSRaphael Isemann }
9795ffd940aSRaphael Isemann 
expectNotFoundError(Error Err)9805ffd940aSRaphael Isemann static void expectNotFoundError(Error Err) {
9815ffd940aSRaphael Isemann   expectError<NotFoundError>("String not found in input", std::move(Err));
9825ffd940aSRaphael Isemann }
9835ffd940aSRaphael Isemann 
9845ffd940aSRaphael Isemann class PatternTester {
9855ffd940aSRaphael Isemann private:
9865ffd940aSRaphael Isemann   size_t LineNumber = 1;
9875ffd940aSRaphael Isemann   SourceMgr SM;
9885ffd940aSRaphael Isemann   FileCheckRequest Req;
9895ffd940aSRaphael Isemann   FileCheckPatternContext Context;
9905ffd940aSRaphael Isemann   Pattern P{Check::CheckPlain, &Context, LineNumber};
9915ffd940aSRaphael Isemann 
9925ffd940aSRaphael Isemann public:
PatternTester()9935ffd940aSRaphael Isemann   PatternTester() {
9945ffd940aSRaphael Isemann     std::vector<StringRef> GlobalDefines = {"#FOO=42", "BAR=BAZ", "#add=7"};
9955ffd940aSRaphael Isemann     // An ASSERT_FALSE would make more sense but cannot be used in a
9965ffd940aSRaphael Isemann     // constructor.
9975ffd940aSRaphael Isemann     EXPECT_THAT_ERROR(Context.defineCmdlineVariables(GlobalDefines, SM),
9985ffd940aSRaphael Isemann                       Succeeded());
9995ffd940aSRaphael Isemann     Context.createLineVariable();
10005ffd940aSRaphael Isemann     // Call parsePattern to have @LINE defined.
10015ffd940aSRaphael Isemann     P.parsePattern("N/A", "CHECK", SM, Req);
10025ffd940aSRaphael Isemann     // parsePattern does not expect to be called twice for the same line and
10035ffd940aSRaphael Isemann     // will set FixedStr and RegExStr incorrectly if it is. Therefore prepare
10045ffd940aSRaphael Isemann     // a pattern for a different line.
10055ffd940aSRaphael Isemann     initNextPattern();
10065ffd940aSRaphael Isemann   }
10075ffd940aSRaphael Isemann 
initNextPattern()10085ffd940aSRaphael Isemann   void initNextPattern() {
10095ffd940aSRaphael Isemann     P = Pattern(Check::CheckPlain, &Context, ++LineNumber);
10105ffd940aSRaphael Isemann   }
10115ffd940aSRaphael Isemann 
getLineNumber() const10125ffd940aSRaphael Isemann   size_t getLineNumber() const { return LineNumber; }
10135ffd940aSRaphael Isemann 
10145ffd940aSRaphael Isemann   Expected<std::unique_ptr<Expression>>
parseSubst(StringRef Expr,bool IsLegacyLineExpr=false)10155ffd940aSRaphael Isemann   parseSubst(StringRef Expr, bool IsLegacyLineExpr = false) {
10165ffd940aSRaphael Isemann     StringRef ExprBufferRef = bufferize(SM, Expr);
10175ffd940aSRaphael Isemann     Optional<NumericVariable *> DefinedNumericVariable;
10185ffd940aSRaphael Isemann     return P.parseNumericSubstitutionBlock(
10195ffd940aSRaphael Isemann         ExprBufferRef, DefinedNumericVariable, IsLegacyLineExpr, LineNumber,
10205ffd940aSRaphael Isemann         &Context, SM);
10215ffd940aSRaphael Isemann   }
10225ffd940aSRaphael Isemann 
parsePattern(StringRef Pattern)10235ffd940aSRaphael Isemann   bool parsePattern(StringRef Pattern) {
10245ffd940aSRaphael Isemann     StringRef PatBufferRef = bufferize(SM, Pattern);
10255ffd940aSRaphael Isemann     return P.parsePattern(PatBufferRef, "CHECK", SM, Req);
10265ffd940aSRaphael Isemann   }
10275ffd940aSRaphael Isemann 
match(StringRef Buffer)10285ffd940aSRaphael Isemann   Expected<size_t> match(StringRef Buffer) {
10295ffd940aSRaphael Isemann     StringRef BufferRef = bufferize(SM, Buffer);
1030dd59c132SJoel E. Denny     Pattern::MatchResult Res = P.match(BufferRef, SM);
1031dd59c132SJoel E. Denny     if (Res.TheError)
1032dd59c132SJoel E. Denny       return std::move(Res.TheError);
1033dd59c132SJoel E. Denny     return Res.TheMatch->Pos;
10345ffd940aSRaphael Isemann   }
10355ffd940aSRaphael Isemann 
printVariableDefs(FileCheckDiag::MatchType MatchTy,std::vector<FileCheckDiag> & Diags)10365ffd940aSRaphael Isemann   void printVariableDefs(FileCheckDiag::MatchType MatchTy,
10375ffd940aSRaphael Isemann                          std::vector<FileCheckDiag> &Diags) {
10385ffd940aSRaphael Isemann     P.printVariableDefs(SM, MatchTy, &Diags);
10395ffd940aSRaphael Isemann   }
10405ffd940aSRaphael Isemann };
10415ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,ParseNumericSubstitutionBlock)10425ffd940aSRaphael Isemann TEST_F(FileCheckTest, ParseNumericSubstitutionBlock) {
10435ffd940aSRaphael Isemann   PatternTester Tester;
10445ffd940aSRaphael Isemann 
10455ffd940aSRaphael Isemann   // Variable definition.
10465ffd940aSRaphael Isemann 
10475ffd940aSRaphael Isemann   expectDiagnosticError("invalid variable name",
10485ffd940aSRaphael Isemann                         Tester.parseSubst("%VAR:").takeError());
10495ffd940aSRaphael Isemann 
10505ffd940aSRaphael Isemann   expectDiagnosticError("definition of pseudo numeric variable unsupported",
10515ffd940aSRaphael Isemann                         Tester.parseSubst("@LINE:").takeError());
10525ffd940aSRaphael Isemann 
10535ffd940aSRaphael Isemann   expectDiagnosticError("string variable with name 'BAR' already exists",
10545ffd940aSRaphael Isemann                         Tester.parseSubst("BAR:").takeError());
10555ffd940aSRaphael Isemann 
10565ffd940aSRaphael Isemann   expectDiagnosticError("unexpected characters after numeric variable name",
10575ffd940aSRaphael Isemann                         Tester.parseSubst("VAR GARBAGE:").takeError());
10585ffd940aSRaphael Isemann 
10595ffd940aSRaphael Isemann   // Change of format.
10605ffd940aSRaphael Isemann   expectDiagnosticError("format different from previous variable definition",
10615ffd940aSRaphael Isemann                         Tester.parseSubst("%X,FOO:").takeError());
10625ffd940aSRaphael Isemann 
10635ffd940aSRaphael Isemann   // Invalid format.
10645ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching format specification in expression",
10655ffd940aSRaphael Isemann                         Tester.parseSubst("X,VAR1:").takeError());
10665ffd940aSRaphael Isemann   expectDiagnosticError("invalid format specifier in expression",
10675ffd940aSRaphael Isemann                         Tester.parseSubst("%F,VAR1:").takeError());
10685ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching format specification in expression",
10695ffd940aSRaphael Isemann                         Tester.parseSubst("%X a,VAR1:").takeError());
10705ffd940aSRaphael Isemann 
10715ffd940aSRaphael Isemann   // Acceptable variable definition.
10725ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("VAR1:"), Succeeded());
10735ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("  VAR2:"), Succeeded());
10745ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("VAR3  :"), Succeeded());
10755ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("VAR3:  "), Succeeded());
10765ffd940aSRaphael Isemann 
10775ffd940aSRaphael Isemann   // Acceptable variable definition with format specifier. Use parsePattern for
10785ffd940aSRaphael Isemann   // variables whose definition needs to be visible for later checks.
10795ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[#%u, VAR_UNSIGNED:]]"));
10805ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[#%x, VAR_LOWER_HEX:]]"));
10815ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%X, VAR_UPPER_HEX:"), Succeeded());
10825ffd940aSRaphael Isemann 
10835ffd940aSRaphael Isemann   // Acceptable variable definition with precision specifier.
10845ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[#%.8X, PADDED_ADDR:]]"));
10855ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[#%.8, PADDED_NUM:]]"));
10865ffd940aSRaphael Isemann 
1087f9e2a62cSThomas Preud'homme   // Acceptable variable definition in alternate form.
1088f9e2a62cSThomas Preud'homme   EXPECT_THAT_EXPECTED(Tester.parseSubst("%#x, PREFIXED_ADDR:"), Succeeded());
1089f9e2a62cSThomas Preud'homme   EXPECT_THAT_EXPECTED(Tester.parseSubst("%#X, PREFIXED_ADDR:"), Succeeded());
1090f9e2a62cSThomas Preud'homme 
1091f9e2a62cSThomas Preud'homme   // Acceptable variable definition in alternate form.
1092f9e2a62cSThomas Preud'homme   expectDiagnosticError("alternate form only supported for hex values",
1093f9e2a62cSThomas Preud'homme                         Tester.parseSubst("%#u, PREFIXED_UNSI:").takeError());
1094f9e2a62cSThomas Preud'homme   expectDiagnosticError("alternate form only supported for hex values",
1095f9e2a62cSThomas Preud'homme                         Tester.parseSubst("%#d, PREFIXED_UNSI:").takeError());
1096f9e2a62cSThomas Preud'homme 
10975ffd940aSRaphael Isemann   // Acceptable variable definition from a numeric expression.
10985ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOOBAR: FOO+1"), Succeeded());
10995ffd940aSRaphael Isemann 
11005ffd940aSRaphael Isemann   // Numeric expression. Switch to next line to make above valid definition
11015ffd940aSRaphael Isemann   // available in expressions.
11025ffd940aSRaphael Isemann   Tester.initNextPattern();
11035ffd940aSRaphael Isemann 
11045ffd940aSRaphael Isemann   // Invalid variable name.
11055ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching constraint or operand format",
11065ffd940aSRaphael Isemann                         Tester.parseSubst("%VAR").takeError());
11075ffd940aSRaphael Isemann 
11085ffd940aSRaphael Isemann   expectDiagnosticError("invalid pseudo numeric variable '@FOO'",
11095ffd940aSRaphael Isemann                         Tester.parseSubst("@FOO").takeError());
11105ffd940aSRaphael Isemann 
11115ffd940aSRaphael Isemann   // parsePattern() is used here instead of parseSubst() for the variable to be
11125ffd940aSRaphael Isemann   // recorded in GlobalNumericVariableTable and thus appear defined to
11135ffd940aSRaphael Isemann   // parseNumericVariableUse(). Note that the same pattern object is used for
11145ffd940aSRaphael Isemann   // the parsePattern() and parseSubst() since no initNextPattern() is called,
11155ffd940aSRaphael Isemann   // thus appearing as being on the same line from the pattern's point of view.
11165ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#SAME_LINE_VAR:]]"));
11175ffd940aSRaphael Isemann   expectDiagnosticError("numeric variable 'SAME_LINE_VAR' defined earlier in "
11185ffd940aSRaphael Isemann                         "the same CHECK directive",
11195ffd940aSRaphael Isemann                         Tester.parseSubst("SAME_LINE_VAR").takeError());
11205ffd940aSRaphael Isemann 
11215ffd940aSRaphael Isemann   // Invalid use of variable defined on the same line from an expression not
11225ffd940aSRaphael Isemann   // using any variable defined on the same line.
11235ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#SAME_LINE_EXPR_VAR:@LINE+1]]"));
11245ffd940aSRaphael Isemann   expectDiagnosticError("numeric variable 'SAME_LINE_EXPR_VAR' defined earlier "
11255ffd940aSRaphael Isemann                         "in the same CHECK directive",
11265ffd940aSRaphael Isemann                         Tester.parseSubst("SAME_LINE_EXPR_VAR").takeError());
11275ffd940aSRaphael Isemann 
11285ffd940aSRaphael Isemann   // Valid use of undefined variable which creates the variable and record it
11295ffd940aSRaphael Isemann   // in GlobalNumericVariableTable.
11305ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(Tester.parseSubst("UNDEF"), Succeeded());
11315ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[UNDEF:.*]]"));
11325ffd940aSRaphael Isemann 
11335ffd940aSRaphael Isemann   // Invalid literal.
11345ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation 'U'",
11355ffd940aSRaphael Isemann                         Tester.parseSubst("42U").takeError());
11365ffd940aSRaphael Isemann 
11375ffd940aSRaphael Isemann   // Valid empty expression.
11385ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst(""), Succeeded());
11395ffd940aSRaphael Isemann 
11405ffd940aSRaphael Isemann   // Invalid equality matching constraint with empty expression.
11415ffd940aSRaphael Isemann   expectDiagnosticError("empty numeric expression should not have a constraint",
11425ffd940aSRaphael Isemann                         Tester.parseSubst("==").takeError());
11435ffd940aSRaphael Isemann 
11445ffd940aSRaphael Isemann   // Valid single operand expression.
11455ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOO"), Succeeded());
11465ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("18"), Succeeded());
11475ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst(std::to_string(MaxUint64)),
11485ffd940aSRaphael Isemann                        Succeeded());
11495ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("0x12"), Succeeded());
11505ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("-30"), Succeeded());
11515ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst(std::to_string(MinInt64)),
11525ffd940aSRaphael Isemann                        Succeeded());
11535ffd940aSRaphael Isemann 
11545ffd940aSRaphael Isemann   // Valid optional matching constraint.
11555ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("==FOO"), Succeeded());
11565ffd940aSRaphael Isemann 
11575ffd940aSRaphael Isemann   // Invalid matching constraint.
11585ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching constraint or operand format",
11595ffd940aSRaphael Isemann                         Tester.parseSubst("+=FOO").takeError());
11605ffd940aSRaphael Isemann 
11615ffd940aSRaphael Isemann   // Invalid format.
11625ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching format specification in expression",
11635ffd940aSRaphael Isemann                         Tester.parseSubst("X,FOO:").takeError());
11645ffd940aSRaphael Isemann   expectDiagnosticError("invalid format specifier in expression",
11655ffd940aSRaphael Isemann                         Tester.parseSubst("%F,FOO").takeError());
11665ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching format specification in expression",
11675ffd940aSRaphael Isemann                         Tester.parseSubst("%X a,FOO").takeError());
11685ffd940aSRaphael Isemann 
11695ffd940aSRaphael Isemann   // Valid expression with 2 or more operands.
11705ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOO+3"), Succeeded());
11715ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOO+0xC"), Succeeded());
11725ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOO-3+FOO"), Succeeded());
11735ffd940aSRaphael Isemann 
11745ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation '/'",
11755ffd940aSRaphael Isemann                         Tester.parseSubst("@LINE/2").takeError());
11765ffd940aSRaphael Isemann 
11775ffd940aSRaphael Isemann   expectDiagnosticError("missing operand in expression",
11785ffd940aSRaphael Isemann                         Tester.parseSubst("@LINE+").takeError());
11795ffd940aSRaphael Isemann 
11805ffd940aSRaphael Isemann   // Errors in RHS operand are bubbled up by parseBinop() to
11815ffd940aSRaphael Isemann   // parseNumericSubstitutionBlock().
11825ffd940aSRaphael Isemann   expectDiagnosticError("invalid operand format",
11835ffd940aSRaphael Isemann                         Tester.parseSubst("@LINE+%VAR").takeError());
11845ffd940aSRaphael Isemann 
11855ffd940aSRaphael Isemann   // Invalid legacy @LINE expression with non literal rhs.
11865ffd940aSRaphael Isemann   expectDiagnosticError(
11875ffd940aSRaphael Isemann       "invalid operand format",
11885ffd940aSRaphael Isemann       Tester.parseSubst("@LINE+@LINE", /*IsLegacyNumExpr=*/true).takeError());
11895ffd940aSRaphael Isemann 
11905ffd940aSRaphael Isemann   // Invalid legacy @LINE expression made of a single literal.
11915ffd940aSRaphael Isemann   expectDiagnosticError(
11925ffd940aSRaphael Isemann       "invalid variable name",
11935ffd940aSRaphael Isemann       Tester.parseSubst("2", /*IsLegacyNumExpr=*/true).takeError());
11945ffd940aSRaphael Isemann 
11955ffd940aSRaphael Isemann   // Invalid hex literal in legacy @LINE expression.
11965ffd940aSRaphael Isemann   expectDiagnosticError(
11975ffd940aSRaphael Isemann       "unexpected characters at end of expression 'xC'",
11985ffd940aSRaphael Isemann       Tester.parseSubst("@LINE+0xC", /*LegacyLineExpr=*/true).takeError());
11995ffd940aSRaphael Isemann 
12005ffd940aSRaphael Isemann   // Valid expression with format specifier.
12015ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%u, FOO"), Succeeded());
12025ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%d, FOO"), Succeeded());
12035ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%x, FOO"), Succeeded());
12045ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%X, FOO"), Succeeded());
12055ffd940aSRaphael Isemann 
12065ffd940aSRaphael Isemann   // Valid expression with precision specifier.
12075ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%.8u, FOO"), Succeeded());
12085ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%.8, FOO"), Succeeded());
12095ffd940aSRaphael Isemann 
12105ffd940aSRaphael Isemann   // Valid legacy @LINE expression.
12115ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("@LINE+2", /*IsLegacyNumExpr=*/true),
12125ffd940aSRaphael Isemann                        Succeeded());
12135ffd940aSRaphael Isemann 
12145ffd940aSRaphael Isemann   // Invalid legacy @LINE expression with more than 2 operands.
12155ffd940aSRaphael Isemann   expectDiagnosticError(
12165ffd940aSRaphael Isemann       "unexpected characters at end of expression '+@LINE'",
12175ffd940aSRaphael Isemann       Tester.parseSubst("@LINE+2+@LINE", /*IsLegacyNumExpr=*/true).takeError());
12185ffd940aSRaphael Isemann   expectDiagnosticError(
12195ffd940aSRaphael Isemann       "unexpected characters at end of expression '+2'",
12205ffd940aSRaphael Isemann       Tester.parseSubst("@LINE+2+2", /*IsLegacyNumExpr=*/true).takeError());
12215ffd940aSRaphael Isemann 
12225ffd940aSRaphael Isemann   // Valid expression with several variables when their implicit formats do not
12235ffd940aSRaphael Isemann   // conflict.
12245ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOO+VAR_UNSIGNED"), Succeeded());
12255ffd940aSRaphael Isemann 
12265ffd940aSRaphael Isemann   // Valid implicit format conflict in presence of explicit formats.
12275ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%X,FOO+VAR_LOWER_HEX"), Succeeded());
12285ffd940aSRaphael Isemann 
12295ffd940aSRaphael Isemann   // Implicit format conflict.
12305ffd940aSRaphael Isemann   expectDiagnosticError(
12315ffd940aSRaphael Isemann       "implicit format conflict between 'FOO' (%u) and "
12325ffd940aSRaphael Isemann       "'VAR_LOWER_HEX' (%x), need an explicit format specifier",
12335ffd940aSRaphael Isemann       Tester.parseSubst("FOO+VAR_LOWER_HEX").takeError());
12345ffd940aSRaphael Isemann 
12355ffd940aSRaphael Isemann   // Simple parenthesized expressions:
12365ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("(1)"), Succeeded());
12375ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("(1+1)"), Succeeded());
12385ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("(1)+1"), Succeeded());
12395ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("((1)+1)"), Succeeded());
12405ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("((1)+X)"), Succeeded());
12415ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("((X)+Y)"), Succeeded());
12425ffd940aSRaphael Isemann 
12435ffd940aSRaphael Isemann   expectDiagnosticError("missing operand in expression",
12445ffd940aSRaphael Isemann                         Tester.parseSubst("(").takeError());
12455ffd940aSRaphael Isemann   expectDiagnosticError("missing ')' at end of nested expression",
12465ffd940aSRaphael Isemann                         Tester.parseSubst("(1").takeError());
12475ffd940aSRaphael Isemann   expectDiagnosticError("missing operand in expression",
12485ffd940aSRaphael Isemann                         Tester.parseSubst("(1+").takeError());
12495ffd940aSRaphael Isemann   expectDiagnosticError("missing ')' at end of nested expression",
12505ffd940aSRaphael Isemann                         Tester.parseSubst("(1+1").takeError());
12515ffd940aSRaphael Isemann   expectDiagnosticError("missing ')' at end of nested expression",
12525ffd940aSRaphael Isemann                         Tester.parseSubst("((1+2+3").takeError());
12535ffd940aSRaphael Isemann   expectDiagnosticError("missing ')' at end of nested expression",
12545ffd940aSRaphael Isemann                         Tester.parseSubst("((1+2)+3").takeError());
12555ffd940aSRaphael Isemann 
12565ffd940aSRaphael Isemann   // Test missing operation between operands:
12575ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation '('",
12585ffd940aSRaphael Isemann                         Tester.parseSubst("(1)(2)").takeError());
12595ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation '('",
12605ffd940aSRaphael Isemann                         Tester.parseSubst("2(X)").takeError());
12615ffd940aSRaphael Isemann 
12625ffd940aSRaphael Isemann   // Test more closing than opening parentheses. The diagnostic messages are
12635ffd940aSRaphael Isemann   // not ideal, but for now simply check that we reject invalid input.
12645ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching constraint or operand format",
12655ffd940aSRaphael Isemann                         Tester.parseSubst(")").takeError());
12665ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation ')'",
12675ffd940aSRaphael Isemann                         Tester.parseSubst("1)").takeError());
12685ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation ')'",
12695ffd940aSRaphael Isemann                         Tester.parseSubst("(1+2))").takeError());
12705ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation ')'",
12715ffd940aSRaphael Isemann                         Tester.parseSubst("(2))").takeError());
12725ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation ')'",
12735ffd940aSRaphael Isemann                         Tester.parseSubst("(1))(").takeError());
12745ffd940aSRaphael Isemann 
12755ffd940aSRaphael Isemann   // Valid expression with function call.
12765ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add(FOO,3)"), Succeeded());
12775ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add (FOO,3)"), Succeeded());
12785ffd940aSRaphael Isemann   // Valid expression with nested function call.
12795ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add(FOO, min(BAR,10))"), Succeeded());
12805ffd940aSRaphael Isemann   // Valid expression with function call taking expression as argument.
12815ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add(FOO, (BAR+10) + 3)"),
12825ffd940aSRaphael Isemann                        Succeeded());
12835ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add(FOO, min (BAR,10) + 3)"),
12845ffd940aSRaphael Isemann                        Succeeded());
12855ffd940aSRaphael Isemann   // Valid expression with variable named the same as a function.
12865ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add"), Succeeded());
12875ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add+FOO"), Succeeded());
12885ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOO+add"), Succeeded());
12895ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add(add,add)+add"), Succeeded());
12905ffd940aSRaphael Isemann 
12915ffd940aSRaphael Isemann   // Malformed call syntax.
12925ffd940aSRaphael Isemann   expectDiagnosticError("missing ')' at end of call expression",
12935ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO,(BAR+7)").takeError());
12945ffd940aSRaphael Isemann   expectDiagnosticError("missing ')' at end of call expression",
12955ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO,min(BAR,7)").takeError());
12965ffd940aSRaphael Isemann   expectDiagnosticError("missing argument",
12975ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO,)").takeError());
12985ffd940aSRaphael Isemann   expectDiagnosticError("missing argument",
12995ffd940aSRaphael Isemann                         Tester.parseSubst("add(,FOO)").takeError());
13005ffd940aSRaphael Isemann   expectDiagnosticError("missing argument",
13015ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO,,3)").takeError());
13025ffd940aSRaphael Isemann 
13035ffd940aSRaphael Isemann   // Valid call, but to an unknown function.
13045ffd940aSRaphael Isemann   expectDiagnosticError("call to undefined function 'bogus_function'",
13055ffd940aSRaphael Isemann                         Tester.parseSubst("bogus_function(FOO,3)").takeError());
13065ffd940aSRaphael Isemann   expectDiagnosticError("call to undefined function '@add'",
13075ffd940aSRaphael Isemann                         Tester.parseSubst("@add(2,3)").takeError());
13085ffd940aSRaphael Isemann   expectDiagnosticError("call to undefined function '$add'",
13095ffd940aSRaphael Isemann                         Tester.parseSubst("$add(2,3)").takeError());
13105ffd940aSRaphael Isemann   expectDiagnosticError("call to undefined function 'FOO'",
13115ffd940aSRaphael Isemann                         Tester.parseSubst("FOO(2,3)").takeError());
13125ffd940aSRaphael Isemann   expectDiagnosticError("call to undefined function 'FOO'",
13135ffd940aSRaphael Isemann                         Tester.parseSubst("FOO (2,3)").takeError());
13145ffd940aSRaphael Isemann 
13155ffd940aSRaphael Isemann   // Valid call, but with incorrect argument count.
13165ffd940aSRaphael Isemann   expectDiagnosticError("function 'add' takes 2 arguments but 1 given",
13175ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO)").takeError());
13185ffd940aSRaphael Isemann   expectDiagnosticError("function 'add' takes 2 arguments but 3 given",
13195ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO,3,4)").takeError());
13205ffd940aSRaphael Isemann 
13215ffd940aSRaphael Isemann   // Valid call, but not part of a valid expression.
13225ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation 'a'",
13235ffd940aSRaphael Isemann                         Tester.parseSubst("2add(FOO,2)").takeError());
13245ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation 'a'",
13255ffd940aSRaphael Isemann                         Tester.parseSubst("FOO add(FOO,2)").takeError());
13265ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation 'a'",
13275ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO,2)add(FOO,2)").takeError());
13285ffd940aSRaphael Isemann }
13295ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,ParsePattern)13305ffd940aSRaphael Isemann TEST_F(FileCheckTest, ParsePattern) {
13315ffd940aSRaphael Isemann   PatternTester Tester;
13325ffd940aSRaphael Isemann 
13335ffd940aSRaphael Isemann   // Invalid space in string substitution.
13345ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[ BAR]]"));
13355ffd940aSRaphael Isemann 
13365ffd940aSRaphael Isemann   // Invalid variable name in string substitution.
13375ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[42INVALID]]"));
13385ffd940aSRaphael Isemann 
13395ffd940aSRaphael Isemann   // Invalid string variable definition.
13405ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[@PAT:]]"));
13415ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[PAT+2:]]"));
13425ffd940aSRaphael Isemann 
13435ffd940aSRaphael Isemann   // Collision with numeric variable.
13445ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[FOO:]]"));
13455ffd940aSRaphael Isemann 
1346058455ffSThomas Preud'homme   // Invalid use of string variable.
1347058455ffSThomas Preud'homme   EXPECT_TRUE(Tester.parsePattern("[[FOO-BAR]]"));
1348058455ffSThomas Preud'homme 
13495ffd940aSRaphael Isemann   // Valid use of string variable.
13505ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[BAR]]"));
13515ffd940aSRaphael Isemann 
13525ffd940aSRaphael Isemann   // Valid string variable definition.
13535ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[PAT:[0-9]+]]"));
13545ffd940aSRaphael Isemann 
13555ffd940aSRaphael Isemann   // Invalid numeric substitution.
13565ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[#42INVALID]]"));
13575ffd940aSRaphael Isemann 
13585ffd940aSRaphael Isemann   // Valid numeric substitution.
13595ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[#FOO]]"));
13605ffd940aSRaphael Isemann 
13615ffd940aSRaphael Isemann   // Valid legacy @LINE expression.
13625ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[@LINE+2]]"));
13635ffd940aSRaphael Isemann 
13645ffd940aSRaphael Isemann   // Invalid legacy @LINE expression with non decimal literal.
13655ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[@LINE+0x3]]"));
13665ffd940aSRaphael Isemann }
13675ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,Match)13685ffd940aSRaphael Isemann TEST_F(FileCheckTest, Match) {
13695ffd940aSRaphael Isemann   PatternTester Tester;
13705ffd940aSRaphael Isemann 
13715ffd940aSRaphael Isemann   // Check a substitution error is diagnosed.
13725ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#%u, -1]]"));
13735ffd940aSRaphael Isemann   expectDiagnosticError(
13745ffd940aSRaphael Isemann       "unable to substitute variable or numeric expression: overflow error",
13755ffd940aSRaphael Isemann       Tester.match("").takeError());
13765ffd940aSRaphael Isemann 
13775ffd940aSRaphael Isemann   // Check matching an empty expression only matches a number.
13785ffd940aSRaphael Isemann   Tester.initNextPattern();
13795ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#]]"));
13805ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("FAIL").takeError());
13815ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
13825ffd940aSRaphael Isemann 
13835ffd940aSRaphael Isemann   // Check matching a definition only matches a number with the right format.
13845ffd940aSRaphael Isemann   Tester.initNextPattern();
13855ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR:]]"));
13865ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("FAIL").takeError());
13875ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("").takeError());
13885ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
13895ffd940aSRaphael Isemann   Tester.initNextPattern();
13905ffd940aSRaphael Isemann   Tester.parsePattern("[[#%u,NUMVAR_UNSIGNED:]]");
13915ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("C").takeError());
13925ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("20"), Succeeded());
13935ffd940aSRaphael Isemann   Tester.initNextPattern();
13945ffd940aSRaphael Isemann   Tester.parsePattern("[[#%x,NUMVAR_LOWER_HEX:]]");
13955ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("g").takeError());
13965ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("C").takeError());
13975ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("c"), Succeeded());
13985ffd940aSRaphael Isemann   Tester.initNextPattern();
13995ffd940aSRaphael Isemann   Tester.parsePattern("[[#%X,NUMVAR_UPPER_HEX:]]");
14005ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("H").takeError());
14015ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("b").takeError());
14025ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("B"), Succeeded());
14035ffd940aSRaphael Isemann 
14045ffd940aSRaphael Isemann   // Check matching expressions with no explicit format matches the values in
14055ffd940aSRaphael Isemann   // the right format.
14065ffd940aSRaphael Isemann   Tester.initNextPattern();
14075ffd940aSRaphael Isemann   Tester.parsePattern("[[#NUMVAR_UNSIGNED-5]]");
14085ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("f").takeError());
14095ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("F").takeError());
14105ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("15"), Succeeded());
14115ffd940aSRaphael Isemann   Tester.initNextPattern();
14125ffd940aSRaphael Isemann   Tester.parsePattern("[[#NUMVAR_LOWER_HEX+1]]");
14135ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("13").takeError());
14145ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("D").takeError());
14155ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("d"), Succeeded());
14165ffd940aSRaphael Isemann   Tester.initNextPattern();
14175ffd940aSRaphael Isemann   Tester.parsePattern("[[#NUMVAR_UPPER_HEX+1]]");
14185ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("12").takeError());
14195ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("c").takeError());
14205ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("C"), Succeeded());
14215ffd940aSRaphael Isemann 
14225ffd940aSRaphael Isemann   // Check matching an undefined variable returns a NotFound error.
14235ffd940aSRaphael Isemann   Tester.initNextPattern();
14245ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("100"));
14255ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("101").takeError());
14265ffd940aSRaphael Isemann 
14275ffd940aSRaphael Isemann   // Check matching the defined variable matches the correct number only.
14285ffd940aSRaphael Isemann   Tester.initNextPattern();
14295ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR]]"));
14305ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
14315ffd940aSRaphael Isemann 
14325ffd940aSRaphael Isemann   // Check matching several substitutions does not match them independently.
14335ffd940aSRaphael Isemann   Tester.initNextPattern();
14345ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR]] [[#NUMVAR+2]]"));
14355ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("19 21").takeError());
14365ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("18 21").takeError());
14375ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18 20"), Succeeded());
14385ffd940aSRaphael Isemann 
14395ffd940aSRaphael Isemann   // Check matching a numeric expression using @LINE after a match failure uses
14405ffd940aSRaphael Isemann   // the correct value for @LINE.
14415ffd940aSRaphael Isemann   Tester.initNextPattern();
14425ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#@LINE]]"));
14435ffd940aSRaphael Isemann   // Ok, @LINE matches the current line number.
14445ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match(std::to_string(Tester.getLineNumber())),
14455ffd940aSRaphael Isemann                        Succeeded());
14465ffd940aSRaphael Isemann   Tester.initNextPattern();
14475ffd940aSRaphael Isemann   // Match with substitution failure.
1448fd941036SThomas Preud'homme   ASSERT_FALSE(Tester.parsePattern("[[#UNKNOWN1+UNKNOWN2]]"));
1449fd941036SThomas Preud'homme   expectSameErrors<ErrorDiagnostic>(
1450fd941036SThomas Preud'homme       {"undefined variable: UNKNOWN1", "undefined variable: UNKNOWN2"},
1451fd941036SThomas Preud'homme       Tester.match("FOO").takeError());
14525ffd940aSRaphael Isemann   Tester.initNextPattern();
14535ffd940aSRaphael Isemann   // Check that @LINE matches the later (given the calls to initNextPattern())
14545ffd940aSRaphael Isemann   // line number.
14555ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[#@LINE]]"));
14565ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match(std::to_string(Tester.getLineNumber())),
14575ffd940aSRaphael Isemann                        Succeeded());
14585ffd940aSRaphael Isemann }
14595ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,MatchParen)14605ffd940aSRaphael Isemann TEST_F(FileCheckTest, MatchParen) {
14615ffd940aSRaphael Isemann   PatternTester Tester;
14625ffd940aSRaphael Isemann   // Check simple parenthesized expressions
14635ffd940aSRaphael Isemann   Tester.initNextPattern();
14645ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR:]]"));
14655ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("FAIL").takeError());
14665ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("").takeError());
14675ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
14685ffd940aSRaphael Isemann 
14695ffd940aSRaphael Isemann   Tester.initNextPattern();
14705ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR + (2 + 2)]]"));
14715ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("21").takeError());
14725ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("22"), Succeeded());
14735ffd940aSRaphael Isemann   Tester.initNextPattern();
14745ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR + (2)]]"));
14755ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("20"), Succeeded());
14765ffd940aSRaphael Isemann   Tester.initNextPattern();
14775ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR+(2)]]"));
14785ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("20"), Succeeded());
14795ffd940aSRaphael Isemann   Tester.initNextPattern();
14805ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR+(NUMVAR)]]"));
14815ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("36"), Succeeded());
14825ffd940aSRaphael Isemann 
14835ffd940aSRaphael Isemann   // Check nested parenthesized expressions:
14845ffd940aSRaphael Isemann   Tester.initNextPattern();
14855ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR+(2+(2))]]"));
14865ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("22"), Succeeded());
14875ffd940aSRaphael Isemann   Tester.initNextPattern();
14885ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR+(2+(NUMVAR))]]"));
14895ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("38"), Succeeded());
14905ffd940aSRaphael Isemann   Tester.initNextPattern();
14915ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR+((((NUMVAR))))]]"));
14925ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("36"), Succeeded());
14935ffd940aSRaphael Isemann   Tester.initNextPattern();
14945ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR+((((NUMVAR)))-1)-1]]"));
14955ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("34"), Succeeded());
14965ffd940aSRaphael Isemann 
14975ffd940aSRaphael Isemann   // Parentheses can also be the first character after the '#':
14985ffd940aSRaphael Isemann   Tester.initNextPattern();
14995ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#(NUMVAR)]]"));
15005ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
15015ffd940aSRaphael Isemann   Tester.initNextPattern();
15025ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#(NUMVAR+2)]]"));
15035ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("20"), Succeeded());
15045ffd940aSRaphael Isemann }
15055ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,MatchBuiltinFunctions)15065ffd940aSRaphael Isemann TEST_F(FileCheckTest, MatchBuiltinFunctions) {
15075ffd940aSRaphael Isemann   PatternTester Tester;
15085ffd940aSRaphael Isemann   // Esnure #NUMVAR has the expected value.
15095ffd940aSRaphael Isemann   Tester.initNextPattern();
15105ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR:]]"));
15115ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("FAIL").takeError());
15125ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("").takeError());
15135ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
15145ffd940aSRaphael Isemann 
15155ffd940aSRaphael Isemann   // Check each builtin function generates the expected result.
15165ffd940aSRaphael Isemann   Tester.initNextPattern();
15175ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#add(NUMVAR,13)]]"));
15185ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("31"), Succeeded());
15195ffd940aSRaphael Isemann   Tester.initNextPattern();
15205ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#div(NUMVAR,3)]]"));
15215ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("6"), Succeeded());
15225ffd940aSRaphael Isemann   Tester.initNextPattern();
15235ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#max(NUMVAR,5)]]"));
15245ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
15255ffd940aSRaphael Isemann   Tester.initNextPattern();
15265ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#max(NUMVAR,99)]]"));
15275ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("99"), Succeeded());
15285ffd940aSRaphael Isemann   Tester.initNextPattern();
15295ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#min(NUMVAR,5)]]"));
15305ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("5"), Succeeded());
15315ffd940aSRaphael Isemann   Tester.initNextPattern();
15325ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#min(NUMVAR,99)]]"));
15335ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
15345ffd940aSRaphael Isemann   Tester.initNextPattern();
15355ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#mul(NUMVAR,3)]]"));
15365ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("54"), Succeeded());
15375ffd940aSRaphael Isemann   Tester.initNextPattern();
15385ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#sub(NUMVAR,7)]]"));
15395ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("11"), Succeeded());
15405ffd940aSRaphael Isemann 
15415ffd940aSRaphael Isemann   // Check nested function calls.
15425ffd940aSRaphael Isemann   Tester.initNextPattern();
15435ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#add(min(7,2),max(4,10))]]"));
15445ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("12"), Succeeded());
15455ffd940aSRaphael Isemann 
15465ffd940aSRaphael Isemann   // Check function call that uses a variable of the same name.
15475ffd940aSRaphael Isemann   Tester.initNextPattern();
15485ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#add(add,add)+min (add,3)+add]]"));
15495ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("24"), Succeeded());
15505ffd940aSRaphael Isemann }
15515ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,Substitution)15525ffd940aSRaphael Isemann TEST_F(FileCheckTest, Substitution) {
15535ffd940aSRaphael Isemann   SourceMgr SM;
15545ffd940aSRaphael Isemann   FileCheckPatternContext Context;
15555ffd940aSRaphael Isemann   EXPECT_THAT_ERROR(Context.defineCmdlineVariables({"FOO=BAR"}, SM),
15565ffd940aSRaphael Isemann                     Succeeded());
15575ffd940aSRaphael Isemann 
15585ffd940aSRaphael Isemann   // Substitution of an undefined string variable fails and error holds that
15595ffd940aSRaphael Isemann   // variable's name.
15605ffd940aSRaphael Isemann   StringSubstitution StringSubstitution(&Context, "VAR404", 42);
15615ffd940aSRaphael Isemann   Expected<std::string> SubstValue = StringSubstitution.getResult();
15625ffd940aSRaphael Isemann   expectUndefErrors({"VAR404"}, SubstValue.takeError());
15635ffd940aSRaphael Isemann 
15645ffd940aSRaphael Isemann   // Numeric substitution blocks constituted of defined numeric variables are
15655ffd940aSRaphael Isemann   // substituted for the variable's value.
15665ffd940aSRaphael Isemann   NumericVariable NVar("N", ExpressionFormat(ExpressionFormat::Kind::Unsigned),
15675ffd940aSRaphael Isemann                        1);
15685ffd940aSRaphael Isemann   NVar.setValue(ExpressionValue(10u));
15695ffd940aSRaphael Isemann   auto NVarUse = std::make_unique<NumericVariableUse>("N", &NVar);
15705ffd940aSRaphael Isemann   auto ExpressionN = std::make_unique<Expression>(
15715ffd940aSRaphael Isemann       std::move(NVarUse), ExpressionFormat(ExpressionFormat::Kind::HexUpper));
15725ffd940aSRaphael Isemann   NumericSubstitution SubstitutionN(&Context, "N", std::move(ExpressionN),
15735ffd940aSRaphael Isemann                                     /*InsertIdx=*/30);
15745ffd940aSRaphael Isemann   SubstValue = SubstitutionN.getResult();
15755ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SubstValue, Succeeded());
15765ffd940aSRaphael Isemann   EXPECT_EQ("A", *SubstValue);
15775ffd940aSRaphael Isemann 
15785ffd940aSRaphael Isemann   // Substitution of an undefined numeric variable fails, error holds name of
15795ffd940aSRaphael Isemann   // undefined variable.
15805ffd940aSRaphael Isemann   NVar.clearValue();
15815ffd940aSRaphael Isemann   SubstValue = SubstitutionN.getResult();
15825ffd940aSRaphael Isemann   expectUndefErrors({"N"}, SubstValue.takeError());
15835ffd940aSRaphael Isemann 
15845ffd940aSRaphael Isemann   // Substitution of a defined string variable returns the right value.
15855ffd940aSRaphael Isemann   Pattern P(Check::CheckPlain, &Context, 1);
15865ffd940aSRaphael Isemann   StringSubstitution = llvm::StringSubstitution(&Context, "FOO", 42);
15875ffd940aSRaphael Isemann   SubstValue = StringSubstitution.getResult();
15885ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SubstValue, Succeeded());
15895ffd940aSRaphael Isemann   EXPECT_EQ("BAR", *SubstValue);
15905ffd940aSRaphael Isemann }
15915ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,FileCheckContext)15925ffd940aSRaphael Isemann TEST_F(FileCheckTest, FileCheckContext) {
15935ffd940aSRaphael Isemann   FileCheckPatternContext Cxt;
15945ffd940aSRaphael Isemann   SourceMgr SM;
15955ffd940aSRaphael Isemann 
15965ffd940aSRaphael Isemann   // No definition.
15975ffd940aSRaphael Isemann   EXPECT_THAT_ERROR(Cxt.defineCmdlineVariables({}, SM), Succeeded());
15985ffd940aSRaphael Isemann 
15995ffd940aSRaphael Isemann   // Missing equal sign.
16005ffd940aSRaphael Isemann   expectDiagnosticError("missing equal sign in global definition",
16015ffd940aSRaphael Isemann                         Cxt.defineCmdlineVariables({"LocalVar"}, SM));
16025ffd940aSRaphael Isemann   expectDiagnosticError("missing equal sign in global definition",
16035ffd940aSRaphael Isemann                         Cxt.defineCmdlineVariables({"#LocalNumVar"}, SM));
16045ffd940aSRaphael Isemann 
16055ffd940aSRaphael Isemann   // Empty variable name.
16065ffd940aSRaphael Isemann   expectDiagnosticError("empty variable name",
16075ffd940aSRaphael Isemann                         Cxt.defineCmdlineVariables({"=18"}, SM));
16085ffd940aSRaphael Isemann   expectDiagnosticError("empty variable name",
16095ffd940aSRaphael Isemann                         Cxt.defineCmdlineVariables({"#=18"}, SM));
16105ffd940aSRaphael Isemann 
16115ffd940aSRaphael Isemann   // Invalid variable name.
16125ffd940aSRaphael Isemann   expectDiagnosticError("invalid variable name",
16135ffd940aSRaphael Isemann                         Cxt.defineCmdlineVariables({"18LocalVar=18"}, SM));
16145ffd940aSRaphael Isemann   expectDiagnosticError("invalid variable name",
16155ffd940aSRaphael Isemann                         Cxt.defineCmdlineVariables({"#18LocalNumVar=18"}, SM));
16165ffd940aSRaphael Isemann 
16175ffd940aSRaphael Isemann   // Name conflict between pattern and numeric variable.
16185ffd940aSRaphael Isemann   expectDiagnosticError(
16195ffd940aSRaphael Isemann       "string variable with name 'LocalVar' already exists",
16205ffd940aSRaphael Isemann       Cxt.defineCmdlineVariables({"LocalVar=18", "#LocalVar=36"}, SM));
16215ffd940aSRaphael Isemann   Cxt = FileCheckPatternContext();
16225ffd940aSRaphael Isemann   expectDiagnosticError(
16235ffd940aSRaphael Isemann       "numeric variable with name 'LocalNumVar' already exists",
16245ffd940aSRaphael Isemann       Cxt.defineCmdlineVariables({"#LocalNumVar=18", "LocalNumVar=36"}, SM));
16255ffd940aSRaphael Isemann   Cxt = FileCheckPatternContext();
16265ffd940aSRaphael Isemann 
16275ffd940aSRaphael Isemann   // Invalid numeric value for numeric variable.
16285ffd940aSRaphael Isemann   expectUndefErrors({"x"}, Cxt.defineCmdlineVariables({"#LocalNumVar=x"}, SM));
16295ffd940aSRaphael Isemann 
16305ffd940aSRaphael Isemann   // Define local variables from command-line.
16315ffd940aSRaphael Isemann   std::vector<StringRef> GlobalDefines;
16325ffd940aSRaphael Isemann   // Clear local variables to remove dummy numeric variable x that
16335ffd940aSRaphael Isemann   // parseNumericSubstitutionBlock would have created and stored in
16345ffd940aSRaphael Isemann   // GlobalNumericVariableTable.
16355ffd940aSRaphael Isemann   Cxt.clearLocalVars();
16365ffd940aSRaphael Isemann   GlobalDefines.emplace_back("LocalVar=FOO");
16375ffd940aSRaphael Isemann   GlobalDefines.emplace_back("EmptyVar=");
16385ffd940aSRaphael Isemann   GlobalDefines.emplace_back("#LocalNumVar1=18");
16395ffd940aSRaphael Isemann   GlobalDefines.emplace_back("#%x,LocalNumVar2=LocalNumVar1+2");
16405ffd940aSRaphael Isemann   GlobalDefines.emplace_back("#LocalNumVar3=0xc");
16415ffd940aSRaphael Isemann   ASSERT_THAT_ERROR(Cxt.defineCmdlineVariables(GlobalDefines, SM), Succeeded());
16425ffd940aSRaphael Isemann 
16435ffd940aSRaphael Isemann   // Create @LINE pseudo numeric variable and check it is present by matching
16445ffd940aSRaphael Isemann   // it.
16455ffd940aSRaphael Isemann   size_t LineNumber = 1;
16465ffd940aSRaphael Isemann   Pattern P(Check::CheckPlain, &Cxt, LineNumber);
16475ffd940aSRaphael Isemann   FileCheckRequest Req;
16485ffd940aSRaphael Isemann   Cxt.createLineVariable();
16495ffd940aSRaphael Isemann   ASSERT_FALSE(P.parsePattern("[[@LINE]]", "CHECK", SM, Req));
1650dd59c132SJoel E. Denny   Pattern::MatchResult Res = P.match("1", SM);
1651dd59c132SJoel E. Denny   ASSERT_THAT_ERROR(std::move(Res.TheError), Succeeded());
16525ffd940aSRaphael Isemann 
16535ffd940aSRaphael Isemann #ifndef NDEBUG
16545ffd940aSRaphael Isemann   // Recreating @LINE pseudo numeric variable fails.
16555ffd940aSRaphael Isemann   EXPECT_DEATH(Cxt.createLineVariable(),
16565ffd940aSRaphael Isemann                "@LINE pseudo numeric variable already created");
16575ffd940aSRaphael Isemann #endif
16585ffd940aSRaphael Isemann 
16595ffd940aSRaphael Isemann   // Check defined variables are present and undefined ones are absent.
16605ffd940aSRaphael Isemann   StringRef LocalVarStr = "LocalVar";
16615ffd940aSRaphael Isemann   StringRef LocalNumVar1Ref = bufferize(SM, "LocalNumVar1");
16625ffd940aSRaphael Isemann   StringRef LocalNumVar2Ref = bufferize(SM, "LocalNumVar2");
16635ffd940aSRaphael Isemann   StringRef LocalNumVar3Ref = bufferize(SM, "LocalNumVar3");
16645ffd940aSRaphael Isemann   StringRef EmptyVarStr = "EmptyVar";
16655ffd940aSRaphael Isemann   StringRef UnknownVarStr = "UnknownVar";
16665ffd940aSRaphael Isemann   Expected<StringRef> LocalVar = Cxt.getPatternVarValue(LocalVarStr);
16675ffd940aSRaphael Isemann   P = Pattern(Check::CheckPlain, &Cxt, ++LineNumber);
16685ffd940aSRaphael Isemann   Optional<NumericVariable *> DefinedNumericVariable;
16695ffd940aSRaphael Isemann   Expected<std::unique_ptr<Expression>> ExpressionPointer =
16705ffd940aSRaphael Isemann       P.parseNumericSubstitutionBlock(LocalNumVar1Ref, DefinedNumericVariable,
16715ffd940aSRaphael Isemann                                       /*IsLegacyLineExpr=*/false, LineNumber,
16725ffd940aSRaphael Isemann                                       &Cxt, SM);
16735ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(LocalVar, Succeeded());
16745ffd940aSRaphael Isemann   EXPECT_EQ(*LocalVar, "FOO");
16755ffd940aSRaphael Isemann   Expected<StringRef> EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
16765ffd940aSRaphael Isemann   Expected<StringRef> UnknownVar = Cxt.getPatternVarValue(UnknownVarStr);
16775ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
16785ffd940aSRaphael Isemann   Expected<ExpressionValue> ExpressionVal =
16795ffd940aSRaphael Isemann       (*ExpressionPointer)->getAST()->eval();
16805ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionVal, Succeeded());
16815ffd940aSRaphael Isemann   EXPECT_EQ(cantFail(ExpressionVal->getSignedValue()), 18);
16825ffd940aSRaphael Isemann   ExpressionPointer = P.parseNumericSubstitutionBlock(
16835ffd940aSRaphael Isemann       LocalNumVar2Ref, DefinedNumericVariable,
16845ffd940aSRaphael Isemann       /*IsLegacyLineExpr=*/false, LineNumber, &Cxt, SM);
16855ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
16865ffd940aSRaphael Isemann   ExpressionVal = (*ExpressionPointer)->getAST()->eval();
16875ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionVal, Succeeded());
16885ffd940aSRaphael Isemann   EXPECT_EQ(cantFail(ExpressionVal->getSignedValue()), 20);
16895ffd940aSRaphael Isemann   ExpressionPointer = P.parseNumericSubstitutionBlock(
16905ffd940aSRaphael Isemann       LocalNumVar3Ref, DefinedNumericVariable,
16915ffd940aSRaphael Isemann       /*IsLegacyLineExpr=*/false, LineNumber, &Cxt, SM);
16925ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
16935ffd940aSRaphael Isemann   ExpressionVal = (*ExpressionPointer)->getAST()->eval();
16945ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionVal, Succeeded());
16955ffd940aSRaphael Isemann   EXPECT_EQ(cantFail(ExpressionVal->getSignedValue()), 12);
16965ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(EmptyVar, Succeeded());
16975ffd940aSRaphael Isemann   EXPECT_EQ(*EmptyVar, "");
16985ffd940aSRaphael Isemann   expectUndefErrors({std::string(UnknownVarStr)}, UnknownVar.takeError());
16995ffd940aSRaphael Isemann 
17005ffd940aSRaphael Isemann   // Clear local variables and check they become absent.
17015ffd940aSRaphael Isemann   Cxt.clearLocalVars();
17025ffd940aSRaphael Isemann   LocalVar = Cxt.getPatternVarValue(LocalVarStr);
17035ffd940aSRaphael Isemann   expectUndefErrors({std::string(LocalVarStr)}, LocalVar.takeError());
17045ffd940aSRaphael Isemann   // Check a numeric expression's evaluation fails if called after clearing of
17055ffd940aSRaphael Isemann   // local variables, if it was created before. This is important because local
17065ffd940aSRaphael Isemann   // variable clearing due to --enable-var-scope happens after numeric
17075ffd940aSRaphael Isemann   // expressions are linked to the numeric variables they use.
17085ffd940aSRaphael Isemann   expectUndefErrors({"LocalNumVar3"},
17095ffd940aSRaphael Isemann                     (*ExpressionPointer)->getAST()->eval().takeError());
17105ffd940aSRaphael Isemann   P = Pattern(Check::CheckPlain, &Cxt, ++LineNumber);
17115ffd940aSRaphael Isemann   ExpressionPointer = P.parseNumericSubstitutionBlock(
17125ffd940aSRaphael Isemann       LocalNumVar1Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
17135ffd940aSRaphael Isemann       LineNumber, &Cxt, SM);
17145ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
17155ffd940aSRaphael Isemann   ExpressionVal = (*ExpressionPointer)->getAST()->eval();
17165ffd940aSRaphael Isemann   expectUndefErrors({"LocalNumVar1"}, ExpressionVal.takeError());
17175ffd940aSRaphael Isemann   ExpressionPointer = P.parseNumericSubstitutionBlock(
17185ffd940aSRaphael Isemann       LocalNumVar2Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
17195ffd940aSRaphael Isemann       LineNumber, &Cxt, SM);
17205ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
17215ffd940aSRaphael Isemann   ExpressionVal = (*ExpressionPointer)->getAST()->eval();
17225ffd940aSRaphael Isemann   expectUndefErrors({"LocalNumVar2"}, ExpressionVal.takeError());
17235ffd940aSRaphael Isemann   EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
17245ffd940aSRaphael Isemann   expectUndefErrors({"EmptyVar"}, EmptyVar.takeError());
17255ffd940aSRaphael Isemann   // Clear again because parseNumericSubstitutionBlock would have created a
17265ffd940aSRaphael Isemann   // dummy variable and stored it in GlobalNumericVariableTable.
17275ffd940aSRaphael Isemann   Cxt.clearLocalVars();
17285ffd940aSRaphael Isemann 
17295ffd940aSRaphael Isemann   // Redefine global variables and check variables are defined again.
17305ffd940aSRaphael Isemann   GlobalDefines.emplace_back("$GlobalVar=BAR");
17315ffd940aSRaphael Isemann   GlobalDefines.emplace_back("#$GlobalNumVar=36");
17325ffd940aSRaphael Isemann   ASSERT_THAT_ERROR(Cxt.defineCmdlineVariables(GlobalDefines, SM), Succeeded());
17335ffd940aSRaphael Isemann   StringRef GlobalVarStr = "$GlobalVar";
17345ffd940aSRaphael Isemann   StringRef GlobalNumVarRef = bufferize(SM, "$GlobalNumVar");
17355ffd940aSRaphael Isemann   Expected<StringRef> GlobalVar = Cxt.getPatternVarValue(GlobalVarStr);
17365ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(GlobalVar, Succeeded());
17375ffd940aSRaphael Isemann   EXPECT_EQ(*GlobalVar, "BAR");
17385ffd940aSRaphael Isemann   P = Pattern(Check::CheckPlain, &Cxt, ++LineNumber);
17395ffd940aSRaphael Isemann   ExpressionPointer = P.parseNumericSubstitutionBlock(
17405ffd940aSRaphael Isemann       GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
17415ffd940aSRaphael Isemann       LineNumber, &Cxt, SM);
17425ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
17435ffd940aSRaphael Isemann   ExpressionVal = (*ExpressionPointer)->getAST()->eval();
17445ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionVal, Succeeded());
17455ffd940aSRaphael Isemann   EXPECT_EQ(cantFail(ExpressionVal->getSignedValue()), 36);
17465ffd940aSRaphael Isemann 
17475ffd940aSRaphael Isemann   // Clear local variables and check global variables remain defined.
17485ffd940aSRaphael Isemann   Cxt.clearLocalVars();
17495ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Cxt.getPatternVarValue(GlobalVarStr), Succeeded());
17505ffd940aSRaphael Isemann   P = Pattern(Check::CheckPlain, &Cxt, ++LineNumber);
17515ffd940aSRaphael Isemann   ExpressionPointer = P.parseNumericSubstitutionBlock(
17525ffd940aSRaphael Isemann       GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
17535ffd940aSRaphael Isemann       LineNumber, &Cxt, SM);
17545ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
17555ffd940aSRaphael Isemann   ExpressionVal = (*ExpressionPointer)->getAST()->eval();
17565ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionVal, Succeeded());
17575ffd940aSRaphael Isemann   EXPECT_EQ(cantFail(ExpressionVal->getSignedValue()), 36);
17585ffd940aSRaphael Isemann }
17595ffd940aSRaphael Isemann 
TEST_F(FileCheckTest,CapturedVarDiags)17605ffd940aSRaphael Isemann TEST_F(FileCheckTest, CapturedVarDiags) {
17615ffd940aSRaphael Isemann   PatternTester Tester;
17625ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[STRVAR:[a-z]+]] [[#NUMVAR:@LINE]]"));
17635ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("foobar 2"), Succeeded());
17645ffd940aSRaphael Isemann   std::vector<FileCheckDiag> Diags;
17655ffd940aSRaphael Isemann   Tester.printVariableDefs(FileCheckDiag::MatchFoundAndExpected, Diags);
17665ffd940aSRaphael Isemann   EXPECT_EQ(Diags.size(), 2ul);
17675ffd940aSRaphael Isemann   for (FileCheckDiag Diag : Diags) {
17685ffd940aSRaphael Isemann     EXPECT_EQ(Diag.CheckTy, Check::CheckPlain);
17695ffd940aSRaphael Isemann     EXPECT_EQ(Diag.MatchTy, FileCheckDiag::MatchFoundAndExpected);
17705ffd940aSRaphael Isemann     EXPECT_EQ(Diag.InputStartLine, 1u);
17715ffd940aSRaphael Isemann     EXPECT_EQ(Diag.InputEndLine, 1u);
17725ffd940aSRaphael Isemann   }
17735ffd940aSRaphael Isemann   EXPECT_EQ(Diags[0].InputStartCol, 1u);
17745ffd940aSRaphael Isemann   EXPECT_EQ(Diags[0].InputEndCol, 7u);
17755ffd940aSRaphael Isemann   EXPECT_EQ(Diags[1].InputStartCol, 8u);
17765ffd940aSRaphael Isemann   EXPECT_EQ(Diags[1].InputEndCol, 9u);
17775ffd940aSRaphael Isemann   EXPECT_EQ(Diags[0].Note, "captured var \"STRVAR\"");
17785ffd940aSRaphael Isemann   EXPECT_EQ(Diags[1].Note, "captured var \"NUMVAR\"");
17795ffd940aSRaphael Isemann }
17805ffd940aSRaphael Isemann } // namespace
1781