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
;
323 IgnoreCase
= Req
.IgnoreCase
;
325 PatternLoc
= SMLoc::getFromPointer(PatternStr
.data());
327 if (!(Req
.NoCanonicalizeWhiteSpace
&& Req
.MatchFullLines
))
328 // Ignore trailing whitespace.
329 while (!PatternStr
.empty() &&
330 (PatternStr
.back() == ' ' || PatternStr
.back() == '\t'))
331 PatternStr
= PatternStr
.substr(0, PatternStr
.size() - 1);
333 // Check that there is something on the line.
334 if (PatternStr
.empty() && CheckTy
!= Check::CheckEmpty
) {
335 SM
.PrintMessage(PatternLoc
, SourceMgr::DK_Error
,
336 "found empty check string with prefix '" + Prefix
+ ":'");
340 if (!PatternStr
.empty() && CheckTy
== Check::CheckEmpty
) {
342 PatternLoc
, SourceMgr::DK_Error
,
343 "found non-empty check string for empty check with prefix '" + Prefix
+
348 if (CheckTy
== Check::CheckEmpty
) {
353 // Check to see if this is a fixed string, or if it has regex pieces.
354 if (!MatchFullLinesHere
&&
355 (PatternStr
.size() < 2 || (PatternStr
.find("{{") == StringRef::npos
&&
356 PatternStr
.find("[[") == StringRef::npos
))) {
357 FixedStr
= PatternStr
;
361 if (MatchFullLinesHere
) {
363 if (!Req
.NoCanonicalizeWhiteSpace
)
367 // Paren value #0 is for the fully matched string. Any new parenthesized
368 // values add from there.
369 unsigned CurParen
= 1;
371 // Otherwise, there is at least one regex piece. Build up the regex pattern
372 // by escaping scary characters in fixed strings, building up one big regex.
373 while (!PatternStr
.empty()) {
375 if (PatternStr
.startswith("{{")) {
376 // This is the start of a regex match. Scan for the }}.
377 size_t End
= PatternStr
.find("}}");
378 if (End
== StringRef::npos
) {
379 SM
.PrintMessage(SMLoc::getFromPointer(PatternStr
.data()),
381 "found start of regex string with no end '}}'");
385 // Enclose {{}} patterns in parens just like [[]] even though we're not
386 // capturing the result for any purpose. This is required in case the
387 // expression contains an alternation like: CHECK: abc{{x|z}}def. We
388 // want this to turn into: "abc(x|z)def" not "abcx|zdef".
392 if (AddRegExToRegEx(PatternStr
.substr(2, End
- 2), CurParen
, SM
))
396 PatternStr
= PatternStr
.substr(End
+ 2);
400 // String and numeric substitution blocks. Pattern substitution blocks come
401 // in two forms: [[foo:.*]] and [[foo]]. The former matches .* (or some
402 // other regex) and assigns it to the string variable 'foo'. The latter
403 // substitutes foo's value. Numeric substitution blocks recognize the same
404 // form as string ones, but start with a '#' sign after the double
405 // brackets. They also accept a combined form which sets a numeric variable
406 // to the evaluation of an expression. Both string and numeric variable
407 // names must satisfy the regular expression "[a-zA-Z_][0-9a-zA-Z_]*" to be
408 // valid, as this helps catch some common errors.
409 if (PatternStr
.startswith("[[")) {
410 StringRef UnparsedPatternStr
= PatternStr
.substr(2);
411 // Find the closing bracket pair ending the match. End is going to be an
412 // offset relative to the beginning of the match string.
413 size_t End
= FindRegexVarEnd(UnparsedPatternStr
, SM
);
414 StringRef MatchStr
= UnparsedPatternStr
.substr(0, End
);
415 bool IsNumBlock
= MatchStr
.consume_front("#");
417 if (End
== StringRef::npos
) {
418 SM
.PrintMessage(SMLoc::getFromPointer(PatternStr
.data()),
420 "Invalid substitution block, no ]] found");
423 // Strip the substitution block we are parsing. End points to the start
424 // of the "]]" closing the expression so account for it in computing the
425 // index of the first unparsed character.
426 PatternStr
= UnparsedPatternStr
.substr(End
+ 2);
428 bool IsDefinition
= false;
429 bool SubstNeeded
= false;
430 // Whether the substitution block is a legacy use of @LINE with string
431 // substitution block syntax.
432 bool IsLegacyLineExpr
= false;
435 StringRef MatchRegexp
;
436 size_t SubstInsertIdx
= RegExStr
.size();
438 // Parse string variable or legacy @LINE expression.
440 size_t VarEndIdx
= MatchStr
.find(":");
441 size_t SpacePos
= MatchStr
.substr(0, VarEndIdx
).find_first_of(" \t");
442 if (SpacePos
!= StringRef::npos
) {
443 SM
.PrintMessage(SMLoc::getFromPointer(MatchStr
.data() + SpacePos
),
444 SourceMgr::DK_Error
, "unexpected whitespace");
448 // Get the name (e.g. "foo") and verify it is well formed.
449 StringRef OrigMatchStr
= MatchStr
;
450 Expected
<FileCheckPattern::VariableProperties
> ParseVarResult
=
451 parseVariable(MatchStr
, SM
);
452 if (!ParseVarResult
) {
453 logAllUnhandledErrors(ParseVarResult
.takeError(), errs());
456 StringRef Name
= ParseVarResult
->Name
;
457 bool IsPseudo
= ParseVarResult
->IsPseudo
;
459 IsDefinition
= (VarEndIdx
!= StringRef::npos
);
460 SubstNeeded
= !IsDefinition
;
462 if ((IsPseudo
|| !MatchStr
.consume_front(":"))) {
463 SM
.PrintMessage(SMLoc::getFromPointer(Name
.data()),
465 "invalid name in string variable definition");
469 // Detect collisions between string and numeric variables when the
470 // former is created later than the latter.
471 if (Context
->GlobalNumericVariableTable
.find(Name
) !=
472 Context
->GlobalNumericVariableTable
.end()) {
474 SMLoc::getFromPointer(Name
.data()), SourceMgr::DK_Error
,
475 "numeric variable with name '" + Name
+ "' already exists");
479 MatchRegexp
= MatchStr
;
482 MatchStr
= OrigMatchStr
;
483 IsLegacyLineExpr
= IsNumBlock
= true;
489 // Parse numeric substitution block.
490 std::unique_ptr
<FileCheckExpressionAST
> ExpressionAST
;
491 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
493 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> ParseResult
=
494 parseNumericSubstitutionBlock(MatchStr
, DefinedNumericVariable
,
495 IsLegacyLineExpr
, LineNumber
, Context
,
498 logAllUnhandledErrors(ParseResult
.takeError(), errs());
501 ExpressionAST
= std::move(*ParseResult
);
502 SubstNeeded
= ExpressionAST
!= nullptr;
503 if (DefinedNumericVariable
) {
505 DefName
= (*DefinedNumericVariable
)->getName();
510 MatchRegexp
= "[0-9]+";
513 // Handle variable definition: [[<def>:(...)]] and [[#(...)<def>:(...)]].
519 FileCheckNumericVariableMatch NumericVariableDefinition
= {
520 *DefinedNumericVariable
, CurParen
};
521 NumericVariableDefs
[DefName
] = NumericVariableDefinition
;
522 // This store is done here rather than in match() to allow
523 // parseNumericVariableUse() to get the pointer to the class instance
524 // of the right variable definition corresponding to a given numeric
526 Context
->GlobalNumericVariableTable
[DefName
] =
527 *DefinedNumericVariable
;
529 VariableDefs
[DefName
] = CurParen
;
530 // Mark string variable as defined to detect collisions between
531 // string and numeric variables in parseNumericVariableUse() and
532 // defineCmdlineVariables() when the latter is created later than the
533 // former. We cannot reuse GlobalVariableTable for this by populating
534 // it with an empty string since we would then lose the ability to
535 // detect the use of an undefined variable in match().
536 Context
->DefinedVariableTable
[DefName
] = true;
542 if (!MatchRegexp
.empty() && AddRegExToRegEx(MatchRegexp
, CurParen
, SM
))
548 // Handle substitutions: [[foo]] and [[#<foo expr>]].
550 // Handle substitution of string variables that were defined earlier on
551 // the same line by emitting a backreference. Expressions do not
552 // support substituting a numeric variable defined on the same line.
553 if (!IsNumBlock
&& VariableDefs
.find(SubstStr
) != VariableDefs
.end()) {
554 unsigned CaptureParenGroup
= VariableDefs
[SubstStr
];
555 if (CaptureParenGroup
< 1 || CaptureParenGroup
> 9) {
556 SM
.PrintMessage(SMLoc::getFromPointer(SubstStr
.data()),
558 "Can't back-reference more than 9 variables");
561 AddBackrefToRegEx(CaptureParenGroup
);
563 // Handle substitution of string variables ([[<var>]]) defined in
564 // previous CHECK patterns, and substitution of expressions.
565 FileCheckSubstitution
*Substitution
=
567 ? Context
->makeNumericSubstitution(
568 SubstStr
, std::move(ExpressionAST
), SubstInsertIdx
)
569 : Context
->makeStringSubstitution(SubstStr
, SubstInsertIdx
);
570 Substitutions
.push_back(Substitution
);
575 // Handle fixed string matches.
576 // Find the end, which is the start of the next regex.
577 size_t FixedMatchEnd
= PatternStr
.find("{{");
578 FixedMatchEnd
= std::min(FixedMatchEnd
, PatternStr
.find("[["));
579 RegExStr
+= Regex::escape(PatternStr
.substr(0, FixedMatchEnd
));
580 PatternStr
= PatternStr
.substr(FixedMatchEnd
);
583 if (MatchFullLinesHere
) {
584 if (!Req
.NoCanonicalizeWhiteSpace
)
592 bool FileCheckPattern::AddRegExToRegEx(StringRef RS
, unsigned &CurParen
, SourceMgr
&SM
) {
595 if (!R
.isValid(Error
)) {
596 SM
.PrintMessage(SMLoc::getFromPointer(RS
.data()), SourceMgr::DK_Error
,
597 "invalid regex: " + Error
);
601 RegExStr
+= RS
.str();
602 CurParen
+= R
.getNumMatches();
606 void FileCheckPattern::AddBackrefToRegEx(unsigned BackrefNum
) {
607 assert(BackrefNum
>= 1 && BackrefNum
<= 9 && "Invalid backref number");
608 std::string Backref
= std::string("\\") + std::string(1, '0' + BackrefNum
);
612 Expected
<size_t> FileCheckPattern::match(StringRef Buffer
, size_t &MatchLen
,
613 const SourceMgr
&SM
) const {
614 // If this is the EOF pattern, match it immediately.
615 if (CheckTy
== Check::CheckEOF
) {
617 return Buffer
.size();
620 // If this is a fixed string pattern, just match it now.
621 if (!FixedStr
.empty()) {
622 MatchLen
= FixedStr
.size();
623 size_t Pos
= IgnoreCase
? Buffer
.find_lower(FixedStr
)
624 : Buffer
.find(FixedStr
);
625 if (Pos
== StringRef::npos
)
626 return make_error
<FileCheckNotFoundError
>();
632 // If there are substitutions, we need to create a temporary string with the
634 StringRef RegExToMatch
= RegExStr
;
636 if (!Substitutions
.empty()) {
639 Context
->LineVariable
->setValue(*LineNumber
);
641 size_t InsertOffset
= 0;
642 // Substitute all string variables and expressions whose values are only
643 // now known. Use of string variables defined on the same line are handled
644 // by back-references.
645 for (const auto &Substitution
: Substitutions
) {
646 // Substitute and check for failure (e.g. use of undefined variable).
647 Expected
<std::string
> Value
= Substitution
->getResult();
649 return Value
.takeError();
651 // Plop it into the regex at the adjusted offset.
652 TmpStr
.insert(TmpStr
.begin() + Substitution
->getIndex() + InsertOffset
,
653 Value
->begin(), Value
->end());
654 InsertOffset
+= Value
->size();
657 // Match the newly constructed regex.
658 RegExToMatch
= TmpStr
;
661 SmallVector
<StringRef
, 4> MatchInfo
;
662 unsigned int Flags
= Regex::Newline
;
664 Flags
|= Regex::IgnoreCase
;
665 if (!Regex(RegExToMatch
, Flags
).match(Buffer
, &MatchInfo
))
666 return make_error
<FileCheckNotFoundError
>();
668 // Successful regex match.
669 assert(!MatchInfo
.empty() && "Didn't get any match");
670 StringRef FullMatch
= MatchInfo
[0];
672 // If this defines any string variables, remember their values.
673 for (const auto &VariableDef
: VariableDefs
) {
674 assert(VariableDef
.second
< MatchInfo
.size() && "Internal paren error");
675 Context
->GlobalVariableTable
[VariableDef
.first
] =
676 MatchInfo
[VariableDef
.second
];
679 // If this defines any numeric variables, remember their values.
680 for (const auto &NumericVariableDef
: NumericVariableDefs
) {
681 const FileCheckNumericVariableMatch
&NumericVariableMatch
=
682 NumericVariableDef
.getValue();
683 unsigned CaptureParenGroup
= NumericVariableMatch
.CaptureParenGroup
;
684 assert(CaptureParenGroup
< MatchInfo
.size() && "Internal paren error");
685 FileCheckNumericVariable
*DefinedNumericVariable
=
686 NumericVariableMatch
.DefinedNumericVariable
;
688 StringRef MatchedValue
= MatchInfo
[CaptureParenGroup
];
690 if (MatchedValue
.getAsInteger(10, Val
))
691 return FileCheckErrorDiagnostic::get(SM
, MatchedValue
,
692 "Unable to represent numeric value");
693 DefinedNumericVariable
->setValue(Val
);
696 // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
697 // the required preceding newline, which is consumed by the pattern in the
698 // case of CHECK-EMPTY but not CHECK-NEXT.
699 size_t MatchStartSkip
= CheckTy
== Check::CheckEmpty
;
700 MatchLen
= FullMatch
.size() - MatchStartSkip
;
701 return FullMatch
.data() - Buffer
.data() + MatchStartSkip
;
704 unsigned FileCheckPattern::computeMatchDistance(StringRef Buffer
) const {
705 // Just compute the number of matching characters. For regular expressions, we
706 // just compare against the regex itself and hope for the best.
708 // FIXME: One easy improvement here is have the regex lib generate a single
709 // example regular expression which matches, and use that as the example
711 StringRef
ExampleString(FixedStr
);
712 if (ExampleString
.empty())
713 ExampleString
= RegExStr
;
715 // Only compare up to the first line in the buffer, or the string size.
716 StringRef BufferPrefix
= Buffer
.substr(0, ExampleString
.size());
717 BufferPrefix
= BufferPrefix
.split('\n').first
;
718 return BufferPrefix
.edit_distance(ExampleString
);
721 void FileCheckPattern::printSubstitutions(const SourceMgr
&SM
, StringRef Buffer
,
722 SMRange MatchRange
) const {
723 // Print what we know about substitutions.
724 if (!Substitutions
.empty()) {
725 for (const auto &Substitution
: Substitutions
) {
726 SmallString
<256> Msg
;
727 raw_svector_ostream
OS(Msg
);
728 Expected
<std::string
> MatchedValue
= Substitution
->getResult();
730 // Substitution failed or is not known at match time, print the undefined
731 // variables it uses.
733 bool UndefSeen
= false;
734 handleAllErrors(MatchedValue
.takeError(),
735 [](const FileCheckNotFoundError
&E
) {},
736 // Handled in PrintNoMatch().
737 [](const FileCheckErrorDiagnostic
&E
) {},
738 [&](const FileCheckUndefVarError
&E
) {
740 OS
<< "uses undefined variable(s):";
747 // Substitution succeeded. Print substituted value.
749 OS
.write_escaped(Substitution
->getFromString()) << "\" equal to \"";
750 OS
.write_escaped(*MatchedValue
) << "\"";
753 if (MatchRange
.isValid())
754 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
, OS
.str(),
757 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()),
758 SourceMgr::DK_Note
, OS
.str());
763 static SMRange
ProcessMatchResult(FileCheckDiag::MatchType MatchTy
,
764 const SourceMgr
&SM
, SMLoc Loc
,
765 Check::FileCheckType CheckTy
,
766 StringRef Buffer
, size_t Pos
, size_t Len
,
767 std::vector
<FileCheckDiag
> *Diags
,
768 bool AdjustPrevDiag
= false) {
769 SMLoc Start
= SMLoc::getFromPointer(Buffer
.data() + Pos
);
770 SMLoc End
= SMLoc::getFromPointer(Buffer
.data() + Pos
+ Len
);
771 SMRange
Range(Start
, End
);
774 Diags
->rbegin()->MatchTy
= MatchTy
;
776 Diags
->emplace_back(SM
, CheckTy
, Loc
, MatchTy
, Range
);
781 void FileCheckPattern::printFuzzyMatch(
782 const SourceMgr
&SM
, StringRef Buffer
,
783 std::vector
<FileCheckDiag
> *Diags
) const {
784 // Attempt to find the closest/best fuzzy match. Usually an error happens
785 // because some string in the output didn't exactly match. In these cases, we
786 // would like to show the user a best guess at what "should have" matched, to
787 // save them having to actually check the input manually.
788 size_t NumLinesForward
= 0;
789 size_t Best
= StringRef::npos
;
790 double BestQuality
= 0;
792 // Use an arbitrary 4k limit on how far we will search.
793 for (size_t i
= 0, e
= std::min(size_t(4096), Buffer
.size()); i
!= e
; ++i
) {
794 if (Buffer
[i
] == '\n')
797 // Patterns have leading whitespace stripped, so skip whitespace when
798 // looking for something which looks like a pattern.
799 if (Buffer
[i
] == ' ' || Buffer
[i
] == '\t')
802 // Compute the "quality" of this match as an arbitrary combination of the
803 // match distance and the number of lines skipped to get to this match.
804 unsigned Distance
= computeMatchDistance(Buffer
.substr(i
));
805 double Quality
= Distance
+ (NumLinesForward
/ 100.);
807 if (Quality
< BestQuality
|| Best
== StringRef::npos
) {
809 BestQuality
= Quality
;
813 // Print the "possible intended match here" line if we found something
814 // reasonable and not equal to what we showed in the "scanning from here"
816 if (Best
&& Best
!= StringRef::npos
&& BestQuality
< 50) {
818 ProcessMatchResult(FileCheckDiag::MatchFuzzy
, SM
, getLoc(),
819 getCheckTy(), Buffer
, Best
, 0, Diags
);
820 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
,
821 "possible intended match here");
823 // FIXME: If we wanted to be really friendly we would show why the match
824 // failed, as it can be hard to spot simple one character differences.
829 FileCheckPatternContext::getPatternVarValue(StringRef VarName
) {
830 auto VarIter
= GlobalVariableTable
.find(VarName
);
831 if (VarIter
== GlobalVariableTable
.end())
832 return make_error
<FileCheckUndefVarError
>(VarName
);
834 return VarIter
->second
;
837 template <class... Types
>
838 FileCheckNumericVariable
*
839 FileCheckPatternContext::makeNumericVariable(Types
... args
) {
840 NumericVariables
.push_back(
841 std::make_unique
<FileCheckNumericVariable
>(args
...));
842 return NumericVariables
.back().get();
845 FileCheckSubstitution
*
846 FileCheckPatternContext::makeStringSubstitution(StringRef VarName
,
848 Substitutions
.push_back(
849 std::make_unique
<FileCheckStringSubstitution
>(this, VarName
, InsertIdx
));
850 return Substitutions
.back().get();
853 FileCheckSubstitution
*FileCheckPatternContext::makeNumericSubstitution(
854 StringRef ExpressionStr
,
855 std::unique_ptr
<FileCheckExpressionAST
> ExpressionAST
, size_t InsertIdx
) {
856 Substitutions
.push_back(std::make_unique
<FileCheckNumericSubstitution
>(
857 this, ExpressionStr
, std::move(ExpressionAST
), InsertIdx
));
858 return Substitutions
.back().get();
861 size_t FileCheckPattern::FindRegexVarEnd(StringRef Str
, SourceMgr
&SM
) {
862 // Offset keeps track of the current offset within the input Str
864 // [...] Nesting depth
865 size_t BracketDepth
= 0;
867 while (!Str
.empty()) {
868 if (Str
.startswith("]]") && BracketDepth
== 0)
870 if (Str
[0] == '\\') {
871 // Backslash escapes the next char within regexes, so skip them both.
882 if (BracketDepth
== 0) {
883 SM
.PrintMessage(SMLoc::getFromPointer(Str
.data()),
885 "missing closing \"]\" for regex variable");
896 return StringRef::npos
;
899 StringRef
FileCheck::CanonicalizeFile(MemoryBuffer
&MB
,
900 SmallVectorImpl
<char> &OutputBuffer
) {
901 OutputBuffer
.reserve(MB
.getBufferSize());
903 for (const char *Ptr
= MB
.getBufferStart(), *End
= MB
.getBufferEnd();
905 // Eliminate trailing dosish \r.
906 if (Ptr
<= End
- 2 && Ptr
[0] == '\r' && Ptr
[1] == '\n') {
910 // If current char is not a horizontal whitespace or if horizontal
911 // whitespace canonicalization is disabled, dump it to output as is.
912 if (Req
.NoCanonicalizeWhiteSpace
|| (*Ptr
!= ' ' && *Ptr
!= '\t')) {
913 OutputBuffer
.push_back(*Ptr
);
917 // Otherwise, add one space and advance over neighboring space.
918 OutputBuffer
.push_back(' ');
919 while (Ptr
+ 1 != End
&& (Ptr
[1] == ' ' || Ptr
[1] == '\t'))
923 // Add a null byte and then return all but that byte.
924 OutputBuffer
.push_back('\0');
925 return StringRef(OutputBuffer
.data(), OutputBuffer
.size() - 1);
928 FileCheckDiag::FileCheckDiag(const SourceMgr
&SM
,
929 const Check::FileCheckType
&CheckTy
,
930 SMLoc CheckLoc
, MatchType MatchTy
,
932 : CheckTy(CheckTy
), MatchTy(MatchTy
) {
933 auto Start
= SM
.getLineAndColumn(InputRange
.Start
);
934 auto End
= SM
.getLineAndColumn(InputRange
.End
);
935 InputStartLine
= Start
.first
;
936 InputStartCol
= Start
.second
;
937 InputEndLine
= End
.first
;
938 InputEndCol
= End
.second
;
939 Start
= SM
.getLineAndColumn(CheckLoc
);
940 CheckLine
= Start
.first
;
941 CheckCol
= Start
.second
;
944 static bool IsPartOfWord(char c
) {
945 return (isalnum(c
) || c
== '-' || c
== '_');
948 Check::FileCheckType
&Check::FileCheckType::setCount(int C
) {
949 assert(Count
> 0 && "zero and negative counts are not supported");
950 assert((C
== 1 || Kind
== CheckPlain
) &&
951 "count supported only for plain CHECK directives");
956 std::string
Check::FileCheckType::getDescription(StringRef Prefix
) const {
958 case Check::CheckNone
:
960 case Check::CheckPlain
:
962 return Prefix
.str() + "-COUNT";
964 case Check::CheckNext
:
965 return Prefix
.str() + "-NEXT";
966 case Check::CheckSame
:
967 return Prefix
.str() + "-SAME";
968 case Check::CheckNot
:
969 return Prefix
.str() + "-NOT";
970 case Check::CheckDAG
:
971 return Prefix
.str() + "-DAG";
972 case Check::CheckLabel
:
973 return Prefix
.str() + "-LABEL";
974 case Check::CheckEmpty
:
975 return Prefix
.str() + "-EMPTY";
976 case Check::CheckEOF
:
977 return "implicit EOF";
978 case Check::CheckBadNot
:
980 case Check::CheckBadCount
:
983 llvm_unreachable("unknown FileCheckType");
986 static std::pair
<Check::FileCheckType
, StringRef
>
987 FindCheckType(StringRef Buffer
, StringRef Prefix
) {
988 if (Buffer
.size() <= Prefix
.size())
989 return {Check::CheckNone
, StringRef()};
991 char NextChar
= Buffer
[Prefix
.size()];
993 StringRef Rest
= Buffer
.drop_front(Prefix
.size() + 1);
994 // Verify that the : is present after the prefix.
996 return {Check::CheckPlain
, Rest
};
999 return {Check::CheckNone
, StringRef()};
1001 if (Rest
.consume_front("COUNT-")) {
1003 if (Rest
.consumeInteger(10, Count
))
1004 // Error happened in parsing integer.
1005 return {Check::CheckBadCount
, Rest
};
1006 if (Count
<= 0 || Count
> INT32_MAX
)
1007 return {Check::CheckBadCount
, Rest
};
1008 if (!Rest
.consume_front(":"))
1009 return {Check::CheckBadCount
, Rest
};
1010 return {Check::FileCheckType(Check::CheckPlain
).setCount(Count
), Rest
};
1013 if (Rest
.consume_front("NEXT:"))
1014 return {Check::CheckNext
, Rest
};
1016 if (Rest
.consume_front("SAME:"))
1017 return {Check::CheckSame
, Rest
};
1019 if (Rest
.consume_front("NOT:"))
1020 return {Check::CheckNot
, Rest
};
1022 if (Rest
.consume_front("DAG:"))
1023 return {Check::CheckDAG
, Rest
};
1025 if (Rest
.consume_front("LABEL:"))
1026 return {Check::CheckLabel
, Rest
};
1028 if (Rest
.consume_front("EMPTY:"))
1029 return {Check::CheckEmpty
, Rest
};
1031 // You can't combine -NOT with another suffix.
1032 if (Rest
.startswith("DAG-NOT:") || Rest
.startswith("NOT-DAG:") ||
1033 Rest
.startswith("NEXT-NOT:") || Rest
.startswith("NOT-NEXT:") ||
1034 Rest
.startswith("SAME-NOT:") || Rest
.startswith("NOT-SAME:") ||
1035 Rest
.startswith("EMPTY-NOT:") || Rest
.startswith("NOT-EMPTY:"))
1036 return {Check::CheckBadNot
, Rest
};
1038 return {Check::CheckNone
, Rest
};
1041 // From the given position, find the next character after the word.
1042 static size_t SkipWord(StringRef Str
, size_t Loc
) {
1043 while (Loc
< Str
.size() && IsPartOfWord(Str
[Loc
]))
1048 /// Searches the buffer for the first prefix in the prefix regular expression.
1050 /// This searches the buffer using the provided regular expression, however it
1051 /// enforces constraints beyond that:
1052 /// 1) The found prefix must not be a suffix of something that looks like
1054 /// 2) The found prefix must be followed by a valid check type suffix using \c
1055 /// FindCheckType above.
1057 /// \returns a pair of StringRefs into the Buffer, which combines:
1058 /// - the first match of the regular expression to satisfy these two is
1060 /// otherwise an empty StringRef is returned to indicate failure.
1061 /// - buffer rewound to the location right after parsed suffix, for parsing
1062 /// to continue from
1064 /// If this routine returns a valid prefix, it will also shrink \p Buffer to
1065 /// start at the beginning of the returned prefix, increment \p LineNumber for
1066 /// each new line consumed from \p Buffer, and set \p CheckTy to the type of
1067 /// check found by examining the suffix.
1069 /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
1071 static std::pair
<StringRef
, StringRef
>
1072 FindFirstMatchingPrefix(Regex
&PrefixRE
, StringRef
&Buffer
,
1073 unsigned &LineNumber
, Check::FileCheckType
&CheckTy
) {
1074 SmallVector
<StringRef
, 2> Matches
;
1076 while (!Buffer
.empty()) {
1077 // Find the first (longest) match using the RE.
1078 if (!PrefixRE
.match(Buffer
, &Matches
))
1079 // No match at all, bail.
1080 return {StringRef(), StringRef()};
1082 StringRef Prefix
= Matches
[0];
1085 assert(Prefix
.data() >= Buffer
.data() &&
1086 Prefix
.data() < Buffer
.data() + Buffer
.size() &&
1087 "Prefix doesn't start inside of buffer!");
1088 size_t Loc
= Prefix
.data() - Buffer
.data();
1089 StringRef Skipped
= Buffer
.substr(0, Loc
);
1090 Buffer
= Buffer
.drop_front(Loc
);
1091 LineNumber
+= Skipped
.count('\n');
1093 // Check that the matched prefix isn't a suffix of some other check-like
1095 // FIXME: This is a very ad-hoc check. it would be better handled in some
1096 // other way. Among other things it seems hard to distinguish between
1097 // intentional and unintentional uses of this feature.
1098 if (Skipped
.empty() || !IsPartOfWord(Skipped
.back())) {
1099 // Now extract the type.
1100 StringRef AfterSuffix
;
1101 std::tie(CheckTy
, AfterSuffix
) = FindCheckType(Buffer
, Prefix
);
1103 // If we've found a valid check type for this prefix, we're done.
1104 if (CheckTy
!= Check::CheckNone
)
1105 return {Prefix
, AfterSuffix
};
1108 // If we didn't successfully find a prefix, we need to skip this invalid
1109 // prefix and continue scanning. We directly skip the prefix that was
1110 // matched and any additional parts of that check-like word.
1111 Buffer
= Buffer
.drop_front(SkipWord(Buffer
, Prefix
.size()));
1114 // We ran out of buffer while skipping partial matches so give up.
1115 return {StringRef(), StringRef()};
1118 void FileCheckPatternContext::createLineVariable() {
1119 assert(!LineVariable
&& "@LINE pseudo numeric variable already created");
1120 StringRef LineName
= "@LINE";
1121 LineVariable
= makeNumericVariable(LineName
);
1122 GlobalNumericVariableTable
[LineName
] = LineVariable
;
1125 FileCheck::FileCheck(FileCheckRequest Req
)
1126 : Req(Req
), PatternContext(std::make_unique
<FileCheckPatternContext
>()),
1127 CheckStrings(std::make_unique
<std::vector
<FileCheckString
>>()) {}
1129 FileCheck::~FileCheck() = default;
1131 bool FileCheck::readCheckFile(SourceMgr
&SM
, StringRef Buffer
,
1134 PatternContext
->defineCmdlineVariables(Req
.GlobalDefines
, SM
);
1136 logAllUnhandledErrors(std::move(DefineError
), errs());
1140 PatternContext
->createLineVariable();
1142 std::vector
<FileCheckPattern
> ImplicitNegativeChecks
;
1143 for (const auto &PatternString
: Req
.ImplicitCheckNot
) {
1144 // Create a buffer with fake command line content in order to display the
1145 // command line option responsible for the specific implicit CHECK-NOT.
1146 std::string Prefix
= "-implicit-check-not='";
1147 std::string Suffix
= "'";
1148 std::unique_ptr
<MemoryBuffer
> CmdLine
= MemoryBuffer::getMemBufferCopy(
1149 Prefix
+ PatternString
+ Suffix
, "command line");
1151 StringRef PatternInBuffer
=
1152 CmdLine
->getBuffer().substr(Prefix
.size(), PatternString
.size());
1153 SM
.AddNewSourceBuffer(std::move(CmdLine
), SMLoc());
1155 ImplicitNegativeChecks
.push_back(
1156 FileCheckPattern(Check::CheckNot
, PatternContext
.get()));
1157 ImplicitNegativeChecks
.back().parsePattern(PatternInBuffer
,
1158 "IMPLICIT-CHECK", SM
, Req
);
1161 std::vector
<FileCheckPattern
> DagNotMatches
= ImplicitNegativeChecks
;
1163 // LineNumber keeps track of the line on which CheckPrefix instances are
1165 unsigned LineNumber
= 1;
1168 Check::FileCheckType CheckTy
;
1170 // See if a prefix occurs in the memory buffer.
1171 StringRef UsedPrefix
;
1172 StringRef AfterSuffix
;
1173 std::tie(UsedPrefix
, AfterSuffix
) =
1174 FindFirstMatchingPrefix(PrefixRE
, Buffer
, LineNumber
, CheckTy
);
1175 if (UsedPrefix
.empty())
1177 assert(UsedPrefix
.data() == Buffer
.data() &&
1178 "Failed to move Buffer's start forward, or pointed prefix outside "
1180 assert(AfterSuffix
.data() >= Buffer
.data() &&
1181 AfterSuffix
.data() < Buffer
.data() + Buffer
.size() &&
1182 "Parsing after suffix doesn't start inside of buffer!");
1184 // Location to use for error messages.
1185 const char *UsedPrefixStart
= UsedPrefix
.data();
1187 // Skip the buffer to the end of parsed suffix (or just prefix, if no good
1188 // suffix was processed).
1189 Buffer
= AfterSuffix
.empty() ? Buffer
.drop_front(UsedPrefix
.size())
1192 // Complain about useful-looking but unsupported suffixes.
1193 if (CheckTy
== Check::CheckBadNot
) {
1194 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Error
,
1195 "unsupported -NOT combo on prefix '" + UsedPrefix
+ "'");
1199 // Complain about invalid count specification.
1200 if (CheckTy
== Check::CheckBadCount
) {
1201 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Error
,
1202 "invalid count in -COUNT specification on prefix '" +
1207 // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
1208 // leading whitespace.
1209 if (!(Req
.NoCanonicalizeWhiteSpace
&& Req
.MatchFullLines
))
1210 Buffer
= Buffer
.substr(Buffer
.find_first_not_of(" \t"));
1212 // Scan ahead to the end of line.
1213 size_t EOL
= Buffer
.find_first_of("\n\r");
1215 // Remember the location of the start of the pattern, for diagnostics.
1216 SMLoc PatternLoc
= SMLoc::getFromPointer(Buffer
.data());
1218 // Parse the pattern.
1219 FileCheckPattern
P(CheckTy
, PatternContext
.get(), LineNumber
);
1220 if (P
.parsePattern(Buffer
.substr(0, EOL
), UsedPrefix
, SM
, Req
))
1223 // Verify that CHECK-LABEL lines do not define or use variables
1224 if ((CheckTy
== Check::CheckLabel
) && P
.hasVariable()) {
1226 SMLoc::getFromPointer(UsedPrefixStart
), SourceMgr::DK_Error
,
1227 "found '" + UsedPrefix
+ "-LABEL:'"
1228 " with variable definition or use");
1232 Buffer
= Buffer
.substr(EOL
);
1234 // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
1235 if ((CheckTy
== Check::CheckNext
|| CheckTy
== Check::CheckSame
||
1236 CheckTy
== Check::CheckEmpty
) &&
1237 CheckStrings
->empty()) {
1238 StringRef Type
= CheckTy
== Check::CheckNext
1240 : CheckTy
== Check::CheckEmpty
? "EMPTY" : "SAME";
1241 SM
.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart
),
1242 SourceMgr::DK_Error
,
1243 "found '" + UsedPrefix
+ "-" + Type
+
1244 "' without previous '" + UsedPrefix
+ ": line");
1248 // Handle CHECK-DAG/-NOT.
1249 if (CheckTy
== Check::CheckDAG
|| CheckTy
== Check::CheckNot
) {
1250 DagNotMatches
.push_back(P
);
1254 // Okay, add the string we captured to the output vector and move on.
1255 CheckStrings
->emplace_back(P
, UsedPrefix
, PatternLoc
);
1256 std::swap(DagNotMatches
, CheckStrings
->back().DagNotStrings
);
1257 DagNotMatches
= ImplicitNegativeChecks
;
1260 // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
1261 // prefix as a filler for the error message.
1262 if (!DagNotMatches
.empty()) {
1263 CheckStrings
->emplace_back(
1264 FileCheckPattern(Check::CheckEOF
, PatternContext
.get(), LineNumber
+ 1),
1265 *Req
.CheckPrefixes
.begin(), SMLoc::getFromPointer(Buffer
.data()));
1266 std::swap(DagNotMatches
, CheckStrings
->back().DagNotStrings
);
1269 if (CheckStrings
->empty()) {
1270 errs() << "error: no check strings found with prefix"
1271 << (Req
.CheckPrefixes
.size() > 1 ? "es " : " ");
1272 auto I
= Req
.CheckPrefixes
.begin();
1273 auto E
= Req
.CheckPrefixes
.end();
1275 errs() << "\'" << *I
<< ":'";
1279 errs() << ", \'" << *I
<< ":'";
1288 static void PrintMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1289 StringRef Prefix
, SMLoc Loc
, const FileCheckPattern
&Pat
,
1290 int MatchedCount
, StringRef Buffer
, size_t MatchPos
,
1291 size_t MatchLen
, const FileCheckRequest
&Req
,
1292 std::vector
<FileCheckDiag
> *Diags
) {
1293 bool PrintDiag
= true;
1294 if (ExpectedMatch
) {
1297 if (!Req
.VerboseVerbose
&& Pat
.getCheckTy() == Check::CheckEOF
)
1299 // Due to their verbosity, we don't print verbose diagnostics here if we're
1300 // gathering them for a different rendering, but we always print other
1304 SMRange MatchRange
= ProcessMatchResult(
1305 ExpectedMatch
? FileCheckDiag::MatchFoundAndExpected
1306 : FileCheckDiag::MatchFoundButExcluded
,
1307 SM
, Loc
, Pat
.getCheckTy(), Buffer
, MatchPos
, MatchLen
, Diags
);
1311 std::string Message
= formatv("{0}: {1} string found in input",
1312 Pat
.getCheckTy().getDescription(Prefix
),
1313 (ExpectedMatch
? "expected" : "excluded"))
1315 if (Pat
.getCount() > 1)
1316 Message
+= formatv(" ({0} out of {1})", MatchedCount
, Pat
.getCount()).str();
1319 Loc
, ExpectedMatch
? SourceMgr::DK_Remark
: SourceMgr::DK_Error
, Message
);
1320 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
, "found here",
1322 Pat
.printSubstitutions(SM
, Buffer
, MatchRange
);
1325 static void PrintMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1326 const FileCheckString
&CheckStr
, int MatchedCount
,
1327 StringRef Buffer
, size_t MatchPos
, size_t MatchLen
,
1328 FileCheckRequest
&Req
,
1329 std::vector
<FileCheckDiag
> *Diags
) {
1330 PrintMatch(ExpectedMatch
, SM
, CheckStr
.Prefix
, CheckStr
.Loc
, CheckStr
.Pat
,
1331 MatchedCount
, Buffer
, MatchPos
, MatchLen
, Req
, Diags
);
1334 static void PrintNoMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1335 StringRef Prefix
, SMLoc Loc
,
1336 const FileCheckPattern
&Pat
, int MatchedCount
,
1337 StringRef Buffer
, bool VerboseVerbose
,
1338 std::vector
<FileCheckDiag
> *Diags
, Error MatchErrors
) {
1339 assert(MatchErrors
&& "Called on successful match");
1340 bool PrintDiag
= true;
1341 if (!ExpectedMatch
) {
1342 if (!VerboseVerbose
) {
1343 consumeError(std::move(MatchErrors
));
1346 // Due to their verbosity, we don't print verbose diagnostics here if we're
1347 // gathering them for a different rendering, but we always print other
1352 // If the current position is at the end of a line, advance to the start of
1354 Buffer
= Buffer
.substr(Buffer
.find_first_not_of(" \t\n\r"));
1355 SMRange SearchRange
= ProcessMatchResult(
1356 ExpectedMatch
? FileCheckDiag::MatchNoneButExpected
1357 : FileCheckDiag::MatchNoneAndExcluded
,
1358 SM
, Loc
, Pat
.getCheckTy(), Buffer
, 0, Buffer
.size(), Diags
);
1360 consumeError(std::move(MatchErrors
));
1365 handleErrors(std::move(MatchErrors
),
1366 [](const FileCheckErrorDiagnostic
&E
) { E
.log(errs()); });
1368 // No problem matching the string per se.
1371 consumeError(std::move(MatchErrors
));
1373 // Print "not found" diagnostic.
1374 std::string Message
= formatv("{0}: {1} string not found in input",
1375 Pat
.getCheckTy().getDescription(Prefix
),
1376 (ExpectedMatch
? "expected" : "excluded"))
1378 if (Pat
.getCount() > 1)
1379 Message
+= formatv(" ({0} out of {1})", MatchedCount
, Pat
.getCount()).str();
1381 Loc
, ExpectedMatch
? SourceMgr::DK_Error
: SourceMgr::DK_Remark
, Message
);
1383 // Print the "scanning from here" line.
1384 SM
.PrintMessage(SearchRange
.Start
, SourceMgr::DK_Note
, "scanning from here");
1386 // Allow the pattern to print additional information if desired.
1387 Pat
.printSubstitutions(SM
, Buffer
);
1390 Pat
.printFuzzyMatch(SM
, Buffer
, Diags
);
1393 static void PrintNoMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1394 const FileCheckString
&CheckStr
, int MatchedCount
,
1395 StringRef Buffer
, bool VerboseVerbose
,
1396 std::vector
<FileCheckDiag
> *Diags
, Error MatchErrors
) {
1397 PrintNoMatch(ExpectedMatch
, SM
, CheckStr
.Prefix
, CheckStr
.Loc
, CheckStr
.Pat
,
1398 MatchedCount
, Buffer
, VerboseVerbose
, Diags
,
1399 std::move(MatchErrors
));
1402 /// Counts the number of newlines in the specified range.
1403 static unsigned CountNumNewlinesBetween(StringRef Range
,
1404 const char *&FirstNewLine
) {
1405 unsigned NumNewLines
= 0;
1407 // Scan for newline.
1408 Range
= Range
.substr(Range
.find_first_of("\n\r"));
1414 // Handle \n\r and \r\n as a single newline.
1415 if (Range
.size() > 1 && (Range
[1] == '\n' || Range
[1] == '\r') &&
1416 (Range
[0] != Range
[1]))
1417 Range
= Range
.substr(1);
1418 Range
= Range
.substr(1);
1420 if (NumNewLines
== 1)
1421 FirstNewLine
= Range
.begin();
1425 size_t FileCheckString::Check(const SourceMgr
&SM
, StringRef Buffer
,
1426 bool IsLabelScanMode
, size_t &MatchLen
,
1427 FileCheckRequest
&Req
,
1428 std::vector
<FileCheckDiag
> *Diags
) const {
1430 std::vector
<const FileCheckPattern
*> NotStrings
;
1432 // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
1433 // bounds; we have not processed variable definitions within the bounded block
1434 // yet so cannot handle any final CHECK-DAG yet; this is handled when going
1435 // over the block again (including the last CHECK-LABEL) in normal mode.
1436 if (!IsLabelScanMode
) {
1437 // Match "dag strings" (with mixed "not strings" if any).
1438 LastPos
= CheckDag(SM
, Buffer
, NotStrings
, Req
, Diags
);
1439 if (LastPos
== StringRef::npos
)
1440 return StringRef::npos
;
1443 // Match itself from the last position after matching CHECK-DAG.
1444 size_t LastMatchEnd
= LastPos
;
1445 size_t FirstMatchPos
= 0;
1446 // Go match the pattern Count times. Majority of patterns only match with
1448 assert(Pat
.getCount() != 0 && "pattern count can not be zero");
1449 for (int i
= 1; i
<= Pat
.getCount(); i
++) {
1450 StringRef MatchBuffer
= Buffer
.substr(LastMatchEnd
);
1451 size_t CurrentMatchLen
;
1452 // get a match at current start point
1453 Expected
<size_t> MatchResult
= Pat
.match(MatchBuffer
, CurrentMatchLen
, SM
);
1457 PrintNoMatch(true, SM
, *this, i
, MatchBuffer
, Req
.VerboseVerbose
, Diags
,
1458 MatchResult
.takeError());
1459 return StringRef::npos
;
1461 size_t MatchPos
= *MatchResult
;
1462 PrintMatch(true, SM
, *this, i
, MatchBuffer
, MatchPos
, CurrentMatchLen
, Req
,
1465 FirstMatchPos
= LastPos
+ MatchPos
;
1467 // move start point after the match
1468 LastMatchEnd
+= MatchPos
+ CurrentMatchLen
;
1470 // Full match len counts from first match pos.
1471 MatchLen
= LastMatchEnd
- FirstMatchPos
;
1473 // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
1475 if (!IsLabelScanMode
) {
1476 size_t MatchPos
= FirstMatchPos
- LastPos
;
1477 StringRef MatchBuffer
= Buffer
.substr(LastPos
);
1478 StringRef SkippedRegion
= Buffer
.substr(LastPos
, MatchPos
);
1480 // If this check is a "CHECK-NEXT", verify that the previous match was on
1481 // the previous line (i.e. that there is one newline between them).
1482 if (CheckNext(SM
, SkippedRegion
)) {
1483 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine
, SM
, Loc
,
1484 Pat
.getCheckTy(), MatchBuffer
, MatchPos
, MatchLen
,
1485 Diags
, Req
.Verbose
);
1486 return StringRef::npos
;
1489 // If this check is a "CHECK-SAME", verify that the previous match was on
1490 // the same line (i.e. that there is no newline between them).
1491 if (CheckSame(SM
, SkippedRegion
)) {
1492 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine
, SM
, Loc
,
1493 Pat
.getCheckTy(), MatchBuffer
, MatchPos
, MatchLen
,
1494 Diags
, Req
.Verbose
);
1495 return StringRef::npos
;
1498 // If this match had "not strings", verify that they don't exist in the
1500 if (CheckNot(SM
, SkippedRegion
, NotStrings
, Req
, Diags
))
1501 return StringRef::npos
;
1504 return FirstMatchPos
;
1507 bool FileCheckString::CheckNext(const SourceMgr
&SM
, StringRef Buffer
) const {
1508 if (Pat
.getCheckTy() != Check::CheckNext
&&
1509 Pat
.getCheckTy() != Check::CheckEmpty
)
1514 Twine(Pat
.getCheckTy() == Check::CheckEmpty
? "-EMPTY" : "-NEXT");
1516 // Count the number of newlines between the previous match and this one.
1517 const char *FirstNewLine
= nullptr;
1518 unsigned NumNewLines
= CountNumNewlinesBetween(Buffer
, FirstNewLine
);
1520 if (NumNewLines
== 0) {
1521 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
1522 CheckName
+ ": is on the same line as previous match");
1523 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
1524 "'next' match was here");
1525 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
1526 "previous match ended here");
1530 if (NumNewLines
!= 1) {
1531 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
1533 ": is not on the line after the previous match");
1534 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
1535 "'next' match was here");
1536 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
1537 "previous match ended here");
1538 SM
.PrintMessage(SMLoc::getFromPointer(FirstNewLine
), SourceMgr::DK_Note
,
1539 "non-matching line after previous match is here");
1546 bool FileCheckString::CheckSame(const SourceMgr
&SM
, StringRef Buffer
) const {
1547 if (Pat
.getCheckTy() != Check::CheckSame
)
1550 // Count the number of newlines between the previous match and this one.
1551 const char *FirstNewLine
= nullptr;
1552 unsigned NumNewLines
= CountNumNewlinesBetween(Buffer
, FirstNewLine
);
1554 if (NumNewLines
!= 0) {
1555 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
1557 "-SAME: is not on the same line as the previous match");
1558 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
1559 "'next' match was here");
1560 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
1561 "previous match ended here");
1568 bool FileCheckString::CheckNot(
1569 const SourceMgr
&SM
, StringRef Buffer
,
1570 const std::vector
<const FileCheckPattern
*> &NotStrings
,
1571 const FileCheckRequest
&Req
, std::vector
<FileCheckDiag
> *Diags
) const {
1572 for (const FileCheckPattern
*Pat
: NotStrings
) {
1573 assert((Pat
->getCheckTy() == Check::CheckNot
) && "Expect CHECK-NOT!");
1575 size_t MatchLen
= 0;
1576 Expected
<size_t> MatchResult
= Pat
->match(Buffer
, MatchLen
, SM
);
1579 PrintNoMatch(false, SM
, Prefix
, Pat
->getLoc(), *Pat
, 1, Buffer
,
1580 Req
.VerboseVerbose
, Diags
, MatchResult
.takeError());
1583 size_t Pos
= *MatchResult
;
1585 PrintMatch(false, SM
, Prefix
, Pat
->getLoc(), *Pat
, 1, Buffer
, Pos
, MatchLen
,
1595 FileCheckString::CheckDag(const SourceMgr
&SM
, StringRef Buffer
,
1596 std::vector
<const FileCheckPattern
*> &NotStrings
,
1597 const FileCheckRequest
&Req
,
1598 std::vector
<FileCheckDiag
> *Diags
) const {
1599 if (DagNotStrings
.empty())
1602 // The start of the search range.
1603 size_t StartPos
= 0;
1609 // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
1610 // ranges are erased from this list once they are no longer in the search
1612 std::list
<MatchRange
> MatchRanges
;
1614 // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
1615 // group, so we don't use a range-based for loop here.
1616 for (auto PatItr
= DagNotStrings
.begin(), PatEnd
= DagNotStrings
.end();
1617 PatItr
!= PatEnd
; ++PatItr
) {
1618 const FileCheckPattern
&Pat
= *PatItr
;
1619 assert((Pat
.getCheckTy() == Check::CheckDAG
||
1620 Pat
.getCheckTy() == Check::CheckNot
) &&
1621 "Invalid CHECK-DAG or CHECK-NOT!");
1623 if (Pat
.getCheckTy() == Check::CheckNot
) {
1624 NotStrings
.push_back(&Pat
);
1628 assert((Pat
.getCheckTy() == Check::CheckDAG
) && "Expect CHECK-DAG!");
1630 // CHECK-DAG always matches from the start.
1631 size_t MatchLen
= 0, MatchPos
= StartPos
;
1633 // Search for a match that doesn't overlap a previous match in this
1635 for (auto MI
= MatchRanges
.begin(), ME
= MatchRanges
.end(); true; ++MI
) {
1636 StringRef MatchBuffer
= Buffer
.substr(MatchPos
);
1637 Expected
<size_t> MatchResult
= Pat
.match(MatchBuffer
, MatchLen
, SM
);
1638 // With a group of CHECK-DAGs, a single mismatching means the match on
1639 // that group of CHECK-DAGs fails immediately.
1641 PrintNoMatch(true, SM
, Prefix
, Pat
.getLoc(), Pat
, 1, MatchBuffer
,
1642 Req
.VerboseVerbose
, Diags
, MatchResult
.takeError());
1643 return StringRef::npos
;
1645 size_t MatchPosBuf
= *MatchResult
;
1646 // Re-calc it as the offset relative to the start of the original string.
1647 MatchPos
+= MatchPosBuf
;
1648 if (Req
.VerboseVerbose
)
1649 PrintMatch(true, SM
, Prefix
, Pat
.getLoc(), Pat
, 1, Buffer
, MatchPos
,
1650 MatchLen
, Req
, Diags
);
1651 MatchRange M
{MatchPos
, MatchPos
+ MatchLen
};
1652 if (Req
.AllowDeprecatedDagOverlap
) {
1653 // We don't need to track all matches in this mode, so we just maintain
1654 // one match range that encompasses the current CHECK-DAG group's
1656 if (MatchRanges
.empty())
1657 MatchRanges
.insert(MatchRanges
.end(), M
);
1659 auto Block
= MatchRanges
.begin();
1660 Block
->Pos
= std::min(Block
->Pos
, M
.Pos
);
1661 Block
->End
= std::max(Block
->End
, M
.End
);
1665 // Iterate previous matches until overlapping match or insertion point.
1666 bool Overlap
= false;
1667 for (; MI
!= ME
; ++MI
) {
1668 if (M
.Pos
< MI
->End
) {
1669 // !Overlap => New match has no overlap and is before this old match.
1670 // Overlap => New match overlaps this old match.
1671 Overlap
= MI
->Pos
< M
.End
;
1676 // Insert non-overlapping match into list.
1677 MatchRanges
.insert(MI
, M
);
1680 if (Req
.VerboseVerbose
) {
1681 // Due to their verbosity, we don't print verbose diagnostics here if
1682 // we're gathering them for a different rendering, but we always print
1683 // other diagnostics.
1685 SMLoc OldStart
= SMLoc::getFromPointer(Buffer
.data() + MI
->Pos
);
1686 SMLoc OldEnd
= SMLoc::getFromPointer(Buffer
.data() + MI
->End
);
1687 SMRange
OldRange(OldStart
, OldEnd
);
1688 SM
.PrintMessage(OldStart
, SourceMgr::DK_Note
,
1689 "match discarded, overlaps earlier DAG match here",
1692 Diags
->rbegin()->MatchTy
= FileCheckDiag::MatchFoundButDiscarded
;
1696 if (!Req
.VerboseVerbose
)
1697 PrintMatch(true, SM
, Prefix
, Pat
.getLoc(), Pat
, 1, Buffer
, MatchPos
,
1698 MatchLen
, Req
, Diags
);
1700 // Handle the end of a CHECK-DAG group.
1701 if (std::next(PatItr
) == PatEnd
||
1702 std::next(PatItr
)->getCheckTy() == Check::CheckNot
) {
1703 if (!NotStrings
.empty()) {
1704 // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
1705 // CHECK-DAG, verify that there are no 'not' strings occurred in that
1707 StringRef SkippedRegion
=
1708 Buffer
.slice(StartPos
, MatchRanges
.begin()->Pos
);
1709 if (CheckNot(SM
, SkippedRegion
, NotStrings
, Req
, Diags
))
1710 return StringRef::npos
;
1711 // Clear "not strings".
1714 // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
1715 // end of this CHECK-DAG group's match range.
1716 StartPos
= MatchRanges
.rbegin()->End
;
1717 // Don't waste time checking for (impossible) overlaps before that.
1718 MatchRanges
.clear();
1725 // A check prefix must contain only alphanumeric, hyphens and underscores.
1726 static bool ValidateCheckPrefix(StringRef CheckPrefix
) {
1727 static const Regex
Validator("^[a-zA-Z0-9_-]*$");
1728 return Validator
.match(CheckPrefix
);
1731 bool FileCheck::ValidateCheckPrefixes() {
1732 StringSet
<> PrefixSet
;
1734 for (StringRef Prefix
: Req
.CheckPrefixes
) {
1735 // Reject empty prefixes.
1739 if (!PrefixSet
.insert(Prefix
).second
)
1742 if (!ValidateCheckPrefix(Prefix
))
1749 Regex
FileCheck::buildCheckPrefixRegex() {
1750 // I don't think there's a way to specify an initial value for cl::list,
1751 // so if nothing was specified, add the default
1752 if (Req
.CheckPrefixes
.empty())
1753 Req
.CheckPrefixes
.push_back("CHECK");
1755 // We already validated the contents of CheckPrefixes so just concatenate
1756 // them as alternatives.
1757 SmallString
<32> PrefixRegexStr
;
1758 for (StringRef Prefix
: Req
.CheckPrefixes
) {
1759 if (Prefix
!= Req
.CheckPrefixes
.front())
1760 PrefixRegexStr
.push_back('|');
1762 PrefixRegexStr
.append(Prefix
);
1765 return Regex(PrefixRegexStr
);
1768 Error
FileCheckPatternContext::defineCmdlineVariables(
1769 std::vector
<std::string
> &CmdlineDefines
, SourceMgr
&SM
) {
1770 assert(GlobalVariableTable
.empty() && GlobalNumericVariableTable
.empty() &&
1771 "Overriding defined variable with command-line variable definitions");
1773 if (CmdlineDefines
.empty())
1774 return Error::success();
1776 // Create a string representing the vector of command-line definitions. Each
1777 // definition is on its own line and prefixed with a definition number to
1778 // clarify which definition a given diagnostic corresponds to.
1780 Error Errs
= Error::success();
1781 std::string CmdlineDefsDiag
;
1782 SmallVector
<std::pair
<size_t, size_t>, 4> CmdlineDefsIndices
;
1783 for (StringRef CmdlineDef
: CmdlineDefines
) {
1784 std::string DefPrefix
= ("Global define #" + Twine(++I
) + ": ").str();
1785 size_t EqIdx
= CmdlineDef
.find('=');
1786 if (EqIdx
== StringRef::npos
) {
1787 CmdlineDefsIndices
.push_back(std::make_pair(CmdlineDefsDiag
.size(), 0));
1790 // Numeric variable definition.
1791 if (CmdlineDef
[0] == '#') {
1792 // Append a copy of the command-line definition adapted to use the same
1793 // format as in the input file to be able to reuse
1794 // parseNumericSubstitutionBlock.
1795 CmdlineDefsDiag
+= (DefPrefix
+ CmdlineDef
+ " (parsed as: [[").str();
1796 std::string SubstitutionStr
= CmdlineDef
;
1797 SubstitutionStr
[EqIdx
] = ':';
1798 CmdlineDefsIndices
.push_back(
1799 std::make_pair(CmdlineDefsDiag
.size(), SubstitutionStr
.size()));
1800 CmdlineDefsDiag
+= (SubstitutionStr
+ Twine("]])\n")).str();
1802 CmdlineDefsDiag
+= DefPrefix
;
1803 CmdlineDefsIndices
.push_back(
1804 std::make_pair(CmdlineDefsDiag
.size(), CmdlineDef
.size()));
1805 CmdlineDefsDiag
+= (CmdlineDef
+ "\n").str();
1809 // Create a buffer with fake command line content in order to display
1810 // parsing diagnostic with location information and point to the
1811 // global definition with invalid syntax.
1812 std::unique_ptr
<MemoryBuffer
> CmdLineDefsDiagBuffer
=
1813 MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag
, "Global defines");
1814 StringRef CmdlineDefsDiagRef
= CmdLineDefsDiagBuffer
->getBuffer();
1815 SM
.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer
), SMLoc());
1817 for (std::pair
<size_t, size_t> CmdlineDefIndices
: CmdlineDefsIndices
) {
1818 StringRef CmdlineDef
= CmdlineDefsDiagRef
.substr(CmdlineDefIndices
.first
,
1819 CmdlineDefIndices
.second
);
1820 if (CmdlineDef
.empty()) {
1823 FileCheckErrorDiagnostic::get(
1824 SM
, CmdlineDef
, "missing equal sign in global definition"));
1828 // Numeric variable definition.
1829 if (CmdlineDef
[0] == '#') {
1830 // Now parse the definition both to check that the syntax is correct and
1831 // to create the necessary class instance.
1832 StringRef CmdlineDefExpr
= CmdlineDef
.substr(1);
1833 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
1834 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> ExpressionASTResult
=
1835 FileCheckPattern::parseNumericSubstitutionBlock(
1836 CmdlineDefExpr
, DefinedNumericVariable
, false, None
, this, SM
);
1837 if (!ExpressionASTResult
) {
1838 Errs
= joinErrors(std::move(Errs
), ExpressionASTResult
.takeError());
1841 std::unique_ptr
<FileCheckExpressionAST
> ExpressionAST
=
1842 std::move(*ExpressionASTResult
);
1843 // Now evaluate the expression whose value this variable should be set
1844 // to, since the expression of a command-line variable definition should
1845 // only use variables defined earlier on the command-line. If not, this
1846 // is an error and we report it.
1847 Expected
<uint64_t> Value
= ExpressionAST
->eval();
1849 Errs
= joinErrors(std::move(Errs
), Value
.takeError());
1853 assert(DefinedNumericVariable
&& "No variable defined");
1854 (*DefinedNumericVariable
)->setValue(*Value
);
1856 // Record this variable definition.
1857 GlobalNumericVariableTable
[(*DefinedNumericVariable
)->getName()] =
1858 *DefinedNumericVariable
;
1860 // String variable definition.
1861 std::pair
<StringRef
, StringRef
> CmdlineNameVal
= CmdlineDef
.split('=');
1862 StringRef CmdlineName
= CmdlineNameVal
.first
;
1863 StringRef OrigCmdlineName
= CmdlineName
;
1864 Expected
<FileCheckPattern::VariableProperties
> ParseVarResult
=
1865 FileCheckPattern::parseVariable(CmdlineName
, SM
);
1866 if (!ParseVarResult
) {
1867 Errs
= joinErrors(std::move(Errs
), ParseVarResult
.takeError());
1870 // Check that CmdlineName does not denote a pseudo variable is only
1871 // composed of the parsed numeric variable. This catches cases like
1872 // "FOO+2" in a "FOO+2=10" definition.
1873 if (ParseVarResult
->IsPseudo
|| !CmdlineName
.empty()) {
1874 Errs
= joinErrors(std::move(Errs
),
1875 FileCheckErrorDiagnostic::get(
1876 SM
, OrigCmdlineName
,
1877 "invalid name in string variable definition '" +
1878 OrigCmdlineName
+ "'"));
1881 StringRef Name
= ParseVarResult
->Name
;
1883 // Detect collisions between string and numeric variables when the former
1884 // is created later than the latter.
1885 if (GlobalNumericVariableTable
.find(Name
) !=
1886 GlobalNumericVariableTable
.end()) {
1887 Errs
= joinErrors(std::move(Errs
), FileCheckErrorDiagnostic::get(
1889 "numeric variable with name '" +
1890 Name
+ "' already exists"));
1893 GlobalVariableTable
.insert(CmdlineNameVal
);
1894 // Mark the string variable as defined to detect collisions between
1895 // string and numeric variables in defineCmdlineVariables when the latter
1896 // is created later than the former. We cannot reuse GlobalVariableTable
1897 // for this by populating it with an empty string since we would then
1898 // lose the ability to detect the use of an undefined variable in
1900 DefinedVariableTable
[Name
] = true;
1907 void FileCheckPatternContext::clearLocalVars() {
1908 SmallVector
<StringRef
, 16> LocalPatternVars
, LocalNumericVars
;
1909 for (const StringMapEntry
<StringRef
> &Var
: GlobalVariableTable
)
1910 if (Var
.first()[0] != '$')
1911 LocalPatternVars
.push_back(Var
.first());
1913 // Numeric substitution reads the value of a variable directly, not via
1914 // GlobalNumericVariableTable. Therefore, we clear local variables by
1915 // clearing their value which will lead to a numeric substitution failure. We
1916 // also mark the variable for removal from GlobalNumericVariableTable since
1917 // this is what defineCmdlineVariables checks to decide that no global
1918 // variable has been defined.
1919 for (const auto &Var
: GlobalNumericVariableTable
)
1920 if (Var
.first()[0] != '$') {
1921 Var
.getValue()->clearValue();
1922 LocalNumericVars
.push_back(Var
.first());
1925 for (const auto &Var
: LocalPatternVars
)
1926 GlobalVariableTable
.erase(Var
);
1927 for (const auto &Var
: LocalNumericVars
)
1928 GlobalNumericVariableTable
.erase(Var
);
1931 bool FileCheck::checkInput(SourceMgr
&SM
, StringRef Buffer
,
1932 std::vector
<FileCheckDiag
> *Diags
) {
1933 bool ChecksFailed
= false;
1935 unsigned i
= 0, j
= 0, e
= CheckStrings
->size();
1937 StringRef CheckRegion
;
1939 CheckRegion
= Buffer
;
1941 const FileCheckString
&CheckLabelStr
= (*CheckStrings
)[j
];
1942 if (CheckLabelStr
.Pat
.getCheckTy() != Check::CheckLabel
) {
1947 // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
1948 size_t MatchLabelLen
= 0;
1949 size_t MatchLabelPos
=
1950 CheckLabelStr
.Check(SM
, Buffer
, true, MatchLabelLen
, Req
, Diags
);
1951 if (MatchLabelPos
== StringRef::npos
)
1952 // Immediately bail if CHECK-LABEL fails, nothing else we can do.
1955 CheckRegion
= Buffer
.substr(0, MatchLabelPos
+ MatchLabelLen
);
1956 Buffer
= Buffer
.substr(MatchLabelPos
+ MatchLabelLen
);
1960 // Do not clear the first region as it's the one before the first
1961 // CHECK-LABEL and it would clear variables defined on the command-line
1962 // before they get used.
1963 if (i
!= 0 && Req
.EnableVarScope
)
1964 PatternContext
->clearLocalVars();
1966 for (; i
!= j
; ++i
) {
1967 const FileCheckString
&CheckStr
= (*CheckStrings
)[i
];
1969 // Check each string within the scanned region, including a second check
1970 // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
1971 size_t MatchLen
= 0;
1973 CheckStr
.Check(SM
, CheckRegion
, false, MatchLen
, Req
, Diags
);
1975 if (MatchPos
== StringRef::npos
) {
1976 ChecksFailed
= true;
1981 CheckRegion
= CheckRegion
.substr(MatchPos
+ MatchLen
);
1988 // Success if no checks failed.
1989 return !ChecksFailed
;