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 use of undefined variables, + // whether string or numeric, are then diagnosed when 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 @@ -69,16 +69,12 @@ CHECK-NEXT: [[#VAR1+9223372036854775808]] ; Numeric expression using undefined variable. -RUN: not FileCheck --check-prefix UNDEF-USE --input-file %s %s 2>&1 \ -RUN: | FileCheck --strict-whitespace --check-prefix UNDEF-USE-MSG %s +RUN: not FileCheck --check-prefix UNDEF-USE --input-file %s %s UNDEF VAR USE 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-NEXT: {{U}}NDEF-USE-NEXT: UNDEFVAR: {{\[\[#UNDEFVAR\]\]}} -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(static_cast(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 store it in GlobalNumericVariableTable. + Cxt.clearLocalVars(); // Redefine global variables and check variables are defined again. GlobalDefines.emplace_back(std::string("$GlobalVar=BAR"));