mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
Fix PR46880: Fail CHECK-NOT with undefined variable
Currently a CHECK-NOT directive succeeds whenever the corresponding match fails. However match can fail due to an error rather than a lack of match, for instance if a variable is undefined. This commit makes match error a failure for CHECK-NOT. Reviewed By: jdenny Differential Revision: https://reviews.llvm.org/D86222
This commit is contained in:
parent
01dd9602ed
commit
2c0468b550
@ -531,7 +531,7 @@ Expected<std::unique_ptr<NumericVariableUse>> Pattern::parseNumericVariableUse(
|
||||
// we get below is null, it means no such variable was defined before. When
|
||||
// that happens, we create a dummy variable so that parsing can continue. All
|
||||
// uses of undefined variables, whether string or numeric, are then diagnosed
|
||||
// in printSubstitutions() after failing to match.
|
||||
// in printNoMatch() after failing to match.
|
||||
auto VarTableIter = Context->GlobalNumericVariableTable.find(Name);
|
||||
NumericVariable *NumericVariable;
|
||||
if (VarTableIter != Context->GlobalNumericVariableTable.end())
|
||||
@ -1250,6 +1250,7 @@ Pattern::MatchResult Pattern::match(StringRef Buffer,
|
||||
// Substitute all string variables and expressions whose values are only
|
||||
// now known. Use of string variables defined on the same line are handled
|
||||
// by back-references.
|
||||
Error Errs = Error::success();
|
||||
for (const auto &Substitution : Substitutions) {
|
||||
// Substitute and check for failure (e.g. use of undefined variable).
|
||||
Expected<std::string> Value = Substitution->getResult();
|
||||
@ -1257,13 +1258,20 @@ Pattern::MatchResult Pattern::match(StringRef Buffer,
|
||||
// Convert to an ErrorDiagnostic to get location information. This is
|
||||
// done here rather than printMatch/printNoMatch since now we know which
|
||||
// substitution block caused the overflow.
|
||||
Error Err =
|
||||
handleErrors(Value.takeError(), [&](const OverflowError &E) {
|
||||
return ErrorDiagnostic::get(SM, Substitution->getFromString(),
|
||||
"unable to substitute variable or "
|
||||
"numeric expression: overflow error");
|
||||
});
|
||||
return std::move(Err);
|
||||
Errs = joinErrors(std::move(Errs),
|
||||
handleErrors(
|
||||
Value.takeError(),
|
||||
[&](const OverflowError &E) {
|
||||
return ErrorDiagnostic::get(
|
||||
SM, Substitution->getFromString(),
|
||||
"unable to substitute variable or "
|
||||
"numeric expression: overflow error");
|
||||
},
|
||||
[&SM](const UndefVarError &E) {
|
||||
return ErrorDiagnostic::get(SM, E.getVarName(),
|
||||
E.message());
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Plop it into the regex at the adjusted offset.
|
||||
@ -1271,6 +1279,8 @@ Pattern::MatchResult Pattern::match(StringRef Buffer,
|
||||
Value->begin(), Value->end());
|
||||
InsertOffset += Value->size();
|
||||
}
|
||||
if (Errs)
|
||||
return std::move(Errs);
|
||||
|
||||
// Match the newly constructed regex.
|
||||
RegExToMatch = TmpStr;
|
||||
@ -1349,35 +1359,18 @@ void Pattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
|
||||
for (const auto &Substitution : Substitutions) {
|
||||
SmallString<256> Msg;
|
||||
raw_svector_ostream OS(Msg);
|
||||
Expected<std::string> MatchedValue = Substitution->getResult();
|
||||
|
||||
// Substitution failed or is not known at match time, print the undefined
|
||||
// variables it uses.
|
||||
Expected<std::string> MatchedValue = Substitution->getResult();
|
||||
// Substitution failures are handled in printNoMatch().
|
||||
if (!MatchedValue) {
|
||||
bool UndefSeen = false;
|
||||
handleAllErrors(
|
||||
MatchedValue.takeError(), [](const NotFoundError &E) {},
|
||||
// Handled in printMatch and printNoMatch().
|
||||
[](const ErrorDiagnostic &E) {},
|
||||
// Handled in match().
|
||||
[](const OverflowError &E) {},
|
||||
[&](const UndefVarError &E) {
|
||||
if (!UndefSeen) {
|
||||
OS << "uses undefined variable(s):";
|
||||
UndefSeen = true;
|
||||
}
|
||||
OS << " ";
|
||||
E.log(OS);
|
||||
});
|
||||
if (!OS.tell())
|
||||
continue;
|
||||
} else {
|
||||
// Substitution succeeded. Print substituted value.
|
||||
OS << "with \"";
|
||||
OS.write_escaped(Substitution->getFromString()) << "\" equal to \"";
|
||||
OS.write_escaped(*MatchedValue) << "\"";
|
||||
consumeError(MatchedValue.takeError());
|
||||
continue;
|
||||
}
|
||||
|
||||
OS << "with \"";
|
||||
OS.write_escaped(Substitution->getFromString()) << "\" equal to \"";
|
||||
OS.write_escaped(*MatchedValue) << "\"";
|
||||
|
||||
// We report only the start of the match/search range to suggest we are
|
||||
// reporting the substitutions as set at the start of the match/search.
|
||||
// Indicating a non-zero-length range might instead seem to imply that the
|
||||
@ -2140,12 +2133,6 @@ static Error printNoMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
if (Diags)
|
||||
ErrorMsgs.push_back(E.getMessage().str());
|
||||
},
|
||||
// UndefVarError is reported in printSubstitutions below.
|
||||
// FIXME: It probably should be handled as a pattern error and actually
|
||||
// change the exit status to 1, even if !ExpectedMatch. To do so, we
|
||||
// could stop calling printSubstitutions and actually report the error
|
||||
// here as we do ErrorDiagnostic above.
|
||||
[](const UndefVarError &E) {},
|
||||
// NotFoundError is why printNoMatch was invoked.
|
||||
[](const NotFoundError &E) {});
|
||||
|
||||
|
@ -229,8 +229,7 @@ public:
|
||||
|
||||
/// Print name of variable associated with this error.
|
||||
void log(raw_ostream &OS) const override {
|
||||
OS << "\"";
|
||||
OS.write_escaped(VarName) << "\"";
|
||||
OS << "undefined variable: " << VarName;
|
||||
}
|
||||
};
|
||||
|
||||
@ -756,8 +755,7 @@ public:
|
||||
/// current values of FileCheck numeric variables and is updated if this
|
||||
/// match defines new numeric values.
|
||||
MatchResult match(StringRef Buffer, const SourceMgr &SM) const;
|
||||
/// Prints the value of successful substitutions or the name of the undefined
|
||||
/// string or numeric variables preventing a successful substitution.
|
||||
/// Prints the value of successful substitutions.
|
||||
void printSubstitutions(const SourceMgr &SM, StringRef Buffer,
|
||||
SMRange MatchRange, FileCheckDiag::MatchType MatchTy,
|
||||
std::vector<FileCheckDiag> *Diags) const;
|
||||
|
@ -692,22 +692,17 @@
|
||||
; SUBST-POS-NEXT:check:1'0 ^~~~~~~~~~~~~~~~~~~~~
|
||||
; SUBST-POS-NEXT:check:1'1 with "DEF_MATCH1" equal to "def-match1"
|
||||
; SUBST-POS-NEXT:check:1'2 with "DEF_MATCH2" equal to "def-match2"
|
||||
; SUBST-POS-NEXT:check:2'0 X error: no match found
|
||||
; SUBST-POS-NEXT:check:2'1 with "DEF_MATCH1" equal to "def-match1"
|
||||
; SUBST-POS-NEXT:check:2'2 uses undefined variable(s): "UNDEF"
|
||||
; SUBST-POS-NEXT:check:2'0 X error: match failed for invalid pattern
|
||||
; SUBST-POS-NEXT:check:2'1 undefined variable: UNDEF
|
||||
; SUBST-POS-NEXT:check:2'2 with "DEF_MATCH1" equal to "def-match1"
|
||||
; SUBST-POS-NEXT:check:2'3 with "DEF_NOMATCH" equal to "foobar"
|
||||
; SUBST-POS-NEXT: 2: def-match1 def-nomatch
|
||||
; SUBST-POS-NEXT:check:2'0 ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
; SUBST-POS-NEXT:check:2'4 ? possible intended match
|
||||
; SUBST-POS-NEXT:check:2'4 ? possible intended match
|
||||
; SUBST-POS-NEXT:>>>>>>
|
||||
|
||||
;--------------------------------------------------
|
||||
; Substitutions: successful and failed negative directives.
|
||||
;
|
||||
; FIXME: The first CHECK-NOT directive below uses an undefined variable.
|
||||
; Because it therefore cannot match regardless of the input, the directive
|
||||
; succeeds. However, it should fail in this case. Update the example below
|
||||
; once that's fixed.
|
||||
;--------------------------------------------------
|
||||
|
||||
; RUN: echo 'def-match1 def-nomatch' > %t.in
|
||||
@ -726,9 +721,9 @@
|
||||
|
||||
; SUBST-NEG:<<<<<<
|
||||
; SUBST-NEG-NEXT: 1: def-match1 def-nomatch
|
||||
; SUBST-NEG-NEXT:not:1'0 X~~~~~~~~~~~~~~~~~~~~~~
|
||||
; SUBST-NEG-NEXT:not:1'1 with "DEF_MATCH1" equal to "def-match1"
|
||||
; SUBST-NEG-NEXT:not:1'2 uses undefined variable(s): "UNDEF"
|
||||
; SUBST-NEG-NEXT:not:1'0 X~~~~~~~~~~~~~~~~~~~~~~ error: match failed for invalid pattern
|
||||
; SUBST-NEG-NEXT:not:1'1 undefined variable: UNDEF
|
||||
; SUBST-NEG-NEXT:not:1'2 with "DEF_MATCH1" equal to "def-match1"
|
||||
; SUBST-NEG-NEXT:not:1'3 with "DEF_NOMATCH" equal to "foobar"
|
||||
; SUBST-NEG-NEXT: 2: def-match1 def-match2
|
||||
; SUBST-NEG-NEXT:not:1'0 ~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -20,8 +20,8 @@ ERR-VV-EMPTY:
|
||||
ERR:{{.*}}: error: unable to substitute variable or numeric expression: overflow error
|
||||
ERR-NEXT:CHECK-NOT: {{.*}}
|
||||
ERR-NEXT:{{ *}}^
|
||||
ERR-NEXT:<stdin>:1:1: note: uses undefined variable(s): "UNDEFVAR"
|
||||
ERR-NEXT:10000000000000000
|
||||
ERR-NEXT:{{.*}}: error: undefined variable: UNDEFVAR
|
||||
ERR-NEXT:{{CHECK-NOT: \[\[#0x8000000000000000\+0x8000000000000000\]\] \[\[UNDEFVAR\]\]}}
|
||||
ERR-NEXT:^
|
||||
ERR-NOT:{{error|note|remark}}:
|
||||
|
||||
@ -29,7 +29,7 @@ ERR-VV-EMPTY:
|
||||
DUMP-NEXT: 1: 10000000000000000
|
||||
DUMP-NEXT:not:1'0 X~~~~~~~~~~~~~~~~~ error: match failed for invalid pattern
|
||||
DUMP-NEXT:not:1'1 unable to substitute variable or numeric expression: overflow error
|
||||
DUMP-NEXT:not:1'2 uses undefined variable(s): "UNDEFVAR"
|
||||
DUMP-NEXT:not:1'2 undefined variable: UNDEFVAR
|
||||
DUMP-VV-NEXT: 2:
|
||||
DUMP-VV-NEXT:eof:1 ^
|
||||
DUMP-NEXT:>>>>>>
|
||||
|
@ -9,8 +9,8 @@ RUN: echo > %t.in '10000000000000000'
|
||||
ERR:{{.*}}: error: unable to substitute variable or numeric expression: overflow error
|
||||
ERR-NEXT:CHECK: {{.*}}
|
||||
ERR-NEXT:{{ *}}^
|
||||
ERR-NEXT:<stdin>:1:1: note: uses undefined variable(s): "UNDEFVAR"
|
||||
ERR-NEXT:10000000000000000
|
||||
ERR-NEXT:{{.*}}: error: undefined variable: UNDEFVAR
|
||||
ERR-NEXT:{{CHECK: \[\[#0x8000000000000000\+0x8000000000000000\]\] \[\[UNDEFVAR\]\]}}
|
||||
ERR-NEXT:^
|
||||
ERR-NOT:{{error|note|remark}}:
|
||||
|
||||
@ -18,7 +18,7 @@ RUN: echo > %t.in '10000000000000000'
|
||||
DUMP-NEXT: 1: 10000000000000000
|
||||
DUMP-NEXT:check:1'0 X~~~~~~~~~~~~~~~~~ error: match failed for invalid pattern
|
||||
DUMP-NEXT:check:1'1 unable to substitute variable or numeric expression: overflow error
|
||||
DUMP-NEXT:check:1'2 uses undefined variable(s): "UNDEFVAR"
|
||||
DUMP-NEXT:check:1'2 undefined variable: UNDEFVAR
|
||||
DUMP-NEXT:>>>>>>
|
||||
|
||||
;--------------------------------------------------
|
||||
|
@ -400,15 +400,29 @@ UNDEF VAR USE
|
||||
UNDEFVAR: 11
|
||||
UNDEF-USE-LABEL: UNDEF VAR USE
|
||||
UNDEF-USE-NEXT: UNDEFVAR: [[#UNDEFVAR1+UNDEFVAR2]]
|
||||
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: {{\[\[#UNDEFVAR1\+UNDEFVAR2\]\]}}
|
||||
UNDEF-USE-MSG-NEXT: {{^}} ^{{$}}
|
||||
UNDEF-USE-MSG-NEXT: numeric-expression.txt:[[#@LINE-7]]:14: note: scanning from here
|
||||
UNDEF-USE-MSG-NEXT: UNDEF VAR USE
|
||||
UNDEF-USE-MSG-NEXT: {{^}} ^{{$}}
|
||||
UNDEF-USE-MSG-NEXT: numeric-expression.txt:[[#@LINE-10]]:14: note: uses undefined variable(s): "UNDEFVAR1" "UNDEFVAR2"
|
||||
UNDEF-USE-MSG-NEXT: UNDEF VAR USE
|
||||
UNDEF-USE-MSG-NEXT: {{^}} ^{{$}}
|
||||
UNDEF-USE-MSG: numeric-expression.txt:[[#@LINE-1]]:30: error: undefined variable: UNDEFVAR1
|
||||
UNDEF-USE-MSG-NEXT: {{U}}NDEF-USE-NEXT: {{U}}NDEFVAR: {{\[\[#UNDEFVAR1\+UNDEFVAR2\]\]}}
|
||||
UNDEF-USE-MSG-NEXT: {{^}} ^{{$}}
|
||||
UNDEF-USE-MSG-NEXT: numeric-expression.txt:[[#@LINE-4]]:40: error: undefined variable: UNDEFVAR2
|
||||
UNDEF-USE-MSG-NEXT: {{U}}NDEF-USE-NEXT: {{U}}NDEFVAR: {{\[\[#UNDEFVAR1\+UNDEFVAR2\]\]}}
|
||||
UNDEF-USE-MSG-NEXT: {{^}} ^{{$}}
|
||||
|
||||
; Numeric expression in negative directive using undefined variables.
|
||||
RUN: %ProtectFileCheckOutput \
|
||||
RUN: not FileCheck --check-prefix UNDEF-USE2 --input-file %s %s 2>&1 \
|
||||
RUN: | FileCheck --strict-whitespace --check-prefix UNDEF-USE-MSG2 %s
|
||||
|
||||
CHECK NOT UNDEF VAR USE
|
||||
END MARKER
|
||||
UNDEF-USE2-LABEL: CHECK NOT UNDEF VAR USE
|
||||
UNDEF-USE2-NOT: UNDEFVAR: [[#UNDEFVAR1+UNDEFVAR2]]
|
||||
UNDEF-USE2: END MARKER
|
||||
UNDEF-USE-MSG2: numeric-expression.txt:[[#@LINE-2]]:30: error: undefined variable: UNDEFVAR1
|
||||
UNDEF-USE-MSG2-NEXT: {{U}}NDEF-USE2-NOT: {{U}}NDEFVAR: {{\[\[#UNDEFVAR1\+UNDEFVAR2\]\]}}
|
||||
UNDEF-USE-MSG2-NEXT: {{^}} ^{{$}}
|
||||
UNDEF-USE-MSG2-NEXT: numeric-expression.txt:[[#@LINE-5]]:40: error: undefined variable: UNDEFVAR2
|
||||
UNDEF-USE-MSG2-NEXT: {{U}}NDEF-USE2-NOT: {{U}}NDEFVAR: {{\[\[#UNDEFVAR1\+UNDEFVAR2\]\]}}
|
||||
UNDEF-USE-MSG2-NEXT: {{^}} ^{{$}}
|
||||
|
||||
; Numeric expression with unsupported operator.
|
||||
RUN: %ProtectFileCheckOutput \
|
||||
|
@ -7,11 +7,11 @@ RUN: FileCheck --check-prefixes CHECK,LOCAL3,GLOBAL --input-file %s %s
|
||||
|
||||
RUN: FileCheck --check-prefixes CHECK,GLOBAL --enable-var-scope --input-file %s %s
|
||||
RUN: %ProtectFileCheckOutput not FileCheck --check-prefixes CHECK,LOCAL1 --enable-var-scope --input-file %s %s 2>&1 \
|
||||
RUN: | FileCheck --check-prefixes ERRUNDEF,ERRUNDEFLOCAL %s
|
||||
RUN: | FileCheck --check-prefix ERRUNDEFLOCAL %s
|
||||
RUN: %ProtectFileCheckOutput not FileCheck --check-prefixes CHECK,LOCAL2 --enable-var-scope --input-file %s %s 2>&1 \
|
||||
RUN: | FileCheck --check-prefixes ERRUNDEF,ERRUNDEFLOCNUM %s
|
||||
RUN: | FileCheck --check-prefix ERRUNDEFLOCNUM %s
|
||||
RUN: %ProtectFileCheckOutput not FileCheck --check-prefixes CHECK,LOCAL3 --enable-var-scope --input-file %s %s 2>&1 \
|
||||
RUN: | FileCheck --check-prefixes ERRUNDEF,ERRUNDEFLOCAL,ERRUNDEFLOCNUM %s
|
||||
RUN: | FileCheck --check-prefixes ERRUNDEFLOCAL,ERRUNDEFLOCNUM %s
|
||||
|
||||
local1
|
||||
global1
|
||||
@ -33,6 +33,5 @@ LOCAL2: local[[#LOCNUM+2]]
|
||||
LOCAL3: [[LOCAL]][[#LOCNUM+2]]
|
||||
GLOBAL: [[$GLOBAL]][[#$GLOBNUM+2]]
|
||||
|
||||
ERRUNDEF: expected string not found in input
|
||||
ERRUNDEFLOCAL: uses undefined variable(s): "LOCAL"
|
||||
ERRUNDEFLOCNUM: uses undefined variable(s): "LOCNUM"
|
||||
ERRUNDEFLOCAL: undefined variable: LOCAL
|
||||
ERRUNDEFLOCNUM: undefined variable: LOCNUM
|
||||
|
@ -1445,8 +1445,10 @@ TEST_F(FileCheckTest, Match) {
|
||||
Succeeded());
|
||||
Tester.initNextPattern();
|
||||
// Match with substitution failure.
|
||||
ASSERT_FALSE(Tester.parsePattern("[[#UNKNOWN]]"));
|
||||
expectUndefErrors({"UNKNOWN"}, Tester.match("FOO").takeError());
|
||||
ASSERT_FALSE(Tester.parsePattern("[[#UNKNOWN1+UNKNOWN2]]"));
|
||||
expectSameErrors<ErrorDiagnostic>(
|
||||
{"undefined variable: UNKNOWN1", "undefined variable: UNKNOWN2"},
|
||||
Tester.match("FOO").takeError());
|
||||
Tester.initNextPattern();
|
||||
// Check that @LINE matches the later (given the calls to initNextPattern())
|
||||
// line number.
|
||||
|
Loading…
Reference in New Issue
Block a user