Index: llvm/trunk/include/llvm/Support/FileCheck.h =================================================================== --- llvm/trunk/include/llvm/Support/FileCheck.h +++ llvm/trunk/include/llvm/Support/FileCheck.h @@ -97,20 +97,18 @@ /// Value of numeric variable, if defined, or None otherwise. Optional 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 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 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; } @@ -125,8 +123,9 @@ /// 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 getDefLineNumber() { return DefLineNumber; } }; /// Class representing the use of a numeric variable in the AST of an @@ -476,13 +475,14 @@ 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 LineNumber; public: FileCheckPattern(Check::FileCheckType Ty, FileCheckPatternContext *Context, - size_t Line) + Optional Line = None) : Context(Context), CheckTy(Ty), LineNumber(Line) {} /// \returns the location in source code. @@ -509,13 +509,13 @@ static Expected 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 - 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 parseNumericVariableDefinition( + StringRef &Expr, FileCheckPatternContext *Context, + Optional 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 Index: llvm/trunk/lib/Support/FileCheck.cpp =================================================================== --- llvm/trunk/lib/Support/FileCheck.cpp +++ llvm/trunk/lib/Support/FileCheck.cpp @@ -124,8 +124,8 @@ Expected FileCheckPattern::parseNumericVariableDefinition( - StringRef &Expr, FileCheckPatternContext *Context, size_t LineNumber, - const SourceMgr &SM) { + StringRef &Expr, FileCheckPatternContext *Context, + Optional LineNumber, const SourceMgr &SM) { Expected ParseVarResult = parseVariable(Expr, SM); if (!ParseVarResult) return ParseVarResult.takeError(); @@ -152,7 +152,7 @@ if (VarTableIter != Context->GlobalNumericVariableTable.end()) DefinedNumericVariable = VarTableIter->second; else - DefinedNumericVariable = Context->makeNumericVariable(LineNumber, Name); + DefinedNumericVariable = Context->makeNumericVariable(Name, LineNumber); return DefinedNumericVariable; } @@ -177,11 +177,12 @@ 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 DefLineNumber = NumericVariable->getDefLineNumber(); + if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber) return FileCheckErrorDiagnostic::get( SM, Name, "numeric variable '" + Name + "' defined on the same line as used"); @@ -620,7 +621,8 @@ 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 @@ -1102,7 +1104,7 @@ void FileCheckPatternContext::createLineVariable() { assert(!LineVariable && "@LINE pseudo numeric variable already created"); StringRef LineName = "@LINE"; - LineVariable = makeNumericVariable(0, LineName); + LineVariable = makeNumericVariable(LineName); GlobalNumericVariableTable[LineName] = LineVariable; } @@ -1131,7 +1133,7 @@ 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); } @@ -1790,8 +1792,8 @@ if (CmdlineDef[0] == '#') { StringRef CmdlineName = CmdlineDef.substr(1, EqIdx - 1); Expected ParseResult = - FileCheckPattern::parseNumericVariableDefinition(CmdlineName, this, 0, - SM); + FileCheckPattern::parseNumericVariableDefinition(CmdlineName, this, + None, SM); if (!ParseResult) { Errs = joinErrors(std::move(Errs), ParseResult.takeError()); continue; Index: llvm/trunk/unittests/Support/FileCheckTest.cpp =================================================================== --- llvm/trunk/unittests/Support/FileCheckTest.cpp +++ llvm/trunk/unittests/Support/FileCheckTest.cpp @@ -56,7 +56,7 @@ 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); @@ -87,10 +87,12 @@ 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 FooVarUse = llvm::make_unique("FOO", &FooVar); - FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR", 18); + FileCheckNumericVariable BarVar = FileCheckNumericVariable("BAR"); + BarVar.setValue(18); std::unique_ptr BarVarUse = llvm::make_unique("BAR", &BarVar); FileCheckASTBinop Binop = @@ -407,8 +409,10 @@ // 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("@LINE", &LineVar); auto NVarUse = llvm::make_unique("N", &NVar);