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