aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Support/FileCheckTest.cpp
diff options
context:
space:
mode:
authorThomas Preud'homme <thomasp@graphcore.ai>2019-07-24 12:38:22 +0000
committerThomas Preud'homme <thomasp@graphcore.ai>2019-07-24 12:38:22 +0000
commit4cd9b853b5ae3f569683cdba955cd70c39a7bbe7 (patch)
treee9076e6c90b01ffa446fda580570b8419f181f1f /llvm/unittests/Support/FileCheckTest.cpp
parent7d79b552e36dc94f81231849443dcb7b63aa8457 (diff)
downloadllvm-4cd9b853b5ae3f569683cdba955cd70c39a7bbe7.zip
llvm-4cd9b853b5ae3f569683cdba955cd70c39a7bbe7.tar.gz
llvm-4cd9b853b5ae3f569683cdba955cd70c39a7bbe7.tar.bz2
FileCheck [8/12]: Define numeric var from expr
Summary: This patch is part of a patch series to add support for FileCheck numeric expressions. This specific patch lift the restriction for a numeric expression to either be a variable definition or a numeric expression to try to match. This commit allows a numeric variable to be set to the result of the evaluation of a numeric expression after it has been matched successfully. When it happens, the variable is allowed to be used on the same line since its value is known at match time. It also makes use of this possibility to reuse the parsing code to parse a command-line definition by crafting a mirror string of the -D option with the equal sign replaced by a colon sign, e.g. for option '-D#NUMVAL=10' it creates the string '-D#NUMVAL=10 (parsed as [[#NUMVAL:10]])' where the numeric expression is parsed to define NUMVAL. This result in a few tests needing updating for the location diagnostics on top of the tests for the new feature. It also enables empty numeric expression which match any number without defining a variable. This is done here rather than in commit #5 of the patch series because it requires to dissociate automatic regex insertion in RegExStr from variable definition which would make commit #5 even bigger than it already is. Copyright: - Linaro (changes up to diff 183612 of revision D55940) - GraphCore (changes in later versions of revision D55940 and in new revision created off D55940) Reviewers: jhenderson, chandlerc, jdenny, probinson, grimar, arichardson, rnk Subscribers: hiraditya, llvm-commits, probinson, dblaikie, grimar, arichardson, tra, rnk, kristina, hfinkel, rogfer01, JonChesterfield Tags: #llvm Differential Revision: https://reviews.llvm.org/D60388 > llvm-svn: 366860 llvm-svn: 366897
Diffstat (limited to 'llvm/unittests/Support/FileCheckTest.cpp')
-rw-r--r--llvm/unittests/Support/FileCheckTest.cpp166
1 files changed, 113 insertions, 53 deletions
diff --git a/llvm/unittests/Support/FileCheckTest.cpp b/llvm/unittests/Support/FileCheckTest.cpp
index 2b7b270..147ed68 100644
--- a/llvm/unittests/Support/FileCheckTest.cpp
+++ b/llvm/unittests/Support/FileCheckTest.cpp
@@ -49,15 +49,21 @@ expectUndefErrors(std::unordered_set<std::string> ExpectedUndefVarNames,
EXPECT_TRUE(ExpectedUndefVarNames.empty()) << toString(ExpectedUndefVarNames);
}
+// Return whether Err contains any FileCheckUndefVarError whose associated name
+// is not ExpectedUndefVarName.
static void expectUndefError(const Twine &ExpectedUndefVarName, Error Err) {
expectUndefErrors({ExpectedUndefVarName.str()}, std::move(Err));
}
+uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; }
+
TEST_F(FileCheckTest, NumericVariable) {
- // Undefined variable: getValue and eval fail, error returned by eval holds
- // the name of the undefined variable.
+ // Undefined variable: isValueKnownAtMatchTime returns false, getValue and
+ // eval fail, error returned by eval holds the name of the undefined
+ // variable.
FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 1);
EXPECT_EQ("FOO", FooVar.getName());
+ EXPECT_FALSE(FooVar.isValueKnownAtMatchTime());
FileCheckNumericVariableUse FooVarUse =
FileCheckNumericVariableUse("FOO", &FooVar);
EXPECT_FALSE(FooVar.getValue());
@@ -67,7 +73,9 @@ TEST_F(FileCheckTest, NumericVariable) {
FooVar.setValue(42);
- // Defined variable: getValue and eval return value set.
+ // Defined variable: isValueKnownAtMatchTime returns true, getValue and eval
+ // return value set.
+ EXPECT_TRUE(FooVar.isValueKnownAtMatchTime());
Optional<uint64_t> Value = FooVar.getValue();
EXPECT_TRUE(bool(Value));
EXPECT_EQ(42U, *Value);
@@ -75,24 +83,51 @@ TEST_F(FileCheckTest, NumericVariable) {
EXPECT_TRUE(bool(EvalResult));
EXPECT_EQ(42U, *EvalResult);
+ // Variable defined by numeric expression: isValueKnownAtMatchTime
+ // returns true, getValue and eval return value of expression, setValue
+ // clears expression.
+ std::unique_ptr<FileCheckNumericVariableUse> FooVarUsePtr =
+ llvm::make_unique<FileCheckNumericVariableUse>("FOO", &FooVar);
+ std::unique_ptr<FileCheckExpressionLiteral> One =
+ llvm::make_unique<FileCheckExpressionLiteral>(1);
+ FileCheckASTBinop Binop =
+ FileCheckASTBinop(doAdd, std::move(FooVarUsePtr), std::move(One));
+ FileCheckNumericVariable FoobarExprVar =
+ FileCheckNumericVariable("FOOBAR", 2, &Binop);
+ EXPECT_TRUE(FoobarExprVar.isValueKnownAtMatchTime());
+ EXPECT_FALSE(FoobarExprVar.getValue());
+ FileCheckNumericVariableUse FoobarExprVarUse =
+ FileCheckNumericVariableUse("FOOBAR", &FoobarExprVar);
+ EvalResult = FoobarExprVarUse.eval();
+ EXPECT_TRUE(bool(EvalResult));
+ EXPECT_EQ(43U, *EvalResult);
+ EXPECT_TRUE(FoobarExprVar.getExpressionAST());
+ FoobarExprVar.setValue(43);
+ EXPECT_FALSE(FoobarExprVar.getExpressionAST());
+ FoobarExprVar = FileCheckNumericVariable("FOOBAR", 2, &Binop);
+ EXPECT_TRUE(FoobarExprVar.getExpressionAST());
+
// Clearing variable: getValue and eval fail. Error returned by eval holds
// the name of the cleared variable.
FooVar.clearValue();
- Value = FooVar.getValue();
- EXPECT_FALSE(Value);
+ FoobarExprVar.clearValue();
+ EXPECT_FALSE(FoobarExprVar.getExpressionAST());
+ EXPECT_FALSE(FooVar.getValue());
+ EXPECT_FALSE(FoobarExprVar.getValue());
EvalResult = FooVarUse.eval();
EXPECT_FALSE(EvalResult);
expectUndefError("FOO", EvalResult.takeError());
+ EvalResult = FoobarExprVarUse.eval();
+ EXPECT_FALSE(EvalResult);
+ expectUndefError("FOOBAR", EvalResult.takeError());
}
-uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; }
-
TEST_F(FileCheckTest, Binop) {
- FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO");
+ FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 1);
FooVar.setValue(42);
std::unique_ptr<FileCheckNumericVariableUse> FooVarUse =
llvm::make_unique<FileCheckNumericVariableUse>("FOO", &FooVar);
- FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR");
+ FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR", 2);
BarVar.setValue(18);
std::unique_ptr<FileCheckNumericVariableUse> BarVarUse =
llvm::make_unique<FileCheckNumericVariableUse>("BAR", &BarVar);
@@ -237,19 +272,13 @@ public:
P = FileCheckPattern(Check::CheckPlain, &Context, LineNumber++);
}
- bool parseNumVarDefExpect(StringRef Expr) {
- StringRef ExprBufferRef = bufferize(SM, Expr);
- return errorToBool(FileCheckPattern::parseNumericVariableDefinition(
- ExprBufferRef, &Context, LineNumber, SM)
- .takeError());
- }
-
bool parseSubstExpect(StringRef Expr) {
StringRef ExprBufferRef = bufferize(SM, Expr);
Optional<FileCheckNumericVariable *> DefinedNumericVariable;
- return errorToBool(P.parseNumericSubstitutionBlock(
- ExprBufferRef, DefinedNumericVariable, false, SM)
- .takeError());
+ return errorToBool(
+ P.parseNumericSubstitutionBlock(ExprBufferRef, DefinedNumericVariable,
+ false, LineNumber - 1, &Context, SM)
+ .takeError());
}
bool parsePatternExpect(StringRef Pattern) {
@@ -264,19 +293,6 @@ public:
}
};
-TEST_F(FileCheckTest, ParseNumericVariableDefinition) {
- PatternTester Tester;
-
- // Invalid definition of pseudo.
- EXPECT_TRUE(Tester.parseNumVarDefExpect("@LINE"));
-
- // Conflict with pattern variable.
- EXPECT_TRUE(Tester.parseNumVarDefExpect("BAR"));
-
- // Defined variable.
- EXPECT_FALSE(Tester.parseNumVarDefExpect("FOO"));
-}
-
TEST_F(FileCheckTest, ParseExpr) {
PatternTester Tester;
@@ -287,17 +303,18 @@ TEST_F(FileCheckTest, ParseExpr) {
EXPECT_TRUE(Tester.parseSubstExpect("@FOO:"));
EXPECT_TRUE(Tester.parseSubstExpect("@LINE:"));
+ // Conflict with pattern variable.
+ EXPECT_TRUE(Tester.parseSubstExpect("BAR:"));
+
// Garbage after name of variable being defined.
EXPECT_TRUE(Tester.parseSubstExpect("VAR GARBAGE:"));
- // Variable defined to numeric expression.
- EXPECT_TRUE(Tester.parseSubstExpect("VAR1: FOO"));
-
// Acceptable variable definition.
EXPECT_FALSE(Tester.parseSubstExpect("VAR1:"));
EXPECT_FALSE(Tester.parseSubstExpect(" VAR2:"));
EXPECT_FALSE(Tester.parseSubstExpect("VAR3 :"));
EXPECT_FALSE(Tester.parseSubstExpect("VAR3: "));
+ EXPECT_FALSE(Tester.parsePatternExpect("[[#FOOBAR: FOO+1]]"));
// Numeric expression.
@@ -310,9 +327,21 @@ TEST_F(FileCheckTest, ParseExpr) {
EXPECT_FALSE(Tester.parseSubstExpect("FOO"));
EXPECT_FALSE(Tester.parseSubstExpect("UNDEF"));
- // Use variable defined on same line.
- EXPECT_FALSE(Tester.parsePatternExpect("[[#LINE1VAR:]]"));
- EXPECT_TRUE(Tester.parseSubstExpect("LINE1VAR"));
+ // Valid empty expression.
+ EXPECT_FALSE(Tester.parseSubstExpect(""));
+
+ // Valid use of variable defined on the same line from expression. Note that
+ // the same pattern object is used for the parsePatternExpect and
+ // parseSubstExpect since no initNextPattern is called, thus appearing as
+ // being on the same line from the pattern's point of view.
+ EXPECT_FALSE(Tester.parsePatternExpect("[[#LINE1VAR:FOO+1]]"));
+ EXPECT_FALSE(Tester.parseSubstExpect("LINE1VAR"));
+
+ // Invalid use of variable defined on same line from input. As above, the
+ // absence of a call to initNextPattern makes it appear to be on the same
+ // line from the pattern's point of view.
+ EXPECT_FALSE(Tester.parsePatternExpect("[[#LINE2VAR:]]"));
+ EXPECT_TRUE(Tester.parseSubstExpect("LINE2VAR"));
// Unsupported operator.
EXPECT_TRUE(Tester.parseSubstExpect("@LINE/2"));
@@ -323,6 +352,7 @@ TEST_F(FileCheckTest, ParseExpr) {
// Valid expression.
EXPECT_FALSE(Tester.parseSubstExpect("@LINE+5"));
EXPECT_FALSE(Tester.parseSubstExpect("FOO+4"));
+ EXPECT_FALSE(Tester.parseSubstExpect("FOOBAR"));
Tester.initNextPattern();
EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO+FOO]]"));
EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO+3-FOO]]"));
@@ -354,7 +384,6 @@ TEST_F(FileCheckTest, ParsePattern) {
EXPECT_TRUE(Tester.parsePatternExpect("[[#42INVALID]]"));
EXPECT_TRUE(Tester.parsePatternExpect("[[#@FOO]]"));
EXPECT_TRUE(Tester.parsePatternExpect("[[#@LINE/2]]"));
- EXPECT_TRUE(Tester.parsePatternExpect("[[#YUP:@LINE]]"));
// Valid numeric expressions and numeric variable definition.
EXPECT_FALSE(Tester.parsePatternExpect("[[#FOO]]"));
@@ -365,9 +394,16 @@ TEST_F(FileCheckTest, ParsePattern) {
TEST_F(FileCheckTest, Match) {
PatternTester Tester;
+ // Check matching an empty expression only matches a number.
+ Tester.parsePatternExpect("[[#]]");
+ EXPECT_TRUE(Tester.matchExpect("FAIL"));
+ EXPECT_FALSE(Tester.matchExpect("18"));
+
// Check matching a definition only matches a number.
+ Tester.initNextPattern();
Tester.parsePatternExpect("[[#NUMVAR:]]");
EXPECT_TRUE(Tester.matchExpect("FAIL"));
+ EXPECT_TRUE(Tester.matchExpect(""));
EXPECT_FALSE(Tester.matchExpect("18"));
// Check matching the variable defined matches the correct number only
@@ -381,16 +417,16 @@ TEST_F(FileCheckTest, Match) {
// the correct value for @LINE.
Tester.initNextPattern();
EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE]]"));
- // Ok, @LINE is 4 now.
- EXPECT_FALSE(Tester.matchExpect("4"));
+ // Ok, @LINE is 5 now.
+ EXPECT_FALSE(Tester.matchExpect("5"));
Tester.initNextPattern();
- // @LINE is now 5, match with substitution failure.
+ // @LINE is now 6, match with substitution failure.
EXPECT_FALSE(Tester.parsePatternExpect("[[#UNKNOWN]]"));
EXPECT_TRUE(Tester.matchExpect("FOO"));
Tester.initNextPattern();
- // Check that @LINE is 6 as expected.
+ // Check that @LINE is 7 as expected.
EXPECT_FALSE(Tester.parsePatternExpect("[[#@LINE]]"));
- EXPECT_FALSE(Tester.matchExpect("6"));
+ EXPECT_FALSE(Tester.matchExpect("7"));
}
TEST_F(FileCheckTest, Substitution) {
@@ -410,9 +446,9 @@ TEST_F(FileCheckTest, Substitution) {
// Substitutions of defined pseudo and non-pseudo numeric variables return
// the right value.
- FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE");
+ FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 1);
+ FileCheckNumericVariable NVar = FileCheckNumericVariable("N", 1);
LineVar.setValue(42);
- FileCheckNumericVariable NVar = FileCheckNumericVariable("N");
NVar.setValue(10);
auto LineVarUse =
llvm::make_unique<FileCheckNumericVariableUse>("@LINE", &LineVar);
@@ -494,22 +530,29 @@ TEST_F(FileCheckTest, FileCheckContext) {
// Define local variables from command-line.
GlobalDefines.clear();
+ // Clear local variables to remove dummy numeric variable x that
+ // parseNumericSubstitutionBlock would have created and stored in
+ // GlobalNumericVariableTable.
+ Cxt.clearLocalVars();
GlobalDefines.emplace_back(std::string("LocalVar=FOO"));
GlobalDefines.emplace_back(std::string("EmptyVar="));
- GlobalDefines.emplace_back(std::string("#LocalNumVar=18"));
+ GlobalDefines.emplace_back(std::string("#LocalNumVar1=18"));
+ GlobalDefines.emplace_back(std::string("#LocalNumVar2=LocalNumVar1+2"));
EXPECT_FALSE(errorToBool(Cxt.defineCmdlineVariables(GlobalDefines, SM)));
// Check defined variables are present and undefined is absent.
StringRef LocalVarStr = "LocalVar";
- StringRef LocalNumVarRef = bufferize(SM, "LocalNumVar");
+ StringRef LocalNumVar1Ref = bufferize(SM, "LocalNumVar1");
+ StringRef LocalNumVar2Ref = bufferize(SM, "LocalNumVar2");
StringRef EmptyVarStr = "EmptyVar";
StringRef UnknownVarStr = "UnknownVar";
Expected<StringRef> LocalVar = Cxt.getPatternVarValue(LocalVarStr);
FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Cxt, 1);
Optional<FileCheckNumericVariable *> DefinedNumericVariable;
Expected<std::unique_ptr<FileCheckExpressionAST>> ExpressionAST =
- P.parseNumericSubstitutionBlock(LocalNumVarRef, DefinedNumericVariable,
- /*IsLegacyLineExpr=*/false, SM);
+ P.parseNumericSubstitutionBlock(LocalNumVar1Ref, DefinedNumericVariable,
+ /*IsLegacyLineExpr=*/false,
+ /*LineNumber=*/1, &Cxt, SM);
EXPECT_TRUE(bool(LocalVar));
EXPECT_EQ(*LocalVar, "FOO");
Expected<StringRef> EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
@@ -518,6 +561,14 @@ TEST_F(FileCheckTest, FileCheckContext) {
Expected<uint64_t> ExpressionVal = (*ExpressionAST)->eval();
EXPECT_TRUE(bool(ExpressionVal));
EXPECT_EQ(*ExpressionVal, 18U);
+ ExpressionAST =
+ P.parseNumericSubstitutionBlock(LocalNumVar2Ref, DefinedNumericVariable,
+ /*IsLegacyLineExpr=*/false,
+ /*LineNumber=*/1, &Cxt, SM);
+ EXPECT_TRUE(bool(ExpressionAST));
+ ExpressionVal = (*ExpressionAST)->eval();
+ EXPECT_TRUE(bool(ExpressionVal));
+ EXPECT_EQ(*ExpressionVal, 20U);
EXPECT_TRUE(bool(EmptyVar));
EXPECT_EQ(*EmptyVar, "");
EXPECT_TRUE(errorToBool(UnknownVar.takeError()));
@@ -533,7 +584,14 @@ TEST_F(FileCheckTest, FileCheckContext) {
EXPECT_TRUE(errorToBool((*ExpressionAST)->eval().takeError()));
P = FileCheckPattern(Check::CheckPlain, &Cxt, 2);
ExpressionAST = P.parseNumericSubstitutionBlock(
- LocalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, SM);
+ LocalNumVar1Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
+ /*LineNumber=*/2, &Cxt, SM);
+ EXPECT_TRUE(bool(ExpressionAST));
+ ExpressionVal = (*ExpressionAST)->eval();
+ EXPECT_TRUE(errorToBool(ExpressionVal.takeError()));
+ ExpressionAST = P.parseNumericSubstitutionBlock(
+ LocalNumVar2Ref, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
+ /*LineNumber=*/2, &Cxt, SM);
EXPECT_TRUE(bool(ExpressionAST));
ExpressionVal = (*ExpressionAST)->eval();
EXPECT_TRUE(errorToBool(ExpressionVal.takeError()));
@@ -554,7 +612,8 @@ TEST_F(FileCheckTest, FileCheckContext) {
EXPECT_EQ(*GlobalVar, "BAR");
P = FileCheckPattern(Check::CheckPlain, &Cxt, 3);
ExpressionAST = P.parseNumericSubstitutionBlock(
- GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, SM);
+ GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
+ /*LineNumber=*/3, &Cxt, SM);
EXPECT_TRUE(bool(ExpressionAST));
ExpressionVal = (*ExpressionAST)->eval();
EXPECT_TRUE(bool(ExpressionVal));
@@ -565,7 +624,8 @@ TEST_F(FileCheckTest, FileCheckContext) {
EXPECT_FALSE(errorToBool(Cxt.getPatternVarValue(GlobalVarStr).takeError()));
P = FileCheckPattern(Check::CheckPlain, &Cxt, 4);
ExpressionAST = P.parseNumericSubstitutionBlock(
- GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false, SM);
+ GlobalNumVarRef, DefinedNumericVariable, /*IsLegacyLineExpr=*/false,
+ /*LineNumber=*/4, &Cxt, SM);
EXPECT_TRUE(bool(ExpressionAST));
ExpressionVal = (*ExpressionAST)->eval();
EXPECT_TRUE(bool(ExpressionVal));