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