diff --git a/llvm/lib/Support/FileCheck.cpp b/llvm/lib/Support/FileCheck.cpp --- a/llvm/lib/Support/FileCheck.cpp +++ b/llvm/lib/Support/FileCheck.cpp @@ -156,13 +156,19 @@ // class instance of the corresponding numeric variable definition is stored // in GlobalNumericVariableTable in parsePattern. Therefore, the pointer we // get below is for the class instance corresponding to the last definition - // of this variable use. + // of this variable use. If we don't find a variable definition we create a + // dummy one so that parsing can continue. All uses of undefined variables, + // whether string or numeric, are then diagnosed in printSubstitutions() + // after failing to match. auto VarTableIter = Context->GlobalNumericVariableTable.find(Name); - if (VarTableIter == Context->GlobalNumericVariableTable.end()) - return FileCheckErrorDiagnostic::get( - SM, Name, "using undefined numeric variable '" + Name + "'"); + FileCheckNumericVariable *NumericVariable; + if (VarTableIter != Context->GlobalNumericVariableTable.end()) + NumericVariable = VarTableIter->second; + else { + NumericVariable = Context->makeNumericVariable(0, Name); + Context->GlobalNumericVariableTable[Name] = NumericVariable; + } - FileCheckNumericVariable *NumericVariable = VarTableIter->second; if (!IsPseudo && NumericVariable->getDefLineNumber() == LineNumber) return FileCheckErrorDiagnostic::get( SM, Name, diff --git a/llvm/test/FileCheck/numeric-expression.txt b/llvm/test/FileCheck/numeric-expression.txt --- a/llvm/test/FileCheck/numeric-expression.txt +++ b/llvm/test/FileCheck/numeric-expression.txt @@ -76,9 +76,15 @@ UNDEFVAR: 11 UNDEF-USE-LABEL: UNDEF VAR USE UNDEF-USE-NEXT: UNDEFVAR: [[#UNDEFVAR]] -UNDEF-USE-MSG: numeric-expression.txt:[[#@LINE-1]]:30: error: using undefined numeric variable 'UNDEFVAR' +UNDEF-USE-MSG: numeric-expression.txt:[[#@LINE-1]]:17: error: {{U}}NDEF-USE-NEXT: expected string not found in input UNDEF-USE-MSG-NEXT: {{U}}NDEF-USE-NEXT: UNDEFVAR: {{\[\[#UNDEFVAR\]\]}} -UNDEF-USE-MSG-NEXT: {{^ \^$}} +UNDEF-USE-MSG-NEXT: {{^ \^$}} +UNDEF-USE-MSG-NEXT: numeric-expression.txt:[[#@LINE-6]]:1: note: scanning from here +UNDEF-USE-MSG-NEXT: UNDEFVAR: 11 +UNDEF-USE-MSG-NEXT: {{^\^$}} +UNDEF-USE-MSG-NEXT: numeric-expression.txt:[[#@LINE-9]]:1: note: uses undefined variable "UNDEFVAR" +UNDEF-USE-MSG-NEXT: UNDEFVAR: 11 +UNDEF-USE-MSG-NEXT: {{^\^$}} ; Numeric expression with unsupported operator. RUN: not FileCheck -D#NUMVAR=10 --check-prefix INVAL-OP --input-file %s %s 2>&1 \ diff --git a/llvm/unittests/Support/FileCheckTest.cpp b/llvm/unittests/Support/FileCheckTest.cpp --- a/llvm/unittests/Support/FileCheckTest.cpp +++ b/llvm/unittests/Support/FileCheckTest.cpp @@ -257,11 +257,11 @@ // Unacceptable variable. EXPECT_TRUE(Tester.parseSubstExpect("10VAR")); EXPECT_TRUE(Tester.parseSubstExpect("@FOO")); - EXPECT_TRUE(Tester.parseSubstExpect("UNDEF")); // Only valid variable. EXPECT_FALSE(Tester.parseSubstExpect("@LINE")); EXPECT_FALSE(Tester.parseSubstExpect("FOO")); + EXPECT_FALSE(Tester.parseSubstExpect("UNDEF")); // Use variable defined on same line. EXPECT_FALSE(Tester.parsePatternExpect("[[#LINE1VAR:]]")); @@ -471,9 +471,14 @@ P = FileCheckPattern(Check::CheckPlain, &Cxt, 2); Expression = P.parseNumericSubstitutionBlock(LocalNumVarRef, DefinedNumericVariable, SM); - EXPECT_TRUE(errorToBool(Expression.takeError())); + EXPECT_TRUE(bool(Expression)); + ExpressionVal = (*Expression)->eval(); + EXPECT_TRUE(errorToBool(ExpressionVal.takeError())); EmptyVar = Cxt.getPatternVarValue(EmptyVarStr); EXPECT_TRUE(errorToBool(EmptyVar.takeError())); + // Clear again because parseNumericSubstitutionBlock would have created a + // dummy variable and stored it in GlobalNumericVariableTable. + Cxt.clearLocalVars(); // Redefine global variables and check variables are defined again. GlobalDefines.emplace_back(std::string("$GlobalVar=BAR"));