brintos

brintos / llvm-project-archived public Read only

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