llvm.org GIT mirror llvm / 58234c1
[FileCheck] Store line numbers as optional values Summary: Processing of command-line definition of variable and logic around implicit not directives both reuse parsing code that expects a line number to be defined. So far, a special line number of 0 was used for those users of the parsing code where a line number does not make sense. This commit instead represents line numbers as Optional values so that they can be None for those cases. Reviewers: jhenderson, chandlerc, jdenny, probinson, grimar, arichardson, rnk Subscribers: JonChesterfield, rogfer01, hfinkel, kristina, rnk, tra, arichardson, grimar, dblaikie, probinson, llvm-commits, hiraditya Tags: #llvm Differential Revision: https://reviews.llvm.org/D64639 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366109 91177308-0d34-0410-b5e6-96231b3b80d8 Thomas Preud'homme a month ago
3 changed file(s) with 46 addition(s) and 40 deletion(s). Raw diff Collapse all Expand all
9696 /// Value of numeric variable, if defined, or None otherwise.
9797 Optional Value;
9898
99 /// Line number where this variable is defined. Used to determine whether a
100 /// variable is defined on the same line as a given use.
101 size_t DefLineNumber;
102
103 public:
104 /// Constructor for a variable \p Name defined at line \p DefLineNumber.
105 FileCheckNumericVariable(size_t DefLineNumber, StringRef Name)
99 /// Line number where this variable is defined, or None if defined before
100 /// input is parsed. Used to determine whether a variable is defined on the
101 /// same line as a given use.
102 Optional DefLineNumber;
103
104 public:
105 /// Constructor for a variable \p Name defined at line \p DefLineNumber or
106 /// defined before input is parsed if DefLineNumber is None.
107 FileCheckNumericVariable(StringRef Name,
108 Optional DefLineNumber = None)
106109 : Name(Name), DefLineNumber(DefLineNumber) {}
107
108 /// Constructor for numeric variable \p Name with a known \p Value at parse
109 /// time (e.g. the @LINE numeric variable).
110 FileCheckNumericVariable(StringRef Name, uint64_t Value)
111 : Name(Name), Value(Value), DefLineNumber(0) {}
112110
113111 /// \returns name of this numeric variable.
114112 StringRef getName() const { return Name; }
124122 /// currently defined or not.
125123 void clearValue();
126124
127 /// \returns the line number where this variable is defined.
128 size_t getDefLineNumber() { return DefLineNumber; }
125 /// \returns the line number where this variable is defined, if any, or None
126 /// if defined before input is parsed.
127 Optional getDefLineNumber() { return DefLineNumber; }
129128 };
130129
131130 /// Class representing the use of a numeric variable in the AST of an
475474
476475 Check::FileCheckType CheckTy;
477476
478 /// Line number for this CHECK pattern. Used to determine whether a variable
479 /// definition is made on an earlier line to the one with this CHECK.
480 size_t LineNumber;
477 /// Line number for this CHECK pattern or None if it is an implicit pattern.
478 /// Used to determine whether a variable definition is made on an earlier
479 /// line to the one with this CHECK.
480 Optional LineNumber;
481481
482482 public:
483483 FileCheckPattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
484 size_t Line)
484 Optional Line = None)
485485 : Context(Context), CheckTy(Ty), LineNumber(Line) {}
486486
487487 /// \returns the location in source code.
508508 static Expected parseVariable(StringRef &Str,
509509 const SourceMgr &SM);
510510 /// Parses \p Expr for the name of a numeric variable to be defined at line
511 /// \p LineNumber. \returns a pointer to the class instance representing that
512 /// variable, creating it if needed, or an error holding a diagnostic against
513 /// \p SM should defining such a variable be invalid.
514 static Expected
515 parseNumericVariableDefinition(StringRef &Expr,
516 FileCheckPatternContext *Context,
517 size_t LineNumber, const SourceMgr &SM);
511 /// \p LineNumber or before input is parsed if \p LineNumber is None.
512 /// \returns a pointer to the class instance representing that variable,
513 /// creating it if needed, or an error holding a diagnostic against \p SM
514 /// should defining such a variable be invalid.
515 static Expected parseNumericVariableDefinition(
516 StringRef &Expr, FileCheckPatternContext *Context,
517 Optional LineNumber, const SourceMgr &SM);
518518 /// Parses \p Expr for a numeric substitution block. Parameter
519519 /// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE
520520 /// expression. \returns a pointer to the class instance representing the AST
123123
124124 Expected
125125 FileCheckPattern::parseNumericVariableDefinition(
126 StringRef &Expr, FileCheckPatternContext *Context, size_t LineNumber,
127 const SourceMgr &SM) {
126 StringRef &Expr, FileCheckPatternContext *Context,
127 Optional LineNumber, const SourceMgr &SM) {
128128 Expected ParseVarResult = parseVariable(Expr, SM);
129129 if (!ParseVarResult)
130130 return ParseVarResult.takeError();
151151 if (VarTableIter != Context->GlobalNumericVariableTable.end())
152152 DefinedNumericVariable = VarTableIter->second;
153153 else
154 DefinedNumericVariable = Context->makeNumericVariable(LineNumber, Name);
154 DefinedNumericVariable = Context->makeNumericVariable(Name, LineNumber);
155155
156156 return DefinedNumericVariable;
157157 }
176176 if (VarTableIter != Context->GlobalNumericVariableTable.end())
177177 NumericVariable = VarTableIter->second;
178178 else {
179 NumericVariable = Context->makeNumericVariable(0, Name);
179 NumericVariable = Context->makeNumericVariable(Name);
180180 Context->GlobalNumericVariableTable[Name] = NumericVariable;
181181 }
182182
183 if (!IsPseudo && NumericVariable->getDefLineNumber() == LineNumber)
183 Optional DefLineNumber = NumericVariable->getDefLineNumber();
184 if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
184185 return FileCheckErrorDiagnostic::get(
185186 SM, Name,
186187 "numeric variable '" + Name + "' defined on the same line as used");
619620 std::string TmpStr;
620621 if (!Substitutions.empty()) {
621622 TmpStr = RegExStr;
622 Context->LineVariable->setValue(LineNumber);
623 if (LineNumber)
624 Context->LineVariable->setValue(*LineNumber);
623625
624626 size_t InsertOffset = 0;
625627 // Substitute all string variables and expressions whose values are only
11011103 void FileCheckPatternContext::createLineVariable() {
11021104 assert(!LineVariable && "@LINE pseudo numeric variable already created");
11031105 StringRef LineName = "@LINE";
1104 LineVariable = makeNumericVariable(0, LineName);
1106 LineVariable = makeNumericVariable(LineName);
11051107 GlobalNumericVariableTable[LineName] = LineVariable;
11061108 }
11071109
11301132 SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
11311133
11321134 ImplicitNegativeChecks.push_back(
1133 FileCheckPattern(Check::CheckNot, &PatternContext, 0));
1135 FileCheckPattern(Check::CheckNot, &PatternContext));
11341136 ImplicitNegativeChecks.back().parsePattern(PatternInBuffer,
11351137 "IMPLICIT-CHECK", SM, Req);
11361138 }
17891791 if (CmdlineDef[0] == '#') {
17901792 StringRef CmdlineName = CmdlineDef.substr(1, EqIdx - 1);
17911793 Expected ParseResult =
1792 FileCheckPattern::parseNumericVariableDefinition(CmdlineName, this, 0,
1793 SM);
1794 FileCheckPattern::parseNumericVariableDefinition(CmdlineName, this,
1795 None, SM);
17941796 if (!ParseResult) {
17951797 Errs = joinErrors(std::move(Errs), ParseResult.takeError());
17961798 continue;
5555 TEST_F(FileCheckTest, NumericVariable) {
5656 // Undefined variable: getValue and eval fail, error returned by eval holds
5757 // the name of the undefined variable and setValue does not trigger assert.
58 FileCheckNumericVariable FooVar = FileCheckNumericVariable(1, "FOO");
58 FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 1);
5959 EXPECT_EQ("FOO", FooVar.getName());
6060 FileCheckNumericVariableUse FooVarUse =
6161 FileCheckNumericVariableUse("FOO", &FooVar);
8686 uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; }
8787
8888 TEST_F(FileCheckTest, Binop) {
89 FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 42);
89 FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO");
90 FooVar.setValue(42);
9091 std::unique_ptr FooVarUse =
9192 llvm::make_unique("FOO", &FooVar);
92 FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR", 18);
93 FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR");
94 BarVar.setValue(18);
9395 std::unique_ptr BarVarUse =
9496 llvm::make_unique("BAR", &BarVar);
9597 FileCheckASTBinop Binop =
406408
407409 // Substitutions of defined pseudo and non-pseudo numeric variables return
408410 // the right value.
409 FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 42);
410 FileCheckNumericVariable NVar = FileCheckNumericVariable("N", 10);
411 FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE");
412 LineVar.setValue(42);
413 FileCheckNumericVariable NVar = FileCheckNumericVariable("N");
414 NVar.setValue(10);
411415 auto LineVarUse =
412416 llvm::make_unique("@LINE", &LineVar);
413417 auto NVarUse = llvm::make_unique("N", &NVar);