1*5ffd940aSRaphael Isemann //===- llvm/unittest/FileCheck/FileCheckTest.cpp - FileCheck tests --------===//
2*5ffd940aSRaphael Isemann //
3*5ffd940aSRaphael Isemann // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5ffd940aSRaphael Isemann // See https://llvm.org/LICENSE.txt for license information.
5*5ffd940aSRaphael Isemann // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5ffd940aSRaphael Isemann //
7*5ffd940aSRaphael Isemann //===----------------------------------------------------------------------===//
8*5ffd940aSRaphael Isemann 
9*5ffd940aSRaphael Isemann #include "llvm/FileCheck/FileCheck.h"
10*5ffd940aSRaphael Isemann #include "../lib/FileCheck/FileCheckImpl.h"
11*5ffd940aSRaphael Isemann #include "llvm/Support/Regex.h"
12*5ffd940aSRaphael Isemann #include "llvm/Testing/Support/Error.h"
13*5ffd940aSRaphael Isemann #include "gtest/gtest.h"
14*5ffd940aSRaphael Isemann #include <tuple>
15*5ffd940aSRaphael Isemann #include <unordered_set>
16*5ffd940aSRaphael Isemann 
17*5ffd940aSRaphael Isemann using namespace llvm;
18*5ffd940aSRaphael Isemann 
19*5ffd940aSRaphael Isemann namespace {
20*5ffd940aSRaphael Isemann 
21*5ffd940aSRaphael Isemann class FileCheckTest : public ::testing::Test {};
22*5ffd940aSRaphael Isemann 
23*5ffd940aSRaphael Isemann static StringRef bufferize(SourceMgr &SM, StringRef Str) {
24*5ffd940aSRaphael Isemann   std::unique_ptr<MemoryBuffer> Buffer =
25*5ffd940aSRaphael Isemann       MemoryBuffer::getMemBufferCopy(Str, "TestBuffer");
26*5ffd940aSRaphael Isemann   StringRef StrBufferRef = Buffer->getBuffer();
27*5ffd940aSRaphael Isemann   SM.AddNewSourceBuffer(std::move(Buffer), SMLoc());
28*5ffd940aSRaphael Isemann   return StrBufferRef;
29*5ffd940aSRaphael Isemann }
30*5ffd940aSRaphael Isemann 
31*5ffd940aSRaphael Isemann static std::string toString(const std::unordered_set<std::string> &Set) {
32*5ffd940aSRaphael Isemann   bool First = true;
33*5ffd940aSRaphael Isemann   std::string Str;
34*5ffd940aSRaphael Isemann   for (StringRef S : Set) {
35*5ffd940aSRaphael Isemann     Str += Twine(First ? "{" + S : ", " + S).str();
36*5ffd940aSRaphael Isemann     First = false;
37*5ffd940aSRaphael Isemann   }
38*5ffd940aSRaphael Isemann   Str += '}';
39*5ffd940aSRaphael Isemann   return Str;
40*5ffd940aSRaphael Isemann }
41*5ffd940aSRaphael Isemann 
42*5ffd940aSRaphael Isemann template <typename ErrorT>
43*5ffd940aSRaphael Isemann static void expectSameErrors(std::unordered_set<std::string> ExpectedMsgs,
44*5ffd940aSRaphael Isemann                              Error Err) {
45*5ffd940aSRaphael Isemann   auto AnyErrorMsgMatch = [&ExpectedMsgs](std::string &&ErrorMsg) -> bool {
46*5ffd940aSRaphael Isemann     for (auto ExpectedMsgItr = ExpectedMsgs.begin(),
47*5ffd940aSRaphael Isemann               ExpectedMsgEnd = ExpectedMsgs.end();
48*5ffd940aSRaphael Isemann          ExpectedMsgItr != ExpectedMsgEnd; ++ExpectedMsgItr) {
49*5ffd940aSRaphael Isemann       if (ErrorMsg.find(*ExpectedMsgItr) != std::string::npos) {
50*5ffd940aSRaphael Isemann         ExpectedMsgs.erase(ExpectedMsgItr);
51*5ffd940aSRaphael Isemann         return true;
52*5ffd940aSRaphael Isemann       }
53*5ffd940aSRaphael Isemann     }
54*5ffd940aSRaphael Isemann     return false;
55*5ffd940aSRaphael Isemann   };
56*5ffd940aSRaphael Isemann 
57*5ffd940aSRaphael Isemann   Error RemainingErrors = std::move(Err);
58*5ffd940aSRaphael Isemann   do {
59*5ffd940aSRaphael Isemann     RemainingErrors =
60*5ffd940aSRaphael Isemann         handleErrors(std::move(RemainingErrors), [&](const ErrorT &E) {
61*5ffd940aSRaphael Isemann           EXPECT_TRUE(AnyErrorMsgMatch(E.message()))
62*5ffd940aSRaphael Isemann               << "Unexpected error message:" << std::endl
63*5ffd940aSRaphael Isemann               << E.message();
64*5ffd940aSRaphael Isemann         });
65*5ffd940aSRaphael Isemann   } while (RemainingErrors && !ExpectedMsgs.empty());
66*5ffd940aSRaphael Isemann   EXPECT_THAT_ERROR(std::move(RemainingErrors), Succeeded());
67*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpectedMsgs.empty())
68*5ffd940aSRaphael Isemann       << "Error message(s) not found:" << std::endl
69*5ffd940aSRaphael Isemann       << toString(ExpectedMsgs);
70*5ffd940aSRaphael Isemann }
71*5ffd940aSRaphael Isemann 
72*5ffd940aSRaphael Isemann template <typename ErrorT>
73*5ffd940aSRaphael Isemann static void expectError(StringRef ExpectedMsg, Error Err) {
74*5ffd940aSRaphael Isemann   expectSameErrors<ErrorT>({ExpectedMsg.str()}, std::move(Err));
75*5ffd940aSRaphael Isemann }
76*5ffd940aSRaphael Isemann 
77*5ffd940aSRaphael Isemann static void expectDiagnosticError(StringRef ExpectedMsg, Error Err) {
78*5ffd940aSRaphael Isemann   expectError<ErrorDiagnostic>(ExpectedMsg, std::move(Err));
79*5ffd940aSRaphael Isemann }
80*5ffd940aSRaphael Isemann 
81*5ffd940aSRaphael Isemann constexpr uint64_t MaxUint64 = std::numeric_limits<uint64_t>::max();
82*5ffd940aSRaphael Isemann constexpr int64_t MaxInt64 = std::numeric_limits<int64_t>::max();
83*5ffd940aSRaphael Isemann constexpr int64_t MinInt64 = std::numeric_limits<int64_t>::min();
84*5ffd940aSRaphael Isemann constexpr uint64_t AbsoluteMinInt64 =
85*5ffd940aSRaphael Isemann     static_cast<uint64_t>(-(MinInt64 + 1)) + 1;
86*5ffd940aSRaphael Isemann constexpr uint64_t AbsoluteMaxInt64 = static_cast<uint64_t>(MaxInt64);
87*5ffd940aSRaphael Isemann 
88*5ffd940aSRaphael Isemann struct ExpressionFormatParameterisedFixture
89*5ffd940aSRaphael Isemann     : public ::testing::TestWithParam<
90*5ffd940aSRaphael Isemann           std::pair<ExpressionFormat::Kind, unsigned>> {
91*5ffd940aSRaphael Isemann   unsigned Precision;
92*5ffd940aSRaphael Isemann   bool Signed;
93*5ffd940aSRaphael Isemann   bool AllowHex;
94*5ffd940aSRaphael Isemann   bool AllowUpperHex;
95*5ffd940aSRaphael Isemann   ExpressionFormat Format;
96*5ffd940aSRaphael Isemann   Regex WildcardRegex;
97*5ffd940aSRaphael Isemann 
98*5ffd940aSRaphael Isemann   StringRef TenStr;
99*5ffd940aSRaphael Isemann   StringRef FifteenStr;
100*5ffd940aSRaphael Isemann   std::string MaxUint64Str;
101*5ffd940aSRaphael Isemann   std::string MaxInt64Str;
102*5ffd940aSRaphael Isemann   std::string MinInt64Str;
103*5ffd940aSRaphael Isemann   StringRef FirstInvalidCharDigits;
104*5ffd940aSRaphael Isemann   StringRef AcceptedHexOnlyDigits;
105*5ffd940aSRaphael Isemann   StringRef RefusedHexOnlyDigits;
106*5ffd940aSRaphael Isemann 
107*5ffd940aSRaphael Isemann   SourceMgr SM;
108*5ffd940aSRaphael Isemann 
109*5ffd940aSRaphael Isemann   void SetUp() override {
110*5ffd940aSRaphael Isemann     ExpressionFormat::Kind Kind;
111*5ffd940aSRaphael Isemann     std::tie(Kind, Precision) = GetParam();
112*5ffd940aSRaphael Isemann     AllowHex = Kind == ExpressionFormat::Kind::HexLower ||
113*5ffd940aSRaphael Isemann                Kind == ExpressionFormat::Kind::HexUpper;
114*5ffd940aSRaphael Isemann     AllowUpperHex = Kind == ExpressionFormat::Kind::HexUpper;
115*5ffd940aSRaphael Isemann     Signed = Kind == ExpressionFormat::Kind::Signed;
116*5ffd940aSRaphael Isemann     Format = ExpressionFormat(Kind, Precision);
117*5ffd940aSRaphael Isemann 
118*5ffd940aSRaphael Isemann     if (!AllowHex) {
119*5ffd940aSRaphael Isemann       MaxUint64Str = std::to_string(MaxUint64);
120*5ffd940aSRaphael Isemann       MaxInt64Str = std::to_string(MaxInt64);
121*5ffd940aSRaphael Isemann       MinInt64Str = std::to_string(MinInt64);
122*5ffd940aSRaphael Isemann       TenStr = "10";
123*5ffd940aSRaphael Isemann       FifteenStr = "15";
124*5ffd940aSRaphael Isemann       FirstInvalidCharDigits = "aA";
125*5ffd940aSRaphael Isemann       AcceptedHexOnlyDigits = RefusedHexOnlyDigits = "N/A";
126*5ffd940aSRaphael Isemann       return;
127*5ffd940aSRaphael Isemann     }
128*5ffd940aSRaphael Isemann 
129*5ffd940aSRaphael Isemann     MaxUint64Str = AllowUpperHex ? "FFFFFFFFFFFFFFFF" : "ffffffffffffffff";
130*5ffd940aSRaphael Isemann     MaxInt64Str = AllowUpperHex ? "7FFFFFFFFFFFFFFF" : "7fffffffffffffff";
131*5ffd940aSRaphael Isemann     TenStr = AllowUpperHex ? "A" : "a";
132*5ffd940aSRaphael Isemann     FifteenStr = AllowUpperHex ? "F" : "f";
133*5ffd940aSRaphael Isemann     AcceptedHexOnlyDigits = AllowUpperHex ? "ABCDEF" : "abcdef";
134*5ffd940aSRaphael Isemann     RefusedHexOnlyDigits = AllowUpperHex ? "abcdef" : "ABCDEF";
135*5ffd940aSRaphael Isemann     MinInt64Str = "N/A";
136*5ffd940aSRaphael Isemann     FirstInvalidCharDigits = "gG";
137*5ffd940aSRaphael Isemann   }
138*5ffd940aSRaphael Isemann 
139*5ffd940aSRaphael Isemann   void checkWildcardRegexMatch(StringRef Input,
140*5ffd940aSRaphael Isemann                                unsigned TrailExtendTo = 0) const {
141*5ffd940aSRaphael Isemann     SmallVector<StringRef, 4> Matches;
142*5ffd940aSRaphael Isemann     std::string ExtendedInput = Input.str();
143*5ffd940aSRaphael Isemann     if (TrailExtendTo > Input.size()) {
144*5ffd940aSRaphael Isemann       ExtendedInput.append(TrailExtendTo - Input.size(), Input[0]);
145*5ffd940aSRaphael Isemann     }
146*5ffd940aSRaphael Isemann     ASSERT_TRUE(WildcardRegex.match(ExtendedInput, &Matches))
147*5ffd940aSRaphael Isemann         << "Wildcard regex does not match " << ExtendedInput;
148*5ffd940aSRaphael Isemann     EXPECT_EQ(Matches[0], ExtendedInput);
149*5ffd940aSRaphael Isemann   }
150*5ffd940aSRaphael Isemann 
151*5ffd940aSRaphael Isemann   void checkWildcardRegexMatchFailure(StringRef Input) const {
152*5ffd940aSRaphael Isemann     EXPECT_FALSE(WildcardRegex.match(Input));
153*5ffd940aSRaphael Isemann   }
154*5ffd940aSRaphael Isemann 
155*5ffd940aSRaphael Isemann   void checkWildcardRegexCharMatchFailure(StringRef Chars) const {
156*5ffd940aSRaphael Isemann     for (auto C : Chars)
157*5ffd940aSRaphael Isemann       EXPECT_FALSE(WildcardRegex.match(StringRef(&C, 1)));
158*5ffd940aSRaphael Isemann   }
159*5ffd940aSRaphael Isemann 
160*5ffd940aSRaphael Isemann   std::string padWithLeadingZeros(StringRef NumStr) const {
161*5ffd940aSRaphael Isemann     bool Negative = NumStr.startswith("-");
162*5ffd940aSRaphael Isemann     if (NumStr.size() - unsigned(Negative) >= Precision)
163*5ffd940aSRaphael Isemann       return NumStr.str();
164*5ffd940aSRaphael Isemann 
165*5ffd940aSRaphael Isemann     std::string PaddedStr;
166*5ffd940aSRaphael Isemann     if (Negative) {
167*5ffd940aSRaphael Isemann       PaddedStr = "-";
168*5ffd940aSRaphael Isemann       NumStr = NumStr.drop_front();
169*5ffd940aSRaphael Isemann     }
170*5ffd940aSRaphael Isemann     PaddedStr.append(Precision - NumStr.size(), '0');
171*5ffd940aSRaphael Isemann     PaddedStr.append(NumStr.str());
172*5ffd940aSRaphael Isemann     return PaddedStr;
173*5ffd940aSRaphael Isemann   }
174*5ffd940aSRaphael Isemann 
175*5ffd940aSRaphael Isemann   template <class T> void checkMatchingString(T Val, StringRef ExpectedStr) {
176*5ffd940aSRaphael Isemann     Expected<std::string> MatchingString =
177*5ffd940aSRaphael Isemann         Format.getMatchingString(ExpressionValue(Val));
178*5ffd940aSRaphael Isemann     ASSERT_THAT_EXPECTED(MatchingString, Succeeded())
179*5ffd940aSRaphael Isemann         << "No matching string for " << Val;
180*5ffd940aSRaphael Isemann     EXPECT_EQ(*MatchingString, ExpectedStr);
181*5ffd940aSRaphael Isemann   }
182*5ffd940aSRaphael Isemann 
183*5ffd940aSRaphael Isemann   template <class T> void checkMatchingStringFailure(T Val) {
184*5ffd940aSRaphael Isemann     Expected<std::string> MatchingString =
185*5ffd940aSRaphael Isemann         Format.getMatchingString(ExpressionValue(Val));
186*5ffd940aSRaphael Isemann     // Error message tested in ExpressionValue unit tests.
187*5ffd940aSRaphael Isemann     EXPECT_THAT_EXPECTED(MatchingString, Failed());
188*5ffd940aSRaphael Isemann   }
189*5ffd940aSRaphael Isemann 
190*5ffd940aSRaphael Isemann   Expected<ExpressionValue> getValueFromStringReprFailure(StringRef Str) {
191*5ffd940aSRaphael Isemann     StringRef BufferizedStr = bufferize(SM, Str);
192*5ffd940aSRaphael Isemann     return Format.valueFromStringRepr(BufferizedStr, SM);
193*5ffd940aSRaphael Isemann   }
194*5ffd940aSRaphael Isemann 
195*5ffd940aSRaphael Isemann   template <class T>
196*5ffd940aSRaphael Isemann   void checkValueFromStringRepr(StringRef Str, T ExpectedVal) {
197*5ffd940aSRaphael Isemann     Expected<ExpressionValue> ResultValue = getValueFromStringReprFailure(Str);
198*5ffd940aSRaphael Isemann     ASSERT_THAT_EXPECTED(ResultValue, Succeeded())
199*5ffd940aSRaphael Isemann         << "Failed to get value from " << Str;
200*5ffd940aSRaphael Isemann     ASSERT_EQ(ResultValue->isNegative(), ExpectedVal < 0)
201*5ffd940aSRaphael Isemann         << "Value for " << Str << " is not " << ExpectedVal;
202*5ffd940aSRaphael Isemann     if (ResultValue->isNegative())
203*5ffd940aSRaphael Isemann       EXPECT_EQ(cantFail(ResultValue->getSignedValue()),
204*5ffd940aSRaphael Isemann                 static_cast<int64_t>(ExpectedVal));
205*5ffd940aSRaphael Isemann     else
206*5ffd940aSRaphael Isemann       EXPECT_EQ(cantFail(ResultValue->getUnsignedValue()),
207*5ffd940aSRaphael Isemann                 static_cast<uint64_t>(ExpectedVal));
208*5ffd940aSRaphael Isemann   }
209*5ffd940aSRaphael Isemann 
210*5ffd940aSRaphael Isemann   void checkValueFromStringReprFailure(StringRef Str) {
211*5ffd940aSRaphael Isemann     StringRef OverflowErrorStr = "unable to represent numeric value";
212*5ffd940aSRaphael Isemann     Expected<ExpressionValue> ResultValue = getValueFromStringReprFailure(Str);
213*5ffd940aSRaphael Isemann     expectDiagnosticError(OverflowErrorStr, ResultValue.takeError());
214*5ffd940aSRaphael Isemann   }
215*5ffd940aSRaphael Isemann };
216*5ffd940aSRaphael Isemann 
217*5ffd940aSRaphael Isemann TEST_P(ExpressionFormatParameterisedFixture, FormatGetWildcardRegex) {
218*5ffd940aSRaphael Isemann   // Wildcard regex is valid.
219*5ffd940aSRaphael Isemann   Expected<std::string> WildcardPattern = Format.getWildcardRegex();
220*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(WildcardPattern, Succeeded());
221*5ffd940aSRaphael Isemann   WildcardRegex = Regex((Twine("^") + *WildcardPattern + "$").str());
222*5ffd940aSRaphael Isemann   ASSERT_TRUE(WildcardRegex.isValid());
223*5ffd940aSRaphael Isemann 
224*5ffd940aSRaphael Isemann   // Does not match empty string.
225*5ffd940aSRaphael Isemann   checkWildcardRegexMatchFailure("");
226*5ffd940aSRaphael Isemann 
227*5ffd940aSRaphael Isemann   // Matches all decimal digits and matches several of them.
228*5ffd940aSRaphael Isemann   StringRef LongNumber = "12345678901234567890";
229*5ffd940aSRaphael Isemann   checkWildcardRegexMatch(LongNumber);
230*5ffd940aSRaphael Isemann 
231*5ffd940aSRaphael Isemann   // Matches negative digits.
232*5ffd940aSRaphael Isemann   LongNumber = "-12345678901234567890";
233*5ffd940aSRaphael Isemann   if (Signed)
234*5ffd940aSRaphael Isemann     checkWildcardRegexMatch(LongNumber);
235*5ffd940aSRaphael Isemann   else
236*5ffd940aSRaphael Isemann     checkWildcardRegexMatchFailure(LongNumber);
237*5ffd940aSRaphael Isemann 
238*5ffd940aSRaphael Isemann   // Check non digits or digits with wrong casing are not matched.
239*5ffd940aSRaphael Isemann   if (AllowHex) {
240*5ffd940aSRaphael Isemann     checkWildcardRegexMatch(AcceptedHexOnlyDigits, 16);
241*5ffd940aSRaphael Isemann     checkWildcardRegexCharMatchFailure(RefusedHexOnlyDigits);
242*5ffd940aSRaphael Isemann   }
243*5ffd940aSRaphael Isemann   checkWildcardRegexCharMatchFailure(FirstInvalidCharDigits);
244*5ffd940aSRaphael Isemann 
245*5ffd940aSRaphael Isemann   // Check leading zeros are only accepted if number of digits is less than the
246*5ffd940aSRaphael Isemann   // precision.
247*5ffd940aSRaphael Isemann   LongNumber = "01234567890123456789";
248*5ffd940aSRaphael Isemann   if (Precision) {
249*5ffd940aSRaphael Isemann     checkWildcardRegexMatch(LongNumber.take_front(Precision));
250*5ffd940aSRaphael Isemann     checkWildcardRegexMatchFailure(LongNumber.take_front(Precision - 1));
251*5ffd940aSRaphael Isemann     if (Precision < LongNumber.size())
252*5ffd940aSRaphael Isemann       checkWildcardRegexMatchFailure(LongNumber.take_front(Precision + 1));
253*5ffd940aSRaphael Isemann   } else
254*5ffd940aSRaphael Isemann     checkWildcardRegexMatch(LongNumber);
255*5ffd940aSRaphael Isemann }
256*5ffd940aSRaphael Isemann 
257*5ffd940aSRaphael Isemann TEST_P(ExpressionFormatParameterisedFixture, FormatGetMatchingString) {
258*5ffd940aSRaphael Isemann   checkMatchingString(0, padWithLeadingZeros("0"));
259*5ffd940aSRaphael Isemann   checkMatchingString(9, padWithLeadingZeros("9"));
260*5ffd940aSRaphael Isemann 
261*5ffd940aSRaphael Isemann   if (Signed) {
262*5ffd940aSRaphael Isemann     checkMatchingString(-5, padWithLeadingZeros("-5"));
263*5ffd940aSRaphael Isemann     checkMatchingStringFailure(MaxUint64);
264*5ffd940aSRaphael Isemann     checkMatchingString(MaxInt64, padWithLeadingZeros(MaxInt64Str));
265*5ffd940aSRaphael Isemann     checkMatchingString(MinInt64, padWithLeadingZeros(MinInt64Str));
266*5ffd940aSRaphael Isemann   } else {
267*5ffd940aSRaphael Isemann     checkMatchingStringFailure(-5);
268*5ffd940aSRaphael Isemann     checkMatchingString(MaxUint64, padWithLeadingZeros(MaxUint64Str));
269*5ffd940aSRaphael Isemann     checkMatchingString(MaxInt64, padWithLeadingZeros(MaxInt64Str));
270*5ffd940aSRaphael Isemann     checkMatchingStringFailure(MinInt64);
271*5ffd940aSRaphael Isemann   }
272*5ffd940aSRaphael Isemann 
273*5ffd940aSRaphael Isemann   checkMatchingString(10, padWithLeadingZeros(TenStr));
274*5ffd940aSRaphael Isemann   checkMatchingString(15, padWithLeadingZeros(FifteenStr));
275*5ffd940aSRaphael Isemann }
276*5ffd940aSRaphael Isemann 
277*5ffd940aSRaphael Isemann TEST_P(ExpressionFormatParameterisedFixture, FormatValueFromStringRepr) {
278*5ffd940aSRaphael Isemann   checkValueFromStringRepr("0", 0);
279*5ffd940aSRaphael Isemann   checkValueFromStringRepr("9", 9);
280*5ffd940aSRaphael Isemann 
281*5ffd940aSRaphael Isemann   if (Signed) {
282*5ffd940aSRaphael Isemann     checkValueFromStringRepr("-5", -5);
283*5ffd940aSRaphael Isemann     checkValueFromStringReprFailure(MaxUint64Str);
284*5ffd940aSRaphael Isemann   } else {
285*5ffd940aSRaphael Isemann     checkValueFromStringReprFailure("-5");
286*5ffd940aSRaphael Isemann     checkValueFromStringRepr(MaxUint64Str, MaxUint64);
287*5ffd940aSRaphael Isemann   }
288*5ffd940aSRaphael Isemann 
289*5ffd940aSRaphael Isemann   checkValueFromStringRepr(TenStr, 10);
290*5ffd940aSRaphael Isemann   checkValueFromStringRepr(FifteenStr, 15);
291*5ffd940aSRaphael Isemann 
292*5ffd940aSRaphael Isemann   // Wrong casing is not tested because valueFromStringRepr() relies on
293*5ffd940aSRaphael Isemann   // StringRef's getAsInteger() which does not allow to restrict casing.
294*5ffd940aSRaphael Isemann   checkValueFromStringReprFailure("G");
295*5ffd940aSRaphael Isemann }
296*5ffd940aSRaphael Isemann 
297*5ffd940aSRaphael Isemann TEST_P(ExpressionFormatParameterisedFixture, FormatBoolOperator) {
298*5ffd940aSRaphael Isemann   EXPECT_TRUE(bool(Format));
299*5ffd940aSRaphael Isemann }
300*5ffd940aSRaphael Isemann 
301*5ffd940aSRaphael Isemann INSTANTIATE_TEST_CASE_P(
302*5ffd940aSRaphael Isemann     AllowedExplicitExpressionFormat, ExpressionFormatParameterisedFixture,
303*5ffd940aSRaphael Isemann     ::testing::Values(std::make_pair(ExpressionFormat::Kind::Unsigned, 0),
304*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::Signed, 0),
305*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::HexLower, 0),
306*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::HexUpper, 0),
307*5ffd940aSRaphael Isemann 
308*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::Unsigned, 1),
309*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::Signed, 1),
310*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::HexLower, 1),
311*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::HexUpper, 1),
312*5ffd940aSRaphael Isemann 
313*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::Unsigned, 16),
314*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::Signed, 16),
315*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::HexLower, 16),
316*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::HexUpper, 16),
317*5ffd940aSRaphael Isemann 
318*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::Unsigned, 20),
319*5ffd940aSRaphael Isemann                       std::make_pair(ExpressionFormat::Kind::Signed, 20)), );
320*5ffd940aSRaphael Isemann 
321*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, NoFormatProperties) {
322*5ffd940aSRaphael Isemann   ExpressionFormat NoFormat(ExpressionFormat::Kind::NoFormat);
323*5ffd940aSRaphael Isemann   expectError<StringError>("trying to match value with invalid format",
324*5ffd940aSRaphael Isemann                            NoFormat.getWildcardRegex().takeError());
325*5ffd940aSRaphael Isemann   expectError<StringError>(
326*5ffd940aSRaphael Isemann       "trying to match value with invalid format",
327*5ffd940aSRaphael Isemann       NoFormat.getMatchingString(ExpressionValue(18u)).takeError());
328*5ffd940aSRaphael Isemann   EXPECT_FALSE(bool(NoFormat));
329*5ffd940aSRaphael Isemann }
330*5ffd940aSRaphael Isemann 
331*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, FormatEqualityOperators) {
332*5ffd940aSRaphael Isemann   ExpressionFormat UnsignedFormat(ExpressionFormat::Kind::Unsigned);
333*5ffd940aSRaphael Isemann   ExpressionFormat UnsignedFormat2(ExpressionFormat::Kind::Unsigned);
334*5ffd940aSRaphael Isemann   EXPECT_TRUE(UnsignedFormat == UnsignedFormat2);
335*5ffd940aSRaphael Isemann   EXPECT_FALSE(UnsignedFormat != UnsignedFormat2);
336*5ffd940aSRaphael Isemann 
337*5ffd940aSRaphael Isemann   ExpressionFormat HexLowerFormat(ExpressionFormat::Kind::HexLower);
338*5ffd940aSRaphael Isemann   EXPECT_FALSE(UnsignedFormat == HexLowerFormat);
339*5ffd940aSRaphael Isemann   EXPECT_TRUE(UnsignedFormat != HexLowerFormat);
340*5ffd940aSRaphael Isemann 
341*5ffd940aSRaphael Isemann   ExpressionFormat NoFormat(ExpressionFormat::Kind::NoFormat);
342*5ffd940aSRaphael Isemann   ExpressionFormat NoFormat2(ExpressionFormat::Kind::NoFormat);
343*5ffd940aSRaphael Isemann   EXPECT_FALSE(NoFormat == NoFormat2);
344*5ffd940aSRaphael Isemann   EXPECT_TRUE(NoFormat != NoFormat2);
345*5ffd940aSRaphael Isemann }
346*5ffd940aSRaphael Isemann 
347*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, FormatKindEqualityOperators) {
348*5ffd940aSRaphael Isemann   ExpressionFormat UnsignedFormat(ExpressionFormat::Kind::Unsigned);
349*5ffd940aSRaphael Isemann   EXPECT_TRUE(UnsignedFormat == ExpressionFormat::Kind::Unsigned);
350*5ffd940aSRaphael Isemann   EXPECT_FALSE(UnsignedFormat != ExpressionFormat::Kind::Unsigned);
351*5ffd940aSRaphael Isemann   EXPECT_FALSE(UnsignedFormat == ExpressionFormat::Kind::HexLower);
352*5ffd940aSRaphael Isemann   EXPECT_TRUE(UnsignedFormat != ExpressionFormat::Kind::HexLower);
353*5ffd940aSRaphael Isemann   ExpressionFormat NoFormat(ExpressionFormat::Kind::NoFormat);
354*5ffd940aSRaphael Isemann   EXPECT_TRUE(NoFormat == ExpressionFormat::Kind::NoFormat);
355*5ffd940aSRaphael Isemann   EXPECT_FALSE(NoFormat != ExpressionFormat::Kind::NoFormat);
356*5ffd940aSRaphael Isemann }
357*5ffd940aSRaphael Isemann 
358*5ffd940aSRaphael Isemann template <class T1, class T2>
359*5ffd940aSRaphael Isemann static Expected<ExpressionValue> doValueOperation(binop_eval_t Operation,
360*5ffd940aSRaphael Isemann                                                   T1 LeftValue, T2 RightValue) {
361*5ffd940aSRaphael Isemann   ExpressionValue LeftOperand(LeftValue);
362*5ffd940aSRaphael Isemann   ExpressionValue RightOperand(RightValue);
363*5ffd940aSRaphael Isemann   return Operation(LeftOperand, RightOperand);
364*5ffd940aSRaphael Isemann }
365*5ffd940aSRaphael Isemann 
366*5ffd940aSRaphael Isemann template <class T>
367*5ffd940aSRaphael Isemann static void expectValueEqual(ExpressionValue ActualValue, T ExpectedValue) {
368*5ffd940aSRaphael Isemann   EXPECT_EQ(ExpectedValue < 0, ActualValue.isNegative());
369*5ffd940aSRaphael Isemann   if (ExpectedValue < 0) {
370*5ffd940aSRaphael Isemann     Expected<int64_t> SignedActualValue = ActualValue.getSignedValue();
371*5ffd940aSRaphael Isemann     ASSERT_THAT_EXPECTED(SignedActualValue, Succeeded());
372*5ffd940aSRaphael Isemann     EXPECT_EQ(*SignedActualValue, static_cast<int64_t>(ExpectedValue));
373*5ffd940aSRaphael Isemann   } else {
374*5ffd940aSRaphael Isemann     Expected<uint64_t> UnsignedActualValue = ActualValue.getUnsignedValue();
375*5ffd940aSRaphael Isemann     ASSERT_THAT_EXPECTED(UnsignedActualValue, Succeeded());
376*5ffd940aSRaphael Isemann     EXPECT_EQ(*UnsignedActualValue, static_cast<uint64_t>(ExpectedValue));
377*5ffd940aSRaphael Isemann   }
378*5ffd940aSRaphael Isemann }
379*5ffd940aSRaphael Isemann 
380*5ffd940aSRaphael Isemann template <class T1, class T2, class TR>
381*5ffd940aSRaphael Isemann static void expectOperationValueResult(binop_eval_t Operation, T1 LeftValue,
382*5ffd940aSRaphael Isemann                                        T2 RightValue, TR ResultValue) {
383*5ffd940aSRaphael Isemann   Expected<ExpressionValue> OperationResult =
384*5ffd940aSRaphael Isemann       doValueOperation(Operation, LeftValue, RightValue);
385*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(OperationResult, Succeeded());
386*5ffd940aSRaphael Isemann   expectValueEqual(*OperationResult, ResultValue);
387*5ffd940aSRaphael Isemann }
388*5ffd940aSRaphael Isemann 
389*5ffd940aSRaphael Isemann template <class T1, class T2>
390*5ffd940aSRaphael Isemann static void expectOperationValueResult(binop_eval_t Operation, T1 LeftValue,
391*5ffd940aSRaphael Isemann                                        T2 RightValue) {
392*5ffd940aSRaphael Isemann   expectError<OverflowError>(
393*5ffd940aSRaphael Isemann       "overflow error",
394*5ffd940aSRaphael Isemann       doValueOperation(Operation, LeftValue, RightValue).takeError());
395*5ffd940aSRaphael Isemann }
396*5ffd940aSRaphael Isemann 
397*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueGetUnsigned) {
398*5ffd940aSRaphael Isemann   // Test positive value.
399*5ffd940aSRaphael Isemann   Expected<uint64_t> UnsignedValue = ExpressionValue(10).getUnsignedValue();
400*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(UnsignedValue, Succeeded());
401*5ffd940aSRaphael Isemann   EXPECT_EQ(*UnsignedValue, 10U);
402*5ffd940aSRaphael Isemann 
403*5ffd940aSRaphael Isemann   // Test 0.
404*5ffd940aSRaphael Isemann   UnsignedValue = ExpressionValue(0).getUnsignedValue();
405*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(UnsignedValue, Succeeded());
406*5ffd940aSRaphael Isemann   EXPECT_EQ(*UnsignedValue, 0U);
407*5ffd940aSRaphael Isemann 
408*5ffd940aSRaphael Isemann   // Test max positive value.
409*5ffd940aSRaphael Isemann   UnsignedValue = ExpressionValue(MaxUint64).getUnsignedValue();
410*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(UnsignedValue, Succeeded());
411*5ffd940aSRaphael Isemann   EXPECT_EQ(*UnsignedValue, MaxUint64);
412*5ffd940aSRaphael Isemann 
413*5ffd940aSRaphael Isemann   // Test failure with negative value.
414*5ffd940aSRaphael Isemann   expectError<OverflowError>(
415*5ffd940aSRaphael Isemann       "overflow error", ExpressionValue(-1).getUnsignedValue().takeError());
416*5ffd940aSRaphael Isemann 
417*5ffd940aSRaphael Isemann   // Test failure with min negative value.
418*5ffd940aSRaphael Isemann   expectError<OverflowError>(
419*5ffd940aSRaphael Isemann       "overflow error",
420*5ffd940aSRaphael Isemann       ExpressionValue(MinInt64).getUnsignedValue().takeError());
421*5ffd940aSRaphael Isemann }
422*5ffd940aSRaphael Isemann 
423*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueGetSigned) {
424*5ffd940aSRaphael Isemann   // Test positive value.
425*5ffd940aSRaphael Isemann   Expected<int64_t> SignedValue = ExpressionValue(10).getSignedValue();
426*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SignedValue, Succeeded());
427*5ffd940aSRaphael Isemann   EXPECT_EQ(*SignedValue, 10);
428*5ffd940aSRaphael Isemann 
429*5ffd940aSRaphael Isemann   // Test 0.
430*5ffd940aSRaphael Isemann   SignedValue = ExpressionValue(0).getSignedValue();
431*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SignedValue, Succeeded());
432*5ffd940aSRaphael Isemann   EXPECT_EQ(*SignedValue, 0);
433*5ffd940aSRaphael Isemann 
434*5ffd940aSRaphael Isemann   // Test max int64_t.
435*5ffd940aSRaphael Isemann   SignedValue = ExpressionValue(MaxInt64).getSignedValue();
436*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SignedValue, Succeeded());
437*5ffd940aSRaphael Isemann   EXPECT_EQ(*SignedValue, MaxInt64);
438*5ffd940aSRaphael Isemann 
439*5ffd940aSRaphael Isemann   // Test failure with too big positive value.
440*5ffd940aSRaphael Isemann   expectError<OverflowError>(
441*5ffd940aSRaphael Isemann       "overflow error", ExpressionValue(static_cast<uint64_t>(MaxInt64) + 1)
442*5ffd940aSRaphael Isemann                             .getSignedValue()
443*5ffd940aSRaphael Isemann                             .takeError());
444*5ffd940aSRaphael Isemann 
445*5ffd940aSRaphael Isemann   // Test failure with max uint64_t.
446*5ffd940aSRaphael Isemann   expectError<OverflowError>(
447*5ffd940aSRaphael Isemann       "overflow error",
448*5ffd940aSRaphael Isemann       ExpressionValue(MaxUint64).getSignedValue().takeError());
449*5ffd940aSRaphael Isemann 
450*5ffd940aSRaphael Isemann   // Test negative value.
451*5ffd940aSRaphael Isemann   SignedValue = ExpressionValue(-10).getSignedValue();
452*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SignedValue, Succeeded());
453*5ffd940aSRaphael Isemann   EXPECT_EQ(*SignedValue, -10);
454*5ffd940aSRaphael Isemann 
455*5ffd940aSRaphael Isemann   // Test min int64_t.
456*5ffd940aSRaphael Isemann   SignedValue = ExpressionValue(MinInt64).getSignedValue();
457*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SignedValue, Succeeded());
458*5ffd940aSRaphael Isemann   EXPECT_EQ(*SignedValue, MinInt64);
459*5ffd940aSRaphael Isemann }
460*5ffd940aSRaphael Isemann 
461*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueAbsolute) {
462*5ffd940aSRaphael Isemann   // Test positive value.
463*5ffd940aSRaphael Isemann   expectValueEqual(ExpressionValue(10).getAbsolute(), 10);
464*5ffd940aSRaphael Isemann 
465*5ffd940aSRaphael Isemann   // Test 0.
466*5ffd940aSRaphael Isemann   expectValueEqual(ExpressionValue(0).getAbsolute(), 0);
467*5ffd940aSRaphael Isemann 
468*5ffd940aSRaphael Isemann   // Test max uint64_t.
469*5ffd940aSRaphael Isemann   expectValueEqual(ExpressionValue(MaxUint64).getAbsolute(), MaxUint64);
470*5ffd940aSRaphael Isemann 
471*5ffd940aSRaphael Isemann   // Test negative value.
472*5ffd940aSRaphael Isemann   expectValueEqual(ExpressionValue(-10).getAbsolute(), 10);
473*5ffd940aSRaphael Isemann 
474*5ffd940aSRaphael Isemann   // Test absence of overflow on min int64_t.
475*5ffd940aSRaphael Isemann   expectValueEqual(ExpressionValue(MinInt64).getAbsolute(),
476*5ffd940aSRaphael Isemann                    static_cast<uint64_t>(-(MinInt64 + 10)) + 10);
477*5ffd940aSRaphael Isemann }
478*5ffd940aSRaphael Isemann 
479*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueAddition) {
480*5ffd940aSRaphael Isemann   // Test both negative values.
481*5ffd940aSRaphael Isemann   expectOperationValueResult(operator+, -10, -10, -20);
482*5ffd940aSRaphael Isemann 
483*5ffd940aSRaphael Isemann   // Test both negative values with underflow.
484*5ffd940aSRaphael Isemann   expectOperationValueResult(operator+, MinInt64, -1);
485*5ffd940aSRaphael Isemann   expectOperationValueResult(operator+, MinInt64, MinInt64);
486*5ffd940aSRaphael Isemann 
487*5ffd940aSRaphael Isemann   // Test negative and positive value.
488*5ffd940aSRaphael Isemann   expectOperationValueResult(operator+, -10, 10, 0);
489*5ffd940aSRaphael Isemann   expectOperationValueResult(operator+, -10, 11, 1);
490*5ffd940aSRaphael Isemann   expectOperationValueResult(operator+, -11, 10, -1);
491*5ffd940aSRaphael Isemann 
492*5ffd940aSRaphael Isemann   // Test positive and negative value.
493*5ffd940aSRaphael Isemann   expectOperationValueResult(operator+, 10, -10, 0);
494*5ffd940aSRaphael Isemann   expectOperationValueResult(operator+, 10, -11, -1);
495*5ffd940aSRaphael Isemann   expectOperationValueResult(operator+, 11, -10, 1);
496*5ffd940aSRaphael Isemann 
497*5ffd940aSRaphael Isemann   // Test both positive values.
498*5ffd940aSRaphael Isemann   expectOperationValueResult(operator+, 10, 10, 20);
499*5ffd940aSRaphael Isemann 
500*5ffd940aSRaphael Isemann   // Test both positive values with overflow.
501*5ffd940aSRaphael Isemann   expectOperationValueResult(operator+, MaxUint64, 1);
502*5ffd940aSRaphael Isemann   expectOperationValueResult(operator+, MaxUint64, MaxUint64);
503*5ffd940aSRaphael Isemann }
504*5ffd940aSRaphael Isemann 
505*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueSubtraction) {
506*5ffd940aSRaphael Isemann   // Test negative value and value bigger than int64_t max.
507*5ffd940aSRaphael Isemann   expectOperationValueResult(operator-, -10, MaxUint64);
508*5ffd940aSRaphael Isemann 
509*5ffd940aSRaphael Isemann   // Test negative and positive value with underflow.
510*5ffd940aSRaphael Isemann   expectOperationValueResult(operator-, MinInt64, 1);
511*5ffd940aSRaphael Isemann 
512*5ffd940aSRaphael Isemann   // Test negative and positive value.
513*5ffd940aSRaphael Isemann   expectOperationValueResult(operator-, -10, 10, -20);
514*5ffd940aSRaphael Isemann 
515*5ffd940aSRaphael Isemann   // Test both negative values.
516*5ffd940aSRaphael Isemann   expectOperationValueResult(operator-, -10, -10, 0);
517*5ffd940aSRaphael Isemann   expectOperationValueResult(operator-, -11, -10, -1);
518*5ffd940aSRaphael Isemann   expectOperationValueResult(operator-, -10, -11, 1);
519*5ffd940aSRaphael Isemann 
520*5ffd940aSRaphael Isemann   // Test positive and negative values.
521*5ffd940aSRaphael Isemann   expectOperationValueResult(operator-, 10, -10, 20);
522*5ffd940aSRaphael Isemann 
523*5ffd940aSRaphael Isemann   // Test both positive values with result positive.
524*5ffd940aSRaphael Isemann   expectOperationValueResult(operator-, 10, 5, 5);
525*5ffd940aSRaphael Isemann 
526*5ffd940aSRaphael Isemann   // Test both positive values with underflow.
527*5ffd940aSRaphael Isemann   expectOperationValueResult(operator-, 0, MaxUint64);
528*5ffd940aSRaphael Isemann   expectOperationValueResult(operator-, 0,
529*5ffd940aSRaphael Isemann                              static_cast<uint64_t>(-(MinInt64 + 10)) + 11);
530*5ffd940aSRaphael Isemann 
531*5ffd940aSRaphael Isemann   // Test both positive values with result < -(max int64_t)
532*5ffd940aSRaphael Isemann   expectOperationValueResult(operator-, 10,
533*5ffd940aSRaphael Isemann                              static_cast<uint64_t>(MaxInt64) + 11,
534*5ffd940aSRaphael Isemann                              -MaxInt64 - 1);
535*5ffd940aSRaphael Isemann 
536*5ffd940aSRaphael Isemann   // Test both positive values with 0 > result > -(max int64_t)
537*5ffd940aSRaphael Isemann   expectOperationValueResult(operator-, 10, 11, -1);
538*5ffd940aSRaphael Isemann }
539*5ffd940aSRaphael Isemann 
540*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueMultiplication) {
541*5ffd940aSRaphael Isemann   // Test mixed signed values.
542*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -3, 10, -30);
543*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 2, -17, -34);
544*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 0, MinInt64, 0);
545*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MinInt64, 1, MinInt64);
546*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 1, MinInt64, MinInt64);
547*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MaxInt64, -1, -MaxInt64);
548*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -1, MaxInt64, -MaxInt64);
549*5ffd940aSRaphael Isemann 
550*5ffd940aSRaphael Isemann   // Test both negative values.
551*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -3, -10, 30);
552*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -2, -17, 34);
553*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MinInt64, -1, AbsoluteMinInt64);
554*5ffd940aSRaphael Isemann 
555*5ffd940aSRaphael Isemann   // Test both positive values.
556*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 3, 10, 30);
557*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 2, 17, 34);
558*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 0, MaxUint64, 0);
559*5ffd940aSRaphael Isemann 
560*5ffd940aSRaphael Isemann   // Test negative results that underflow.
561*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -10, MaxInt64);
562*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MaxInt64, -10);
563*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 10, MinInt64);
564*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MinInt64, 10);
565*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -1, MaxUint64);
566*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MaxUint64, -1);
567*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -1, AbsoluteMaxInt64 + 2);
568*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, AbsoluteMaxInt64 + 2, -1);
569*5ffd940aSRaphael Isemann 
570*5ffd940aSRaphael Isemann   // Test positive results that overflow.
571*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, 10, MaxUint64);
572*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MaxUint64, 10);
573*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, MinInt64, -10);
574*5ffd940aSRaphael Isemann   expectOperationValueResult(operator*, -10, MinInt64);
575*5ffd940aSRaphael Isemann }
576*5ffd940aSRaphael Isemann 
577*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueDivision) {
578*5ffd940aSRaphael Isemann   // Test mixed signed values.
579*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, -30, 10, -3);
580*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 34, -17, -2);
581*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 0, -10, 0);
582*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, MinInt64, 1, MinInt64);
583*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, MaxInt64, -1, -MaxInt64);
584*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, -MaxInt64, 1, -MaxInt64);
585*5ffd940aSRaphael Isemann 
586*5ffd940aSRaphael Isemann   // Test both negative values.
587*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, -30, -10, 3);
588*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, -34, -17, 2);
589*5ffd940aSRaphael Isemann 
590*5ffd940aSRaphael Isemann   // Test both positive values.
591*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 30, 10, 3);
592*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 34, 17, 2);
593*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 0, 10, 0);
594*5ffd940aSRaphael Isemann 
595*5ffd940aSRaphael Isemann   // Test divide by zero.
596*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, -10, 0);
597*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 10, 0);
598*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, 0, 0);
599*5ffd940aSRaphael Isemann 
600*5ffd940aSRaphael Isemann   // Test negative result that underflows.
601*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, MaxUint64, -1);
602*5ffd940aSRaphael Isemann   expectOperationValueResult(operator/, AbsoluteMaxInt64 + 2, -1);
603*5ffd940aSRaphael Isemann }
604*5ffd940aSRaphael Isemann 
605*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, ExpressionValueEquality) {
606*5ffd940aSRaphael Isemann   // Test negative and positive value.
607*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(5) == ExpressionValue(-3));
608*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(5) != ExpressionValue(-3));
609*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(-2) == ExpressionValue(6));
610*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(-2) != ExpressionValue(6));
611*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(-7) == ExpressionValue(7));
612*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(-7) != ExpressionValue(7));
613*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(4) == ExpressionValue(-4));
614*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(4) != ExpressionValue(-4));
615*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(MaxUint64) == ExpressionValue(-1));
616*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(MaxUint64) != ExpressionValue(-1));
617*5ffd940aSRaphael Isemann 
618*5ffd940aSRaphael Isemann   // Test both negative values.
619*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(-2) == ExpressionValue(-7));
620*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(-2) != ExpressionValue(-7));
621*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(-3) == ExpressionValue(-3));
622*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(-3) != ExpressionValue(-3));
623*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(MinInt64) == ExpressionValue(-1));
624*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(MinInt64) != ExpressionValue(-1));
625*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(MinInt64) == ExpressionValue(-0));
626*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(MinInt64) != ExpressionValue(-0));
627*5ffd940aSRaphael Isemann 
628*5ffd940aSRaphael Isemann   // Test both positive values.
629*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(8) == ExpressionValue(9));
630*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(8) != ExpressionValue(9));
631*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(1) == ExpressionValue(1));
632*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(1) != ExpressionValue(1));
633*5ffd940aSRaphael Isemann 
634*5ffd940aSRaphael Isemann   // Check the signedness of zero doesn't affect equality.
635*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(0) == ExpressionValue(0));
636*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(0) != ExpressionValue(0));
637*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(0) == ExpressionValue(-0));
638*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(0) != ExpressionValue(-0));
639*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(-0) == ExpressionValue(0));
640*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(-0) != ExpressionValue(0));
641*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpressionValue(-0) == ExpressionValue(-0));
642*5ffd940aSRaphael Isemann   EXPECT_FALSE(ExpressionValue(-0) != ExpressionValue(-0));
643*5ffd940aSRaphael Isemann }
644*5ffd940aSRaphael Isemann 
645*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, Literal) {
646*5ffd940aSRaphael Isemann   SourceMgr SM;
647*5ffd940aSRaphael Isemann 
648*5ffd940aSRaphael Isemann   // Eval returns the literal's value.
649*5ffd940aSRaphael Isemann   ExpressionLiteral Ten(bufferize(SM, "10"), 10u);
650*5ffd940aSRaphael Isemann   Expected<ExpressionValue> Value = Ten.eval();
651*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(Value, Succeeded());
652*5ffd940aSRaphael Isemann   EXPECT_EQ(10, cantFail(Value->getSignedValue()));
653*5ffd940aSRaphael Isemann   Expected<ExpressionFormat> ImplicitFormat = Ten.getImplicitFormat(SM);
654*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ImplicitFormat, Succeeded());
655*5ffd940aSRaphael Isemann   EXPECT_EQ(*ImplicitFormat, ExpressionFormat::Kind::NoFormat);
656*5ffd940aSRaphael Isemann 
657*5ffd940aSRaphael Isemann   // Min value can be correctly represented.
658*5ffd940aSRaphael Isemann   ExpressionLiteral Min(bufferize(SM, std::to_string(MinInt64)), MinInt64);
659*5ffd940aSRaphael Isemann   Value = Min.eval();
660*5ffd940aSRaphael Isemann   ASSERT_TRUE(bool(Value));
661*5ffd940aSRaphael Isemann   EXPECT_EQ(MinInt64, cantFail(Value->getSignedValue()));
662*5ffd940aSRaphael Isemann 
663*5ffd940aSRaphael Isemann   // Max value can be correctly represented.
664*5ffd940aSRaphael Isemann   ExpressionLiteral Max(bufferize(SM, std::to_string(MaxUint64)), MaxUint64);
665*5ffd940aSRaphael Isemann   Value = Max.eval();
666*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(Value, Succeeded());
667*5ffd940aSRaphael Isemann   EXPECT_EQ(MaxUint64, cantFail(Value->getUnsignedValue()));
668*5ffd940aSRaphael Isemann }
669*5ffd940aSRaphael Isemann 
670*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, Expression) {
671*5ffd940aSRaphael Isemann   SourceMgr SM;
672*5ffd940aSRaphael Isemann 
673*5ffd940aSRaphael Isemann   std::unique_ptr<ExpressionLiteral> Ten =
674*5ffd940aSRaphael Isemann       std::make_unique<ExpressionLiteral>(bufferize(SM, "10"), 10u);
675*5ffd940aSRaphael Isemann   ExpressionLiteral *TenPtr = Ten.get();
676*5ffd940aSRaphael Isemann   Expression Expr(std::move(Ten),
677*5ffd940aSRaphael Isemann                   ExpressionFormat(ExpressionFormat::Kind::HexLower));
678*5ffd940aSRaphael Isemann   EXPECT_EQ(Expr.getAST(), TenPtr);
679*5ffd940aSRaphael Isemann   EXPECT_EQ(Expr.getFormat(), ExpressionFormat::Kind::HexLower);
680*5ffd940aSRaphael Isemann }
681*5ffd940aSRaphael Isemann 
682*5ffd940aSRaphael Isemann static void
683*5ffd940aSRaphael Isemann expectUndefErrors(std::unordered_set<std::string> ExpectedUndefVarNames,
684*5ffd940aSRaphael Isemann                   Error Err) {
685*5ffd940aSRaphael Isemann   EXPECT_THAT_ERROR(handleErrors(std::move(Err),
686*5ffd940aSRaphael Isemann                                  [&](const UndefVarError &E) {
687*5ffd940aSRaphael Isemann                                    EXPECT_EQ(ExpectedUndefVarNames.erase(
688*5ffd940aSRaphael Isemann                                                  std::string(E.getVarName())),
689*5ffd940aSRaphael Isemann                                              1U);
690*5ffd940aSRaphael Isemann                                  }),
691*5ffd940aSRaphael Isemann                     Succeeded());
692*5ffd940aSRaphael Isemann   EXPECT_TRUE(ExpectedUndefVarNames.empty()) << toString(ExpectedUndefVarNames);
693*5ffd940aSRaphael Isemann }
694*5ffd940aSRaphael Isemann 
695*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, NumericVariable) {
696*5ffd940aSRaphael Isemann   SourceMgr SM;
697*5ffd940aSRaphael Isemann 
698*5ffd940aSRaphael Isemann   // Undefined variable: getValue and eval fail, error returned by eval holds
699*5ffd940aSRaphael Isemann   // the name of the undefined variable.
700*5ffd940aSRaphael Isemann   NumericVariable FooVar("FOO",
701*5ffd940aSRaphael Isemann                          ExpressionFormat(ExpressionFormat::Kind::Unsigned), 1);
702*5ffd940aSRaphael Isemann   EXPECT_EQ("FOO", FooVar.getName());
703*5ffd940aSRaphael Isemann   EXPECT_EQ(FooVar.getImplicitFormat(), ExpressionFormat::Kind::Unsigned);
704*5ffd940aSRaphael Isemann   NumericVariableUse FooVarUse("FOO", &FooVar);
705*5ffd940aSRaphael Isemann   Expected<ExpressionFormat> ImplicitFormat = FooVarUse.getImplicitFormat(SM);
706*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ImplicitFormat, Succeeded());
707*5ffd940aSRaphael Isemann   EXPECT_EQ(*ImplicitFormat, ExpressionFormat::Kind::Unsigned);
708*5ffd940aSRaphael Isemann   EXPECT_FALSE(FooVar.getValue());
709*5ffd940aSRaphael Isemann   Expected<ExpressionValue> EvalResult = FooVarUse.eval();
710*5ffd940aSRaphael Isemann   expectUndefErrors({"FOO"}, EvalResult.takeError());
711*5ffd940aSRaphael Isemann 
712*5ffd940aSRaphael Isemann   // Defined variable without string: only getValue and eval return value set.
713*5ffd940aSRaphael Isemann   FooVar.setValue(ExpressionValue(42u));
714*5ffd940aSRaphael Isemann   Optional<ExpressionValue> Value = FooVar.getValue();
715*5ffd940aSRaphael Isemann   ASSERT_TRUE(Value);
716*5ffd940aSRaphael Isemann   EXPECT_EQ(42, cantFail(Value->getSignedValue()));
717*5ffd940aSRaphael Isemann   EXPECT_FALSE(FooVar.getStringValue());
718*5ffd940aSRaphael Isemann   EvalResult = FooVarUse.eval();
719*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(EvalResult, Succeeded());
720*5ffd940aSRaphael Isemann   EXPECT_EQ(42, cantFail(EvalResult->getSignedValue()));
721*5ffd940aSRaphael Isemann 
722*5ffd940aSRaphael Isemann   // Defined variable with string: getValue, eval, and getStringValue return
723*5ffd940aSRaphael Isemann   // value set.
724*5ffd940aSRaphael Isemann   StringRef StringValue = "925";
725*5ffd940aSRaphael Isemann   FooVar.setValue(ExpressionValue(925u), StringValue);
726*5ffd940aSRaphael Isemann   Value = FooVar.getValue();
727*5ffd940aSRaphael Isemann   ASSERT_TRUE(Value);
728*5ffd940aSRaphael Isemann   EXPECT_EQ(925, cantFail(Value->getSignedValue()));
729*5ffd940aSRaphael Isemann   // getStringValue should return the same memory not just the same characters.
730*5ffd940aSRaphael Isemann   EXPECT_EQ(StringValue.begin(), FooVar.getStringValue().getValue().begin());
731*5ffd940aSRaphael Isemann   EXPECT_EQ(StringValue.end(), FooVar.getStringValue().getValue().end());
732*5ffd940aSRaphael Isemann   EvalResult = FooVarUse.eval();
733*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(EvalResult, Succeeded());
734*5ffd940aSRaphael Isemann   EXPECT_EQ(925, cantFail(EvalResult->getSignedValue()));
735*5ffd940aSRaphael Isemann   EXPECT_EQ(925, cantFail(EvalResult->getSignedValue()));
736*5ffd940aSRaphael Isemann 
737*5ffd940aSRaphael Isemann   // Clearing variable: getValue and eval fail. Error returned by eval holds
738*5ffd940aSRaphael Isemann   // the name of the cleared variable.
739*5ffd940aSRaphael Isemann   FooVar.clearValue();
740*5ffd940aSRaphael Isemann   EXPECT_FALSE(FooVar.getValue());
741*5ffd940aSRaphael Isemann   EXPECT_FALSE(FooVar.getStringValue());
742*5ffd940aSRaphael Isemann   EvalResult = FooVarUse.eval();
743*5ffd940aSRaphael Isemann   expectUndefErrors({"FOO"}, EvalResult.takeError());
744*5ffd940aSRaphael Isemann }
745*5ffd940aSRaphael Isemann 
746*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, Binop) {
747*5ffd940aSRaphael Isemann   SourceMgr SM;
748*5ffd940aSRaphael Isemann 
749*5ffd940aSRaphael Isemann   StringRef ExprStr = bufferize(SM, "FOO+BAR");
750*5ffd940aSRaphael Isemann   StringRef FooStr = ExprStr.take_front(3);
751*5ffd940aSRaphael Isemann   NumericVariable FooVar(FooStr,
752*5ffd940aSRaphael Isemann                          ExpressionFormat(ExpressionFormat::Kind::Unsigned), 1);
753*5ffd940aSRaphael Isemann   FooVar.setValue(ExpressionValue(42u));
754*5ffd940aSRaphael Isemann   std::unique_ptr<NumericVariableUse> FooVarUse =
755*5ffd940aSRaphael Isemann       std::make_unique<NumericVariableUse>(FooStr, &FooVar);
756*5ffd940aSRaphael Isemann   StringRef BarStr = ExprStr.take_back(3);
757*5ffd940aSRaphael Isemann   NumericVariable BarVar(BarStr,
758*5ffd940aSRaphael Isemann                          ExpressionFormat(ExpressionFormat::Kind::Unsigned), 2);
759*5ffd940aSRaphael Isemann   BarVar.setValue(ExpressionValue(18u));
760*5ffd940aSRaphael Isemann   std::unique_ptr<NumericVariableUse> BarVarUse =
761*5ffd940aSRaphael Isemann       std::make_unique<NumericVariableUse>(BarStr, &BarVar);
762*5ffd940aSRaphael Isemann   binop_eval_t doAdd = operator+;
763*5ffd940aSRaphael Isemann   BinaryOperation Binop(ExprStr, doAdd, std::move(FooVarUse),
764*5ffd940aSRaphael Isemann                         std::move(BarVarUse));
765*5ffd940aSRaphael Isemann 
766*5ffd940aSRaphael Isemann   // Defined variables: eval returns right value; implicit format is as
767*5ffd940aSRaphael Isemann   // expected.
768*5ffd940aSRaphael Isemann   Expected<ExpressionValue> Value = Binop.eval();
769*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(Value, Succeeded());
770*5ffd940aSRaphael Isemann   EXPECT_EQ(60, cantFail(Value->getSignedValue()));
771*5ffd940aSRaphael Isemann   Expected<ExpressionFormat> ImplicitFormat = Binop.getImplicitFormat(SM);
772*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ImplicitFormat, Succeeded());
773*5ffd940aSRaphael Isemann   EXPECT_EQ(*ImplicitFormat, ExpressionFormat::Kind::Unsigned);
774*5ffd940aSRaphael Isemann 
775*5ffd940aSRaphael Isemann   // 1 undefined variable: eval fails, error contains name of undefined
776*5ffd940aSRaphael Isemann   // variable.
777*5ffd940aSRaphael Isemann   FooVar.clearValue();
778*5ffd940aSRaphael Isemann   Value = Binop.eval();
779*5ffd940aSRaphael Isemann   expectUndefErrors({"FOO"}, Value.takeError());
780*5ffd940aSRaphael Isemann 
781*5ffd940aSRaphael Isemann   // 2 undefined variables: eval fails, error contains names of all undefined
782*5ffd940aSRaphael Isemann   // variables.
783*5ffd940aSRaphael Isemann   BarVar.clearValue();
784*5ffd940aSRaphael Isemann   Value = Binop.eval();
785*5ffd940aSRaphael Isemann   expectUndefErrors({"FOO", "BAR"}, Value.takeError());
786*5ffd940aSRaphael Isemann 
787*5ffd940aSRaphael Isemann   // Literal + Variable has format of variable.
788*5ffd940aSRaphael Isemann   ExprStr = bufferize(SM, "FOO+18");
789*5ffd940aSRaphael Isemann   FooStr = ExprStr.take_front(3);
790*5ffd940aSRaphael Isemann   StringRef EighteenStr = ExprStr.take_back(2);
791*5ffd940aSRaphael Isemann   FooVarUse = std::make_unique<NumericVariableUse>(FooStr, &FooVar);
792*5ffd940aSRaphael Isemann   std::unique_ptr<ExpressionLiteral> Eighteen =
793*5ffd940aSRaphael Isemann       std::make_unique<ExpressionLiteral>(EighteenStr, 18u);
794*5ffd940aSRaphael Isemann   Binop = BinaryOperation(ExprStr, doAdd, std::move(FooVarUse),
795*5ffd940aSRaphael Isemann                           std::move(Eighteen));
796*5ffd940aSRaphael Isemann   ImplicitFormat = Binop.getImplicitFormat(SM);
797*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ImplicitFormat, Succeeded());
798*5ffd940aSRaphael Isemann   EXPECT_EQ(*ImplicitFormat, ExpressionFormat::Kind::Unsigned);
799*5ffd940aSRaphael Isemann   ExprStr = bufferize(SM, "18+FOO");
800*5ffd940aSRaphael Isemann   FooStr = ExprStr.take_back(3);
801*5ffd940aSRaphael Isemann   EighteenStr = ExprStr.take_front(2);
802*5ffd940aSRaphael Isemann   FooVarUse = std::make_unique<NumericVariableUse>(FooStr, &FooVar);
803*5ffd940aSRaphael Isemann   Eighteen = std::make_unique<ExpressionLiteral>(EighteenStr, 18u);
804*5ffd940aSRaphael Isemann   Binop = BinaryOperation(ExprStr, doAdd, std::move(Eighteen),
805*5ffd940aSRaphael Isemann                           std::move(FooVarUse));
806*5ffd940aSRaphael Isemann   ImplicitFormat = Binop.getImplicitFormat(SM);
807*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ImplicitFormat, Succeeded());
808*5ffd940aSRaphael Isemann   EXPECT_EQ(*ImplicitFormat, ExpressionFormat::Kind::Unsigned);
809*5ffd940aSRaphael Isemann 
810*5ffd940aSRaphael Isemann   // Variables with different implicit format conflict.
811*5ffd940aSRaphael Isemann   ExprStr = bufferize(SM, "FOO+BAZ");
812*5ffd940aSRaphael Isemann   FooStr = ExprStr.take_front(3);
813*5ffd940aSRaphael Isemann   StringRef BazStr = ExprStr.take_back(3);
814*5ffd940aSRaphael Isemann   NumericVariable BazVar(BazStr,
815*5ffd940aSRaphael Isemann                          ExpressionFormat(ExpressionFormat::Kind::HexLower), 3);
816*5ffd940aSRaphael Isemann   FooVarUse = std::make_unique<NumericVariableUse>(FooStr, &FooVar);
817*5ffd940aSRaphael Isemann   std::unique_ptr<NumericVariableUse> BazVarUse =
818*5ffd940aSRaphael Isemann       std::make_unique<NumericVariableUse>(BazStr, &BazVar);
819*5ffd940aSRaphael Isemann   Binop = BinaryOperation(ExprStr, doAdd, std::move(FooVarUse),
820*5ffd940aSRaphael Isemann                           std::move(BazVarUse));
821*5ffd940aSRaphael Isemann   ImplicitFormat = Binop.getImplicitFormat(SM);
822*5ffd940aSRaphael Isemann   expectDiagnosticError(
823*5ffd940aSRaphael Isemann       "implicit format conflict between 'FOO' (%u) and 'BAZ' (%x), "
824*5ffd940aSRaphael Isemann       "need an explicit format specifier",
825*5ffd940aSRaphael Isemann       ImplicitFormat.takeError());
826*5ffd940aSRaphael Isemann 
827*5ffd940aSRaphael Isemann   // All variable conflicts are reported.
828*5ffd940aSRaphael Isemann   ExprStr = bufferize(SM, "(FOO+BAZ)+(FOO+QUUX)");
829*5ffd940aSRaphael Isemann   StringRef Paren1ExprStr = ExprStr.substr(1, 7);
830*5ffd940aSRaphael Isemann   FooStr = Paren1ExprStr.take_front(3);
831*5ffd940aSRaphael Isemann   BazStr = Paren1ExprStr.take_back(3);
832*5ffd940aSRaphael Isemann   StringRef Paren2ExprStr = ExprStr.substr(ExprStr.rfind('(') + 1, 8);
833*5ffd940aSRaphael Isemann   StringRef FooStr2 = Paren2ExprStr.take_front(3);
834*5ffd940aSRaphael Isemann   StringRef QuuxStr = Paren2ExprStr.take_back(4);
835*5ffd940aSRaphael Isemann   FooVarUse = std::make_unique<NumericVariableUse>(FooStr, &FooVar);
836*5ffd940aSRaphael Isemann   BazVarUse = std::make_unique<NumericVariableUse>(BazStr, &BazVar);
837*5ffd940aSRaphael Isemann   std::unique_ptr<NumericVariableUse> FooVarUse2 =
838*5ffd940aSRaphael Isemann       std::make_unique<NumericVariableUse>(FooStr2, &FooVar);
839*5ffd940aSRaphael Isemann   NumericVariable QuuxVar(
840*5ffd940aSRaphael Isemann       QuuxStr, ExpressionFormat(ExpressionFormat::Kind::HexLower), 4);
841*5ffd940aSRaphael Isemann   std::unique_ptr<NumericVariableUse> QuuxVarUse =
842*5ffd940aSRaphael Isemann       std::make_unique<NumericVariableUse>(QuuxStr, &QuuxVar);
843*5ffd940aSRaphael Isemann   std::unique_ptr<BinaryOperation> Binop1 = std::make_unique<BinaryOperation>(
844*5ffd940aSRaphael Isemann       ExprStr.take_front(9), doAdd, std::move(FooVarUse), std::move(BazVarUse));
845*5ffd940aSRaphael Isemann   std::unique_ptr<BinaryOperation> Binop2 = std::make_unique<BinaryOperation>(
846*5ffd940aSRaphael Isemann       ExprStr.take_back(10), doAdd, std::move(FooVarUse2),
847*5ffd940aSRaphael Isemann       std::move(QuuxVarUse));
848*5ffd940aSRaphael Isemann   std::unique_ptr<BinaryOperation> OuterBinop =
849*5ffd940aSRaphael Isemann       std::make_unique<BinaryOperation>(ExprStr, doAdd, std::move(Binop1),
850*5ffd940aSRaphael Isemann                                         std::move(Binop2));
851*5ffd940aSRaphael Isemann   ImplicitFormat = OuterBinop->getImplicitFormat(SM);
852*5ffd940aSRaphael Isemann   expectSameErrors<ErrorDiagnostic>(
853*5ffd940aSRaphael Isemann       {("implicit format conflict between 'FOO' (%u) and 'BAZ' (%x), need an "
854*5ffd940aSRaphael Isemann        "explicit format specifier"),
855*5ffd940aSRaphael Isemann        ("implicit format conflict between 'FOO' (%u) and 'QUUX' (%x), need an "
856*5ffd940aSRaphael Isemann        "explicit format specifier")},
857*5ffd940aSRaphael Isemann       ImplicitFormat.takeError());
858*5ffd940aSRaphael Isemann }
859*5ffd940aSRaphael Isemann 
860*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, ValidVarNameStart) {
861*5ffd940aSRaphael Isemann   EXPECT_TRUE(Pattern::isValidVarNameStart('a'));
862*5ffd940aSRaphael Isemann   EXPECT_TRUE(Pattern::isValidVarNameStart('G'));
863*5ffd940aSRaphael Isemann   EXPECT_TRUE(Pattern::isValidVarNameStart('_'));
864*5ffd940aSRaphael Isemann   EXPECT_FALSE(Pattern::isValidVarNameStart('2'));
865*5ffd940aSRaphael Isemann   EXPECT_FALSE(Pattern::isValidVarNameStart('$'));
866*5ffd940aSRaphael Isemann   EXPECT_FALSE(Pattern::isValidVarNameStart('@'));
867*5ffd940aSRaphael Isemann   EXPECT_FALSE(Pattern::isValidVarNameStart('+'));
868*5ffd940aSRaphael Isemann   EXPECT_FALSE(Pattern::isValidVarNameStart('-'));
869*5ffd940aSRaphael Isemann   EXPECT_FALSE(Pattern::isValidVarNameStart(':'));
870*5ffd940aSRaphael Isemann }
871*5ffd940aSRaphael Isemann 
872*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, ParseVar) {
873*5ffd940aSRaphael Isemann   SourceMgr SM;
874*5ffd940aSRaphael Isemann   StringRef OrigVarName = bufferize(SM, "GoodVar42");
875*5ffd940aSRaphael Isemann   StringRef VarName = OrigVarName;
876*5ffd940aSRaphael Isemann   Expected<Pattern::VariableProperties> ParsedVarResult =
877*5ffd940aSRaphael Isemann       Pattern::parseVariable(VarName, SM);
878*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
879*5ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
880*5ffd940aSRaphael Isemann   EXPECT_TRUE(VarName.empty());
881*5ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
882*5ffd940aSRaphael Isemann 
883*5ffd940aSRaphael Isemann   VarName = OrigVarName = bufferize(SM, "$GoodGlobalVar");
884*5ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
885*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
886*5ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
887*5ffd940aSRaphael Isemann   EXPECT_TRUE(VarName.empty());
888*5ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
889*5ffd940aSRaphael Isemann 
890*5ffd940aSRaphael Isemann   VarName = OrigVarName = bufferize(SM, "@GoodPseudoVar");
891*5ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
892*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
893*5ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, OrigVarName);
894*5ffd940aSRaphael Isemann   EXPECT_TRUE(VarName.empty());
895*5ffd940aSRaphael Isemann   EXPECT_TRUE(ParsedVarResult->IsPseudo);
896*5ffd940aSRaphael Isemann 
897*5ffd940aSRaphael Isemann   VarName = bufferize(SM, "42BadVar");
898*5ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
899*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid variable name", ParsedVarResult.takeError());
900*5ffd940aSRaphael Isemann 
901*5ffd940aSRaphael Isemann   VarName = bufferize(SM, "$@");
902*5ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
903*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid variable name", ParsedVarResult.takeError());
904*5ffd940aSRaphael Isemann 
905*5ffd940aSRaphael Isemann   VarName = OrigVarName = bufferize(SM, "B@dVar");
906*5ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
907*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
908*5ffd940aSRaphael Isemann   EXPECT_EQ(VarName, OrigVarName.substr(1));
909*5ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, "B");
910*5ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
911*5ffd940aSRaphael Isemann 
912*5ffd940aSRaphael Isemann   VarName = OrigVarName = bufferize(SM, "B$dVar");
913*5ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
914*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
915*5ffd940aSRaphael Isemann   EXPECT_EQ(VarName, OrigVarName.substr(1));
916*5ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, "B");
917*5ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
918*5ffd940aSRaphael Isemann 
919*5ffd940aSRaphael Isemann   VarName = bufferize(SM, "BadVar+");
920*5ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
921*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
922*5ffd940aSRaphael Isemann   EXPECT_EQ(VarName, "+");
923*5ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, "BadVar");
924*5ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
925*5ffd940aSRaphael Isemann 
926*5ffd940aSRaphael Isemann   VarName = bufferize(SM, "BadVar-");
927*5ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
928*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
929*5ffd940aSRaphael Isemann   EXPECT_EQ(VarName, "-");
930*5ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, "BadVar");
931*5ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
932*5ffd940aSRaphael Isemann 
933*5ffd940aSRaphael Isemann   VarName = bufferize(SM, "BadVar:");
934*5ffd940aSRaphael Isemann   ParsedVarResult = Pattern::parseVariable(VarName, SM);
935*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ParsedVarResult, Succeeded());
936*5ffd940aSRaphael Isemann   EXPECT_EQ(VarName, ":");
937*5ffd940aSRaphael Isemann   EXPECT_EQ(ParsedVarResult->Name, "BadVar");
938*5ffd940aSRaphael Isemann   EXPECT_FALSE(ParsedVarResult->IsPseudo);
939*5ffd940aSRaphael Isemann }
940*5ffd940aSRaphael Isemann 
941*5ffd940aSRaphael Isemann static void expectNotFoundError(Error Err) {
942*5ffd940aSRaphael Isemann   expectError<NotFoundError>("String not found in input", std::move(Err));
943*5ffd940aSRaphael Isemann }
944*5ffd940aSRaphael Isemann 
945*5ffd940aSRaphael Isemann class PatternTester {
946*5ffd940aSRaphael Isemann private:
947*5ffd940aSRaphael Isemann   size_t LineNumber = 1;
948*5ffd940aSRaphael Isemann   SourceMgr SM;
949*5ffd940aSRaphael Isemann   FileCheckRequest Req;
950*5ffd940aSRaphael Isemann   FileCheckPatternContext Context;
951*5ffd940aSRaphael Isemann   Pattern P{Check::CheckPlain, &Context, LineNumber};
952*5ffd940aSRaphael Isemann 
953*5ffd940aSRaphael Isemann public:
954*5ffd940aSRaphael Isemann   PatternTester() {
955*5ffd940aSRaphael Isemann     std::vector<StringRef> GlobalDefines = {"#FOO=42", "BAR=BAZ", "#add=7"};
956*5ffd940aSRaphael Isemann     // An ASSERT_FALSE would make more sense but cannot be used in a
957*5ffd940aSRaphael Isemann     // constructor.
958*5ffd940aSRaphael Isemann     EXPECT_THAT_ERROR(Context.defineCmdlineVariables(GlobalDefines, SM),
959*5ffd940aSRaphael Isemann                       Succeeded());
960*5ffd940aSRaphael Isemann     Context.createLineVariable();
961*5ffd940aSRaphael Isemann     // Call parsePattern to have @LINE defined.
962*5ffd940aSRaphael Isemann     P.parsePattern("N/A", "CHECK", SM, Req);
963*5ffd940aSRaphael Isemann     // parsePattern does not expect to be called twice for the same line and
964*5ffd940aSRaphael Isemann     // will set FixedStr and RegExStr incorrectly if it is. Therefore prepare
965*5ffd940aSRaphael Isemann     // a pattern for a different line.
966*5ffd940aSRaphael Isemann     initNextPattern();
967*5ffd940aSRaphael Isemann   }
968*5ffd940aSRaphael Isemann 
969*5ffd940aSRaphael Isemann   void initNextPattern() {
970*5ffd940aSRaphael Isemann     P = Pattern(Check::CheckPlain, &Context, ++LineNumber);
971*5ffd940aSRaphael Isemann   }
972*5ffd940aSRaphael Isemann 
973*5ffd940aSRaphael Isemann   size_t getLineNumber() const { return LineNumber; }
974*5ffd940aSRaphael Isemann 
975*5ffd940aSRaphael Isemann   Expected<std::unique_ptr<Expression>>
976*5ffd940aSRaphael Isemann   parseSubst(StringRef Expr, bool IsLegacyLineExpr = false) {
977*5ffd940aSRaphael Isemann     StringRef ExprBufferRef = bufferize(SM, Expr);
978*5ffd940aSRaphael Isemann     Optional<NumericVariable *> DefinedNumericVariable;
979*5ffd940aSRaphael Isemann     return P.parseNumericSubstitutionBlock(
980*5ffd940aSRaphael Isemann         ExprBufferRef, DefinedNumericVariable, IsLegacyLineExpr, LineNumber,
981*5ffd940aSRaphael Isemann         &Context, SM);
982*5ffd940aSRaphael Isemann   }
983*5ffd940aSRaphael Isemann 
984*5ffd940aSRaphael Isemann   bool parsePattern(StringRef Pattern) {
985*5ffd940aSRaphael Isemann     StringRef PatBufferRef = bufferize(SM, Pattern);
986*5ffd940aSRaphael Isemann     return P.parsePattern(PatBufferRef, "CHECK", SM, Req);
987*5ffd940aSRaphael Isemann   }
988*5ffd940aSRaphael Isemann 
989*5ffd940aSRaphael Isemann   Expected<size_t> match(StringRef Buffer) {
990*5ffd940aSRaphael Isemann     StringRef BufferRef = bufferize(SM, Buffer);
991*5ffd940aSRaphael Isemann     size_t MatchLen;
992*5ffd940aSRaphael Isemann     return P.match(BufferRef, MatchLen, SM);
993*5ffd940aSRaphael Isemann   }
994*5ffd940aSRaphael Isemann 
995*5ffd940aSRaphael Isemann   void printVariableDefs(FileCheckDiag::MatchType MatchTy,
996*5ffd940aSRaphael Isemann                          std::vector<FileCheckDiag> &Diags) {
997*5ffd940aSRaphael Isemann     P.printVariableDefs(SM, MatchTy, &Diags);
998*5ffd940aSRaphael Isemann   }
999*5ffd940aSRaphael Isemann };
1000*5ffd940aSRaphael Isemann 
1001*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, ParseNumericSubstitutionBlock) {
1002*5ffd940aSRaphael Isemann   PatternTester Tester;
1003*5ffd940aSRaphael Isemann 
1004*5ffd940aSRaphael Isemann   // Variable definition.
1005*5ffd940aSRaphael Isemann 
1006*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid variable name",
1007*5ffd940aSRaphael Isemann                         Tester.parseSubst("%VAR:").takeError());
1008*5ffd940aSRaphael Isemann 
1009*5ffd940aSRaphael Isemann   expectDiagnosticError("definition of pseudo numeric variable unsupported",
1010*5ffd940aSRaphael Isemann                         Tester.parseSubst("@LINE:").takeError());
1011*5ffd940aSRaphael Isemann 
1012*5ffd940aSRaphael Isemann   expectDiagnosticError("string variable with name 'BAR' already exists",
1013*5ffd940aSRaphael Isemann                         Tester.parseSubst("BAR:").takeError());
1014*5ffd940aSRaphael Isemann 
1015*5ffd940aSRaphael Isemann   expectDiagnosticError("unexpected characters after numeric variable name",
1016*5ffd940aSRaphael Isemann                         Tester.parseSubst("VAR GARBAGE:").takeError());
1017*5ffd940aSRaphael Isemann 
1018*5ffd940aSRaphael Isemann   // Change of format.
1019*5ffd940aSRaphael Isemann   expectDiagnosticError("format different from previous variable definition",
1020*5ffd940aSRaphael Isemann                         Tester.parseSubst("%X,FOO:").takeError());
1021*5ffd940aSRaphael Isemann 
1022*5ffd940aSRaphael Isemann   // Invalid format.
1023*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching format specification in expression",
1024*5ffd940aSRaphael Isemann                         Tester.parseSubst("X,VAR1:").takeError());
1025*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid format specifier in expression",
1026*5ffd940aSRaphael Isemann                         Tester.parseSubst("%F,VAR1:").takeError());
1027*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching format specification in expression",
1028*5ffd940aSRaphael Isemann                         Tester.parseSubst("%X a,VAR1:").takeError());
1029*5ffd940aSRaphael Isemann 
1030*5ffd940aSRaphael Isemann   // Acceptable variable definition.
1031*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("VAR1:"), Succeeded());
1032*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("  VAR2:"), Succeeded());
1033*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("VAR3  :"), Succeeded());
1034*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("VAR3:  "), Succeeded());
1035*5ffd940aSRaphael Isemann 
1036*5ffd940aSRaphael Isemann   // Acceptable variable definition with format specifier. Use parsePattern for
1037*5ffd940aSRaphael Isemann   // variables whose definition needs to be visible for later checks.
1038*5ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[#%u, VAR_UNSIGNED:]]"));
1039*5ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[#%x, VAR_LOWER_HEX:]]"));
1040*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%X, VAR_UPPER_HEX:"), Succeeded());
1041*5ffd940aSRaphael Isemann 
1042*5ffd940aSRaphael Isemann   // Acceptable variable definition with precision specifier.
1043*5ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[#%.8X, PADDED_ADDR:]]"));
1044*5ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[#%.8, PADDED_NUM:]]"));
1045*5ffd940aSRaphael Isemann 
1046*5ffd940aSRaphael Isemann   // Acceptable variable definition from a numeric expression.
1047*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOOBAR: FOO+1"), Succeeded());
1048*5ffd940aSRaphael Isemann 
1049*5ffd940aSRaphael Isemann   // Numeric expression. Switch to next line to make above valid definition
1050*5ffd940aSRaphael Isemann   // available in expressions.
1051*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1052*5ffd940aSRaphael Isemann 
1053*5ffd940aSRaphael Isemann   // Invalid variable name.
1054*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching constraint or operand format",
1055*5ffd940aSRaphael Isemann                         Tester.parseSubst("%VAR").takeError());
1056*5ffd940aSRaphael Isemann 
1057*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid pseudo numeric variable '@FOO'",
1058*5ffd940aSRaphael Isemann                         Tester.parseSubst("@FOO").takeError());
1059*5ffd940aSRaphael Isemann 
1060*5ffd940aSRaphael Isemann   // parsePattern() is used here instead of parseSubst() for the variable to be
1061*5ffd940aSRaphael Isemann   // recorded in GlobalNumericVariableTable and thus appear defined to
1062*5ffd940aSRaphael Isemann   // parseNumericVariableUse(). Note that the same pattern object is used for
1063*5ffd940aSRaphael Isemann   // the parsePattern() and parseSubst() since no initNextPattern() is called,
1064*5ffd940aSRaphael Isemann   // thus appearing as being on the same line from the pattern's point of view.
1065*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#SAME_LINE_VAR:]]"));
1066*5ffd940aSRaphael Isemann   expectDiagnosticError("numeric variable 'SAME_LINE_VAR' defined earlier in "
1067*5ffd940aSRaphael Isemann                         "the same CHECK directive",
1068*5ffd940aSRaphael Isemann                         Tester.parseSubst("SAME_LINE_VAR").takeError());
1069*5ffd940aSRaphael Isemann 
1070*5ffd940aSRaphael Isemann   // Invalid use of variable defined on the same line from an expression not
1071*5ffd940aSRaphael Isemann   // using any variable defined on the same line.
1072*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#SAME_LINE_EXPR_VAR:@LINE+1]]"));
1073*5ffd940aSRaphael Isemann   expectDiagnosticError("numeric variable 'SAME_LINE_EXPR_VAR' defined earlier "
1074*5ffd940aSRaphael Isemann                         "in the same CHECK directive",
1075*5ffd940aSRaphael Isemann                         Tester.parseSubst("SAME_LINE_EXPR_VAR").takeError());
1076*5ffd940aSRaphael Isemann 
1077*5ffd940aSRaphael Isemann   // Valid use of undefined variable which creates the variable and record it
1078*5ffd940aSRaphael Isemann   // in GlobalNumericVariableTable.
1079*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(Tester.parseSubst("UNDEF"), Succeeded());
1080*5ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[UNDEF:.*]]"));
1081*5ffd940aSRaphael Isemann 
1082*5ffd940aSRaphael Isemann   // Invalid literal.
1083*5ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation 'U'",
1084*5ffd940aSRaphael Isemann                         Tester.parseSubst("42U").takeError());
1085*5ffd940aSRaphael Isemann 
1086*5ffd940aSRaphael Isemann   // Valid empty expression.
1087*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst(""), Succeeded());
1088*5ffd940aSRaphael Isemann 
1089*5ffd940aSRaphael Isemann   // Invalid equality matching constraint with empty expression.
1090*5ffd940aSRaphael Isemann   expectDiagnosticError("empty numeric expression should not have a constraint",
1091*5ffd940aSRaphael Isemann                         Tester.parseSubst("==").takeError());
1092*5ffd940aSRaphael Isemann 
1093*5ffd940aSRaphael Isemann   // Valid single operand expression.
1094*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOO"), Succeeded());
1095*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("18"), Succeeded());
1096*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst(std::to_string(MaxUint64)),
1097*5ffd940aSRaphael Isemann                        Succeeded());
1098*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("0x12"), Succeeded());
1099*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("-30"), Succeeded());
1100*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst(std::to_string(MinInt64)),
1101*5ffd940aSRaphael Isemann                        Succeeded());
1102*5ffd940aSRaphael Isemann 
1103*5ffd940aSRaphael Isemann   // Valid optional matching constraint.
1104*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("==FOO"), Succeeded());
1105*5ffd940aSRaphael Isemann 
1106*5ffd940aSRaphael Isemann   // Invalid matching constraint.
1107*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching constraint or operand format",
1108*5ffd940aSRaphael Isemann                         Tester.parseSubst("+=FOO").takeError());
1109*5ffd940aSRaphael Isemann 
1110*5ffd940aSRaphael Isemann   // Invalid format.
1111*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching format specification in expression",
1112*5ffd940aSRaphael Isemann                         Tester.parseSubst("X,FOO:").takeError());
1113*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid format specifier in expression",
1114*5ffd940aSRaphael Isemann                         Tester.parseSubst("%F,FOO").takeError());
1115*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching format specification in expression",
1116*5ffd940aSRaphael Isemann                         Tester.parseSubst("%X a,FOO").takeError());
1117*5ffd940aSRaphael Isemann 
1118*5ffd940aSRaphael Isemann   // Valid expression with 2 or more operands.
1119*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOO+3"), Succeeded());
1120*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOO+0xC"), Succeeded());
1121*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOO-3+FOO"), Succeeded());
1122*5ffd940aSRaphael Isemann 
1123*5ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation '/'",
1124*5ffd940aSRaphael Isemann                         Tester.parseSubst("@LINE/2").takeError());
1125*5ffd940aSRaphael Isemann 
1126*5ffd940aSRaphael Isemann   expectDiagnosticError("missing operand in expression",
1127*5ffd940aSRaphael Isemann                         Tester.parseSubst("@LINE+").takeError());
1128*5ffd940aSRaphael Isemann 
1129*5ffd940aSRaphael Isemann   // Errors in RHS operand are bubbled up by parseBinop() to
1130*5ffd940aSRaphael Isemann   // parseNumericSubstitutionBlock().
1131*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid operand format",
1132*5ffd940aSRaphael Isemann                         Tester.parseSubst("@LINE+%VAR").takeError());
1133*5ffd940aSRaphael Isemann 
1134*5ffd940aSRaphael Isemann   // Invalid legacy @LINE expression with non literal rhs.
1135*5ffd940aSRaphael Isemann   expectDiagnosticError(
1136*5ffd940aSRaphael Isemann       "invalid operand format",
1137*5ffd940aSRaphael Isemann       Tester.parseSubst("@LINE+@LINE", /*IsLegacyNumExpr=*/true).takeError());
1138*5ffd940aSRaphael Isemann 
1139*5ffd940aSRaphael Isemann   // Invalid legacy @LINE expression made of a single literal.
1140*5ffd940aSRaphael Isemann   expectDiagnosticError(
1141*5ffd940aSRaphael Isemann       "invalid variable name",
1142*5ffd940aSRaphael Isemann       Tester.parseSubst("2", /*IsLegacyNumExpr=*/true).takeError());
1143*5ffd940aSRaphael Isemann 
1144*5ffd940aSRaphael Isemann   // Invalid hex literal in legacy @LINE expression.
1145*5ffd940aSRaphael Isemann   expectDiagnosticError(
1146*5ffd940aSRaphael Isemann       "unexpected characters at end of expression 'xC'",
1147*5ffd940aSRaphael Isemann       Tester.parseSubst("@LINE+0xC", /*LegacyLineExpr=*/true).takeError());
1148*5ffd940aSRaphael Isemann 
1149*5ffd940aSRaphael Isemann   // Valid expression with format specifier.
1150*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%u, FOO"), Succeeded());
1151*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%d, FOO"), Succeeded());
1152*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%x, FOO"), Succeeded());
1153*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%X, FOO"), Succeeded());
1154*5ffd940aSRaphael Isemann 
1155*5ffd940aSRaphael Isemann   // Valid expression with precision specifier.
1156*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%.8u, FOO"), Succeeded());
1157*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%.8, FOO"), Succeeded());
1158*5ffd940aSRaphael Isemann 
1159*5ffd940aSRaphael Isemann   // Valid legacy @LINE expression.
1160*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("@LINE+2", /*IsLegacyNumExpr=*/true),
1161*5ffd940aSRaphael Isemann                        Succeeded());
1162*5ffd940aSRaphael Isemann 
1163*5ffd940aSRaphael Isemann   // Invalid legacy @LINE expression with more than 2 operands.
1164*5ffd940aSRaphael Isemann   expectDiagnosticError(
1165*5ffd940aSRaphael Isemann       "unexpected characters at end of expression '+@LINE'",
1166*5ffd940aSRaphael Isemann       Tester.parseSubst("@LINE+2+@LINE", /*IsLegacyNumExpr=*/true).takeError());
1167*5ffd940aSRaphael Isemann   expectDiagnosticError(
1168*5ffd940aSRaphael Isemann       "unexpected characters at end of expression '+2'",
1169*5ffd940aSRaphael Isemann       Tester.parseSubst("@LINE+2+2", /*IsLegacyNumExpr=*/true).takeError());
1170*5ffd940aSRaphael Isemann 
1171*5ffd940aSRaphael Isemann   // Valid expression with several variables when their implicit formats do not
1172*5ffd940aSRaphael Isemann   // conflict.
1173*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOO+VAR_UNSIGNED"), Succeeded());
1174*5ffd940aSRaphael Isemann 
1175*5ffd940aSRaphael Isemann   // Valid implicit format conflict in presence of explicit formats.
1176*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("%X,FOO+VAR_LOWER_HEX"), Succeeded());
1177*5ffd940aSRaphael Isemann 
1178*5ffd940aSRaphael Isemann   // Implicit format conflict.
1179*5ffd940aSRaphael Isemann   expectDiagnosticError(
1180*5ffd940aSRaphael Isemann       "implicit format conflict between 'FOO' (%u) and "
1181*5ffd940aSRaphael Isemann       "'VAR_LOWER_HEX' (%x), need an explicit format specifier",
1182*5ffd940aSRaphael Isemann       Tester.parseSubst("FOO+VAR_LOWER_HEX").takeError());
1183*5ffd940aSRaphael Isemann 
1184*5ffd940aSRaphael Isemann   // Simple parenthesized expressions:
1185*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("(1)"), Succeeded());
1186*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("(1+1)"), Succeeded());
1187*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("(1)+1"), Succeeded());
1188*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("((1)+1)"), Succeeded());
1189*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("((1)+X)"), Succeeded());
1190*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("((X)+Y)"), Succeeded());
1191*5ffd940aSRaphael Isemann 
1192*5ffd940aSRaphael Isemann   expectDiagnosticError("missing operand in expression",
1193*5ffd940aSRaphael Isemann                         Tester.parseSubst("(").takeError());
1194*5ffd940aSRaphael Isemann   expectDiagnosticError("missing ')' at end of nested expression",
1195*5ffd940aSRaphael Isemann                         Tester.parseSubst("(1").takeError());
1196*5ffd940aSRaphael Isemann   expectDiagnosticError("missing operand in expression",
1197*5ffd940aSRaphael Isemann                         Tester.parseSubst("(1+").takeError());
1198*5ffd940aSRaphael Isemann   expectDiagnosticError("missing ')' at end of nested expression",
1199*5ffd940aSRaphael Isemann                         Tester.parseSubst("(1+1").takeError());
1200*5ffd940aSRaphael Isemann   expectDiagnosticError("missing ')' at end of nested expression",
1201*5ffd940aSRaphael Isemann                         Tester.parseSubst("((1+2+3").takeError());
1202*5ffd940aSRaphael Isemann   expectDiagnosticError("missing ')' at end of nested expression",
1203*5ffd940aSRaphael Isemann                         Tester.parseSubst("((1+2)+3").takeError());
1204*5ffd940aSRaphael Isemann 
1205*5ffd940aSRaphael Isemann   // Test missing operation between operands:
1206*5ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation '('",
1207*5ffd940aSRaphael Isemann                         Tester.parseSubst("(1)(2)").takeError());
1208*5ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation '('",
1209*5ffd940aSRaphael Isemann                         Tester.parseSubst("2(X)").takeError());
1210*5ffd940aSRaphael Isemann 
1211*5ffd940aSRaphael Isemann   // Test more closing than opening parentheses. The diagnostic messages are
1212*5ffd940aSRaphael Isemann   // not ideal, but for now simply check that we reject invalid input.
1213*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid matching constraint or operand format",
1214*5ffd940aSRaphael Isemann                         Tester.parseSubst(")").takeError());
1215*5ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation ')'",
1216*5ffd940aSRaphael Isemann                         Tester.parseSubst("1)").takeError());
1217*5ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation ')'",
1218*5ffd940aSRaphael Isemann                         Tester.parseSubst("(1+2))").takeError());
1219*5ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation ')'",
1220*5ffd940aSRaphael Isemann                         Tester.parseSubst("(2))").takeError());
1221*5ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation ')'",
1222*5ffd940aSRaphael Isemann                         Tester.parseSubst("(1))(").takeError());
1223*5ffd940aSRaphael Isemann 
1224*5ffd940aSRaphael Isemann   // Valid expression with function call.
1225*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add(FOO,3)"), Succeeded());
1226*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add (FOO,3)"), Succeeded());
1227*5ffd940aSRaphael Isemann   // Valid expression with nested function call.
1228*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add(FOO, min(BAR,10))"), Succeeded());
1229*5ffd940aSRaphael Isemann   // Valid expression with function call taking expression as argument.
1230*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add(FOO, (BAR+10) + 3)"),
1231*5ffd940aSRaphael Isemann                        Succeeded());
1232*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add(FOO, min (BAR,10) + 3)"),
1233*5ffd940aSRaphael Isemann                        Succeeded());
1234*5ffd940aSRaphael Isemann   // Valid expression with variable named the same as a function.
1235*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add"), Succeeded());
1236*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add+FOO"), Succeeded());
1237*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("FOO+add"), Succeeded());
1238*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.parseSubst("add(add,add)+add"), Succeeded());
1239*5ffd940aSRaphael Isemann 
1240*5ffd940aSRaphael Isemann   // Malformed call syntax.
1241*5ffd940aSRaphael Isemann   expectDiagnosticError("missing ')' at end of call expression",
1242*5ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO,(BAR+7)").takeError());
1243*5ffd940aSRaphael Isemann   expectDiagnosticError("missing ')' at end of call expression",
1244*5ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO,min(BAR,7)").takeError());
1245*5ffd940aSRaphael Isemann   expectDiagnosticError("missing argument",
1246*5ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO,)").takeError());
1247*5ffd940aSRaphael Isemann   expectDiagnosticError("missing argument",
1248*5ffd940aSRaphael Isemann                         Tester.parseSubst("add(,FOO)").takeError());
1249*5ffd940aSRaphael Isemann   expectDiagnosticError("missing argument",
1250*5ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO,,3)").takeError());
1251*5ffd940aSRaphael Isemann 
1252*5ffd940aSRaphael Isemann   // Valid call, but to an unknown function.
1253*5ffd940aSRaphael Isemann   expectDiagnosticError("call to undefined function 'bogus_function'",
1254*5ffd940aSRaphael Isemann                         Tester.parseSubst("bogus_function(FOO,3)").takeError());
1255*5ffd940aSRaphael Isemann   expectDiagnosticError("call to undefined function '@add'",
1256*5ffd940aSRaphael Isemann                         Tester.parseSubst("@add(2,3)").takeError());
1257*5ffd940aSRaphael Isemann   expectDiagnosticError("call to undefined function '$add'",
1258*5ffd940aSRaphael Isemann                         Tester.parseSubst("$add(2,3)").takeError());
1259*5ffd940aSRaphael Isemann   expectDiagnosticError("call to undefined function 'FOO'",
1260*5ffd940aSRaphael Isemann                         Tester.parseSubst("FOO(2,3)").takeError());
1261*5ffd940aSRaphael Isemann   expectDiagnosticError("call to undefined function 'FOO'",
1262*5ffd940aSRaphael Isemann                         Tester.parseSubst("FOO (2,3)").takeError());
1263*5ffd940aSRaphael Isemann 
1264*5ffd940aSRaphael Isemann   // Valid call, but with incorrect argument count.
1265*5ffd940aSRaphael Isemann   expectDiagnosticError("function 'add' takes 2 arguments but 1 given",
1266*5ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO)").takeError());
1267*5ffd940aSRaphael Isemann   expectDiagnosticError("function 'add' takes 2 arguments but 3 given",
1268*5ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO,3,4)").takeError());
1269*5ffd940aSRaphael Isemann 
1270*5ffd940aSRaphael Isemann   // Valid call, but not part of a valid expression.
1271*5ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation 'a'",
1272*5ffd940aSRaphael Isemann                         Tester.parseSubst("2add(FOO,2)").takeError());
1273*5ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation 'a'",
1274*5ffd940aSRaphael Isemann                         Tester.parseSubst("FOO add(FOO,2)").takeError());
1275*5ffd940aSRaphael Isemann   expectDiagnosticError("unsupported operation 'a'",
1276*5ffd940aSRaphael Isemann                         Tester.parseSubst("add(FOO,2)add(FOO,2)").takeError());
1277*5ffd940aSRaphael Isemann }
1278*5ffd940aSRaphael Isemann 
1279*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, ParsePattern) {
1280*5ffd940aSRaphael Isemann   PatternTester Tester;
1281*5ffd940aSRaphael Isemann 
1282*5ffd940aSRaphael Isemann   // Invalid space in string substitution.
1283*5ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[ BAR]]"));
1284*5ffd940aSRaphael Isemann 
1285*5ffd940aSRaphael Isemann   // Invalid variable name in string substitution.
1286*5ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[42INVALID]]"));
1287*5ffd940aSRaphael Isemann 
1288*5ffd940aSRaphael Isemann   // Invalid string variable definition.
1289*5ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[@PAT:]]"));
1290*5ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[PAT+2:]]"));
1291*5ffd940aSRaphael Isemann 
1292*5ffd940aSRaphael Isemann   // Collision with numeric variable.
1293*5ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[FOO:]]"));
1294*5ffd940aSRaphael Isemann 
1295*5ffd940aSRaphael Isemann   // Valid use of string variable.
1296*5ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[BAR]]"));
1297*5ffd940aSRaphael Isemann 
1298*5ffd940aSRaphael Isemann   // Valid string variable definition.
1299*5ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[PAT:[0-9]+]]"));
1300*5ffd940aSRaphael Isemann 
1301*5ffd940aSRaphael Isemann   // Invalid numeric substitution.
1302*5ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[#42INVALID]]"));
1303*5ffd940aSRaphael Isemann 
1304*5ffd940aSRaphael Isemann   // Valid numeric substitution.
1305*5ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[#FOO]]"));
1306*5ffd940aSRaphael Isemann 
1307*5ffd940aSRaphael Isemann   // Valid legacy @LINE expression.
1308*5ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[@LINE+2]]"));
1309*5ffd940aSRaphael Isemann 
1310*5ffd940aSRaphael Isemann   // Invalid legacy @LINE expression with non decimal literal.
1311*5ffd940aSRaphael Isemann   EXPECT_TRUE(Tester.parsePattern("[[@LINE+0x3]]"));
1312*5ffd940aSRaphael Isemann }
1313*5ffd940aSRaphael Isemann 
1314*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, Match) {
1315*5ffd940aSRaphael Isemann   PatternTester Tester;
1316*5ffd940aSRaphael Isemann 
1317*5ffd940aSRaphael Isemann   // Check a substitution error is diagnosed.
1318*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#%u, -1]]"));
1319*5ffd940aSRaphael Isemann   expectDiagnosticError(
1320*5ffd940aSRaphael Isemann       "unable to substitute variable or numeric expression: overflow error",
1321*5ffd940aSRaphael Isemann       Tester.match("").takeError());
1322*5ffd940aSRaphael Isemann 
1323*5ffd940aSRaphael Isemann   // Check matching an empty expression only matches a number.
1324*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1325*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#]]"));
1326*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("FAIL").takeError());
1327*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
1328*5ffd940aSRaphael Isemann 
1329*5ffd940aSRaphael Isemann   // Check matching a definition only matches a number with the right format.
1330*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1331*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR:]]"));
1332*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("FAIL").takeError());
1333*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("").takeError());
1334*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
1335*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1336*5ffd940aSRaphael Isemann   Tester.parsePattern("[[#%u,NUMVAR_UNSIGNED:]]");
1337*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("C").takeError());
1338*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("20"), Succeeded());
1339*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1340*5ffd940aSRaphael Isemann   Tester.parsePattern("[[#%x,NUMVAR_LOWER_HEX:]]");
1341*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("g").takeError());
1342*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("C").takeError());
1343*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("c"), Succeeded());
1344*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1345*5ffd940aSRaphael Isemann   Tester.parsePattern("[[#%X,NUMVAR_UPPER_HEX:]]");
1346*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("H").takeError());
1347*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("b").takeError());
1348*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("B"), Succeeded());
1349*5ffd940aSRaphael Isemann 
1350*5ffd940aSRaphael Isemann   // Check matching expressions with no explicit format matches the values in
1351*5ffd940aSRaphael Isemann   // the right format.
1352*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1353*5ffd940aSRaphael Isemann   Tester.parsePattern("[[#NUMVAR_UNSIGNED-5]]");
1354*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("f").takeError());
1355*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("F").takeError());
1356*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("15"), Succeeded());
1357*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1358*5ffd940aSRaphael Isemann   Tester.parsePattern("[[#NUMVAR_LOWER_HEX+1]]");
1359*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("13").takeError());
1360*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("D").takeError());
1361*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("d"), Succeeded());
1362*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1363*5ffd940aSRaphael Isemann   Tester.parsePattern("[[#NUMVAR_UPPER_HEX+1]]");
1364*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("12").takeError());
1365*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("c").takeError());
1366*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("C"), Succeeded());
1367*5ffd940aSRaphael Isemann 
1368*5ffd940aSRaphael Isemann   // Check matching an undefined variable returns a NotFound error.
1369*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1370*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("100"));
1371*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("101").takeError());
1372*5ffd940aSRaphael Isemann 
1373*5ffd940aSRaphael Isemann   // Check matching the defined variable matches the correct number only.
1374*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1375*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR]]"));
1376*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
1377*5ffd940aSRaphael Isemann 
1378*5ffd940aSRaphael Isemann   // Check matching several substitutions does not match them independently.
1379*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1380*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR]] [[#NUMVAR+2]]"));
1381*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("19 21").takeError());
1382*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("18 21").takeError());
1383*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18 20"), Succeeded());
1384*5ffd940aSRaphael Isemann 
1385*5ffd940aSRaphael Isemann   // Check matching a numeric expression using @LINE after a match failure uses
1386*5ffd940aSRaphael Isemann   // the correct value for @LINE.
1387*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1388*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#@LINE]]"));
1389*5ffd940aSRaphael Isemann   // Ok, @LINE matches the current line number.
1390*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match(std::to_string(Tester.getLineNumber())),
1391*5ffd940aSRaphael Isemann                        Succeeded());
1392*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1393*5ffd940aSRaphael Isemann   // Match with substitution failure.
1394*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#UNKNOWN]]"));
1395*5ffd940aSRaphael Isemann   expectUndefErrors({"UNKNOWN"}, Tester.match("FOO").takeError());
1396*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1397*5ffd940aSRaphael Isemann   // Check that @LINE matches the later (given the calls to initNextPattern())
1398*5ffd940aSRaphael Isemann   // line number.
1399*5ffd940aSRaphael Isemann   EXPECT_FALSE(Tester.parsePattern("[[#@LINE]]"));
1400*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match(std::to_string(Tester.getLineNumber())),
1401*5ffd940aSRaphael Isemann                        Succeeded());
1402*5ffd940aSRaphael Isemann }
1403*5ffd940aSRaphael Isemann 
1404*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, MatchParen) {
1405*5ffd940aSRaphael Isemann   PatternTester Tester;
1406*5ffd940aSRaphael Isemann   // Check simple parenthesized expressions
1407*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1408*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR:]]"));
1409*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("FAIL").takeError());
1410*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("").takeError());
1411*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
1412*5ffd940aSRaphael Isemann 
1413*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1414*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR + (2 + 2)]]"));
1415*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("21").takeError());
1416*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("22"), Succeeded());
1417*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1418*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR + (2)]]"));
1419*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("20"), Succeeded());
1420*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1421*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR+(2)]]"));
1422*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("20"), Succeeded());
1423*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1424*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR+(NUMVAR)]]"));
1425*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("36"), Succeeded());
1426*5ffd940aSRaphael Isemann 
1427*5ffd940aSRaphael Isemann   // Check nested parenthesized expressions:
1428*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1429*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR+(2+(2))]]"));
1430*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("22"), Succeeded());
1431*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1432*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR+(2+(NUMVAR))]]"));
1433*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("38"), Succeeded());
1434*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1435*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR+((((NUMVAR))))]]"));
1436*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("36"), Succeeded());
1437*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1438*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR+((((NUMVAR)))-1)-1]]"));
1439*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("34"), Succeeded());
1440*5ffd940aSRaphael Isemann 
1441*5ffd940aSRaphael Isemann   // Parentheses can also be the first character after the '#':
1442*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1443*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#(NUMVAR)]]"));
1444*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
1445*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1446*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#(NUMVAR+2)]]"));
1447*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("20"), Succeeded());
1448*5ffd940aSRaphael Isemann }
1449*5ffd940aSRaphael Isemann 
1450*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, MatchBuiltinFunctions) {
1451*5ffd940aSRaphael Isemann   PatternTester Tester;
1452*5ffd940aSRaphael Isemann   // Esnure #NUMVAR has the expected value.
1453*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1454*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#NUMVAR:]]"));
1455*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("FAIL").takeError());
1456*5ffd940aSRaphael Isemann   expectNotFoundError(Tester.match("").takeError());
1457*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
1458*5ffd940aSRaphael Isemann 
1459*5ffd940aSRaphael Isemann   // Check each builtin function generates the expected result.
1460*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1461*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#add(NUMVAR,13)]]"));
1462*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("31"), Succeeded());
1463*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1464*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#div(NUMVAR,3)]]"));
1465*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("6"), Succeeded());
1466*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1467*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#max(NUMVAR,5)]]"));
1468*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
1469*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1470*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#max(NUMVAR,99)]]"));
1471*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("99"), Succeeded());
1472*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1473*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#min(NUMVAR,5)]]"));
1474*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("5"), Succeeded());
1475*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1476*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#min(NUMVAR,99)]]"));
1477*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("18"), Succeeded());
1478*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1479*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#mul(NUMVAR,3)]]"));
1480*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("54"), Succeeded());
1481*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1482*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#sub(NUMVAR,7)]]"));
1483*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("11"), Succeeded());
1484*5ffd940aSRaphael Isemann 
1485*5ffd940aSRaphael Isemann   // Check nested function calls.
1486*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1487*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#add(min(7,2),max(4,10))]]"));
1488*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("12"), Succeeded());
1489*5ffd940aSRaphael Isemann 
1490*5ffd940aSRaphael Isemann   // Check function call that uses a variable of the same name.
1491*5ffd940aSRaphael Isemann   Tester.initNextPattern();
1492*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[#add(add,add)+min (add,3)+add]]"));
1493*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("24"), Succeeded());
1494*5ffd940aSRaphael Isemann }
1495*5ffd940aSRaphael Isemann 
1496*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, Substitution) {
1497*5ffd940aSRaphael Isemann   SourceMgr SM;
1498*5ffd940aSRaphael Isemann   FileCheckPatternContext Context;
1499*5ffd940aSRaphael Isemann   EXPECT_THAT_ERROR(Context.defineCmdlineVariables({"FOO=BAR"}, SM),
1500*5ffd940aSRaphael Isemann                     Succeeded());
1501*5ffd940aSRaphael Isemann 
1502*5ffd940aSRaphael Isemann   // Substitution of an undefined string variable fails and error holds that
1503*5ffd940aSRaphael Isemann   // variable's name.
1504*5ffd940aSRaphael Isemann   StringSubstitution StringSubstitution(&Context, "VAR404", 42);
1505*5ffd940aSRaphael Isemann   Expected<std::string> SubstValue = StringSubstitution.getResult();
1506*5ffd940aSRaphael Isemann   expectUndefErrors({"VAR404"}, SubstValue.takeError());
1507*5ffd940aSRaphael Isemann 
1508*5ffd940aSRaphael Isemann   // Numeric substitution blocks constituted of defined numeric variables are
1509*5ffd940aSRaphael Isemann   // substituted for the variable's value.
1510*5ffd940aSRaphael Isemann   NumericVariable NVar("N", ExpressionFormat(ExpressionFormat::Kind::Unsigned),
1511*5ffd940aSRaphael Isemann                        1);
1512*5ffd940aSRaphael Isemann   NVar.setValue(ExpressionValue(10u));
1513*5ffd940aSRaphael Isemann   auto NVarUse = std::make_unique<NumericVariableUse>("N", &NVar);
1514*5ffd940aSRaphael Isemann   auto ExpressionN = std::make_unique<Expression>(
1515*5ffd940aSRaphael Isemann       std::move(NVarUse), ExpressionFormat(ExpressionFormat::Kind::HexUpper));
1516*5ffd940aSRaphael Isemann   NumericSubstitution SubstitutionN(&Context, "N", std::move(ExpressionN),
1517*5ffd940aSRaphael Isemann                                     /*InsertIdx=*/30);
1518*5ffd940aSRaphael Isemann   SubstValue = SubstitutionN.getResult();
1519*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SubstValue, Succeeded());
1520*5ffd940aSRaphael Isemann   EXPECT_EQ("A", *SubstValue);
1521*5ffd940aSRaphael Isemann 
1522*5ffd940aSRaphael Isemann   // Substitution of an undefined numeric variable fails, error holds name of
1523*5ffd940aSRaphael Isemann   // undefined variable.
1524*5ffd940aSRaphael Isemann   NVar.clearValue();
1525*5ffd940aSRaphael Isemann   SubstValue = SubstitutionN.getResult();
1526*5ffd940aSRaphael Isemann   expectUndefErrors({"N"}, SubstValue.takeError());
1527*5ffd940aSRaphael Isemann 
1528*5ffd940aSRaphael Isemann   // Substitution of a defined string variable returns the right value.
1529*5ffd940aSRaphael Isemann   Pattern P(Check::CheckPlain, &Context, 1);
1530*5ffd940aSRaphael Isemann   StringSubstitution = llvm::StringSubstitution(&Context, "FOO", 42);
1531*5ffd940aSRaphael Isemann   SubstValue = StringSubstitution.getResult();
1532*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(SubstValue, Succeeded());
1533*5ffd940aSRaphael Isemann   EXPECT_EQ("BAR", *SubstValue);
1534*5ffd940aSRaphael Isemann }
1535*5ffd940aSRaphael Isemann 
1536*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, FileCheckContext) {
1537*5ffd940aSRaphael Isemann   FileCheckPatternContext Cxt;
1538*5ffd940aSRaphael Isemann   SourceMgr SM;
1539*5ffd940aSRaphael Isemann 
1540*5ffd940aSRaphael Isemann   // No definition.
1541*5ffd940aSRaphael Isemann   EXPECT_THAT_ERROR(Cxt.defineCmdlineVariables({}, SM), Succeeded());
1542*5ffd940aSRaphael Isemann 
1543*5ffd940aSRaphael Isemann   // Missing equal sign.
1544*5ffd940aSRaphael Isemann   expectDiagnosticError("missing equal sign in global definition",
1545*5ffd940aSRaphael Isemann                         Cxt.defineCmdlineVariables({"LocalVar"}, SM));
1546*5ffd940aSRaphael Isemann   expectDiagnosticError("missing equal sign in global definition",
1547*5ffd940aSRaphael Isemann                         Cxt.defineCmdlineVariables({"#LocalNumVar"}, SM));
1548*5ffd940aSRaphael Isemann 
1549*5ffd940aSRaphael Isemann   // Empty variable name.
1550*5ffd940aSRaphael Isemann   expectDiagnosticError("empty variable name",
1551*5ffd940aSRaphael Isemann                         Cxt.defineCmdlineVariables({"=18"}, SM));
1552*5ffd940aSRaphael Isemann   expectDiagnosticError("empty variable name",
1553*5ffd940aSRaphael Isemann                         Cxt.defineCmdlineVariables({"#=18"}, SM));
1554*5ffd940aSRaphael Isemann 
1555*5ffd940aSRaphael Isemann   // Invalid variable name.
1556*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid variable name",
1557*5ffd940aSRaphael Isemann                         Cxt.defineCmdlineVariables({"18LocalVar=18"}, SM));
1558*5ffd940aSRaphael Isemann   expectDiagnosticError("invalid variable name",
1559*5ffd940aSRaphael Isemann                         Cxt.defineCmdlineVariables({"#18LocalNumVar=18"}, SM));
1560*5ffd940aSRaphael Isemann 
1561*5ffd940aSRaphael Isemann   // Name conflict between pattern and numeric variable.
1562*5ffd940aSRaphael Isemann   expectDiagnosticError(
1563*5ffd940aSRaphael Isemann       "string variable with name 'LocalVar' already exists",
1564*5ffd940aSRaphael Isemann       Cxt.defineCmdlineVariables({"LocalVar=18", "#LocalVar=36"}, SM));
1565*5ffd940aSRaphael Isemann   Cxt = FileCheckPatternContext();
1566*5ffd940aSRaphael Isemann   expectDiagnosticError(
1567*5ffd940aSRaphael Isemann       "numeric variable with name 'LocalNumVar' already exists",
1568*5ffd940aSRaphael Isemann       Cxt.defineCmdlineVariables({"#LocalNumVar=18", "LocalNumVar=36"}, SM));
1569*5ffd940aSRaphael Isemann   Cxt = FileCheckPatternContext();
1570*5ffd940aSRaphael Isemann 
1571*5ffd940aSRaphael Isemann   // Invalid numeric value for numeric variable.
1572*5ffd940aSRaphael Isemann   expectUndefErrors({"x"}, Cxt.defineCmdlineVariables({"#LocalNumVar=x"}, SM));
1573*5ffd940aSRaphael Isemann 
1574*5ffd940aSRaphael Isemann   // Define local variables from command-line.
1575*5ffd940aSRaphael Isemann   std::vector<StringRef> GlobalDefines;
1576*5ffd940aSRaphael Isemann   // Clear local variables to remove dummy numeric variable x that
1577*5ffd940aSRaphael Isemann   // parseNumericSubstitutionBlock would have created and stored in
1578*5ffd940aSRaphael Isemann   // GlobalNumericVariableTable.
1579*5ffd940aSRaphael Isemann   Cxt.clearLocalVars();
1580*5ffd940aSRaphael Isemann   GlobalDefines.emplace_back("LocalVar=FOO");
1581*5ffd940aSRaphael Isemann   GlobalDefines.emplace_back("EmptyVar=");
1582*5ffd940aSRaphael Isemann   GlobalDefines.emplace_back("#LocalNumVar1=18");
1583*5ffd940aSRaphael Isemann   GlobalDefines.emplace_back("#%x,LocalNumVar2=LocalNumVar1+2");
1584*5ffd940aSRaphael Isemann   GlobalDefines.emplace_back("#LocalNumVar3=0xc");
1585*5ffd940aSRaphael Isemann   ASSERT_THAT_ERROR(Cxt.defineCmdlineVariables(GlobalDefines, SM), Succeeded());
1586*5ffd940aSRaphael Isemann 
1587*5ffd940aSRaphael Isemann   // Create @LINE pseudo numeric variable and check it is present by matching
1588*5ffd940aSRaphael Isemann   // it.
1589*5ffd940aSRaphael Isemann   size_t LineNumber = 1;
1590*5ffd940aSRaphael Isemann   Pattern P(Check::CheckPlain, &Cxt, LineNumber);
1591*5ffd940aSRaphael Isemann   FileCheckRequest Req;
1592*5ffd940aSRaphael Isemann   Cxt.createLineVariable();
1593*5ffd940aSRaphael Isemann   ASSERT_FALSE(P.parsePattern("[[@LINE]]", "CHECK", SM, Req));
1594*5ffd940aSRaphael Isemann   size_t MatchLen;
1595*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(P.match("1", MatchLen, SM), Succeeded());
1596*5ffd940aSRaphael Isemann 
1597*5ffd940aSRaphael Isemann #ifndef NDEBUG
1598*5ffd940aSRaphael Isemann   // Recreating @LINE pseudo numeric variable fails.
1599*5ffd940aSRaphael Isemann   EXPECT_DEATH(Cxt.createLineVariable(),
1600*5ffd940aSRaphael Isemann                "@LINE pseudo numeric variable already created");
1601*5ffd940aSRaphael Isemann #endif
1602*5ffd940aSRaphael Isemann 
1603*5ffd940aSRaphael Isemann   // Check defined variables are present and undefined ones are absent.
1604*5ffd940aSRaphael Isemann   StringRef LocalVarStr = "LocalVar";
1605*5ffd940aSRaphael Isemann   StringRef LocalNumVar1Ref = bufferize(SM, "LocalNumVar1");
1606*5ffd940aSRaphael Isemann   StringRef LocalNumVar2Ref = bufferize(SM, "LocalNumVar2");
1607*5ffd940aSRaphael Isemann   StringRef LocalNumVar3Ref = bufferize(SM, "LocalNumVar3");
1608*5ffd940aSRaphael Isemann   StringRef EmptyVarStr = "EmptyVar";
1609*5ffd940aSRaphael Isemann   StringRef UnknownVarStr = "UnknownVar";
1610*5ffd940aSRaphael Isemann   Expected<StringRef> LocalVar = Cxt.getPatternVarValue(LocalVarStr);
1611*5ffd940aSRaphael Isemann   P = Pattern(Check::CheckPlain, &Cxt, ++LineNumber);
1612*5ffd940aSRaphael Isemann   Optional<NumericVariable *> DefinedNumericVariable;
1613*5ffd940aSRaphael Isemann   Expected<std::unique_ptr<Expression>> ExpressionPointer =
1614*5ffd940aSRaphael Isemann       P.parseNumericSubstitutionBlock(LocalNumVar1Ref, DefinedNumericVariable,
1615*5ffd940aSRaphael Isemann                                       /*IsLegacyLineExpr=*/false, LineNumber,
1616*5ffd940aSRaphael Isemann                                       &Cxt, SM);
1617*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(LocalVar, Succeeded());
1618*5ffd940aSRaphael Isemann   EXPECT_EQ(*LocalVar, "FOO");
1619*5ffd940aSRaphael Isemann   Expected<StringRef> EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
1620*5ffd940aSRaphael Isemann   Expected<StringRef> UnknownVar = Cxt.getPatternVarValue(UnknownVarStr);
1621*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
1622*5ffd940aSRaphael Isemann   Expected<ExpressionValue> ExpressionVal =
1623*5ffd940aSRaphael Isemann       (*ExpressionPointer)->getAST()->eval();
1624*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionVal, Succeeded());
1625*5ffd940aSRaphael Isemann   EXPECT_EQ(cantFail(ExpressionVal->getSignedValue()), 18);
1626*5ffd940aSRaphael Isemann   ExpressionPointer = P.parseNumericSubstitutionBlock(
1627*5ffd940aSRaphael Isemann       LocalNumVar2Ref, DefinedNumericVariable,
1628*5ffd940aSRaphael Isemann       /*IsLegacyLineExpr=*/false, LineNumber, &Cxt, SM);
1629*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
1630*5ffd940aSRaphael Isemann   ExpressionVal = (*ExpressionPointer)->getAST()->eval();
1631*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionVal, Succeeded());
1632*5ffd940aSRaphael Isemann   EXPECT_EQ(cantFail(ExpressionVal->getSignedValue()), 20);
1633*5ffd940aSRaphael Isemann   ExpressionPointer = P.parseNumericSubstitutionBlock(
1634*5ffd940aSRaphael Isemann       LocalNumVar3Ref, DefinedNumericVariable,
1635*5ffd940aSRaphael Isemann       /*IsLegacyLineExpr=*/false, LineNumber, &Cxt, SM);
1636*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
1637*5ffd940aSRaphael Isemann   ExpressionVal = (*ExpressionPointer)->getAST()->eval();
1638*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionVal, Succeeded());
1639*5ffd940aSRaphael Isemann   EXPECT_EQ(cantFail(ExpressionVal->getSignedValue()), 12);
1640*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(EmptyVar, Succeeded());
1641*5ffd940aSRaphael Isemann   EXPECT_EQ(*EmptyVar, "");
1642*5ffd940aSRaphael Isemann   expectUndefErrors({std::string(UnknownVarStr)}, UnknownVar.takeError());
1643*5ffd940aSRaphael Isemann 
1644*5ffd940aSRaphael Isemann   // Clear local variables and check they become absent.
1645*5ffd940aSRaphael Isemann   Cxt.clearLocalVars();
1646*5ffd940aSRaphael Isemann   LocalVar = Cxt.getPatternVarValue(LocalVarStr);
1647*5ffd940aSRaphael Isemann   expectUndefErrors({std::string(LocalVarStr)}, LocalVar.takeError());
1648*5ffd940aSRaphael Isemann   // Check a numeric expression's evaluation fails if called after clearing of
1649*5ffd940aSRaphael Isemann   // local variables, if it was created before. This is important because local
1650*5ffd940aSRaphael Isemann   // variable clearing due to --enable-var-scope happens after numeric
1651*5ffd940aSRaphael Isemann   // expressions are linked to the numeric variables they use.
1652*5ffd940aSRaphael Isemann   expectUndefErrors({"LocalNumVar3"},
1653*5ffd940aSRaphael Isemann                     (*ExpressionPointer)->getAST()->eval().takeError());
1654*5ffd940aSRaphael Isemann   P = Pattern(Check::CheckPlain, &Cxt, ++LineNumber);
1655*5ffd940aSRaphael Isemann   ExpressionPointer = P.parseNumericSubstitutionBlock(
1656*5ffd940aSRaphael Isemann       LocalNumVar1Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
1657*5ffd940aSRaphael Isemann       LineNumber, &Cxt, SM);
1658*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
1659*5ffd940aSRaphael Isemann   ExpressionVal = (*ExpressionPointer)->getAST()->eval();
1660*5ffd940aSRaphael Isemann   expectUndefErrors({"LocalNumVar1"}, ExpressionVal.takeError());
1661*5ffd940aSRaphael Isemann   ExpressionPointer = P.parseNumericSubstitutionBlock(
1662*5ffd940aSRaphael Isemann       LocalNumVar2Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
1663*5ffd940aSRaphael Isemann       LineNumber, &Cxt, SM);
1664*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
1665*5ffd940aSRaphael Isemann   ExpressionVal = (*ExpressionPointer)->getAST()->eval();
1666*5ffd940aSRaphael Isemann   expectUndefErrors({"LocalNumVar2"}, ExpressionVal.takeError());
1667*5ffd940aSRaphael Isemann   EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
1668*5ffd940aSRaphael Isemann   expectUndefErrors({"EmptyVar"}, EmptyVar.takeError());
1669*5ffd940aSRaphael Isemann   // Clear again because parseNumericSubstitutionBlock would have created a
1670*5ffd940aSRaphael Isemann   // dummy variable and stored it in GlobalNumericVariableTable.
1671*5ffd940aSRaphael Isemann   Cxt.clearLocalVars();
1672*5ffd940aSRaphael Isemann 
1673*5ffd940aSRaphael Isemann   // Redefine global variables and check variables are defined again.
1674*5ffd940aSRaphael Isemann   GlobalDefines.emplace_back("$GlobalVar=BAR");
1675*5ffd940aSRaphael Isemann   GlobalDefines.emplace_back("#$GlobalNumVar=36");
1676*5ffd940aSRaphael Isemann   ASSERT_THAT_ERROR(Cxt.defineCmdlineVariables(GlobalDefines, SM), Succeeded());
1677*5ffd940aSRaphael Isemann   StringRef GlobalVarStr = "$GlobalVar";
1678*5ffd940aSRaphael Isemann   StringRef GlobalNumVarRef = bufferize(SM, "$GlobalNumVar");
1679*5ffd940aSRaphael Isemann   Expected<StringRef> GlobalVar = Cxt.getPatternVarValue(GlobalVarStr);
1680*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(GlobalVar, Succeeded());
1681*5ffd940aSRaphael Isemann   EXPECT_EQ(*GlobalVar, "BAR");
1682*5ffd940aSRaphael Isemann   P = Pattern(Check::CheckPlain, &Cxt, ++LineNumber);
1683*5ffd940aSRaphael Isemann   ExpressionPointer = P.parseNumericSubstitutionBlock(
1684*5ffd940aSRaphael Isemann       GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
1685*5ffd940aSRaphael Isemann       LineNumber, &Cxt, SM);
1686*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
1687*5ffd940aSRaphael Isemann   ExpressionVal = (*ExpressionPointer)->getAST()->eval();
1688*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionVal, Succeeded());
1689*5ffd940aSRaphael Isemann   EXPECT_EQ(cantFail(ExpressionVal->getSignedValue()), 36);
1690*5ffd940aSRaphael Isemann 
1691*5ffd940aSRaphael Isemann   // Clear local variables and check global variables remain defined.
1692*5ffd940aSRaphael Isemann   Cxt.clearLocalVars();
1693*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Cxt.getPatternVarValue(GlobalVarStr), Succeeded());
1694*5ffd940aSRaphael Isemann   P = Pattern(Check::CheckPlain, &Cxt, ++LineNumber);
1695*5ffd940aSRaphael Isemann   ExpressionPointer = P.parseNumericSubstitutionBlock(
1696*5ffd940aSRaphael Isemann       GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
1697*5ffd940aSRaphael Isemann       LineNumber, &Cxt, SM);
1698*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionPointer, Succeeded());
1699*5ffd940aSRaphael Isemann   ExpressionVal = (*ExpressionPointer)->getAST()->eval();
1700*5ffd940aSRaphael Isemann   ASSERT_THAT_EXPECTED(ExpressionVal, Succeeded());
1701*5ffd940aSRaphael Isemann   EXPECT_EQ(cantFail(ExpressionVal->getSignedValue()), 36);
1702*5ffd940aSRaphael Isemann }
1703*5ffd940aSRaphael Isemann 
1704*5ffd940aSRaphael Isemann TEST_F(FileCheckTest, CapturedVarDiags) {
1705*5ffd940aSRaphael Isemann   PatternTester Tester;
1706*5ffd940aSRaphael Isemann   ASSERT_FALSE(Tester.parsePattern("[[STRVAR:[a-z]+]] [[#NUMVAR:@LINE]]"));
1707*5ffd940aSRaphael Isemann   EXPECT_THAT_EXPECTED(Tester.match("foobar 2"), Succeeded());
1708*5ffd940aSRaphael Isemann   std::vector<FileCheckDiag> Diags;
1709*5ffd940aSRaphael Isemann   Tester.printVariableDefs(FileCheckDiag::MatchFoundAndExpected, Diags);
1710*5ffd940aSRaphael Isemann   EXPECT_EQ(Diags.size(), 2ul);
1711*5ffd940aSRaphael Isemann   for (FileCheckDiag Diag : Diags) {
1712*5ffd940aSRaphael Isemann     EXPECT_EQ(Diag.CheckTy, Check::CheckPlain);
1713*5ffd940aSRaphael Isemann     EXPECT_EQ(Diag.MatchTy, FileCheckDiag::MatchFoundAndExpected);
1714*5ffd940aSRaphael Isemann     EXPECT_EQ(Diag.InputStartLine, 1u);
1715*5ffd940aSRaphael Isemann     EXPECT_EQ(Diag.InputEndLine, 1u);
1716*5ffd940aSRaphael Isemann   }
1717*5ffd940aSRaphael Isemann   EXPECT_EQ(Diags[0].InputStartCol, 1u);
1718*5ffd940aSRaphael Isemann   EXPECT_EQ(Diags[0].InputEndCol, 7u);
1719*5ffd940aSRaphael Isemann   EXPECT_EQ(Diags[1].InputStartCol, 8u);
1720*5ffd940aSRaphael Isemann   EXPECT_EQ(Diags[1].InputEndCol, 9u);
1721*5ffd940aSRaphael Isemann   EXPECT_EQ(Diags[0].Note, "captured var \"STRVAR\"");
1722*5ffd940aSRaphael Isemann   EXPECT_EQ(Diags[1].Note, "captured var \"NUMVAR\"");
1723*5ffd940aSRaphael Isemann }
1724*5ffd940aSRaphael Isemann } // namespace
1725