1 //===- FileCheck.cpp - Check that File's Contents match what is expected --===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // FileCheck does a line-by line check of a file that validates whether it
10 // contains the expected content. This is useful for regression tests etc.
12 // This file implements most of the API that will be used by the FileCheck utility
13 // as well as various unittests.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/Support/FileCheck.h"
17 #include "FileCheckImpl.h"
18 #include "llvm/ADT/StringSet.h"
19 #include "llvm/ADT/Twine.h"
20 #include "llvm/Support/FormatVariadic.h"
28 Expected
<uint64_t> FileCheckNumericVariableUse::eval() const {
29 Optional
<uint64_t> Value
= NumericVariable
->getValue();
33 return make_error
<FileCheckUndefVarError
>(Name
);
36 Expected
<uint64_t> FileCheckASTBinop::eval() const {
37 Expected
<uint64_t> LeftOp
= LeftOperand
->eval();
38 Expected
<uint64_t> RightOp
= RightOperand
->eval();
40 // Bubble up any error (e.g. undefined variables) in the recursive
42 if (!LeftOp
|| !RightOp
) {
43 Error Err
= Error::success();
45 Err
= joinErrors(std::move(Err
), LeftOp
.takeError());
47 Err
= joinErrors(std::move(Err
), RightOp
.takeError());
48 return std::move(Err
);
51 return EvalBinop(*LeftOp
, *RightOp
);
54 Expected
<std::string
> FileCheckNumericSubstitution::getResult() const {
55 Expected
<uint64_t> EvaluatedValue
= ExpressionAST
->eval();
57 return EvaluatedValue
.takeError();
58 return utostr(*EvaluatedValue
);
61 Expected
<std::string
> FileCheckStringSubstitution::getResult() const {
62 // Look up the value and escape it so that we can put it into the regex.
63 Expected
<StringRef
> VarVal
= Context
->getPatternVarValue(FromStr
);
65 return VarVal
.takeError();
66 return Regex::escape(*VarVal
);
69 bool FileCheckPattern::isValidVarNameStart(char C
) {
70 return C
== '_' || isalpha(C
);
73 Expected
<FileCheckPattern::VariableProperties
>
74 FileCheckPattern::parseVariable(StringRef
&Str
, const SourceMgr
&SM
) {
76 return FileCheckErrorDiagnostic::get(SM
, Str
, "empty variable name");
78 bool ParsedOneChar
= false;
80 bool IsPseudo
= Str
[0] == '@';
82 // Global vars start with '$'.
83 if (Str
[0] == '$' || IsPseudo
)
86 for (unsigned E
= Str
.size(); I
!= E
; ++I
) {
87 if (!ParsedOneChar
&& !isValidVarNameStart(Str
[I
]))
88 return FileCheckErrorDiagnostic::get(SM
, Str
, "invalid variable name");
90 // Variable names are composed of alphanumeric characters and underscores.
91 if (Str
[I
] != '_' && !isalnum(Str
[I
]))
96 StringRef Name
= Str
.take_front(I
);
98 return VariableProperties
{Name
, IsPseudo
};
101 // StringRef holding all characters considered as horizontal whitespaces by
102 // FileCheck input canonicalization.
103 constexpr StringLiteral SpaceChars
= " \t";
105 // Parsing helper function that strips the first character in S and returns it.
106 static char popFront(StringRef
&S
) {
112 char FileCheckUndefVarError::ID
= 0;
113 char FileCheckErrorDiagnostic::ID
= 0;
114 char FileCheckNotFoundError::ID
= 0;
116 Expected
<FileCheckNumericVariable
*>
117 FileCheckPattern::parseNumericVariableDefinition(
118 StringRef
&Expr
, FileCheckPatternContext
*Context
,
119 Optional
<size_t> LineNumber
, const SourceMgr
&SM
) {
120 Expected
<VariableProperties
> ParseVarResult
= parseVariable(Expr
, SM
);
122 return ParseVarResult
.takeError();
123 StringRef Name
= ParseVarResult
->Name
;
125 if (ParseVarResult
->IsPseudo
)
126 return FileCheckErrorDiagnostic::get(
127 SM
, Name
, "definition of pseudo numeric variable unsupported");
129 // Detect collisions between string and numeric variables when the latter
130 // is created later than the former.
131 if (Context
->DefinedVariableTable
.find(Name
) !=
132 Context
->DefinedVariableTable
.end())
133 return FileCheckErrorDiagnostic::get(
134 SM
, Name
, "string variable with name '" + Name
+ "' already exists");
136 Expr
= Expr
.ltrim(SpaceChars
);
138 return FileCheckErrorDiagnostic::get(
139 SM
, Expr
, "unexpected characters after numeric variable name");
141 FileCheckNumericVariable
*DefinedNumericVariable
;
142 auto VarTableIter
= Context
->GlobalNumericVariableTable
.find(Name
);
143 if (VarTableIter
!= Context
->GlobalNumericVariableTable
.end())
144 DefinedNumericVariable
= VarTableIter
->second
;
146 DefinedNumericVariable
= Context
->makeNumericVariable(Name
, LineNumber
);
148 return DefinedNumericVariable
;
151 Expected
<std::unique_ptr
<FileCheckNumericVariableUse
>>
152 FileCheckPattern::parseNumericVariableUse(StringRef Name
, bool IsPseudo
,
153 Optional
<size_t> LineNumber
,
154 FileCheckPatternContext
*Context
,
155 const SourceMgr
&SM
) {
156 if (IsPseudo
&& !Name
.equals("@LINE"))
157 return FileCheckErrorDiagnostic::get(
158 SM
, Name
, "invalid pseudo numeric variable '" + Name
+ "'");
160 // Numeric variable definitions and uses are parsed in the order in which
161 // they appear in the CHECK patterns. For each definition, the pointer to the
162 // class instance of the corresponding numeric variable definition is stored
163 // in GlobalNumericVariableTable in parsePattern. Therefore, if the pointer
164 // we get below is null, it means no such variable was defined before. When
165 // that happens, we create a dummy variable so that parsing can continue. All
166 // uses of undefined variables, whether string or numeric, are then diagnosed
167 // in printSubstitutions() after failing to match.
168 auto VarTableIter
= Context
->GlobalNumericVariableTable
.find(Name
);
169 FileCheckNumericVariable
*NumericVariable
;
170 if (VarTableIter
!= Context
->GlobalNumericVariableTable
.end())
171 NumericVariable
= VarTableIter
->second
;
173 NumericVariable
= Context
->makeNumericVariable(Name
);
174 Context
->GlobalNumericVariableTable
[Name
] = NumericVariable
;
177 Optional
<size_t> DefLineNumber
= NumericVariable
->getDefLineNumber();
178 if (DefLineNumber
&& LineNumber
&& *DefLineNumber
== *LineNumber
)
179 return FileCheckErrorDiagnostic::get(
181 "numeric variable '" + Name
+
182 "' defined earlier in the same CHECK directive");
184 return std::make_unique
<FileCheckNumericVariableUse
>(Name
, NumericVariable
);
187 Expected
<std::unique_ptr
<FileCheckExpressionAST
>>
188 FileCheckPattern::parseNumericOperand(StringRef
&Expr
, AllowedOperand AO
,
189 Optional
<size_t> LineNumber
,
190 FileCheckPatternContext
*Context
,
191 const SourceMgr
&SM
) {
192 if (AO
== AllowedOperand::LineVar
|| AO
== AllowedOperand::Any
) {
193 // Try to parse as a numeric variable use.
194 Expected
<FileCheckPattern::VariableProperties
> ParseVarResult
=
195 parseVariable(Expr
, SM
);
197 return parseNumericVariableUse(ParseVarResult
->Name
,
198 ParseVarResult
->IsPseudo
, LineNumber
,
200 if (AO
== AllowedOperand::LineVar
)
201 return ParseVarResult
.takeError();
202 // Ignore the error and retry parsing as a literal.
203 consumeError(ParseVarResult
.takeError());
206 // Otherwise, parse it as a literal.
207 uint64_t LiteralValue
;
208 if (!Expr
.consumeInteger(/*Radix=*/10, LiteralValue
))
209 return std::make_unique
<FileCheckExpressionLiteral
>(LiteralValue
);
211 return FileCheckErrorDiagnostic::get(SM
, Expr
,
212 "invalid operand format '" + Expr
+ "'");
215 static uint64_t add(uint64_t LeftOp
, uint64_t RightOp
) {
216 return LeftOp
+ RightOp
;
219 static uint64_t sub(uint64_t LeftOp
, uint64_t RightOp
) {
220 return LeftOp
- RightOp
;
223 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> FileCheckPattern::parseBinop(
224 StringRef
&Expr
, std::unique_ptr
<FileCheckExpressionAST
> LeftOp
,
225 bool IsLegacyLineExpr
, Optional
<size_t> LineNumber
,
226 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
227 Expr
= Expr
.ltrim(SpaceChars
);
229 return std::move(LeftOp
);
231 // Check if this is a supported operation and select a function to perform
233 SMLoc OpLoc
= SMLoc::getFromPointer(Expr
.data());
234 char Operator
= popFront(Expr
);
235 binop_eval_t EvalBinop
;
244 return FileCheckErrorDiagnostic::get(
245 SM
, OpLoc
, Twine("unsupported operation '") + Twine(Operator
) + "'");
248 // Parse right operand.
249 Expr
= Expr
.ltrim(SpaceChars
);
251 return FileCheckErrorDiagnostic::get(SM
, Expr
,
252 "missing operand in expression");
253 // The second operand in a legacy @LINE expression is always a literal.
255 IsLegacyLineExpr
? AllowedOperand::Literal
: AllowedOperand::Any
;
256 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> RightOpResult
=
257 parseNumericOperand(Expr
, AO
, LineNumber
, Context
, SM
);
259 return RightOpResult
;
261 Expr
= Expr
.ltrim(SpaceChars
);
262 return std::make_unique
<FileCheckASTBinop
>(EvalBinop
, std::move(LeftOp
),
263 std::move(*RightOpResult
));
266 Expected
<std::unique_ptr
<FileCheckExpressionAST
>>
267 FileCheckPattern::parseNumericSubstitutionBlock(
269 Optional
<FileCheckNumericVariable
*> &DefinedNumericVariable
,
270 bool IsLegacyLineExpr
, Optional
<size_t> LineNumber
,
271 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
272 std::unique_ptr
<FileCheckExpressionAST
> ExpressionAST
= nullptr;
273 StringRef DefExpr
= StringRef();
274 DefinedNumericVariable
= None
;
275 // Save variable definition expression if any.
276 size_t DefEnd
= Expr
.find(':');
277 if (DefEnd
!= StringRef::npos
) {
278 DefExpr
= Expr
.substr(0, DefEnd
);
279 Expr
= Expr
.substr(DefEnd
+ 1);
282 // Parse the expression itself.
283 Expr
= Expr
.ltrim(SpaceChars
);
285 // The first operand in a legacy @LINE expression is always the @LINE
288 IsLegacyLineExpr
? AllowedOperand::LineVar
: AllowedOperand::Any
;
289 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> ParseResult
=
290 parseNumericOperand(Expr
, AO
, LineNumber
, Context
, SM
);
291 while (ParseResult
&& !Expr
.empty()) {
292 ParseResult
= parseBinop(Expr
, std::move(*ParseResult
), IsLegacyLineExpr
,
293 LineNumber
, Context
, SM
);
294 // Legacy @LINE expressions only allow 2 operands.
295 if (ParseResult
&& IsLegacyLineExpr
&& !Expr
.empty())
296 return FileCheckErrorDiagnostic::get(
298 "unexpected characters at end of expression '" + Expr
+ "'");
302 ExpressionAST
= std::move(*ParseResult
);
305 // Parse the numeric variable definition.
306 if (DefEnd
!= StringRef::npos
) {
307 DefExpr
= DefExpr
.ltrim(SpaceChars
);
308 Expected
<FileCheckNumericVariable
*> ParseResult
=
309 parseNumericVariableDefinition(DefExpr
, Context
, LineNumber
, SM
);
312 return ParseResult
.takeError();
313 DefinedNumericVariable
= *ParseResult
;
316 return std::move(ExpressionAST
);
319 bool FileCheckPattern::parsePattern(StringRef PatternStr
, StringRef Prefix
,
321 const FileCheckRequest
&Req
) {
322 bool MatchFullLinesHere
= Req
.MatchFullLines
&& CheckTy
!= Check::CheckNot
;
324 PatternLoc
= SMLoc::getFromPointer(PatternStr
.data());
326 if (!(Req
.NoCanonicalizeWhiteSpace
&& Req
.MatchFullLines
))
327 // Ignore trailing whitespace.
328 while (!PatternStr
.empty() &&
329 (PatternStr
.back() == ' ' || PatternStr
.back() == '\t'))
330 PatternStr
= PatternStr
.substr(0, PatternStr
.size() - 1);
332 // Check that there is something on the line.
333 if (PatternStr
.empty() && CheckTy
!= Check::CheckEmpty
) {
334 SM
.PrintMessage(PatternLoc
, SourceMgr::DK_Error
,
335 "found empty check string with prefix '" + Prefix
+ ":'");
339 if (!PatternStr
.empty() && CheckTy
== Check::CheckEmpty
) {
341 PatternLoc
, SourceMgr::DK_Error
,
342 "found non-empty check string for empty check with prefix '" + Prefix
+
347 if (CheckTy
== Check::CheckEmpty
) {
352 // Check to see if this is a fixed string, or if it has regex pieces.
353 if (!MatchFullLinesHere
&&
354 (PatternStr
.size() < 2 || (PatternStr
.find("{{") == StringRef::npos
&&
355 PatternStr
.find("[[") == StringRef::npos
))) {
356 FixedStr
= PatternStr
;
360 if (MatchFullLinesHere
) {
362 if (!Req
.NoCanonicalizeWhiteSpace
)
366 // Paren value #0 is for the fully matched string. Any new parenthesized
367 // values add from there.
368 unsigned CurParen
= 1;
370 // Otherwise, there is at least one regex piece. Build up the regex pattern
371 // by escaping scary characters in fixed strings, building up one big regex.
372 while (!PatternStr
.empty()) {
374 if (PatternStr
.startswith("{{")) {
375 // This is the start of a regex match. Scan for the }}.
376 size_t End
= PatternStr
.find("}}");
377 if (End
== StringRef::npos
) {
378 SM
.PrintMessage(SMLoc::getFromPointer(PatternStr
.data()),
380 "found start of regex string with no end '}}'");
384 // Enclose {{}} patterns in parens just like [[]] even though we're not
385 // capturing the result for any purpose. This is required in case the
386 // expression contains an alternation like: CHECK: abc{{x|z}}def. We
387 // want this to turn into: "abc(x|z)def" not "abcx|zdef".
391 if (AddRegExToRegEx(PatternStr
.substr(2, End
- 2), CurParen
, SM
))
395 PatternStr
= PatternStr
.substr(End
+ 2);
399 // String and numeric substitution blocks. Pattern substitution blocks come
400 // in two forms: [[foo:.*]] and [[foo]]. The former matches .* (or some
401 // other regex) and assigns it to the string variable 'foo'. The latter
402 // substitutes foo's value. Numeric substitution blocks recognize the same
403 // form as string ones, but start with a '#' sign after the double
404 // brackets. They also accept a combined form which sets a numeric variable
405 // to the evaluation of an expression. Both string and numeric variable
406 // names must satisfy the regular expression "[a-zA-Z_][0-9a-zA-Z_]*" to be
407 // valid, as this helps catch some common errors.
408 if (PatternStr
.startswith("[[")) {
409 StringRef UnparsedPatternStr
= PatternStr
.substr(2);
410 // Find the closing bracket pair ending the match. End is going to be an
411 // offset relative to the beginning of the match string.
412 size_t End
= FindRegexVarEnd(UnparsedPatternStr
, SM
);
413 StringRef MatchStr
= UnparsedPatternStr
.substr(0, End
);
414 bool IsNumBlock
= MatchStr
.consume_front("#");
416 if (End
== StringRef::npos
) {
417 SM
.PrintMessage(SMLoc::getFromPointer(PatternStr
.data()),
419 "Invalid substitution block, no ]] found");
422 // Strip the substitution block we are parsing. End points to the start
423 // of the "]]" closing the expression so account for it in computing the
424 // index of the first unparsed character.
425 PatternStr
= UnparsedPatternStr
.substr(End
+ 2);
427 bool IsDefinition
= false;
428 bool SubstNeeded
= false;
429 // Whether the substitution block is a legacy use of @LINE with string
430 // substitution block syntax.
431 bool IsLegacyLineExpr
= false;
434 StringRef MatchRegexp
;
435 size_t SubstInsertIdx
= RegExStr
.size();
437 // Parse string variable or legacy @LINE expression.
439 size_t VarEndIdx
= MatchStr
.find(":");
440 size_t SpacePos
= MatchStr
.substr(0, VarEndIdx
).find_first_of(" \t");
441 if (SpacePos
!= StringRef::npos
) {
442 SM
.PrintMessage(SMLoc::getFromPointer(MatchStr
.data() + SpacePos
),
443 SourceMgr::DK_Error
, "unexpected whitespace");
447 // Get the name (e.g. "foo") and verify it is well formed.
448 StringRef OrigMatchStr
= MatchStr
;
449 Expected
<FileCheckPattern::VariableProperties
> ParseVarResult
=
450 parseVariable(MatchStr
, SM
);
451 if (!ParseVarResult
) {
452 logAllUnhandledErrors(ParseVarResult
.takeError(), errs());
455 StringRef Name
= ParseVarResult
->Name
;
456 bool IsPseudo
= ParseVarResult
->IsPseudo
;
458 IsDefinition
= (VarEndIdx
!= StringRef::npos
);
459 SubstNeeded
= !IsDefinition
;
461 if ((IsPseudo
|| !MatchStr
.consume_front(":"))) {
462 SM
.PrintMessage(SMLoc::getFromPointer(Name
.data()),
464 "invalid name in string variable definition");
468 // Detect collisions between string and numeric variables when the
469 // former is created later than the latter.
470 if (Context
->GlobalNumericVariableTable
.find(Name
) !=
471 Context
->GlobalNumericVariableTable
.end()) {
473 SMLoc::getFromPointer(Name
.data()), SourceMgr::DK_Error
,
474 "numeric variable with name '" + Name
+ "' already exists");
478 MatchRegexp
= MatchStr
;
481 MatchStr
= OrigMatchStr
;
482 IsLegacyLineExpr
= IsNumBlock
= true;
488 // Parse numeric substitution block.
489 std::unique_ptr
<FileCheckExpressionAST
> ExpressionAST
;
490 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
492 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> ParseResult
=
493 parseNumericSubstitutionBlock(MatchStr
, DefinedNumericVariable
,
494 IsLegacyLineExpr
, LineNumber
, Context
,
497 logAllUnhandledErrors(ParseResult
.takeError(), errs());
500 ExpressionAST
= std::move(*ParseResult
);
501 SubstNeeded
= ExpressionAST
!= nullptr;
502 if (DefinedNumericVariable
) {
504 DefName
= (*DefinedNumericVariable
)->getName();
509 MatchRegexp
= "[0-9]+";
512 // Handle variable definition: [[<def>:(...)]] and [[#(...)<def>:(...)]].
518 FileCheckNumericVariableMatch NumericVariableDefinition
= {
519 *DefinedNumericVariable
, CurParen
};
520 NumericVariableDefs
[DefName
] = NumericVariableDefinition
;
521 // This store is done here rather than in match() to allow
522 // parseNumericVariableUse() to get the pointer to the class instance
523 // of the right variable definition corresponding to a given numeric
525 Context
->GlobalNumericVariableTable
[DefName
] =
526 *DefinedNumericVariable
;
528 VariableDefs
[DefName
] = CurParen
;
529 // Mark string variable as defined to detect collisions between
530 // string and numeric variables in parseNumericVariableUse() and
531 // defineCmdlineVariables() when the latter is created later than the
532 // former. We cannot reuse GlobalVariableTable for this by populating
533 // it with an empty string since we would then lose the ability to
534 // detect the use of an undefined variable in match().
535 Context
->DefinedVariableTable
[DefName
] = true;
541 if (!MatchRegexp
.empty() && AddRegExToRegEx(MatchRegexp
, CurParen
, SM
))
547 // Handle substitutions: [[foo]] and [[#<foo expr>]].
549 // Handle substitution of string variables that were defined earlier on
550 // the same line by emitting a backreference. Expressions do not
551 // support substituting a numeric variable defined on the same line.
552 if (!IsNumBlock
&& VariableDefs
.find(SubstStr
) != VariableDefs
.end()) {
553 unsigned CaptureParenGroup
= VariableDefs
[SubstStr
];
554 if (CaptureParenGroup
< 1 || CaptureParenGroup
> 9) {
555 SM
.PrintMessage(SMLoc::getFromPointer(SubstStr
.data()),
557 "Can't back-reference more than 9 variables");
560 AddBackrefToRegEx(CaptureParenGroup
);
562 // Handle substitution of string variables ([[<var>]]) defined in
563 // previous CHECK patterns, and substitution of expressions.
564 FileCheckSubstitution
*Substitution
=
566 ? Context
->makeNumericSubstitution(
567 SubstStr
, std::move(ExpressionAST
), SubstInsertIdx
)
568 : Context
->makeStringSubstitution(SubstStr
, SubstInsertIdx
);
569 Substitutions
.push_back(Substitution
);
574 // Handle fixed string matches.
575 // Find the end, which is the start of the next regex.
576 size_t FixedMatchEnd
= PatternStr
.find("{{");
577 FixedMatchEnd
= std::min(FixedMatchEnd
, PatternStr
.find("[["));
578 RegExStr
+= Regex::escape(PatternStr
.substr(0, FixedMatchEnd
));
579 PatternStr
= PatternStr
.substr(FixedMatchEnd
);
582 if (MatchFullLinesHere
) {
583 if (!Req
.NoCanonicalizeWhiteSpace
)
591 bool FileCheckPattern::AddRegExToRegEx(StringRef RS
, unsigned &CurParen
, SourceMgr
&SM
) {
594 if (!R
.isValid(Error
)) {
595 SM
.PrintMessage(SMLoc::getFromPointer(RS
.data()), SourceMgr::DK_Error
,
596 "invalid regex: " + Error
);
600 RegExStr
+= RS
.str();
601 CurParen
+= R
.getNumMatches();
605 void FileCheckPattern::AddBackrefToRegEx(unsigned BackrefNum
) {
606 assert(BackrefNum
>= 1 && BackrefNum
<= 9 && "Invalid backref number");
607 std::string Backref
= std::string("\\") + std::string(1, '0' + BackrefNum
);
611 Expected
<size_t> FileCheckPattern::match(StringRef Buffer
, size_t &MatchLen
,
612 const SourceMgr
&SM
) const {
613 // If this is the EOF pattern, match it immediately.
614 if (CheckTy
== Check::CheckEOF
) {
616 return Buffer
.size();
619 // If this is a fixed string pattern, just match it now.
620 if (!FixedStr
.empty()) {
621 MatchLen
= FixedStr
.size();
622 size_t Pos
= Buffer
.find(FixedStr
);
623 if (Pos
== StringRef::npos
)
624 return make_error
<FileCheckNotFoundError
>();
630 // If there are substitutions, we need to create a temporary string with the
632 StringRef RegExToMatch
= RegExStr
;
634 if (!Substitutions
.empty()) {
637 Context
->LineVariable
->setValue(*LineNumber
);
639 size_t InsertOffset
= 0;
640 // Substitute all string variables and expressions whose values are only
641 // now known. Use of string variables defined on the same line are handled
642 // by back-references.
643 for (const auto &Substitution
: Substitutions
) {
644 // Substitute and check for failure (e.g. use of undefined variable).
645 Expected
<std::string
> Value
= Substitution
->getResult();
647 return Value
.takeError();
649 // Plop it into the regex at the adjusted offset.
650 TmpStr
.insert(TmpStr
.begin() + Substitution
->getIndex() + InsertOffset
,
651 Value
->begin(), Value
->end());
652 InsertOffset
+= Value
->size();
655 // Match the newly constructed regex.
656 RegExToMatch
= TmpStr
;
659 SmallVector
<StringRef
, 4> MatchInfo
;
660 if (!Regex(RegExToMatch
, Regex::Newline
).match(Buffer
, &MatchInfo
))
661 return make_error
<FileCheckNotFoundError
>();
663 // Successful regex match.
664 assert(!MatchInfo
.empty() && "Didn't get any match");
665 StringRef FullMatch
= MatchInfo
[0];
667 // If this defines any string variables, remember their values.
668 for (const auto &VariableDef
: VariableDefs
) {
669 assert(VariableDef
.second
< MatchInfo
.size() && "Internal paren error");
670 Context
->GlobalVariableTable
[VariableDef
.first
] =
671 MatchInfo
[VariableDef
.second
];
674 // If this defines any numeric variables, remember their values.
675 for (const auto &NumericVariableDef
: NumericVariableDefs
) {
676 const FileCheckNumericVariableMatch
&NumericVariableMatch
=
677 NumericVariableDef
.getValue();
678 unsigned CaptureParenGroup
= NumericVariableMatch
.CaptureParenGroup
;
679 assert(CaptureParenGroup
< MatchInfo
.size() && "Internal paren error");
680 FileCheckNumericVariable
*DefinedNumericVariable
=
681 NumericVariableMatch
.DefinedNumericVariable
;
683 StringRef MatchedValue
= MatchInfo
[CaptureParenGroup
];
685 if (MatchedValue
.getAsInteger(10, Val
))
686 return FileCheckErrorDiagnostic::get(SM
, MatchedValue
,
687 "Unable to represent numeric value");
688 DefinedNumericVariable
->setValue(Val
);
691 // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
692 // the required preceding newline, which is consumed by the pattern in the
693 // case of CHECK-EMPTY but not CHECK-NEXT.
694 size_t MatchStartSkip
= CheckTy
== Check::CheckEmpty
;
695 MatchLen
= FullMatch
.size() - MatchStartSkip
;
696 return FullMatch
.data() - Buffer
.data() + MatchStartSkip
;
699 unsigned FileCheckPattern::computeMatchDistance(StringRef Buffer
) const {
700 // Just compute the number of matching characters. For regular expressions, we
701 // just compare against the regex itself and hope for the best.
703 // FIXME: One easy improvement here is have the regex lib generate a single
704 // example regular expression which matches, and use that as the example
706 StringRef
ExampleString(FixedStr
);
707 if (ExampleString
.empty())
708 ExampleString
= RegExStr
;
710 // Only compare up to the first line in the buffer, or the string size.
711 StringRef BufferPrefix
= Buffer
.substr(0, ExampleString
.size());
712 BufferPrefix
= BufferPrefix
.split('\n').first
;
713 return BufferPrefix
.edit_distance(ExampleString
);
716 void FileCheckPattern::printSubstitutions(const SourceMgr
&SM
, StringRef Buffer
,
717 SMRange MatchRange
) const {
718 // Print what we know about substitutions.
719 if (!Substitutions
.empty()) {
720 for (const auto &Substitution
: Substitutions
) {
721 SmallString
<256> Msg
;
722 raw_svector_ostream
OS(Msg
);
723 Expected
<std::string
> MatchedValue
= Substitution
->getResult();
725 // Substitution failed or is not known at match time, print the undefined
726 // variables it uses.
728 bool UndefSeen
= false;
729 handleAllErrors(MatchedValue
.takeError(),
730 [](const FileCheckNotFoundError
&E
) {},
731 // Handled in PrintNoMatch().
732 [](const FileCheckErrorDiagnostic
&E
) {},
733 [&](const FileCheckUndefVarError
&E
) {
735 OS
<< "uses undefined variable(s):";
742 // Substitution succeeded. Print substituted value.
744 OS
.write_escaped(Substitution
->getFromString()) << "\" equal to \"";
745 OS
.write_escaped(*MatchedValue
) << "\"";
748 if (MatchRange
.isValid())
749 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
, OS
.str(),
752 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()),
753 SourceMgr::DK_Note
, OS
.str());
758 static SMRange
ProcessMatchResult(FileCheckDiag::MatchType MatchTy
,
759 const SourceMgr
&SM
, SMLoc Loc
,
760 Check::FileCheckType CheckTy
,
761 StringRef Buffer
, size_t Pos
, size_t Len
,
762 std::vector
<FileCheckDiag
> *Diags
,
763 bool AdjustPrevDiag
= false) {
764 SMLoc Start
= SMLoc::getFromPointer(Buffer
.data() + Pos
);
765 SMLoc End
= SMLoc::getFromPointer(Buffer
.data() + Pos
+ Len
);
766 SMRange
Range(Start
, End
);
769 Diags
->rbegin()->MatchTy
= MatchTy
;
771 Diags
->emplace_back(SM
, CheckTy
, Loc
, MatchTy
, Range
);
776 void FileCheckPattern::printFuzzyMatch(
777 const SourceMgr
&SM
, StringRef Buffer
,
778 std::vector
<FileCheckDiag
> *Diags
) const {
779 // Attempt to find the closest/best fuzzy match. Usually an error happens
780 // because some string in the output didn't exactly match. In these cases, we
781 // would like to show the user a best guess at what "should have" matched, to
782 // save them having to actually check the input manually.
783 size_t NumLinesForward
= 0;
784 size_t Best
= StringRef::npos
;
785 double BestQuality
= 0;
787 // Use an arbitrary 4k limit on how far we will search.
788 for (size_t i
= 0, e
= std::min(size_t(4096), Buffer
.size()); i
!= e
; ++i
) {
789 if (Buffer
[i
] == '\n')
792 // Patterns have leading whitespace stripped, so skip whitespace when
793 // looking for something which looks like a pattern.
794 if (Buffer
[i
] == ' ' || Buffer
[i
] == '\t')
797 // Compute the "quality" of this match as an arbitrary combination of the
798 // match distance and the number of lines skipped to get to this match.
799 unsigned Distance
= computeMatchDistance(Buffer
.substr(i
));
800 double Quality
= Distance
+ (NumLinesForward
/ 100.);
802 if (Quality
< BestQuality
|| Best
== StringRef::npos
) {
804 BestQuality
= Quality
;
808 // Print the "possible intended match here" line if we found something
809 // reasonable and not equal to what we showed in the "scanning from here"
811 if (Best
&& Best
!= StringRef::npos
&& BestQuality
< 50) {
813 ProcessMatchResult(FileCheckDiag::MatchFuzzy
, SM
, getLoc(),
814 getCheckTy(), Buffer
, Best
, 0, Diags
);
815 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
,
816 "possible intended match here");
818 // FIXME: If we wanted to be really friendly we would show why the match
819 // failed, as it can be hard to spot simple one character differences.
824 FileCheckPatternContext::getPatternVarValue(StringRef VarName
) {
825 auto VarIter
= GlobalVariableTable
.find(VarName
);
826 if (VarIter
== GlobalVariableTable
.end())
827 return make_error
<FileCheckUndefVarError
>(VarName
);
829 return VarIter
->second
;
832 template <class... Types
>
833 FileCheckNumericVariable
*
834 FileCheckPatternContext::makeNumericVariable(Types
... args
) {
835 NumericVariables
.push_back(
836 std::make_unique
<FileCheckNumericVariable
>(args
...));
837 return NumericVariables
.back().get();
840 FileCheckSubstitution
*
841 FileCheckPatternContext::makeStringSubstitution(StringRef VarName
,
843 Substitutions
.push_back(
844 std::make_unique
<FileCheckStringSubstitution
>(this, VarName
, InsertIdx
));
845 return Substitutions
.back().get();
848 FileCheckSubstitution
*FileCheckPatternContext::makeNumericSubstitution(
849 StringRef ExpressionStr
,
850 std::unique_ptr
<FileCheckExpressionAST
> ExpressionAST
, size_t InsertIdx
) {
851 Substitutions
.push_back(std::make_unique
<FileCheckNumericSubstitution
>(
852 this, ExpressionStr
, std::move(ExpressionAST
), InsertIdx
));
853 return Substitutions
.back().get();
856 size_t FileCheckPattern::FindRegexVarEnd(StringRef Str
, SourceMgr
&SM
) {
857 // Offset keeps track of the current offset within the input Str
859 // [...] Nesting depth
860 size_t BracketDepth
= 0;
862 while (!Str
.empty()) {
863 if (Str
.startswith("]]") && BracketDepth
== 0)
865 if (Str
[0] == '\\') {
866 // Backslash escapes the next char within regexes, so skip them both.
877 if (BracketDepth
== 0) {
878 SM
.PrintMessage(SMLoc::getFromPointer(Str
.data()),
880 "missing closing \"]\" for regex variable");
891 return StringRef::npos
;
894 StringRef
FileCheck::CanonicalizeFile(MemoryBuffer
&MB
,
895 SmallVectorImpl
<char> &OutputBuffer
) {
896 OutputBuffer
.reserve(MB
.getBufferSize());
898 for (const char *Ptr
= MB
.getBufferStart(), *End
= MB
.getBufferEnd();
900 // Eliminate trailing dosish \r.
901 if (Ptr
<= End
- 2 && Ptr
[0] == '\r' && Ptr
[1] == '\n') {
905 // If current char is not a horizontal whitespace or if horizontal
906 // whitespace canonicalization is disabled, dump it to output as is.
907 if (Req
.NoCanonicalizeWhiteSpace
|| (*Ptr
!= ' ' && *Ptr
!= '\t')) {
908 OutputBuffer
.push_back(*Ptr
);
912 // Otherwise, add one space and advance over neighboring space.
913 OutputBuffer
.push_back(' ');
914 while (Ptr
+ 1 != End
&& (Ptr
[1] == ' ' || Ptr
[1] == '\t'))
918 // Add a null byte and then return all but that byte.
919 OutputBuffer
.push_back('\0');
920 return StringRef(OutputBuffer
.data(), OutputBuffer
.size() - 1);
923 FileCheckDiag::FileCheckDiag(const SourceMgr
&SM
,
924 const Check::FileCheckType
&CheckTy
,
925 SMLoc CheckLoc
, MatchType MatchTy
,
927 : CheckTy(CheckTy
), MatchTy(MatchTy
) {
928 auto Start
= SM
.getLineAndColumn(InputRange
.Start
);
929 auto End
= SM
.getLineAndColumn(InputRange
.End
);
930 InputStartLine
= Start
.first
;
931 InputStartCol
= Start
.second
;
932 InputEndLine
= End
.first
;
933 InputEndCol
= End
.second
;
934 Start
= SM
.getLineAndColumn(CheckLoc
);
935 CheckLine
= Start
.first
;
936 CheckCol
= Start
.second
;
939 static bool IsPartOfWord(char c
) {
940 return (isalnum(c
) || c
== '-' || c
== '_');
943 Check::FileCheckType
&Check::FileCheckType::setCount(int C
) {
944 assert(Count
> 0 && "zero and negative counts are not supported");
945 assert((C
== 1 || Kind
== CheckPlain
) &&
946 "count supported only for plain CHECK directives");
951 std::string
Check::FileCheckType::getDescription(StringRef Prefix
) const {
953 case Check::CheckNone
:
955 case Check::CheckPlain
:
957 return Prefix
.str() + "-COUNT";
959 case Check::CheckNext
:
960 return Prefix
.str() + "-NEXT";
961 case Check::CheckSame
:
962 return Prefix
.str() + "-SAME";
963 case Check::CheckNot
:
964 return Prefix
.str() + "-NOT";
965 case Check::CheckDAG
:
966 return Prefix
.str() + "-DAG";
967 case Check::CheckLabel
:
968 return Prefix
.str() + "-LABEL";
969 case Check::CheckEmpty
:
970 return Prefix
.str() + "-EMPTY";
971 case Check::CheckEOF
:
972 return "implicit EOF";
973 case Check::CheckBadNot
:
975 case Check::CheckBadCount
:
978 llvm_unreachable("unknown FileCheckType");
981 static std::pair
<Check::FileCheckType
, StringRef
>
982 FindCheckType(StringRef Buffer
, StringRef Prefix
) {
983 if (Buffer
.size() <= Prefix
.size())
984 return {Check::CheckNone
, StringRef()};
986 char NextChar
= Buffer
[Prefix
.size()];
988 StringRef Rest
= Buffer
.drop_front(Prefix
.size() + 1);
989 // Verify that the : is present after the prefix.
991 return {Check::CheckPlain
, Rest
};
994 return {Check::CheckNone
, StringRef()};
996 if (Rest
.consume_front("COUNT-")) {
998 if (Rest
.consumeInteger(10, Count
))
999 // Error happened in parsing integer.
1000 return {Check::CheckBadCount
, Rest
};
1001 if (Count
<= 0 || Count
> INT32_MAX
)
1002 return {Check::CheckBadCount
, Rest
};
1003 if (!Rest
.consume_front(":"))
1004 return {Check::CheckBadCount
, Rest
};
1005 return {Check::FileCheckType(Check::CheckPlain
).setCount(Count
), Rest
};
1008 if (Rest
.consume_front("NEXT:"))
1009 return {Check::CheckNext
, Rest
};
1011 if (Rest
.consume_front("SAME:"))
1012 return {Check::CheckSame
, Rest
};
1014 if (Rest
.consume_front("NOT:"))
1015 return {Check::CheckNot
, Rest
};
1017 if (Rest
.consume_front("DAG:"))
1018 return {Check::CheckDAG
, Rest
};
1020 if (Rest
.consume_front("LABEL:"))
1021 return {Check::CheckLabel
, Rest
};
1023 if (Rest
.consume_front("EMPTY:"))
1024 return {Check::CheckEmpty
, Rest
};
1026 // You can't combine -NOT with another suffix.
1027 if (Rest
.startswith("DAG-NOT:") || Rest
.startswith("NOT-DAG:") ||
1028 Rest
.startswith("NEXT-NOT:") || Rest
.startswith("NOT-NEXT:") ||
1029 Rest
.startswith("SAME-NOT:") || Rest
.startswith("NOT-SAME:") ||
1030 Rest
.startswith("EMPTY-NOT:") || Rest
.startswith("NOT-EMPTY:"))
1031 return {Check::CheckBadNot
, Rest
};
1033 return {Check::CheckNone
, Rest
};
1036 // From the given position, find the next character after the word.
1037 static size_t SkipWord(StringRef Str
, size_t Loc
) {
1038 while (Loc
< Str
.size() && IsPartOfWord(Str
[Loc
]))
1043 /// Searches the buffer for the first prefix in the prefix regular expression.
1045 /// This searches the buffer using the provided regular expression, however it
1046 /// enforces constraints beyond that:
1047 /// 1) The found prefix must not be a suffix of something that looks like
1049 /// 2) The found prefix must be followed by a valid check type suffix using \c
1050 /// FindCheckType above.
1052 /// \returns a pair of StringRefs into the Buffer, which combines:
1053 /// - the first match of the regular expression to satisfy these two is
1055 /// otherwise an empty StringRef is returned to indicate failure.
1056 /// - buffer rewound to the location right after parsed suffix, for parsing
1057 /// to continue from
1059 /// If this routine returns a valid prefix, it will also shrink \p Buffer to
1060 /// start at the beginning of the returned prefix, increment \p LineNumber for
1061 /// each new line consumed from \p Buffer, and set \p CheckTy to the type of
1062 /// check found by examining the suffix.
1064 /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
1066 static std::pair
<StringRef
, StringRef
>
1067 FindFirstMatchingPrefix(Regex
&PrefixRE
, StringRef
&Buffer
,
1068 unsigned &LineNumber
, Check::FileCheckType
&CheckTy
) {
1069 SmallVector
<StringRef
, 2> Matches
;
1071 while (!Buffer
.empty()) {
1072 // Find the first (longest) match using the RE.
1073 if (!PrefixRE
.match(Buffer
, &Matches
))
1074 // No match at all, bail.
1075 return {StringRef(), StringRef()};
1077 StringRef Prefix
= Matches
[0];
1080 assert(Prefix
.data() >= Buffer
.data() &&
1081 Prefix
.data() < Buffer
.data() + Buffer
.size() &&
1082 "Prefix doesn't start inside of buffer!");
1083 size_t Loc
= Prefix
.data() - Buffer
.data();
1084 StringRef Skipped
= Buffer
.substr(0, Loc
);
1085 Buffer
= Buffer
.drop_front(Loc
);
1086 LineNumber
+= Skipped
.count('\n');
1088 // Check that the matched prefix isn't a suffix of some other check-like
1090 // FIXME: This is a very ad-hoc check. it would be better handled in some
1091 // other way. Among other things it seems hard to distinguish between
1092 // intentional and unintentional uses of this feature.
1093 if (Skipped
.empty() || !IsPartOfWord(Skipped
.back())) {
1094 // Now extract the type.
1095 StringRef AfterSuffix
;
1096 std::tie(CheckTy
, AfterSuffix
) = FindCheckType(Buffer
, Prefix
);
1098 // If we've found a valid check type for this prefix, we're done.
1099 if (CheckTy
!= Check::CheckNone
)
1100 return {Prefix
, AfterSuffix
};
1103 // If we didn't successfully find a prefix, we need to skip this invalid
1104 // prefix and continue scanning. We directly skip the prefix that was
1105 // matched and any additional parts of that check-like word.
1106 Buffer
= Buffer
.drop_front(SkipWord(Buffer
, Prefix
.size()));
1109 // We ran out of buffer while skipping partial matches so give up.
1110 return {StringRef(), StringRef()};
1113 void FileCheckPatternContext::createLineVariable() {
1114 assert(!LineVariable
&& "@LINE pseudo numeric variable already created");
1115 StringRef LineName
= "@LINE";
1116 LineVariable
= makeNumericVariable(LineName
);
1117 GlobalNumericVariableTable
[LineName
] = LineVariable
;
1120 FileCheck::FileCheck(FileCheckRequest Req
)
1121 : Req(Req
), PatternContext(std::make_unique
<FileCheckPatternContext
>()),
1122 CheckStrings(std::make_unique
<std::vector
<FileCheckString
>>()) {}
1124 FileCheck::~FileCheck() = default;
1126 bool FileCheck::readCheckFile(SourceMgr
&SM
, StringRef Buffer
,
1129 PatternContext
->defineCmdlineVariables(Req
.GlobalDefines
, SM
);
1131 logAllUnhandledErrors(std::move(DefineError
), errs());
1135 PatternContext
->createLineVariable();
1137 std::vector
<FileCheckPattern
> ImplicitNegativeChecks
;
1138 for (const auto &PatternString
: Req
.ImplicitCheckNot
) {
1139 // Create a buffer with fake command line content in order to display the
1140 // command line option responsible for the specific implicit CHECK-NOT.
1141 std::string Prefix
= "-implicit-check-not='";
1142 std::string Suffix
= "'";
1143 std::unique_ptr
<MemoryBuffer
> CmdLine
= MemoryBuffer::getMemBufferCopy(
1144 Prefix
+ PatternString
+ Suffix
, "command line");
1146 StringRef PatternInBuffer
=
1147 CmdLine
->getBuffer().substr(Prefix
.size(), PatternString
.size());
1148 SM
.AddNewSourceBuffer(std::move(CmdLine
), SMLoc());
1150 ImplicitNegativeChecks
.push_back(
1151 FileCheckPattern(Check::CheckNot
, PatternContext
.get()));
1152 ImplicitNegativeChecks
.back().parsePattern(PatternInBuffer
,
1153 "IMPLICIT-CHECK", SM
, Req
);
1156 std::vector
<FileCheckPattern
> DagNotMatches
= ImplicitNegativeChecks
;
1158 // LineNumber keeps track of the line on which CheckPrefix instances are
1160 unsigned LineNumber
= 1;
1163 Check::FileCheckType CheckTy
;
1165 // See if a prefix occurs in the memory buffer.
1166 StringRef UsedPrefix
;
1167 StringRef AfterSuffix
;
1168 std::tie(UsedPrefix
, AfterSuffix
) =
1169 FindFirstMatchingPrefix(PrefixRE
, Buffer
, LineNumber
, CheckTy
);
1170 if (UsedPrefix
.empty())
1172 assert(UsedPrefix
.data() == Buffer
.data() &&
1173 "Failed to move Buffer's start forward, or pointed prefix outside "
1175 assert(AfterSuffix
.data() >= Buffer
.data() &&
1176 AfterSuffix
.data() < Buffer
.data() + Buffer
.size() &&
1177 "Parsing after suffix doesn't start inside of buffer!");
1179 // Location to use for error messages.
1180 const char *UsedPrefixStart
= UsedPrefix
.data();
1182 // Skip the buffer to the end of parsed suffix (or just prefix, if no good
1183 // suffix was processed).
1184 Buffer
= AfterSuffix
.empty() ? Buffer
.drop_front(UsedPrefix
.size())
1187 // Complain about useful-looking but unsupported suffixes.
1188 if (CheckTy
== Check::CheckBadNot
) {
1189 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Error
,
1190 "unsupported -NOT combo on prefix '" + UsedPrefix
+ "'");
1194 // Complain about invalid count specification.
1195 if (CheckTy
== Check::CheckBadCount
) {
1196 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Error
,
1197 "invalid count in -COUNT specification on prefix '" +
1202 // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
1203 // leading whitespace.
1204 if (!(Req
.NoCanonicalizeWhiteSpace
&& Req
.MatchFullLines
))
1205 Buffer
= Buffer
.substr(Buffer
.find_first_not_of(" \t"));
1207 // Scan ahead to the end of line.
1208 size_t EOL
= Buffer
.find_first_of("\n\r");
1210 // Remember the location of the start of the pattern, for diagnostics.
1211 SMLoc PatternLoc
= SMLoc::getFromPointer(Buffer
.data());
1213 // Parse the pattern.
1214 FileCheckPattern
P(CheckTy
, PatternContext
.get(), LineNumber
);
1215 if (P
.parsePattern(Buffer
.substr(0, EOL
), UsedPrefix
, SM
, Req
))
1218 // Verify that CHECK-LABEL lines do not define or use variables
1219 if ((CheckTy
== Check::CheckLabel
) && P
.hasVariable()) {
1221 SMLoc::getFromPointer(UsedPrefixStart
), SourceMgr::DK_Error
,
1222 "found '" + UsedPrefix
+ "-LABEL:'"
1223 " with variable definition or use");
1227 Buffer
= Buffer
.substr(EOL
);
1229 // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
1230 if ((CheckTy
== Check::CheckNext
|| CheckTy
== Check::CheckSame
||
1231 CheckTy
== Check::CheckEmpty
) &&
1232 CheckStrings
->empty()) {
1233 StringRef Type
= CheckTy
== Check::CheckNext
1235 : CheckTy
== Check::CheckEmpty
? "EMPTY" : "SAME";
1236 SM
.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart
),
1237 SourceMgr::DK_Error
,
1238 "found '" + UsedPrefix
+ "-" + Type
+
1239 "' without previous '" + UsedPrefix
+ ": line");
1243 // Handle CHECK-DAG/-NOT.
1244 if (CheckTy
== Check::CheckDAG
|| CheckTy
== Check::CheckNot
) {
1245 DagNotMatches
.push_back(P
);
1249 // Okay, add the string we captured to the output vector and move on.
1250 CheckStrings
->emplace_back(P
, UsedPrefix
, PatternLoc
);
1251 std::swap(DagNotMatches
, CheckStrings
->back().DagNotStrings
);
1252 DagNotMatches
= ImplicitNegativeChecks
;
1255 // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
1256 // prefix as a filler for the error message.
1257 if (!DagNotMatches
.empty()) {
1258 CheckStrings
->emplace_back(
1259 FileCheckPattern(Check::CheckEOF
, PatternContext
.get(), LineNumber
+ 1),
1260 *Req
.CheckPrefixes
.begin(), SMLoc::getFromPointer(Buffer
.data()));
1261 std::swap(DagNotMatches
, CheckStrings
->back().DagNotStrings
);
1264 if (CheckStrings
->empty()) {
1265 errs() << "error: no check strings found with prefix"
1266 << (Req
.CheckPrefixes
.size() > 1 ? "es " : " ");
1267 auto I
= Req
.CheckPrefixes
.begin();
1268 auto E
= Req
.CheckPrefixes
.end();
1270 errs() << "\'" << *I
<< ":'";
1274 errs() << ", \'" << *I
<< ":'";
1283 static void PrintMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1284 StringRef Prefix
, SMLoc Loc
, const FileCheckPattern
&Pat
,
1285 int MatchedCount
, StringRef Buffer
, size_t MatchPos
,
1286 size_t MatchLen
, const FileCheckRequest
&Req
,
1287 std::vector
<FileCheckDiag
> *Diags
) {
1288 bool PrintDiag
= true;
1289 if (ExpectedMatch
) {
1292 if (!Req
.VerboseVerbose
&& Pat
.getCheckTy() == Check::CheckEOF
)
1294 // Due to their verbosity, we don't print verbose diagnostics here if we're
1295 // gathering them for a different rendering, but we always print other
1299 SMRange MatchRange
= ProcessMatchResult(
1300 ExpectedMatch
? FileCheckDiag::MatchFoundAndExpected
1301 : FileCheckDiag::MatchFoundButExcluded
,
1302 SM
, Loc
, Pat
.getCheckTy(), Buffer
, MatchPos
, MatchLen
, Diags
);
1306 std::string Message
= formatv("{0}: {1} string found in input",
1307 Pat
.getCheckTy().getDescription(Prefix
),
1308 (ExpectedMatch
? "expected" : "excluded"))
1310 if (Pat
.getCount() > 1)
1311 Message
+= formatv(" ({0} out of {1})", MatchedCount
, Pat
.getCount()).str();
1314 Loc
, ExpectedMatch
? SourceMgr::DK_Remark
: SourceMgr::DK_Error
, Message
);
1315 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
, "found here",
1317 Pat
.printSubstitutions(SM
, Buffer
, MatchRange
);
1320 static void PrintMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1321 const FileCheckString
&CheckStr
, int MatchedCount
,
1322 StringRef Buffer
, size_t MatchPos
, size_t MatchLen
,
1323 FileCheckRequest
&Req
,
1324 std::vector
<FileCheckDiag
> *Diags
) {
1325 PrintMatch(ExpectedMatch
, SM
, CheckStr
.Prefix
, CheckStr
.Loc
, CheckStr
.Pat
,
1326 MatchedCount
, Buffer
, MatchPos
, MatchLen
, Req
, Diags
);
1329 static void PrintNoMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1330 StringRef Prefix
, SMLoc Loc
,
1331 const FileCheckPattern
&Pat
, int MatchedCount
,
1332 StringRef Buffer
, bool VerboseVerbose
,
1333 std::vector
<FileCheckDiag
> *Diags
, Error MatchErrors
) {
1334 assert(MatchErrors
&& "Called on successful match");
1335 bool PrintDiag
= true;
1336 if (!ExpectedMatch
) {
1337 if (!VerboseVerbose
) {
1338 consumeError(std::move(MatchErrors
));
1341 // Due to their verbosity, we don't print verbose diagnostics here if we're
1342 // gathering them for a different rendering, but we always print other
1347 // If the current position is at the end of a line, advance to the start of
1349 Buffer
= Buffer
.substr(Buffer
.find_first_not_of(" \t\n\r"));
1350 SMRange SearchRange
= ProcessMatchResult(
1351 ExpectedMatch
? FileCheckDiag::MatchNoneButExpected
1352 : FileCheckDiag::MatchNoneAndExcluded
,
1353 SM
, Loc
, Pat
.getCheckTy(), Buffer
, 0, Buffer
.size(), Diags
);
1355 consumeError(std::move(MatchErrors
));
1360 handleErrors(std::move(MatchErrors
),
1361 [](const FileCheckErrorDiagnostic
&E
) { E
.log(errs()); });
1363 // No problem matching the string per se.
1366 consumeError(std::move(MatchErrors
));
1368 // Print "not found" diagnostic.
1369 std::string Message
= formatv("{0}: {1} string not found in input",
1370 Pat
.getCheckTy().getDescription(Prefix
),
1371 (ExpectedMatch
? "expected" : "excluded"))
1373 if (Pat
.getCount() > 1)
1374 Message
+= formatv(" ({0} out of {1})", MatchedCount
, Pat
.getCount()).str();
1376 Loc
, ExpectedMatch
? SourceMgr::DK_Error
: SourceMgr::DK_Remark
, Message
);
1378 // Print the "scanning from here" line.
1379 SM
.PrintMessage(SearchRange
.Start
, SourceMgr::DK_Note
, "scanning from here");
1381 // Allow the pattern to print additional information if desired.
1382 Pat
.printSubstitutions(SM
, Buffer
);
1385 Pat
.printFuzzyMatch(SM
, Buffer
, Diags
);
1388 static void PrintNoMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1389 const FileCheckString
&CheckStr
, int MatchedCount
,
1390 StringRef Buffer
, bool VerboseVerbose
,
1391 std::vector
<FileCheckDiag
> *Diags
, Error MatchErrors
) {
1392 PrintNoMatch(ExpectedMatch
, SM
, CheckStr
.Prefix
, CheckStr
.Loc
, CheckStr
.Pat
,
1393 MatchedCount
, Buffer
, VerboseVerbose
, Diags
,
1394 std::move(MatchErrors
));
1397 /// Counts the number of newlines in the specified range.
1398 static unsigned CountNumNewlinesBetween(StringRef Range
,
1399 const char *&FirstNewLine
) {
1400 unsigned NumNewLines
= 0;
1402 // Scan for newline.
1403 Range
= Range
.substr(Range
.find_first_of("\n\r"));
1409 // Handle \n\r and \r\n as a single newline.
1410 if (Range
.size() > 1 && (Range
[1] == '\n' || Range
[1] == '\r') &&
1411 (Range
[0] != Range
[1]))
1412 Range
= Range
.substr(1);
1413 Range
= Range
.substr(1);
1415 if (NumNewLines
== 1)
1416 FirstNewLine
= Range
.begin();
1420 size_t FileCheckString::Check(const SourceMgr
&SM
, StringRef Buffer
,
1421 bool IsLabelScanMode
, size_t &MatchLen
,
1422 FileCheckRequest
&Req
,
1423 std::vector
<FileCheckDiag
> *Diags
) const {
1425 std::vector
<const FileCheckPattern
*> NotStrings
;
1427 // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
1428 // bounds; we have not processed variable definitions within the bounded block
1429 // yet so cannot handle any final CHECK-DAG yet; this is handled when going
1430 // over the block again (including the last CHECK-LABEL) in normal mode.
1431 if (!IsLabelScanMode
) {
1432 // Match "dag strings" (with mixed "not strings" if any).
1433 LastPos
= CheckDag(SM
, Buffer
, NotStrings
, Req
, Diags
);
1434 if (LastPos
== StringRef::npos
)
1435 return StringRef::npos
;
1438 // Match itself from the last position after matching CHECK-DAG.
1439 size_t LastMatchEnd
= LastPos
;
1440 size_t FirstMatchPos
= 0;
1441 // Go match the pattern Count times. Majority of patterns only match with
1443 assert(Pat
.getCount() != 0 && "pattern count can not be zero");
1444 for (int i
= 1; i
<= Pat
.getCount(); i
++) {
1445 StringRef MatchBuffer
= Buffer
.substr(LastMatchEnd
);
1446 size_t CurrentMatchLen
;
1447 // get a match at current start point
1448 Expected
<size_t> MatchResult
= Pat
.match(MatchBuffer
, CurrentMatchLen
, SM
);
1452 PrintNoMatch(true, SM
, *this, i
, MatchBuffer
, Req
.VerboseVerbose
, Diags
,
1453 MatchResult
.takeError());
1454 return StringRef::npos
;
1456 size_t MatchPos
= *MatchResult
;
1457 PrintMatch(true, SM
, *this, i
, MatchBuffer
, MatchPos
, CurrentMatchLen
, Req
,
1460 FirstMatchPos
= LastPos
+ MatchPos
;
1462 // move start point after the match
1463 LastMatchEnd
+= MatchPos
+ CurrentMatchLen
;
1465 // Full match len counts from first match pos.
1466 MatchLen
= LastMatchEnd
- FirstMatchPos
;
1468 // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
1470 if (!IsLabelScanMode
) {
1471 size_t MatchPos
= FirstMatchPos
- LastPos
;
1472 StringRef MatchBuffer
= Buffer
.substr(LastPos
);
1473 StringRef SkippedRegion
= Buffer
.substr(LastPos
, MatchPos
);
1475 // If this check is a "CHECK-NEXT", verify that the previous match was on
1476 // the previous line (i.e. that there is one newline between them).
1477 if (CheckNext(SM
, SkippedRegion
)) {
1478 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine
, SM
, Loc
,
1479 Pat
.getCheckTy(), MatchBuffer
, MatchPos
, MatchLen
,
1480 Diags
, Req
.Verbose
);
1481 return StringRef::npos
;
1484 // If this check is a "CHECK-SAME", verify that the previous match was on
1485 // the same line (i.e. that there is no newline between them).
1486 if (CheckSame(SM
, SkippedRegion
)) {
1487 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine
, SM
, Loc
,
1488 Pat
.getCheckTy(), MatchBuffer
, MatchPos
, MatchLen
,
1489 Diags
, Req
.Verbose
);
1490 return StringRef::npos
;
1493 // If this match had "not strings", verify that they don't exist in the
1495 if (CheckNot(SM
, SkippedRegion
, NotStrings
, Req
, Diags
))
1496 return StringRef::npos
;
1499 return FirstMatchPos
;
1502 bool FileCheckString::CheckNext(const SourceMgr
&SM
, StringRef Buffer
) const {
1503 if (Pat
.getCheckTy() != Check::CheckNext
&&
1504 Pat
.getCheckTy() != Check::CheckEmpty
)
1509 Twine(Pat
.getCheckTy() == Check::CheckEmpty
? "-EMPTY" : "-NEXT");
1511 // Count the number of newlines between the previous match and this one.
1512 const char *FirstNewLine
= nullptr;
1513 unsigned NumNewLines
= CountNumNewlinesBetween(Buffer
, FirstNewLine
);
1515 if (NumNewLines
== 0) {
1516 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
1517 CheckName
+ ": is on the same line as previous match");
1518 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
1519 "'next' match was here");
1520 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
1521 "previous match ended here");
1525 if (NumNewLines
!= 1) {
1526 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
1528 ": is not on the line after the previous match");
1529 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
1530 "'next' match was here");
1531 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
1532 "previous match ended here");
1533 SM
.PrintMessage(SMLoc::getFromPointer(FirstNewLine
), SourceMgr::DK_Note
,
1534 "non-matching line after previous match is here");
1541 bool FileCheckString::CheckSame(const SourceMgr
&SM
, StringRef Buffer
) const {
1542 if (Pat
.getCheckTy() != Check::CheckSame
)
1545 // Count the number of newlines between the previous match and this one.
1546 const char *FirstNewLine
= nullptr;
1547 unsigned NumNewLines
= CountNumNewlinesBetween(Buffer
, FirstNewLine
);
1549 if (NumNewLines
!= 0) {
1550 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
1552 "-SAME: is not on the same line as the previous match");
1553 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
1554 "'next' match was here");
1555 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
1556 "previous match ended here");
1563 bool FileCheckString::CheckNot(
1564 const SourceMgr
&SM
, StringRef Buffer
,
1565 const std::vector
<const FileCheckPattern
*> &NotStrings
,
1566 const FileCheckRequest
&Req
, std::vector
<FileCheckDiag
> *Diags
) const {
1567 for (const FileCheckPattern
*Pat
: NotStrings
) {
1568 assert((Pat
->getCheckTy() == Check::CheckNot
) && "Expect CHECK-NOT!");
1570 size_t MatchLen
= 0;
1571 Expected
<size_t> MatchResult
= Pat
->match(Buffer
, MatchLen
, SM
);
1574 PrintNoMatch(false, SM
, Prefix
, Pat
->getLoc(), *Pat
, 1, Buffer
,
1575 Req
.VerboseVerbose
, Diags
, MatchResult
.takeError());
1578 size_t Pos
= *MatchResult
;
1580 PrintMatch(false, SM
, Prefix
, Pat
->getLoc(), *Pat
, 1, Buffer
, Pos
, MatchLen
,
1590 FileCheckString::CheckDag(const SourceMgr
&SM
, StringRef Buffer
,
1591 std::vector
<const FileCheckPattern
*> &NotStrings
,
1592 const FileCheckRequest
&Req
,
1593 std::vector
<FileCheckDiag
> *Diags
) const {
1594 if (DagNotStrings
.empty())
1597 // The start of the search range.
1598 size_t StartPos
= 0;
1604 // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
1605 // ranges are erased from this list once they are no longer in the search
1607 std::list
<MatchRange
> MatchRanges
;
1609 // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
1610 // group, so we don't use a range-based for loop here.
1611 for (auto PatItr
= DagNotStrings
.begin(), PatEnd
= DagNotStrings
.end();
1612 PatItr
!= PatEnd
; ++PatItr
) {
1613 const FileCheckPattern
&Pat
= *PatItr
;
1614 assert((Pat
.getCheckTy() == Check::CheckDAG
||
1615 Pat
.getCheckTy() == Check::CheckNot
) &&
1616 "Invalid CHECK-DAG or CHECK-NOT!");
1618 if (Pat
.getCheckTy() == Check::CheckNot
) {
1619 NotStrings
.push_back(&Pat
);
1623 assert((Pat
.getCheckTy() == Check::CheckDAG
) && "Expect CHECK-DAG!");
1625 // CHECK-DAG always matches from the start.
1626 size_t MatchLen
= 0, MatchPos
= StartPos
;
1628 // Search for a match that doesn't overlap a previous match in this
1630 for (auto MI
= MatchRanges
.begin(), ME
= MatchRanges
.end(); true; ++MI
) {
1631 StringRef MatchBuffer
= Buffer
.substr(MatchPos
);
1632 Expected
<size_t> MatchResult
= Pat
.match(MatchBuffer
, MatchLen
, SM
);
1633 // With a group of CHECK-DAGs, a single mismatching means the match on
1634 // that group of CHECK-DAGs fails immediately.
1636 PrintNoMatch(true, SM
, Prefix
, Pat
.getLoc(), Pat
, 1, MatchBuffer
,
1637 Req
.VerboseVerbose
, Diags
, MatchResult
.takeError());
1638 return StringRef::npos
;
1640 size_t MatchPosBuf
= *MatchResult
;
1641 // Re-calc it as the offset relative to the start of the original string.
1642 MatchPos
+= MatchPosBuf
;
1643 if (Req
.VerboseVerbose
)
1644 PrintMatch(true, SM
, Prefix
, Pat
.getLoc(), Pat
, 1, Buffer
, MatchPos
,
1645 MatchLen
, Req
, Diags
);
1646 MatchRange M
{MatchPos
, MatchPos
+ MatchLen
};
1647 if (Req
.AllowDeprecatedDagOverlap
) {
1648 // We don't need to track all matches in this mode, so we just maintain
1649 // one match range that encompasses the current CHECK-DAG group's
1651 if (MatchRanges
.empty())
1652 MatchRanges
.insert(MatchRanges
.end(), M
);
1654 auto Block
= MatchRanges
.begin();
1655 Block
->Pos
= std::min(Block
->Pos
, M
.Pos
);
1656 Block
->End
= std::max(Block
->End
, M
.End
);
1660 // Iterate previous matches until overlapping match or insertion point.
1661 bool Overlap
= false;
1662 for (; MI
!= ME
; ++MI
) {
1663 if (M
.Pos
< MI
->End
) {
1664 // !Overlap => New match has no overlap and is before this old match.
1665 // Overlap => New match overlaps this old match.
1666 Overlap
= MI
->Pos
< M
.End
;
1671 // Insert non-overlapping match into list.
1672 MatchRanges
.insert(MI
, M
);
1675 if (Req
.VerboseVerbose
) {
1676 // Due to their verbosity, we don't print verbose diagnostics here if
1677 // we're gathering them for a different rendering, but we always print
1678 // other diagnostics.
1680 SMLoc OldStart
= SMLoc::getFromPointer(Buffer
.data() + MI
->Pos
);
1681 SMLoc OldEnd
= SMLoc::getFromPointer(Buffer
.data() + MI
->End
);
1682 SMRange
OldRange(OldStart
, OldEnd
);
1683 SM
.PrintMessage(OldStart
, SourceMgr::DK_Note
,
1684 "match discarded, overlaps earlier DAG match here",
1687 Diags
->rbegin()->MatchTy
= FileCheckDiag::MatchFoundButDiscarded
;
1691 if (!Req
.VerboseVerbose
)
1692 PrintMatch(true, SM
, Prefix
, Pat
.getLoc(), Pat
, 1, Buffer
, MatchPos
,
1693 MatchLen
, Req
, Diags
);
1695 // Handle the end of a CHECK-DAG group.
1696 if (std::next(PatItr
) == PatEnd
||
1697 std::next(PatItr
)->getCheckTy() == Check::CheckNot
) {
1698 if (!NotStrings
.empty()) {
1699 // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
1700 // CHECK-DAG, verify that there are no 'not' strings occurred in that
1702 StringRef SkippedRegion
=
1703 Buffer
.slice(StartPos
, MatchRanges
.begin()->Pos
);
1704 if (CheckNot(SM
, SkippedRegion
, NotStrings
, Req
, Diags
))
1705 return StringRef::npos
;
1706 // Clear "not strings".
1709 // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
1710 // end of this CHECK-DAG group's match range.
1711 StartPos
= MatchRanges
.rbegin()->End
;
1712 // Don't waste time checking for (impossible) overlaps before that.
1713 MatchRanges
.clear();
1720 // A check prefix must contain only alphanumeric, hyphens and underscores.
1721 static bool ValidateCheckPrefix(StringRef CheckPrefix
) {
1722 static const Regex
Validator("^[a-zA-Z0-9_-]*$");
1723 return Validator
.match(CheckPrefix
);
1726 bool FileCheck::ValidateCheckPrefixes() {
1727 StringSet
<> PrefixSet
;
1729 for (StringRef Prefix
: Req
.CheckPrefixes
) {
1730 // Reject empty prefixes.
1734 if (!PrefixSet
.insert(Prefix
).second
)
1737 if (!ValidateCheckPrefix(Prefix
))
1744 Regex
FileCheck::buildCheckPrefixRegex() {
1745 // I don't think there's a way to specify an initial value for cl::list,
1746 // so if nothing was specified, add the default
1747 if (Req
.CheckPrefixes
.empty())
1748 Req
.CheckPrefixes
.push_back("CHECK");
1750 // We already validated the contents of CheckPrefixes so just concatenate
1751 // them as alternatives.
1752 SmallString
<32> PrefixRegexStr
;
1753 for (StringRef Prefix
: Req
.CheckPrefixes
) {
1754 if (Prefix
!= Req
.CheckPrefixes
.front())
1755 PrefixRegexStr
.push_back('|');
1757 PrefixRegexStr
.append(Prefix
);
1760 return Regex(PrefixRegexStr
);
1763 Error
FileCheckPatternContext::defineCmdlineVariables(
1764 std::vector
<std::string
> &CmdlineDefines
, SourceMgr
&SM
) {
1765 assert(GlobalVariableTable
.empty() && GlobalNumericVariableTable
.empty() &&
1766 "Overriding defined variable with command-line variable definitions");
1768 if (CmdlineDefines
.empty())
1769 return Error::success();
1771 // Create a string representing the vector of command-line definitions. Each
1772 // definition is on its own line and prefixed with a definition number to
1773 // clarify which definition a given diagnostic corresponds to.
1775 Error Errs
= Error::success();
1776 std::string CmdlineDefsDiag
;
1777 SmallVector
<std::pair
<size_t, size_t>, 4> CmdlineDefsIndices
;
1778 for (StringRef CmdlineDef
: CmdlineDefines
) {
1779 std::string DefPrefix
= ("Global define #" + Twine(++I
) + ": ").str();
1780 size_t EqIdx
= CmdlineDef
.find('=');
1781 if (EqIdx
== StringRef::npos
) {
1782 CmdlineDefsIndices
.push_back(std::make_pair(CmdlineDefsDiag
.size(), 0));
1785 // Numeric variable definition.
1786 if (CmdlineDef
[0] == '#') {
1787 // Append a copy of the command-line definition adapted to use the same
1788 // format as in the input file to be able to reuse
1789 // parseNumericSubstitutionBlock.
1790 CmdlineDefsDiag
+= (DefPrefix
+ CmdlineDef
+ " (parsed as: [[").str();
1791 std::string SubstitutionStr
= CmdlineDef
;
1792 SubstitutionStr
[EqIdx
] = ':';
1793 CmdlineDefsIndices
.push_back(
1794 std::make_pair(CmdlineDefsDiag
.size(), SubstitutionStr
.size()));
1795 CmdlineDefsDiag
+= (SubstitutionStr
+ Twine("]])\n")).str();
1797 CmdlineDefsDiag
+= DefPrefix
;
1798 CmdlineDefsIndices
.push_back(
1799 std::make_pair(CmdlineDefsDiag
.size(), CmdlineDef
.size()));
1800 CmdlineDefsDiag
+= (CmdlineDef
+ "\n").str();
1804 // Create a buffer with fake command line content in order to display
1805 // parsing diagnostic with location information and point to the
1806 // global definition with invalid syntax.
1807 std::unique_ptr
<MemoryBuffer
> CmdLineDefsDiagBuffer
=
1808 MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag
, "Global defines");
1809 StringRef CmdlineDefsDiagRef
= CmdLineDefsDiagBuffer
->getBuffer();
1810 SM
.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer
), SMLoc());
1812 for (std::pair
<size_t, size_t> CmdlineDefIndices
: CmdlineDefsIndices
) {
1813 StringRef CmdlineDef
= CmdlineDefsDiagRef
.substr(CmdlineDefIndices
.first
,
1814 CmdlineDefIndices
.second
);
1815 if (CmdlineDef
.empty()) {
1818 FileCheckErrorDiagnostic::get(
1819 SM
, CmdlineDef
, "missing equal sign in global definition"));
1823 // Numeric variable definition.
1824 if (CmdlineDef
[0] == '#') {
1825 // Now parse the definition both to check that the syntax is correct and
1826 // to create the necessary class instance.
1827 StringRef CmdlineDefExpr
= CmdlineDef
.substr(1);
1828 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
1829 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> ExpressionASTResult
=
1830 FileCheckPattern::parseNumericSubstitutionBlock(
1831 CmdlineDefExpr
, DefinedNumericVariable
, false, None
, this, SM
);
1832 if (!ExpressionASTResult
) {
1833 Errs
= joinErrors(std::move(Errs
), ExpressionASTResult
.takeError());
1836 std::unique_ptr
<FileCheckExpressionAST
> ExpressionAST
=
1837 std::move(*ExpressionASTResult
);
1838 // Now evaluate the expression whose value this variable should be set
1839 // to, since the expression of a command-line variable definition should
1840 // only use variables defined earlier on the command-line. If not, this
1841 // is an error and we report it.
1842 Expected
<uint64_t> Value
= ExpressionAST
->eval();
1844 Errs
= joinErrors(std::move(Errs
), Value
.takeError());
1848 assert(DefinedNumericVariable
&& "No variable defined");
1849 (*DefinedNumericVariable
)->setValue(*Value
);
1851 // Record this variable definition.
1852 GlobalNumericVariableTable
[(*DefinedNumericVariable
)->getName()] =
1853 *DefinedNumericVariable
;
1855 // String variable definition.
1856 std::pair
<StringRef
, StringRef
> CmdlineNameVal
= CmdlineDef
.split('=');
1857 StringRef CmdlineName
= CmdlineNameVal
.first
;
1858 StringRef OrigCmdlineName
= CmdlineName
;
1859 Expected
<FileCheckPattern::VariableProperties
> ParseVarResult
=
1860 FileCheckPattern::parseVariable(CmdlineName
, SM
);
1861 if (!ParseVarResult
) {
1862 Errs
= joinErrors(std::move(Errs
), ParseVarResult
.takeError());
1865 // Check that CmdlineName does not denote a pseudo variable is only
1866 // composed of the parsed numeric variable. This catches cases like
1867 // "FOO+2" in a "FOO+2=10" definition.
1868 if (ParseVarResult
->IsPseudo
|| !CmdlineName
.empty()) {
1869 Errs
= joinErrors(std::move(Errs
),
1870 FileCheckErrorDiagnostic::get(
1871 SM
, OrigCmdlineName
,
1872 "invalid name in string variable definition '" +
1873 OrigCmdlineName
+ "'"));
1876 StringRef Name
= ParseVarResult
->Name
;
1878 // Detect collisions between string and numeric variables when the former
1879 // is created later than the latter.
1880 if (GlobalNumericVariableTable
.find(Name
) !=
1881 GlobalNumericVariableTable
.end()) {
1882 Errs
= joinErrors(std::move(Errs
), FileCheckErrorDiagnostic::get(
1884 "numeric variable with name '" +
1885 Name
+ "' already exists"));
1888 GlobalVariableTable
.insert(CmdlineNameVal
);
1889 // Mark the string variable as defined to detect collisions between
1890 // string and numeric variables in defineCmdlineVariables when the latter
1891 // is created later than the former. We cannot reuse GlobalVariableTable
1892 // for this by populating it with an empty string since we would then
1893 // lose the ability to detect the use of an undefined variable in
1895 DefinedVariableTable
[Name
] = true;
1902 void FileCheckPatternContext::clearLocalVars() {
1903 SmallVector
<StringRef
, 16> LocalPatternVars
, LocalNumericVars
;
1904 for (const StringMapEntry
<StringRef
> &Var
: GlobalVariableTable
)
1905 if (Var
.first()[0] != '$')
1906 LocalPatternVars
.push_back(Var
.first());
1908 // Numeric substitution reads the value of a variable directly, not via
1909 // GlobalNumericVariableTable. Therefore, we clear local variables by
1910 // clearing their value which will lead to a numeric substitution failure. We
1911 // also mark the variable for removal from GlobalNumericVariableTable since
1912 // this is what defineCmdlineVariables checks to decide that no global
1913 // variable has been defined.
1914 for (const auto &Var
: GlobalNumericVariableTable
)
1915 if (Var
.first()[0] != '$') {
1916 Var
.getValue()->clearValue();
1917 LocalNumericVars
.push_back(Var
.first());
1920 for (const auto &Var
: LocalPatternVars
)
1921 GlobalVariableTable
.erase(Var
);
1922 for (const auto &Var
: LocalNumericVars
)
1923 GlobalNumericVariableTable
.erase(Var
);
1926 bool FileCheck::checkInput(SourceMgr
&SM
, StringRef Buffer
,
1927 std::vector
<FileCheckDiag
> *Diags
) {
1928 bool ChecksFailed
= false;
1930 unsigned i
= 0, j
= 0, e
= CheckStrings
->size();
1932 StringRef CheckRegion
;
1934 CheckRegion
= Buffer
;
1936 const FileCheckString
&CheckLabelStr
= (*CheckStrings
)[j
];
1937 if (CheckLabelStr
.Pat
.getCheckTy() != Check::CheckLabel
) {
1942 // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
1943 size_t MatchLabelLen
= 0;
1944 size_t MatchLabelPos
=
1945 CheckLabelStr
.Check(SM
, Buffer
, true, MatchLabelLen
, Req
, Diags
);
1946 if (MatchLabelPos
== StringRef::npos
)
1947 // Immediately bail if CHECK-LABEL fails, nothing else we can do.
1950 CheckRegion
= Buffer
.substr(0, MatchLabelPos
+ MatchLabelLen
);
1951 Buffer
= Buffer
.substr(MatchLabelPos
+ MatchLabelLen
);
1955 // Do not clear the first region as it's the one before the first
1956 // CHECK-LABEL and it would clear variables defined on the command-line
1957 // before they get used.
1958 if (i
!= 0 && Req
.EnableVarScope
)
1959 PatternContext
->clearLocalVars();
1961 for (; i
!= j
; ++i
) {
1962 const FileCheckString
&CheckStr
= (*CheckStrings
)[i
];
1964 // Check each string within the scanned region, including a second check
1965 // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
1966 size_t MatchLen
= 0;
1968 CheckStr
.Check(SM
, CheckRegion
, false, MatchLen
, Req
, Diags
);
1970 if (MatchPos
== StringRef::npos
) {
1971 ChecksFailed
= true;
1976 CheckRegion
= CheckRegion
.substr(MatchPos
+ MatchLen
);
1983 // Success if no checks failed.
1984 return !ChecksFailed
;