diff options
author | Thomas Preud'homme <thomasp@graphcore.ai> | 2019-07-23 22:41:38 +0000 |
---|---|---|
committer | Thomas Preud'homme <thomasp@graphcore.ai> | 2019-07-23 22:41:38 +0000 |
commit | 1b05977538d9487aa845ee2f3bec8b89c63c4f29 (patch) | |
tree | a07940c8253e44d48e5a95de8c113a77d3311a55 /llvm/unittests/Support/FileCheckTest.cpp | |
parent | f8552e67e91177911351f3ffa8028d44ec1e8b66 (diff) | |
download | llvm-1b05977538d9487aa845ee2f3bec8b89c63c4f29.zip llvm-1b05977538d9487aa845ee2f3bec8b89c63c4f29.tar.gz llvm-1b05977538d9487aa845ee2f3bec8b89c63c4f29.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
Diffstat (limited to 'llvm/unittests/Support/FileCheckTest.cpp')
-rw-r--r-- | llvm/unittests/Support/FileCheckTest.cpp | 166 |
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)); |