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