llvm.org GIT mirror llvm / 4a675fb
[FileCheck] Stop qualifying expressions as numeric Summary: Stop referring to "numeric expression", using simply the term "expression" instead. Likewise for numeric operation since operations are only used in numeric expressions. Reviewers: jhenderson, jdenny, probinson, arichardson Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63500 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363901 91177308-0d34-0410-b5e6-96231b3b80d8 Thomas Preud'homme 2 months ago
6 changed file(s) with 140 addition(s) and 140 deletion(s). Raw diff Collapse all Expand all
591591
592592 * ```` is the name of a defined numeric variable.
593593
594 * ```` is an optional numeric operation to perform on the value of
595 ````. Currently supported numeric operations are ``+`` and ``-``.
594 * ```` is an optional operation to perform on the value of ````.
595 Currently supported operations are ``+`` and ``-``.
596596
597597 * ```` is the immediate value that constitutes the second operand of
598 the numeric operation . It must be present if ```` is present,
599 absent otherwise.
598 the operation ````. It must be present if ```` is present, absent
599 otherwise.
600600
601601 Spaces are accepted before, after and between any of these elements.
602602
626626 The ``--enable-var-scope`` option has the same effect on numeric variables as
627627 on string variables.
628628
629 Important note: In its current implementation, a numeric expression cannot use
630 a numeric variable defined on the same line.
629 Important note: In its current implementation, an expression cannot use a
630 numeric variable defined on the same line.
631631
632632 FileCheck Pseudo Numeric Variables
633633 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
638638 line numbers in the same file, which have to be updated whenever line numbers
639639 change due to text addition or deletion.
640640
641 To support this case, FileCheck numeric expressions understand the ``@LINE``
642 pseudo numeric variable which evaluates to the line number of the CHECK pattern
643 where it is found.
641 To support this case, FileCheck expressions understand the ``@LINE`` pseudo
642 numeric variable which evaluates to the line number of the CHECK pattern where
643 it is found.
644644
645645 This way match patterns can be put near the relevant test lines and include
646646 relative line number references, for example:
6565 FileCheckNumericVariable(StringRef Name, uint64_t Value)
6666 : Name(Name), Value(Value), DefLineNumber(0) {}
6767
68 /// \returns name of that numeric variable.
68 /// \returns name of this numeric variable.
6969 StringRef getName() const { return Name; }
7070
71 /// \returns value of this numeric variable.
71 /// \returns this variable's value.
7272 Optional getValue() const { return Value; }
7373
7474 /// Sets value of this numeric variable if not defined. \returns whether the
110110 }
111111 };
112112
113 /// Class representing a numeric expression consisting of either a single
114 /// numeric variable or a binary operation between a numeric variable and an
113 /// Class representing an expression consisting of either a single numeric
114 /// variable or a binary operation between a numeric variable and an
115115 /// immediate.
116 class FileCheckNumExpr {
116 class FileCheckExpression {
117117 private:
118118 /// Left operand.
119119 FileCheckNumericVariable *LeftOp;
125125 binop_eval_t EvalBinop;
126126
127127 public:
128 FileCheckNumExpr(binop_eval_t EvalBinop,
129 FileCheckNumericVariable *OperandLeft, uint64_t OperandRight)
128 FileCheckExpression(binop_eval_t EvalBinop,
129 FileCheckNumericVariable *OperandLeft,
130 uint64_t OperandRight)
130131 : LeftOp(OperandLeft), RightOp(OperandRight), EvalBinop(EvalBinop) {}
131132
132 /// Evaluates the value of this numeric expression, using EvalBinop to
133 /// perform the binary operation it consists of. \returns an error if the
134 /// numeric variable used is undefined, or the expression value otherwise.
133 /// Evaluates the value of this expression, using EvalBinop to perform the
134 /// binary operation it consists of. \returns an error if the numeric
135 /// variable used is undefined, or the expression value otherwise.
135136 Expected eval() const;
136137 };
137138
143144 /// Pointer to a class instance holding, among other things, the table with
144145 /// the values of live string variables at the start of any given CHECK line.
145146 /// Used for substituting string variables with the text they were defined
146 /// as. Numeric expressions are linked to the numeric variables they use at
147 /// as. Expressions are linked to the numeric variables they use at
147148 /// parse time and directly access the value of the numeric variable to
148149 /// evaluate their value.
149150 FileCheckPatternContext *Context;
150151
151152 /// The string that needs to be substituted for something else. For a
152 /// string variable this is its name, otherwise this is the whole numeric
153 /// expression.
153 /// string variable this is its name, otherwise this is the whole expression.
154154 StringRef FromStr;
155155
156156 // Index in RegExStr of where to do the substitution.
187187
188188 class FileCheckNumericSubstitution : public FileCheckSubstitution {
189189 private:
190 /// Pointer to the class representing the numeric expression whose value is
191 /// to be substituted.
192 FileCheckNumExpr *NumExpr;
193
194 public:
195 FileCheckNumericSubstitution(FileCheckPatternContext *Context, StringRef Expr,
196 FileCheckNumExpr *NumExpr, size_t InsertIdx)
197 : FileCheckSubstitution(Context, Expr, InsertIdx), NumExpr(NumExpr) {}
198
199 /// \returns a string containing the result of evaluating the numeric
200 /// expression in this substitution, or an error if evaluation failed.
190 /// Pointer to the class representing the expression whose value is to be
191 /// substituted.
192 FileCheckExpression *Expression;
193
194 public:
195 FileCheckNumericSubstitution(FileCheckPatternContext *Context,
196 StringRef ExpressionStr,
197 FileCheckExpression *Expression,
198 size_t InsertIdx)
199 : FileCheckSubstitution(Context, ExpressionStr, InsertIdx),
200 Expression(Expression) {}
201
202 /// \returns a string containing the result of evaluating the expression in
203 /// this substitution, or an error if evaluation failed.
201204 Expected getResult() const override;
202205 };
203206
275278 /// pattern.
276279 StringMap GlobalNumericVariableTable;
277280
278 /// Vector holding pointers to all parsed numeric expressions. Used to
279 /// automatically free the numeric expressions once they are guaranteed to no
280 /// longer be used.
281 std::vector> NumExprs;
281 /// Vector holding pointers to all parsed expressions. Used to automatically
282 /// free the expressions once they are guaranteed to no longer be used.
283 std::vector> Expressions;
282284
283285 /// Vector holding pointers to all parsed numeric variables. Used to
284286 /// automatically free them once they are guaranteed to no longer be used.
307309 void clearLocalVars();
308310
309311 private:
310 /// Makes a new numeric expression instance and registers it for destruction
311 /// when the context is destroyed.
312 FileCheckNumExpr *makeNumExpr(binop_eval_t EvalBinop,
313 FileCheckNumericVariable *OperandLeft,
314 uint64_t OperandRight);
312 /// Makes a new expression instance and registers it for destruction when
313 /// the context is destroyed.
314 FileCheckExpression *makeExpression(binop_eval_t EvalBinop,
315 FileCheckNumericVariable *OperandLeft,
316 uint64_t OperandRight);
315317
316318 /// Makes a new numeric variable and registers it for destruction when the
317319 /// context is destroyed.
325327
326328 /// Makes a new numeric substitution and registers it for destruction when
327329 /// the context is destroyed.
328 FileCheckSubstitution *makeNumericSubstitution(StringRef Expr,
329 FileCheckNumExpr *NumExpr,
330 size_t InsertIdx);
330 FileCheckSubstitution *
331 makeNumericSubstitution(StringRef ExpressionStr,
332 FileCheckExpression *Expression, size_t InsertIdx);
331333 };
332334
333335 /// Class to represent an error holding a diagnostic with location information
383385 /// a fixed string to match.
384386 std::string RegExStr;
385387
386 /// Entries in this vector represent a substitution of a string variable or a
387 /// numeric expression in the RegExStr regex at match time. For example, in
388 /// the case of a CHECK directive with the pattern "foo[[bar]]baz[[#N+1]]",
388 /// Entries in this vector represent a substitution of a string variable or
389 /// an expression in the RegExStr regex at match time. For example, in the
390 /// case of a CHECK directive with the pattern "foo[[bar]]baz[[#N+1]]",
389391 /// RegExStr will contain "foobaz" and we'll get two entries in this vector
390392 /// that tells us to insert the value of string variable "bar" at offset 3
391 /// and the value of numeric expression "N+1" at offset 6.
393 /// and the value of expression "N+1" at offset 6.
392394 std::vector Substitutions;
393395
394396 /// Maps names of string variables defined in a pattern to the number of
408410 /// It holds the pointer to the class representing the numeric variable whose
409411 /// value is being defined and the number of the parenthesis group in
410412 /// RegExStr to capture that value.
411 struct FileCheckNumExprMatch {
413 struct FileCheckNumericVariableMatch {
412414 /// Pointer to class representing the numeric variable whose value is being
413415 /// defined.
414416 FileCheckNumericVariable *DefinedNumericVariable;
422424 /// corresponding FileCheckNumericVariable class instance of all numeric
423425 /// variable definitions. Used to set the matched value of all those
424426 /// variables.
425 StringMapExprMatch> NumericVariableDefs;
427 StringMapericVariableMatch> NumericVariableDefs;
426428
427429 /// Pointer to a class instance holding the global state shared by all
428430 /// patterns:
467469 FileCheckPatternContext *Context,
468470 const SourceMgr &SM);
469471 /// Parses \p Expr for a numeric substitution block. \returns the class
470 /// representing the AST of the numeric expression whose value must be
471 /// substituted, or an error holding a diagnostic against \p SM if parsing
472 /// fails. If substitution was successful, sets \p DefinedNumericVariable to
473 /// point to the class representing the numeric variable defined in this
474 /// numeric substitution block, or None if this block does not define any
475 /// variable.
476 Expected parseNumericSubstitutionBlock(
472 /// representing the AST of the expression whose value must be substituted,
473 /// or an error holding a diagnostic against \p SM if parsing fails. If
474 /// substitution was successful, sets \p DefinedNumericVariable to point to
475 /// the class representing the numeric variable defined in this numeric
476 /// substitution block, or None if this block does not define any variable.
477 Expected parseNumericSubstitutionBlock(
477478 StringRef Expr,
478479 Optional &DefinedNumericVariable,
479480 const SourceMgr &SM) const;
536537 Expected
537538 parseNumericVariableUse(StringRef &Expr, const SourceMgr &SM) const;
538539 /// Parses \p Expr for a binary operation.
539 /// \returns the class representing the binary operation of the numeric
540 /// expression, or an error holding a diagnostic against \p SM otherwise.
541 Expected parseBinop(StringRef &Expr,
542 const SourceMgr &SM) const;
540 /// \returns the class representing the binary operation of the expression,
541 /// or an error holding a diagnostic against \p SM otherwise.
542 Expected parseBinop(StringRef &Expr,
543 const SourceMgr &SM) const;
543544 };
544545
545546 //===----------------------------------------------------------------------===//
3737 return false;
3838 }
3939
40 Expected FileCheckNumExpr::eval() const {
41 assert(LeftOp && "Evaluating an empty numeric expression");
40 Expected FileCheckExpression::eval() const {
41 assert(LeftOp && "Evaluating an empty expression");
4242 Optional LeftOpValue = LeftOp->getValue();
4343 // Variable is undefined.
4444 if (!LeftOpValue)
4747 }
4848
4949 Expected FileCheckNumericSubstitution::getResult() const {
50 Expected EvaluatedValue = NumExpr->eval();
50 Expected EvaluatedValue = Expression->eval();
5151 if (!EvaluatedValue)
5252 return EvaluatedValue.takeError();
5353 return utostr(*EvaluatedValue);
173173 return LeftOp - RightOp;
174174 }
175175
176 ExpectedNumExpr *>
176 ExpectedExpression *>
177177 FileCheckPattern::parseBinop(StringRef &Expr, const SourceMgr &SM) const {
178178 Expected LeftParseResult =
179179 parseNumericVariableUse(Expr, SM);
186186 // it.
187187 Expr = Expr.ltrim(SpaceChars);
188188 if (Expr.empty())
189 return Context->makeNumExpr(add, LeftOp, 0);
189 return Context->makeExpression(add, LeftOp, 0);
190190 SMLoc OpLoc = SMLoc::getFromPointer(Expr.data());
191191 char Operator = popFront(Expr);
192192 binop_eval_t EvalBinop;
199199 break;
200200 default:
201201 return FileCheckErrorDiagnostic::get(
202 SM, OpLoc,
203 Twine("unsupported numeric operation '") + Twine(Operator) + "'");
202 SM, OpLoc, Twine("unsupported operation '") + Twine(Operator) + "'");
204203 }
205204
206205 // Parse right operand.
207206 Expr = Expr.ltrim(SpaceChars);
208207 if (Expr.empty())
209 return FileCheckErrorDiagnostic::get(
210 SM, Expr, "missing operand in numeric expression");
208 return FileCheckErrorDiagnostic::get(SM, Expr,
209 "missing operand in expression");
211210 uint64_t RightOp;
212211 if (Expr.consumeInteger(10, RightOp))
213212 return FileCheckErrorDiagnostic::get(
214 SM, Expr, "invalid offset in numeric expression '" + Expr + "'");
213 SM, Expr, "invalid offset in expression '" + Expr + "'");
215214 Expr = Expr.ltrim(SpaceChars);
216215 if (!Expr.empty())
217216 return FileCheckErrorDiagnostic::get(
218 SM, Expr,
219 "unexpected characters at end of numeric expression '" + Expr + "'");
220
221 return Context->makeNumExpr(EvalBinop, LeftOp, RightOp);
222 }
223
224 Expected FileCheckPattern::parseNumericSubstitutionBlock(
217 SM, Expr, "unexpected characters at end of expression '" + Expr + "'");
218
219 return Context->makeExpression(EvalBinop, LeftOp, RightOp);
220 }
221
222 Expected FileCheckPattern::parseNumericSubstitutionBlock(
225223 StringRef Expr,
226224 Optional &DefinedNumericVariable,
227225 const SourceMgr &SM) const {
251249 return FileCheckErrorDiagnostic::get(
252250 SM, UseExpr,
253251 "unexpected string after variable definition: '" + UseExpr + "'");
254 return Context->makeNumExpr(add, nullptr, 0);
255 }
256
257 // Parse the numeric expression itself.
252 return Context->makeExpression(add, nullptr, 0);
253 }
254
255 // Parse the expression itself.
258256 Expr = Expr.ltrim(SpaceChars);
259257 return parseBinop(Expr, SM);
260258 }
379377 StringRef MatchRegexp;
380378 size_t SubstInsertIdx = RegExStr.size();
381379
382 // Parse string variable or legacy numeric expression.
380 // Parse string variable or legacy expression.
383381 if (!IsNumBlock) {
384382 size_t VarEndIdx = MatchStr.find(":");
385383 size_t SpacePos = MatchStr.substr(0, VarEndIdx).find_first_of(" \t");
430428 }
431429
432430 // Parse numeric substitution block.
433 FileCheckNumExpr *NumExpr;
431 FileCheckExpression *Expression;
434432 Optional DefinedNumericVariable;
435433 if (IsNumBlock) {
436 ExpectedNumExpr *> ParseResult =
434 ExpectedExpression *> ParseResult =
437435 parseNumericSubstitutionBlock(MatchStr, DefinedNumericVariable, SM);
438436 if (!ParseResult) {
439437 logAllUnhandledErrors(ParseResult.takeError(), errs());
440438 return true;
441439 }
442 NumExpr = *ParseResult;
440 Expression = *ParseResult;
443441 if (DefinedNumericVariable) {
444442 IsDefinition = true;
445443 DefName = (*DefinedNumericVariable)->getName();
451449 // Handle substitutions: [[foo]] and [[#]].
452450 if (!IsDefinition) {
453451 // Handle substitution of string variables that were defined earlier on
454 // the same line by emitting a backreference. Numeric expressions do
455 // not support substituting a numeric variable defined on the same
456 // line.
452 // the same line by emitting a backreference. Expressions do not
453 // support substituting a numeric variable defined on the same line.
457454 if (!IsNumBlock && VariableDefs.find(SubstStr) != VariableDefs.end()) {
458455 unsigned CaptureParenGroup = VariableDefs[SubstStr];
459456 if (CaptureParenGroup < 1 || CaptureParenGroup > 9) {
465462 AddBackrefToRegEx(CaptureParenGroup);
466463 } else {
467464 // Handle substitution of string variables ([[]]) defined in
468 // previous CHECK patterns, and substitution of numeric expressions.
465 // previous CHECK patterns, and substitution of expressions.
469466 FileCheckSubstitution *Substitution =
470467 IsNumBlock
471 ? Context->makeNumericSubstitution(SubstStr, NumExpr,
468 ? Context->makeNumericSubstitution(SubstStr, Expression,
472469 SubstInsertIdx)
473470 : Context->makeStringSubstitution(SubstStr, SubstInsertIdx);
474471 Substitutions.push_back(Substitution);
479476 // Handle variable definitions: [[:(...)]] and
480477 // [[#(...):(...)]].
481478 if (IsNumBlock) {
482 FileCheckNumExprMatch NumExprDef = {*DefinedNumericVariable, CurParen};
483 NumericVariableDefs[DefName] = NumExprDef;
479 FileCheckNumericVariableMatch NumericVariableDefinition = {
480 *DefinedNumericVariable, CurParen};
481 NumericVariableDefs[DefName] = NumericVariableDefinition;
484482 // This store is done here rather than in match() to allow
485483 // parseNumericVariableUse() to get the pointer to the class instance
486484 // of the right variable definition corresponding to a given numeric
569567 TmpStr = RegExStr;
570568
571569 size_t InsertOffset = 0;
572 // Substitute all string variables and numeric expressions whose values are
573 // only now known. Use of string variables defined on the same line are
574 // handled by back-references.
570 // Substitute all string variables and expressions whose values are only
571 // now known. Use of string variables defined on the same line are handled
572 // by back-references.
575573 for (const auto &Substitution : Substitutions) {
576574 // Substitute and check for failure (e.g. use of undefined variable).
577575 Expected Value = Substitution->getResult();
605603
606604 // If this defines any numeric variables, remember their values.
607605 for (const auto &NumericVariableDef : NumericVariableDefs) {
608 const FileCheckNumExprMatch &NumericVariableMatch =
606 const FileCheckNumericVariableMatch &NumericVariableMatch =
609607 NumericVariableDef.getValue();
610608 unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup;
611609 assert(CaptureParenGroup < MatchInfo.size() && "Internal paren error");
764762 return VarIter->second;
765763 }
766764
767 FileCheckNumExpr *
768 FileCheckPatternContext::makeNumExpr(binop_eval_t EvalBinop,
769 FileCheckNumericVariable *OperandLeft,
770 uint64_t OperandRight) {
771 NumExprs.push_back(llvm::make_unique(EvalBinop, OperandLeft,
772 OperandRight));
773 return NumExprs.back().get();
765 FileCheckExpression *
766 FileCheckPatternContext::makeExpression(binop_eval_t EvalBinop,
767 FileCheckNumericVariable *OperandLeft,
768 uint64_t OperandRight) {
769 Expressions.push_back(llvm::make_unique(
770 EvalBinop, OperandLeft, OperandRight));
771 return Expressions.back().get();
774772 }
775773
776774 template
790788 }
791789
792790 FileCheckSubstitution *FileCheckPatternContext::makeNumericSubstitution(
793 StringRef Expr, FileCheckNumExpr *NumExpr, size_t InsertIdx) {
791 StringRef ExpressionStr, FileCheckExpression *Expression,
792 size_t InsertIdx) {
794793 Substitutions.push_back(llvm::make_unique(
795 this, Expr, NumExpr, InsertIdx));
794 this, ExpressionStr, Expression, InsertIdx));
796795 return Substitutions.back().get();
797796 }
798797
4646 47 ERR8: line-count.txt:[[#@LINE-1]]:12: error: invalid pseudo numeric variable '@LIN'
4747 48
4848 49 BAD9: [[@LINE*2]]
49 50 ERR9: line-count.txt:[[#@LINE-1]]:17: error: unsupported numeric operation '*'
49 50 ERR9: line-count.txt:[[#@LINE-1]]:17: error: unsupported operation '*'
5050 51
5151 52 BAD10: [[@LINE-x]]
52 53 ERR10: line-count.txt:[[#@LINE-1]]:19: error: invalid offset in numeric expression 'x'
52 53 ERR10: line-count.txt:[[#@LINE-1]]:19: error: invalid offset in expression 'x'
5353 54
5454 55 BAD11: [[@LINE-1x]]
55 56 ERR11: line-count.txt:[[#@LINE-1]]:20: error: unexpected characters at end of numeric expression 'x'
55 56 ERR11: line-count.txt:[[#@LINE-1]]:20: error: unexpected characters at end of expression 'x'
5656 57
5757 58 CHECK: [[#@LINE]] CHECK
5858 59 CHECK: [[# @LINE]] CHECK
8787 NUMVAR*2: 22
8888 INVAL-OP-LABEL: INVALID OPERATOR
8989 INVAL-OP-NEXT: NUMVAR*2: [[#NUMVAR*2]]
90 INVAL-OP-MSG: numeric-expression.txt:[[#@LINE-1]]:35: error: unsupported numeric operation '*'
90 INVAL-OP-MSG: numeric-expression.txt:[[#@LINE-1]]:35: error: unsupported operation '*'
9191 INVAL-OP-MSG-NEXT: {{I}}NVAL-OP-NEXT: NUMVAR*2: {{\[\[#NUMVAR\*2\]\]}}
9292 INVAL-OP-MSG-NEXT: {{^ \^$}}
9393
4646 });
4747 }
4848
49 TEST_F(FileCheckTest, NumExpr) {
49 TEST_F(FileCheckTest, Expression) {
5050 FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 42);
51 FileCheckNumExpr NumExpr = FileCheckNumExpr(doAdd, &FooVar, 18);
51 FileCheckExpression Expression = FileCheckExpression(doAdd, &FooVar, 18);
5252
5353 // Defined variable: eval returns right value.
54 Expected Value = NumExpr.eval();
54 Expected Value = Expression.eval();
5555 EXPECT_TRUE(static_cast(Value));
5656 EXPECT_EQ(60U, *Value);
5757
5959 // getUndefVarName first to check that it can be called without calling
6060 // eval() first.
6161 FooVar.clearValue();
62 Error EvalError = NumExpr.eval().takeError();
62 Error EvalError = Expression.eval().takeError();
6363 EXPECT_TRUE(errorToBool(std::move(EvalError)));
6464 expectUndefError("FOO", std::move(EvalError));
6565 }
353353 // the right value.
354354 FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 42);
355355 FileCheckNumericVariable NVar = FileCheckNumericVariable("N", 10);
356 FileCheckNumExpr NumExprLine = FileCheckNumExpr(doAdd, &LineVar, 0);
357 FileCheckNumExpr NumExprN = FileCheckNumExpr(doAdd, &NVar, 3);
356 FileCheckExpression LineExpression = FileCheckExpression(doAdd, &LineVar, 0);
357 FileCheckExpression NExpression = FileCheckExpression(doAdd, &NVar, 3);
358358 FileCheckNumericSubstitution SubstitutionLine =
359 FileCheckNumericSubstitution(&Context, "@LINE", &NumExprLine, 12);
359 FileCheckNumericSubstitution(&Context, "@LINE", &LineExpression, 12);
360360 FileCheckNumericSubstitution SubstitutionN =
361 FileCheckNumericSubstitution(&Context, "N", &NumExprN, 30);
361 FileCheckNumericSubstitution(&Context, "N", &NExpression, 30);
362362 Expected Value = SubstitutionLine.getResult();
363363 EXPECT_TRUE(static_cast(Value));
364364 EXPECT_EQ("42", *Value);
444444 Expected LocalVar = Cxt.getPatternVarValue(LocalVarStr);
445445 FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Cxt, 1);
446446 Optional DefinedNumericVariable;
447 ExpectedNumExpr *> NumExpr = P.parseNumericSubstitutionBlock(
447 ExpectedExpression *> Expression = P.parseNumericSubstitutionBlock(
448448 LocalNumVarRef, DefinedNumericVariable, SM);
449449 Expected EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
450450 Expected UnknownVar = Cxt.getPatternVarValue(UnknownVarStr);
451451 EXPECT_TRUE(static_cast(LocalVar));
452452 EXPECT_EQ(*LocalVar, "FOO");
453 EXPECT_TRUE(static_cast(NumExpr));
454 Expected NumExprVal = (*NumExpr)->eval();
455 EXPECT_TRUE(static_cast(NumExprVal));
456 EXPECT_EQ(*NumExprVal, 18U);
453 EXPECT_TRUE(static_cast(Expression));
454 Expected ExpressionVal = (*Expression)->eval();
455 EXPECT_TRUE(static_cast(ExpressionVal));
456 EXPECT_EQ(*ExpressionVal, 18U);
457457 EXPECT_TRUE(static_cast(EmptyVar));
458458 EXPECT_EQ(*EmptyVar, "");
459459 EXPECT_TRUE(errorToBool(UnknownVar.takeError()));
466466 // local variables, if it was created before. This is important because local
467467 // variable clearing due to --enable-var-scope happens after numeric
468468 // expressions are linked to the numeric variables they use.
469 EXPECT_TRUE(errorToBool((*NumExpr)->eval().takeError()));
469 EXPECT_TRUE(errorToBool((*Expression)->eval().takeError()));
470470 P = FileCheckPattern(Check::CheckPlain, &Cxt, 2);
471 NumExpr = P.parseNumericSubstitutionBlock(LocalNumVarRef,
472 DefinedNumericVariable, SM);
473 EXPECT_TRUE(errorToBool(NumExpr.takeError()));
471 Expression = P.parseNumericSubstitutionBlock(LocalNumVarRef,
472 DefinedNumericVariable, SM);
473 EXPECT_TRUE(errorToBool(Expression.takeError()));
474474 EmptyVar = Cxt.getPatternVarValue(EmptyVarStr);
475475 EXPECT_TRUE(errorToBool(EmptyVar.takeError()));
476476
484484 EXPECT_TRUE(static_cast(GlobalVar));
485485 EXPECT_EQ(*GlobalVar, "BAR");
486486 P = FileCheckPattern(Check::CheckPlain, &Cxt, 3);
487 NumExpr = P.parseNumericSubstitutionBlock(GlobalNumVarRef,
488 DefinedNumericVariable, SM);
489 EXPECT_TRUE(static_cast(NumExpr));
490 NumExprVal = (*NumExpr)->eval();
491 EXPECT_TRUE(static_cast(NumExprVal));
492 EXPECT_EQ(*NumExprVal, 36U);
487 Expression = P.parseNumericSubstitutionBlock(GlobalNumVarRef,
488 DefinedNumericVariable, SM);
489 EXPECT_TRUE(static_cast(Expression));
490 ExpressionVal = (*Expression)->eval();
491 EXPECT_TRUE(static_cast(ExpressionVal));
492 EXPECT_EQ(*ExpressionVal, 36U);
493493
494494 // Clear local variables and check global variables remain defined.
495495 Cxt.clearLocalVars();
496496 EXPECT_FALSE(errorToBool(Cxt.getPatternVarValue(GlobalVarStr).takeError()));
497497 P = FileCheckPattern(Check::CheckPlain, &Cxt, 4);
498 NumExpr = P.parseNumericSubstitutionBlock(GlobalNumVarRef,
499 DefinedNumericVariable, SM);
500 EXPECT_TRUE(static_cast(NumExpr));
501 NumExprVal = (*NumExpr)->eval();
502 EXPECT_TRUE(static_cast(NumExprVal));
503 EXPECT_EQ(*NumExprVal, 36U);
498 Expression = P.parseNumericSubstitutionBlock(GlobalNumVarRef,
499 DefinedNumericVariable, SM);
500 EXPECT_TRUE(static_cast(Expression));
501 ExpressionVal = (*Expression)->eval();
502 EXPECT_TRUE(static_cast(ExpressionVal));
503 EXPECT_EQ(*ExpressionVal, 36U);
504504 }
505505 } // namespace