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
/// Value of numeric variable, if defined, or None otherwise.
Optional<uint64_t> Value;
- /// Line number where this variable is defined. Used to determine whether a
- /// variable is defined on the same line as a given use.
- size_t DefLineNumber;
+ /// Line number where this variable is defined, or None if defined before
+ /// input is parsed. Used to determine whether a variable is defined on the
+ /// same line as a given use.
+ Optional<size_t> DefLineNumber;
public:
- /// Constructor for a variable \p Name defined at line \p DefLineNumber.
- FileCheckNumericVariable(size_t DefLineNumber, StringRef Name)
+ /// Constructor for a variable \p Name defined at line \p DefLineNumber or
+ /// defined before input is parsed if DefLineNumber is None.
+ FileCheckNumericVariable(StringRef Name,
+ Optional<size_t> DefLineNumber = None)
: Name(Name), DefLineNumber(DefLineNumber) {}
- /// Constructor for numeric variable \p Name with a known \p Value at parse
- /// time (e.g. the @LINE numeric variable).
- FileCheckNumericVariable(StringRef Name, uint64_t Value)
- : Name(Name), Value(Value), DefLineNumber(0) {}
-
/// \returns name of this numeric variable.
StringRef getName() const { return Name; }
/// currently defined or not.
void clearValue();
- /// \returns the line number where this variable is defined.
- size_t getDefLineNumber() { return DefLineNumber; }
+ /// \returns the line number where this variable is defined, if any, or None
+ /// if defined before input is parsed.
+ Optional<size_t> getDefLineNumber() { return DefLineNumber; }
};
/// Class representing the use of a numeric variable in the AST of an
Check::FileCheckType CheckTy;
- /// Line number for this CHECK pattern. Used to determine whether a variable
- /// definition is made on an earlier line to the one with this CHECK.
- size_t LineNumber;
+ /// Line number for this CHECK pattern or None if it is an implicit pattern.
+ /// Used to determine whether a variable definition is made on an earlier
+ /// line to the one with this CHECK.
+ Optional<size_t> LineNumber;
public:
FileCheckPattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
- size_t Line)
+ Optional<size_t> Line = None)
: Context(Context), CheckTy(Ty), LineNumber(Line) {}
/// \returns the location in source code.
static Expected<VariableProperties> parseVariable(StringRef &Str,
const SourceMgr &SM);
/// Parses \p Expr for the name of a numeric variable to be defined at line
- /// \p LineNumber. \returns a pointer to the class instance representing that
- /// variable, creating it if needed, or an error holding a diagnostic against
- /// \p SM should defining such a variable be invalid.
- static Expected<FileCheckNumericVariable *>
- parseNumericVariableDefinition(StringRef &Expr,
- FileCheckPatternContext *Context,
- size_t LineNumber, const SourceMgr &SM);
+ /// \p LineNumber or before input is parsed if \p LineNumber is None.
+ /// \returns a pointer to the class instance representing that variable,
+ /// creating it if needed, or an error holding a diagnostic against \p SM
+ /// should defining such a variable be invalid.
+ static Expected<FileCheckNumericVariable *> parseNumericVariableDefinition(
+ StringRef &Expr, FileCheckPatternContext *Context,
+ Optional<size_t> LineNumber, const SourceMgr &SM);
/// Parses \p Expr for a numeric substitution block. Parameter
/// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE
/// expression. \returns a pointer to the class instance representing the AST
Expected<FileCheckNumericVariable *>
FileCheckPattern::parseNumericVariableDefinition(
- StringRef &Expr, FileCheckPatternContext *Context, size_t LineNumber,
- const SourceMgr &SM) {
+ StringRef &Expr, FileCheckPatternContext *Context,
+ Optional<size_t> LineNumber, const SourceMgr &SM) {
Expected<VariableProperties> ParseVarResult = parseVariable(Expr, SM);
if (!ParseVarResult)
return ParseVarResult.takeError();
if (VarTableIter != Context->GlobalNumericVariableTable.end())
DefinedNumericVariable = VarTableIter->second;
else
- DefinedNumericVariable = Context->makeNumericVariable(LineNumber, Name);
+ DefinedNumericVariable = Context->makeNumericVariable(Name, LineNumber);
return DefinedNumericVariable;
}
if (VarTableIter != Context->GlobalNumericVariableTable.end())
NumericVariable = VarTableIter->second;
else {
- NumericVariable = Context->makeNumericVariable(0, Name);
+ NumericVariable = Context->makeNumericVariable(Name);
Context->GlobalNumericVariableTable[Name] = NumericVariable;
}
- if (!IsPseudo && NumericVariable->getDefLineNumber() == LineNumber)
+ Optional<size_t> DefLineNumber = NumericVariable->getDefLineNumber();
+ if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber)
return FileCheckErrorDiagnostic::get(
SM, Name,
"numeric variable '" + Name + "' defined on the same line as used");
std::string TmpStr;
if (!Substitutions.empty()) {
TmpStr = RegExStr;
- Context->LineVariable->setValue(LineNumber);
+ if (LineNumber)
+ Context->LineVariable->setValue(*LineNumber);
size_t InsertOffset = 0;
// Substitute all string variables and expressions whose values are only
void FileCheckPatternContext::createLineVariable() {
assert(!LineVariable && "@LINE pseudo numeric variable already created");
StringRef LineName = "@LINE";
- LineVariable = makeNumericVariable(0, LineName);
+ LineVariable = makeNumericVariable(LineName);
GlobalNumericVariableTable[LineName] = LineVariable;
}
SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
ImplicitNegativeChecks.push_back(
- FileCheckPattern(Check::CheckNot, &PatternContext, 0));
+ FileCheckPattern(Check::CheckNot, &PatternContext));
ImplicitNegativeChecks.back().parsePattern(PatternInBuffer,
"IMPLICIT-CHECK", SM, Req);
}
if (CmdlineDef[0] == '#') {
StringRef CmdlineName = CmdlineDef.substr(1, EqIdx - 1);
Expected<FileCheckNumericVariable *> ParseResult =
- FileCheckPattern::parseNumericVariableDefinition(CmdlineName, this, 0,
- SM);
+ FileCheckPattern::parseNumericVariableDefinition(CmdlineName, this,
+ None, SM);
if (!ParseResult) {
Errs = joinErrors(std::move(Errs), ParseResult.takeError());
continue;
TEST_F(FileCheckTest, NumericVariable) {
// Undefined variable: getValue and eval fail, error returned by eval holds
// the name of the undefined variable and setValue does not trigger assert.
- FileCheckNumericVariable FooVar = FileCheckNumericVariable(1, "FOO");
+ FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 1);
EXPECT_EQ("FOO", FooVar.getName());
FileCheckNumericVariableUse FooVarUse =
FileCheckNumericVariableUse("FOO", &FooVar);
uint64_t doAdd(uint64_t OpL, uint64_t OpR) { return OpL + OpR; }
TEST_F(FileCheckTest, Binop) {
- FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO", 42);
+ FileCheckNumericVariable FooVar = FileCheckNumericVariable("FOO");
+ FooVar.setValue(42);
std::unique_ptr<FileCheckNumericVariableUse> FooVarUse =
llvm::make_unique<FileCheckNumericVariableUse>("FOO", &FooVar);
- FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR", 18);
+ FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR");
+ BarVar.setValue(18);
std::unique_ptr<FileCheckNumericVariableUse> BarVarUse =
llvm::make_unique<FileCheckNumericVariableUse>("BAR", &BarVar);
FileCheckASTBinop Binop =
// Substitutions of defined pseudo and non-pseudo numeric variables return
// the right value.
- FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE", 42);
- FileCheckNumericVariable NVar = FileCheckNumericVariable("N", 10);
+ FileCheckNumericVariable LineVar = FileCheckNumericVariable("@LINE");
+ LineVar.setValue(42);
+ FileCheckNumericVariable NVar = FileCheckNumericVariable("N");
+ NVar.setValue(10);
auto LineVarUse =
llvm::make_unique<FileCheckNumericVariableUse>("@LINE", &LineVar);
auto NVarUse = llvm::make_unique<FileCheckNumericVariableUse>("N", &NVar);