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 "llvm/ADT/StringSet.h"
18 #include "llvm/Support/FormatVariadic.h"
27 bool FileCheckNumericVariable::isValueKnownAtMatchTime() const {
31 return ExpressionAST
!= nullptr;
34 void FileCheckNumericVariable::setValue(uint64_t NewValue
) {
35 if (ExpressionAST
!= nullptr) {
36 // Caller is expected to call setValue only if substitution was successful.
37 assert(NewValue
== cantFail(ExpressionAST
->eval(),
38 "Failed to evaluate associated expression when "
39 "sanity checking value") &&
40 "Value being set to different from variable evaluation");
43 // Clear pointer to AST to ensure it is not used after the numeric
44 // substitution defining this variable is processed since it's the
45 // substitution that owns the pointer.
46 ExpressionAST
= nullptr;
49 Expected
<uint64_t> FileCheckNumericVariableUse::eval() const {
50 Optional
<uint64_t> Value
= NumericVariable
->getValue();
54 FileCheckExpressionAST
*ExpressionAST
= NumericVariable
->getExpressionAST();
56 return make_error
<FileCheckUndefVarError
>(Name
);
58 return ExpressionAST
->eval();
61 Expected
<uint64_t> FileCheckASTBinop::eval() const {
62 Expected
<uint64_t> LeftOp
= LeftOperand
->eval();
63 Expected
<uint64_t> RightOp
= RightOperand
->eval();
65 // Bubble up any error (e.g. undefined variables) in the recursive
67 if (!LeftOp
|| !RightOp
) {
68 Error Err
= Error::success();
70 Err
= joinErrors(std::move(Err
), LeftOp
.takeError());
72 Err
= joinErrors(std::move(Err
), RightOp
.takeError());
73 return std::move(Err
);
76 return EvalBinop(*LeftOp
, *RightOp
);
79 Expected
<std::string
> FileCheckNumericSubstitution::getResult() const {
80 Expected
<uint64_t> EvaluatedValue
= ExpressionAST
->eval();
82 return EvaluatedValue
.takeError();
83 return utostr(*EvaluatedValue
);
86 Expected
<std::string
> FileCheckStringSubstitution::getResult() const {
87 // Look up the value and escape it so that we can put it into the regex.
88 Expected
<StringRef
> VarVal
= Context
->getPatternVarValue(FromStr
);
90 return VarVal
.takeError();
91 return Regex::escape(*VarVal
);
94 bool FileCheckPattern::isValidVarNameStart(char C
) {
95 return C
== '_' || isalpha(C
);
98 Expected
<FileCheckPattern::VariableProperties
>
99 FileCheckPattern::parseVariable(StringRef
&Str
, const SourceMgr
&SM
) {
101 return FileCheckErrorDiagnostic::get(SM
, Str
, "empty variable name");
103 bool ParsedOneChar
= false;
105 bool IsPseudo
= Str
[0] == '@';
107 // Global vars start with '$'.
108 if (Str
[0] == '$' || IsPseudo
)
111 for (unsigned E
= Str
.size(); I
!= E
; ++I
) {
112 if (!ParsedOneChar
&& !isValidVarNameStart(Str
[I
]))
113 return FileCheckErrorDiagnostic::get(SM
, Str
, "invalid variable name");
115 // Variable names are composed of alphanumeric characters and underscores.
116 if (Str
[I
] != '_' && !isalnum(Str
[I
]))
118 ParsedOneChar
= true;
121 StringRef Name
= Str
.take_front(I
);
123 return VariableProperties
{Name
, IsPseudo
};
126 // StringRef holding all characters considered as horizontal whitespaces by
127 // FileCheck input canonicalization.
128 StringRef SpaceChars
= " \t";
130 // Parsing helper function that strips the first character in S and returns it.
131 static char popFront(StringRef
&S
) {
137 char FileCheckUndefVarError::ID
= 0;
138 char FileCheckErrorDiagnostic::ID
= 0;
139 char FileCheckNotFoundError::ID
= 0;
141 Expected
<FileCheckNumericVariable
*>
142 FileCheckPattern::parseNumericVariableDefinition(
143 StringRef
&Expr
, FileCheckPatternContext
*Context
,
144 Optional
<size_t> LineNumber
, FileCheckExpressionAST
*ExpressionAST
,
145 const SourceMgr
&SM
) {
146 Expected
<VariableProperties
> ParseVarResult
= parseVariable(Expr
, SM
);
148 return ParseVarResult
.takeError();
149 StringRef Name
= ParseVarResult
->Name
;
151 if (ParseVarResult
->IsPseudo
)
152 return FileCheckErrorDiagnostic::get(
153 SM
, Name
, "definition of pseudo numeric variable unsupported");
155 // Detect collisions between string and numeric variables when the latter
156 // is created later than the former.
157 if (Context
->DefinedVariableTable
.find(Name
) !=
158 Context
->DefinedVariableTable
.end())
159 return FileCheckErrorDiagnostic::get(
160 SM
, Name
, "string variable with name '" + Name
+ "' already exists");
162 Expr
= Expr
.ltrim(SpaceChars
);
164 return FileCheckErrorDiagnostic::get(
165 SM
, Expr
, "unexpected characters after numeric variable name");
167 FileCheckNumericVariable
*DefinedNumericVariable
;
168 auto VarTableIter
= Context
->GlobalNumericVariableTable
.find(Name
);
169 if (VarTableIter
!= Context
->GlobalNumericVariableTable
.end())
170 DefinedNumericVariable
= VarTableIter
->second
;
172 DefinedNumericVariable
=
173 Context
->makeNumericVariable(Name
, LineNumber
, ExpressionAST
);
175 return DefinedNumericVariable
;
178 Expected
<std::unique_ptr
<FileCheckNumericVariableUse
>>
179 FileCheckPattern::parseNumericVariableUse(StringRef Name
, bool IsPseudo
,
180 Optional
<size_t> LineNumber
,
181 FileCheckPatternContext
*Context
,
182 const SourceMgr
&SM
) {
183 if (IsPseudo
&& !Name
.equals("@LINE"))
184 return FileCheckErrorDiagnostic::get(
185 SM
, Name
, "invalid pseudo numeric variable '" + Name
+ "'");
187 // Numeric variable definitions and uses are parsed in the order in which
188 // they appear in the CHECK patterns. For each definition, the pointer to the
189 // class instance of the corresponding numeric variable definition is stored
190 // in GlobalNumericVariableTable in parsePattern. Therefore, if the pointer
191 // we get below is null, it means no such variable was defined before. When
192 // that happens, we create a dummy variable so that parsing can continue. All
193 // uses of undefined variables, whether string or numeric, are then diagnosed
194 // in printSubstitutions() after failing to match.
195 auto VarTableIter
= Context
->GlobalNumericVariableTable
.find(Name
);
196 FileCheckNumericVariable
*NumericVariable
;
197 if (VarTableIter
!= Context
->GlobalNumericVariableTable
.end())
198 NumericVariable
= VarTableIter
->second
;
200 NumericVariable
= Context
->makeNumericVariable(Name
);
201 Context
->GlobalNumericVariableTable
[Name
] = NumericVariable
;
204 Optional
<size_t> DefLineNumber
= NumericVariable
->getDefLineNumber();
205 if (DefLineNumber
&& LineNumber
&& *DefLineNumber
== *LineNumber
&&
206 !NumericVariable
->isValueKnownAtMatchTime())
207 return FileCheckErrorDiagnostic::get(
209 "numeric variable '" + Name
+
210 "' defined from input on the same line as used");
212 return llvm::make_unique
<FileCheckNumericVariableUse
>(Name
, NumericVariable
);
215 Expected
<std::unique_ptr
<FileCheckExpressionAST
>>
216 FileCheckPattern::parseNumericOperand(StringRef
&Expr
, AllowedOperand AO
,
217 Optional
<size_t> LineNumber
,
218 FileCheckPatternContext
*Context
,
219 const SourceMgr
&SM
) {
220 if (AO
== AllowedOperand::LineVar
|| AO
== AllowedOperand::Any
) {
221 // Try to parse as a numeric variable use.
222 Expected
<FileCheckPattern::VariableProperties
> ParseVarResult
=
223 parseVariable(Expr
, SM
);
225 return parseNumericVariableUse(ParseVarResult
->Name
,
226 ParseVarResult
->IsPseudo
, LineNumber
,
228 if (AO
== AllowedOperand::LineVar
)
229 return ParseVarResult
.takeError();
230 // Ignore the error and retry parsing as a literal.
231 consumeError(ParseVarResult
.takeError());
234 // Otherwise, parse it as a literal.
235 uint64_t LiteralValue
;
236 if (!Expr
.consumeInteger(/*Radix=*/10, LiteralValue
))
237 return llvm::make_unique
<FileCheckExpressionLiteral
>(LiteralValue
);
239 return FileCheckErrorDiagnostic::get(SM
, Expr
,
240 "invalid operand format '" + Expr
+ "'");
243 static uint64_t add(uint64_t LeftOp
, uint64_t RightOp
) {
244 return LeftOp
+ RightOp
;
247 static uint64_t sub(uint64_t LeftOp
, uint64_t RightOp
) {
248 return LeftOp
- RightOp
;
251 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> FileCheckPattern::parseBinop(
252 StringRef
&Expr
, std::unique_ptr
<FileCheckExpressionAST
> LeftOp
,
253 bool IsLegacyLineExpr
, Optional
<size_t> LineNumber
,
254 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
255 Expr
= Expr
.ltrim(SpaceChars
);
257 return std::move(LeftOp
);
259 // Check if this is a supported operation and select a function to perform
261 SMLoc OpLoc
= SMLoc::getFromPointer(Expr
.data());
262 char Operator
= popFront(Expr
);
263 binop_eval_t EvalBinop
;
272 return FileCheckErrorDiagnostic::get(
273 SM
, OpLoc
, Twine("unsupported operation '") + Twine(Operator
) + "'");
276 // Parse right operand.
277 Expr
= Expr
.ltrim(SpaceChars
);
279 return FileCheckErrorDiagnostic::get(SM
, Expr
,
280 "missing operand in expression");
281 // The second operand in a legacy @LINE expression is always a literal.
283 IsLegacyLineExpr
? AllowedOperand::Literal
: AllowedOperand::Any
;
284 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> RightOpResult
=
285 parseNumericOperand(Expr
, AO
, LineNumber
, Context
, SM
);
287 return RightOpResult
;
289 Expr
= Expr
.ltrim(SpaceChars
);
290 return llvm::make_unique
<FileCheckASTBinop
>(EvalBinop
, std::move(LeftOp
),
291 std::move(*RightOpResult
));
294 Expected
<std::unique_ptr
<FileCheckExpressionAST
>>
295 FileCheckPattern::parseNumericSubstitutionBlock(
297 Optional
<FileCheckNumericVariable
*> &DefinedNumericVariable
,
298 bool IsLegacyLineExpr
, Optional
<size_t> LineNumber
,
299 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
300 std::unique_ptr
<FileCheckExpressionAST
> ExpressionAST
= nullptr;
301 StringRef DefExpr
= StringRef();
302 DefinedNumericVariable
= None
;
303 // Save variable definition expression if any.
304 size_t DefEnd
= Expr
.find(':');
305 if (DefEnd
!= StringRef::npos
) {
306 DefExpr
= Expr
.substr(0, DefEnd
);
307 Expr
= Expr
.substr(DefEnd
+ 1);
310 // Parse the expression itself.
311 Expr
= Expr
.ltrim(SpaceChars
);
313 // The first operand in a legacy @LINE expression is always the @LINE
316 IsLegacyLineExpr
? AllowedOperand::LineVar
: AllowedOperand::Any
;
317 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> ParseResult
=
318 parseNumericOperand(Expr
, AO
, LineNumber
, Context
, SM
);
319 while (ParseResult
&& !Expr
.empty()) {
320 ParseResult
= parseBinop(Expr
, std::move(*ParseResult
), IsLegacyLineExpr
,
321 LineNumber
, Context
, SM
);
322 // Legacy @LINE expressions only allow 2 operands.
323 if (ParseResult
&& IsLegacyLineExpr
&& !Expr
.empty())
324 return FileCheckErrorDiagnostic::get(
326 "unexpected characters at end of expression '" + Expr
+ "'");
330 ExpressionAST
= std::move(*ParseResult
);
333 // Parse the numeric variable definition.
334 if (DefEnd
!= StringRef::npos
) {
335 DefExpr
= DefExpr
.ltrim(SpaceChars
);
336 Expected
<FileCheckNumericVariable
*> ParseResult
=
337 parseNumericVariableDefinition(DefExpr
, Context
, LineNumber
,
338 ExpressionAST
.get(), SM
);
341 return ParseResult
.takeError();
342 DefinedNumericVariable
= *ParseResult
;
345 return std::move(ExpressionAST
);
348 bool FileCheckPattern::parsePattern(StringRef PatternStr
, StringRef Prefix
,
350 const FileCheckRequest
&Req
) {
351 bool MatchFullLinesHere
= Req
.MatchFullLines
&& CheckTy
!= Check::CheckNot
;
353 PatternLoc
= SMLoc::getFromPointer(PatternStr
.data());
355 if (!(Req
.NoCanonicalizeWhiteSpace
&& Req
.MatchFullLines
))
356 // Ignore trailing whitespace.
357 while (!PatternStr
.empty() &&
358 (PatternStr
.back() == ' ' || PatternStr
.back() == '\t'))
359 PatternStr
= PatternStr
.substr(0, PatternStr
.size() - 1);
361 // Check that there is something on the line.
362 if (PatternStr
.empty() && CheckTy
!= Check::CheckEmpty
) {
363 SM
.PrintMessage(PatternLoc
, SourceMgr::DK_Error
,
364 "found empty check string with prefix '" + Prefix
+ ":'");
368 if (!PatternStr
.empty() && CheckTy
== Check::CheckEmpty
) {
370 PatternLoc
, SourceMgr::DK_Error
,
371 "found non-empty check string for empty check with prefix '" + Prefix
+
376 if (CheckTy
== Check::CheckEmpty
) {
381 // Check to see if this is a fixed string, or if it has regex pieces.
382 if (!MatchFullLinesHere
&&
383 (PatternStr
.size() < 2 || (PatternStr
.find("{{") == StringRef::npos
&&
384 PatternStr
.find("[[") == StringRef::npos
))) {
385 FixedStr
= PatternStr
;
389 if (MatchFullLinesHere
) {
391 if (!Req
.NoCanonicalizeWhiteSpace
)
395 // Paren value #0 is for the fully matched string. Any new parenthesized
396 // values add from there.
397 unsigned CurParen
= 1;
399 // Otherwise, there is at least one regex piece. Build up the regex pattern
400 // by escaping scary characters in fixed strings, building up one big regex.
401 while (!PatternStr
.empty()) {
403 if (PatternStr
.startswith("{{")) {
404 // This is the start of a regex match. Scan for the }}.
405 size_t End
= PatternStr
.find("}}");
406 if (End
== StringRef::npos
) {
407 SM
.PrintMessage(SMLoc::getFromPointer(PatternStr
.data()),
409 "found start of regex string with no end '}}'");
413 // Enclose {{}} patterns in parens just like [[]] even though we're not
414 // capturing the result for any purpose. This is required in case the
415 // expression contains an alternation like: CHECK: abc{{x|z}}def. We
416 // want this to turn into: "abc(x|z)def" not "abcx|zdef".
420 if (AddRegExToRegEx(PatternStr
.substr(2, End
- 2), CurParen
, SM
))
424 PatternStr
= PatternStr
.substr(End
+ 2);
428 // String and numeric substitution blocks. Pattern substitution blocks come
429 // in two forms: [[foo:.*]] and [[foo]]. The former matches .* (or some
430 // other regex) and assigns it to the string variable 'foo'. The latter
431 // substitutes foo's value. Numeric substitution blocks recognize the same
432 // form as string ones, but start with a '#' sign after the double
433 // brackets. They also accept a combined form which sets a numeric variable
434 // to the evaluation of an expression. Both string and numeric variable
435 // names must satisfy the regular expression "[a-zA-Z_][0-9a-zA-Z_]*" to be
436 // valid, as this helps catch some common errors.
437 if (PatternStr
.startswith("[[")) {
438 StringRef UnparsedPatternStr
= PatternStr
.substr(2);
439 // Find the closing bracket pair ending the match. End is going to be an
440 // offset relative to the beginning of the match string.
441 size_t End
= FindRegexVarEnd(UnparsedPatternStr
, SM
);
442 StringRef MatchStr
= UnparsedPatternStr
.substr(0, End
);
443 bool IsNumBlock
= MatchStr
.consume_front("#");
445 if (End
== StringRef::npos
) {
446 SM
.PrintMessage(SMLoc::getFromPointer(PatternStr
.data()),
448 "Invalid substitution block, no ]] found");
451 // Strip the substitution block we are parsing. End points to the start
452 // of the "]]" closing the expression so account for it in computing the
453 // index of the first unparsed character.
454 PatternStr
= UnparsedPatternStr
.substr(End
+ 2);
456 bool IsDefinition
= false;
457 bool SubstNeeded
= false;
458 // Whether the substitution block is a legacy use of @LINE with string
459 // substitution block syntax.
460 bool IsLegacyLineExpr
= false;
463 StringRef MatchRegexp
;
464 size_t SubstInsertIdx
= RegExStr
.size();
466 // Parse string variable or legacy @LINE expression.
468 size_t VarEndIdx
= MatchStr
.find(":");
469 size_t SpacePos
= MatchStr
.substr(0, VarEndIdx
).find_first_of(" \t");
470 if (SpacePos
!= StringRef::npos
) {
471 SM
.PrintMessage(SMLoc::getFromPointer(MatchStr
.data() + SpacePos
),
472 SourceMgr::DK_Error
, "unexpected whitespace");
476 // Get the name (e.g. "foo") and verify it is well formed.
477 StringRef OrigMatchStr
= MatchStr
;
478 Expected
<FileCheckPattern::VariableProperties
> ParseVarResult
=
479 parseVariable(MatchStr
, SM
);
480 if (!ParseVarResult
) {
481 logAllUnhandledErrors(ParseVarResult
.takeError(), errs());
484 StringRef Name
= ParseVarResult
->Name
;
485 bool IsPseudo
= ParseVarResult
->IsPseudo
;
487 IsDefinition
= (VarEndIdx
!= StringRef::npos
);
488 SubstNeeded
= !IsDefinition
;
490 if ((IsPseudo
|| !MatchStr
.consume_front(":"))) {
491 SM
.PrintMessage(SMLoc::getFromPointer(Name
.data()),
493 "invalid name in string variable definition");
497 // Detect collisions between string and numeric variables when the
498 // former is created later than the latter.
499 if (Context
->GlobalNumericVariableTable
.find(Name
) !=
500 Context
->GlobalNumericVariableTable
.end()) {
502 SMLoc::getFromPointer(Name
.data()), SourceMgr::DK_Error
,
503 "numeric variable with name '" + Name
+ "' already exists");
507 MatchRegexp
= MatchStr
;
510 MatchStr
= OrigMatchStr
;
511 IsLegacyLineExpr
= IsNumBlock
= true;
517 // Parse numeric substitution block.
518 std::unique_ptr
<FileCheckExpressionAST
> ExpressionAST
;
519 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
521 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> ParseResult
=
522 parseNumericSubstitutionBlock(MatchStr
, DefinedNumericVariable
,
523 IsLegacyLineExpr
, LineNumber
, Context
,
526 logAllUnhandledErrors(ParseResult
.takeError(), errs());
529 ExpressionAST
= std::move(*ParseResult
);
530 SubstNeeded
= ExpressionAST
!= nullptr;
531 if (DefinedNumericVariable
) {
533 DefName
= (*DefinedNumericVariable
)->getName();
538 MatchRegexp
= "[0-9]+";
541 // Handle variable definition: [[<def>:(...)]] and [[#(...)<def>:(...)]].
547 FileCheckNumericVariableMatch NumericVariableDefinition
= {
548 *DefinedNumericVariable
, CurParen
};
549 NumericVariableDefs
[DefName
] = NumericVariableDefinition
;
550 // This store is done here rather than in match() to allow
551 // parseNumericVariableUse() to get the pointer to the class instance
552 // of the right variable definition corresponding to a given numeric
554 Context
->GlobalNumericVariableTable
[DefName
] =
555 *DefinedNumericVariable
;
557 VariableDefs
[DefName
] = CurParen
;
558 // Mark string variable as defined to detect collisions between
559 // string and numeric variables in parseNumericVariableUse() and
560 // defineCmdlineVariables() when the latter is created later than the
561 // former. We cannot reuse GlobalVariableTable for this by populating
562 // it with an empty string since we would then lose the ability to
563 // detect the use of an undefined variable in match().
564 Context
->DefinedVariableTable
[DefName
] = true;
570 if (!MatchRegexp
.empty() && AddRegExToRegEx(MatchRegexp
, CurParen
, SM
))
576 // Handle substitutions: [[foo]] and [[#<foo expr>]].
578 // Handle substitution of string variables that were defined earlier on
579 // the same line by emitting a backreference. Expressions do not
580 // support substituting a numeric variable defined on the same line.
581 if (!IsNumBlock
&& VariableDefs
.find(SubstStr
) != VariableDefs
.end()) {
582 unsigned CaptureParenGroup
= VariableDefs
[SubstStr
];
583 if (CaptureParenGroup
< 1 || CaptureParenGroup
> 9) {
584 SM
.PrintMessage(SMLoc::getFromPointer(SubstStr
.data()),
586 "Can't back-reference more than 9 variables");
589 AddBackrefToRegEx(CaptureParenGroup
);
591 // Handle substitution of string variables ([[<var>]]) defined in
592 // previous CHECK patterns, and substitution of expressions.
593 FileCheckSubstitution
*Substitution
=
595 ? Context
->makeNumericSubstitution(
596 SubstStr
, std::move(ExpressionAST
), SubstInsertIdx
)
597 : Context
->makeStringSubstitution(SubstStr
, SubstInsertIdx
);
598 Substitutions
.push_back(Substitution
);
603 // Handle fixed string matches.
604 // Find the end, which is the start of the next regex.
605 size_t FixedMatchEnd
= PatternStr
.find("{{");
606 FixedMatchEnd
= std::min(FixedMatchEnd
, PatternStr
.find("[["));
607 RegExStr
+= Regex::escape(PatternStr
.substr(0, FixedMatchEnd
));
608 PatternStr
= PatternStr
.substr(FixedMatchEnd
);
611 if (MatchFullLinesHere
) {
612 if (!Req
.NoCanonicalizeWhiteSpace
)
620 bool FileCheckPattern::AddRegExToRegEx(StringRef RS
, unsigned &CurParen
, SourceMgr
&SM
) {
623 if (!R
.isValid(Error
)) {
624 SM
.PrintMessage(SMLoc::getFromPointer(RS
.data()), SourceMgr::DK_Error
,
625 "invalid regex: " + Error
);
629 RegExStr
+= RS
.str();
630 CurParen
+= R
.getNumMatches();
634 void FileCheckPattern::AddBackrefToRegEx(unsigned BackrefNum
) {
635 assert(BackrefNum
>= 1 && BackrefNum
<= 9 && "Invalid backref number");
636 std::string Backref
= std::string("\\") + std::string(1, '0' + BackrefNum
);
640 Expected
<size_t> FileCheckPattern::match(StringRef Buffer
, size_t &MatchLen
,
641 const SourceMgr
&SM
) const {
642 // If this is the EOF pattern, match it immediately.
643 if (CheckTy
== Check::CheckEOF
) {
645 return Buffer
.size();
648 // If this is a fixed string pattern, just match it now.
649 if (!FixedStr
.empty()) {
650 MatchLen
= FixedStr
.size();
651 size_t Pos
= Buffer
.find(FixedStr
);
652 if (Pos
== StringRef::npos
)
653 return make_error
<FileCheckNotFoundError
>();
659 // If there are substitutions, we need to create a temporary string with the
661 StringRef RegExToMatch
= RegExStr
;
663 if (!Substitutions
.empty()) {
666 Context
->LineVariable
->setValue(*LineNumber
);
668 size_t InsertOffset
= 0;
669 // Substitute all string variables and expressions whose values are only
670 // now known. Use of string variables defined on the same line are handled
671 // by back-references.
672 for (const auto &Substitution
: Substitutions
) {
673 // Substitute and check for failure (e.g. use of undefined variable).
674 Expected
<std::string
> Value
= Substitution
->getResult();
676 return Value
.takeError();
678 // Plop it into the regex at the adjusted offset.
679 TmpStr
.insert(TmpStr
.begin() + Substitution
->getIndex() + InsertOffset
,
680 Value
->begin(), Value
->end());
681 InsertOffset
+= Value
->size();
684 // Match the newly constructed regex.
685 RegExToMatch
= TmpStr
;
688 SmallVector
<StringRef
, 4> MatchInfo
;
689 if (!Regex(RegExToMatch
, Regex::Newline
).match(Buffer
, &MatchInfo
))
690 return make_error
<FileCheckNotFoundError
>();
692 // Successful regex match.
693 assert(!MatchInfo
.empty() && "Didn't get any match");
694 StringRef FullMatch
= MatchInfo
[0];
696 // If this defines any string variables, remember their values.
697 for (const auto &VariableDef
: VariableDefs
) {
698 assert(VariableDef
.second
< MatchInfo
.size() && "Internal paren error");
699 Context
->GlobalVariableTable
[VariableDef
.first
] =
700 MatchInfo
[VariableDef
.second
];
703 // If this defines any numeric variables, remember their values.
704 for (const auto &NumericVariableDef
: NumericVariableDefs
) {
705 const FileCheckNumericVariableMatch
&NumericVariableMatch
=
706 NumericVariableDef
.getValue();
707 unsigned CaptureParenGroup
= NumericVariableMatch
.CaptureParenGroup
;
708 assert(CaptureParenGroup
< MatchInfo
.size() && "Internal paren error");
709 FileCheckNumericVariable
*DefinedNumericVariable
=
710 NumericVariableMatch
.DefinedNumericVariable
;
712 StringRef MatchedValue
= MatchInfo
[CaptureParenGroup
];
714 if (MatchedValue
.getAsInteger(10, Val
))
715 return FileCheckErrorDiagnostic::get(SM
, MatchedValue
,
716 "Unable to represent numeric value");
717 DefinedNumericVariable
->setValue(Val
);
720 // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
721 // the required preceding newline, which is consumed by the pattern in the
722 // case of CHECK-EMPTY but not CHECK-NEXT.
723 size_t MatchStartSkip
= CheckTy
== Check::CheckEmpty
;
724 MatchLen
= FullMatch
.size() - MatchStartSkip
;
725 return FullMatch
.data() - Buffer
.data() + MatchStartSkip
;
728 unsigned FileCheckPattern::computeMatchDistance(StringRef Buffer
) const {
729 // Just compute the number of matching characters. For regular expressions, we
730 // just compare against the regex itself and hope for the best.
732 // FIXME: One easy improvement here is have the regex lib generate a single
733 // example regular expression which matches, and use that as the example
735 StringRef
ExampleString(FixedStr
);
736 if (ExampleString
.empty())
737 ExampleString
= RegExStr
;
739 // Only compare up to the first line in the buffer, or the string size.
740 StringRef BufferPrefix
= Buffer
.substr(0, ExampleString
.size());
741 BufferPrefix
= BufferPrefix
.split('\n').first
;
742 return BufferPrefix
.edit_distance(ExampleString
);
745 void FileCheckPattern::printSubstitutions(const SourceMgr
&SM
, StringRef Buffer
,
746 SMRange MatchRange
) const {
747 // Print what we know about substitutions.
748 if (!Substitutions
.empty()) {
749 for (const auto &Substitution
: Substitutions
) {
750 SmallString
<256> Msg
;
751 raw_svector_ostream
OS(Msg
);
752 Expected
<std::string
> MatchedValue
= Substitution
->getResult();
754 // Substitution failed or is not known at match time, print the undefined
755 // variables it uses.
757 bool UndefSeen
= false;
758 handleAllErrors(MatchedValue
.takeError(),
759 [](const FileCheckNotFoundError
&E
) {},
760 // Handled in PrintNoMatch().
761 [](const FileCheckErrorDiagnostic
&E
) {},
762 [&](const FileCheckUndefVarError
&E
) {
764 OS
<< "uses undefined variable(s):";
771 // Substitution succeeded. Print substituted value.
773 OS
.write_escaped(Substitution
->getFromString()) << "\" equal to \"";
774 OS
.write_escaped(*MatchedValue
) << "\"";
777 if (MatchRange
.isValid())
778 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
, OS
.str(),
781 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()),
782 SourceMgr::DK_Note
, OS
.str());
787 static SMRange
ProcessMatchResult(FileCheckDiag::MatchType MatchTy
,
788 const SourceMgr
&SM
, SMLoc Loc
,
789 Check::FileCheckType CheckTy
,
790 StringRef Buffer
, size_t Pos
, size_t Len
,
791 std::vector
<FileCheckDiag
> *Diags
,
792 bool AdjustPrevDiag
= false) {
793 SMLoc Start
= SMLoc::getFromPointer(Buffer
.data() + Pos
);
794 SMLoc End
= SMLoc::getFromPointer(Buffer
.data() + Pos
+ Len
);
795 SMRange
Range(Start
, End
);
798 Diags
->rbegin()->MatchTy
= MatchTy
;
800 Diags
->emplace_back(SM
, CheckTy
, Loc
, MatchTy
, Range
);
805 void FileCheckPattern::printFuzzyMatch(
806 const SourceMgr
&SM
, StringRef Buffer
,
807 std::vector
<FileCheckDiag
> *Diags
) const {
808 // Attempt to find the closest/best fuzzy match. Usually an error happens
809 // because some string in the output didn't exactly match. In these cases, we
810 // would like to show the user a best guess at what "should have" matched, to
811 // save them having to actually check the input manually.
812 size_t NumLinesForward
= 0;
813 size_t Best
= StringRef::npos
;
814 double BestQuality
= 0;
816 // Use an arbitrary 4k limit on how far we will search.
817 for (size_t i
= 0, e
= std::min(size_t(4096), Buffer
.size()); i
!= e
; ++i
) {
818 if (Buffer
[i
] == '\n')
821 // Patterns have leading whitespace stripped, so skip whitespace when
822 // looking for something which looks like a pattern.
823 if (Buffer
[i
] == ' ' || Buffer
[i
] == '\t')
826 // Compute the "quality" of this match as an arbitrary combination of the
827 // match distance and the number of lines skipped to get to this match.
828 unsigned Distance
= computeMatchDistance(Buffer
.substr(i
));
829 double Quality
= Distance
+ (NumLinesForward
/ 100.);
831 if (Quality
< BestQuality
|| Best
== StringRef::npos
) {
833 BestQuality
= Quality
;
837 // Print the "possible intended match here" line if we found something
838 // reasonable and not equal to what we showed in the "scanning from here"
840 if (Best
&& Best
!= StringRef::npos
&& BestQuality
< 50) {
842 ProcessMatchResult(FileCheckDiag::MatchFuzzy
, SM
, getLoc(),
843 getCheckTy(), Buffer
, Best
, 0, Diags
);
844 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
,
845 "possible intended match here");
847 // FIXME: If we wanted to be really friendly we would show why the match
848 // failed, as it can be hard to spot simple one character differences.
853 FileCheckPatternContext::getPatternVarValue(StringRef VarName
) {
854 auto VarIter
= GlobalVariableTable
.find(VarName
);
855 if (VarIter
== GlobalVariableTable
.end())
856 return make_error
<FileCheckUndefVarError
>(VarName
);
858 return VarIter
->second
;
861 template <class... Types
>
862 FileCheckNumericVariable
*
863 FileCheckPatternContext::makeNumericVariable(Types
... args
) {
864 NumericVariables
.push_back(
865 llvm::make_unique
<FileCheckNumericVariable
>(args
...));
866 return NumericVariables
.back().get();
869 FileCheckSubstitution
*
870 FileCheckPatternContext::makeStringSubstitution(StringRef VarName
,
872 Substitutions
.push_back(
873 llvm::make_unique
<FileCheckStringSubstitution
>(this, VarName
, InsertIdx
));
874 return Substitutions
.back().get();
877 FileCheckSubstitution
*FileCheckPatternContext::makeNumericSubstitution(
878 StringRef ExpressionStr
,
879 std::unique_ptr
<FileCheckExpressionAST
> ExpressionAST
, size_t InsertIdx
) {
880 Substitutions
.push_back(llvm::make_unique
<FileCheckNumericSubstitution
>(
881 this, ExpressionStr
, std::move(ExpressionAST
), InsertIdx
));
882 return Substitutions
.back().get();
885 size_t FileCheckPattern::FindRegexVarEnd(StringRef Str
, SourceMgr
&SM
) {
886 // Offset keeps track of the current offset within the input Str
888 // [...] Nesting depth
889 size_t BracketDepth
= 0;
891 while (!Str
.empty()) {
892 if (Str
.startswith("]]") && BracketDepth
== 0)
894 if (Str
[0] == '\\') {
895 // Backslash escapes the next char within regexes, so skip them both.
906 if (BracketDepth
== 0) {
907 SM
.PrintMessage(SMLoc::getFromPointer(Str
.data()),
909 "missing closing \"]\" for regex variable");
920 return StringRef::npos
;
923 StringRef
FileCheck::CanonicalizeFile(MemoryBuffer
&MB
,
924 SmallVectorImpl
<char> &OutputBuffer
) {
925 OutputBuffer
.reserve(MB
.getBufferSize());
927 for (const char *Ptr
= MB
.getBufferStart(), *End
= MB
.getBufferEnd();
929 // Eliminate trailing dosish \r.
930 if (Ptr
<= End
- 2 && Ptr
[0] == '\r' && Ptr
[1] == '\n') {
934 // If current char is not a horizontal whitespace or if horizontal
935 // whitespace canonicalization is disabled, dump it to output as is.
936 if (Req
.NoCanonicalizeWhiteSpace
|| (*Ptr
!= ' ' && *Ptr
!= '\t')) {
937 OutputBuffer
.push_back(*Ptr
);
941 // Otherwise, add one space and advance over neighboring space.
942 OutputBuffer
.push_back(' ');
943 while (Ptr
+ 1 != End
&& (Ptr
[1] == ' ' || Ptr
[1] == '\t'))
947 // Add a null byte and then return all but that byte.
948 OutputBuffer
.push_back('\0');
949 return StringRef(OutputBuffer
.data(), OutputBuffer
.size() - 1);
952 FileCheckDiag::FileCheckDiag(const SourceMgr
&SM
,
953 const Check::FileCheckType
&CheckTy
,
954 SMLoc CheckLoc
, MatchType MatchTy
,
956 : CheckTy(CheckTy
), MatchTy(MatchTy
) {
957 auto Start
= SM
.getLineAndColumn(InputRange
.Start
);
958 auto End
= SM
.getLineAndColumn(InputRange
.End
);
959 InputStartLine
= Start
.first
;
960 InputStartCol
= Start
.second
;
961 InputEndLine
= End
.first
;
962 InputEndCol
= End
.second
;
963 Start
= SM
.getLineAndColumn(CheckLoc
);
964 CheckLine
= Start
.first
;
965 CheckCol
= Start
.second
;
968 static bool IsPartOfWord(char c
) {
969 return (isalnum(c
) || c
== '-' || c
== '_');
972 Check::FileCheckType
&Check::FileCheckType::setCount(int C
) {
973 assert(Count
> 0 && "zero and negative counts are not supported");
974 assert((C
== 1 || Kind
== CheckPlain
) &&
975 "count supported only for plain CHECK directives");
980 std::string
Check::FileCheckType::getDescription(StringRef Prefix
) const {
982 case Check::CheckNone
:
984 case Check::CheckPlain
:
986 return Prefix
.str() + "-COUNT";
988 case Check::CheckNext
:
989 return Prefix
.str() + "-NEXT";
990 case Check::CheckSame
:
991 return Prefix
.str() + "-SAME";
992 case Check::CheckNot
:
993 return Prefix
.str() + "-NOT";
994 case Check::CheckDAG
:
995 return Prefix
.str() + "-DAG";
996 case Check::CheckLabel
:
997 return Prefix
.str() + "-LABEL";
998 case Check::CheckEmpty
:
999 return Prefix
.str() + "-EMPTY";
1000 case Check::CheckEOF
:
1001 return "implicit EOF";
1002 case Check::CheckBadNot
:
1004 case Check::CheckBadCount
:
1007 llvm_unreachable("unknown FileCheckType");
1010 static std::pair
<Check::FileCheckType
, StringRef
>
1011 FindCheckType(StringRef Buffer
, StringRef Prefix
) {
1012 if (Buffer
.size() <= Prefix
.size())
1013 return {Check::CheckNone
, StringRef()};
1015 char NextChar
= Buffer
[Prefix
.size()];
1017 StringRef Rest
= Buffer
.drop_front(Prefix
.size() + 1);
1018 // Verify that the : is present after the prefix.
1019 if (NextChar
== ':')
1020 return {Check::CheckPlain
, Rest
};
1022 if (NextChar
!= '-')
1023 return {Check::CheckNone
, StringRef()};
1025 if (Rest
.consume_front("COUNT-")) {
1027 if (Rest
.consumeInteger(10, Count
))
1028 // Error happened in parsing integer.
1029 return {Check::CheckBadCount
, Rest
};
1030 if (Count
<= 0 || Count
> INT32_MAX
)
1031 return {Check::CheckBadCount
, Rest
};
1032 if (!Rest
.consume_front(":"))
1033 return {Check::CheckBadCount
, Rest
};
1034 return {Check::FileCheckType(Check::CheckPlain
).setCount(Count
), Rest
};
1037 if (Rest
.consume_front("NEXT:"))
1038 return {Check::CheckNext
, Rest
};
1040 if (Rest
.consume_front("SAME:"))
1041 return {Check::CheckSame
, Rest
};
1043 if (Rest
.consume_front("NOT:"))
1044 return {Check::CheckNot
, Rest
};
1046 if (Rest
.consume_front("DAG:"))
1047 return {Check::CheckDAG
, Rest
};
1049 if (Rest
.consume_front("LABEL:"))
1050 return {Check::CheckLabel
, Rest
};
1052 if (Rest
.consume_front("EMPTY:"))
1053 return {Check::CheckEmpty
, Rest
};
1055 // You can't combine -NOT with another suffix.
1056 if (Rest
.startswith("DAG-NOT:") || Rest
.startswith("NOT-DAG:") ||
1057 Rest
.startswith("NEXT-NOT:") || Rest
.startswith("NOT-NEXT:") ||
1058 Rest
.startswith("SAME-NOT:") || Rest
.startswith("NOT-SAME:") ||
1059 Rest
.startswith("EMPTY-NOT:") || Rest
.startswith("NOT-EMPTY:"))
1060 return {Check::CheckBadNot
, Rest
};
1062 return {Check::CheckNone
, Rest
};
1065 // From the given position, find the next character after the word.
1066 static size_t SkipWord(StringRef Str
, size_t Loc
) {
1067 while (Loc
< Str
.size() && IsPartOfWord(Str
[Loc
]))
1072 /// Searches the buffer for the first prefix in the prefix regular expression.
1074 /// This searches the buffer using the provided regular expression, however it
1075 /// enforces constraints beyond that:
1076 /// 1) The found prefix must not be a suffix of something that looks like
1078 /// 2) The found prefix must be followed by a valid check type suffix using \c
1079 /// FindCheckType above.
1081 /// \returns a pair of StringRefs into the Buffer, which combines:
1082 /// - the first match of the regular expression to satisfy these two is
1084 /// otherwise an empty StringRef is returned to indicate failure.
1085 /// - buffer rewound to the location right after parsed suffix, for parsing
1086 /// to continue from
1088 /// If this routine returns a valid prefix, it will also shrink \p Buffer to
1089 /// start at the beginning of the returned prefix, increment \p LineNumber for
1090 /// each new line consumed from \p Buffer, and set \p CheckTy to the type of
1091 /// check found by examining the suffix.
1093 /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
1095 static std::pair
<StringRef
, StringRef
>
1096 FindFirstMatchingPrefix(Regex
&PrefixRE
, StringRef
&Buffer
,
1097 unsigned &LineNumber
, Check::FileCheckType
&CheckTy
) {
1098 SmallVector
<StringRef
, 2> Matches
;
1100 while (!Buffer
.empty()) {
1101 // Find the first (longest) match using the RE.
1102 if (!PrefixRE
.match(Buffer
, &Matches
))
1103 // No match at all, bail.
1104 return {StringRef(), StringRef()};
1106 StringRef Prefix
= Matches
[0];
1109 assert(Prefix
.data() >= Buffer
.data() &&
1110 Prefix
.data() < Buffer
.data() + Buffer
.size() &&
1111 "Prefix doesn't start inside of buffer!");
1112 size_t Loc
= Prefix
.data() - Buffer
.data();
1113 StringRef Skipped
= Buffer
.substr(0, Loc
);
1114 Buffer
= Buffer
.drop_front(Loc
);
1115 LineNumber
+= Skipped
.count('\n');
1117 // Check that the matched prefix isn't a suffix of some other check-like
1119 // FIXME: This is a very ad-hoc check. it would be better handled in some
1120 // other way. Among other things it seems hard to distinguish between
1121 // intentional and unintentional uses of this feature.
1122 if (Skipped
.empty() || !IsPartOfWord(Skipped
.back())) {
1123 // Now extract the type.
1124 StringRef AfterSuffix
;
1125 std::tie(CheckTy
, AfterSuffix
) = FindCheckType(Buffer
, Prefix
);
1127 // If we've found a valid check type for this prefix, we're done.
1128 if (CheckTy
!= Check::CheckNone
)
1129 return {Prefix
, AfterSuffix
};
1132 // If we didn't successfully find a prefix, we need to skip this invalid
1133 // prefix and continue scanning. We directly skip the prefix that was
1134 // matched and any additional parts of that check-like word.
1135 Buffer
= Buffer
.drop_front(SkipWord(Buffer
, Prefix
.size()));
1138 // We ran out of buffer while skipping partial matches so give up.
1139 return {StringRef(), StringRef()};
1142 void FileCheckPatternContext::createLineVariable() {
1143 assert(!LineVariable
&& "@LINE pseudo numeric variable already created");
1144 StringRef LineName
= "@LINE";
1145 LineVariable
= makeNumericVariable(LineName
);
1146 GlobalNumericVariableTable
[LineName
] = LineVariable
;
1149 bool FileCheck::ReadCheckFile(SourceMgr
&SM
, StringRef Buffer
, Regex
&PrefixRE
,
1150 std::vector
<FileCheckString
> &CheckStrings
) {
1152 PatternContext
.defineCmdlineVariables(Req
.GlobalDefines
, SM
);
1154 logAllUnhandledErrors(std::move(DefineError
), errs());
1158 PatternContext
.createLineVariable();
1160 std::vector
<FileCheckPattern
> ImplicitNegativeChecks
;
1161 for (const auto &PatternString
: Req
.ImplicitCheckNot
) {
1162 // Create a buffer with fake command line content in order to display the
1163 // command line option responsible for the specific implicit CHECK-NOT.
1164 std::string Prefix
= "-implicit-check-not='";
1165 std::string Suffix
= "'";
1166 std::unique_ptr
<MemoryBuffer
> CmdLine
= MemoryBuffer::getMemBufferCopy(
1167 Prefix
+ PatternString
+ Suffix
, "command line");
1169 StringRef PatternInBuffer
=
1170 CmdLine
->getBuffer().substr(Prefix
.size(), PatternString
.size());
1171 SM
.AddNewSourceBuffer(std::move(CmdLine
), SMLoc());
1173 ImplicitNegativeChecks
.push_back(
1174 FileCheckPattern(Check::CheckNot
, &PatternContext
));
1175 ImplicitNegativeChecks
.back().parsePattern(PatternInBuffer
,
1176 "IMPLICIT-CHECK", SM
, Req
);
1179 std::vector
<FileCheckPattern
> DagNotMatches
= ImplicitNegativeChecks
;
1181 // LineNumber keeps track of the line on which CheckPrefix instances are
1183 unsigned LineNumber
= 1;
1186 Check::FileCheckType CheckTy
;
1188 // See if a prefix occurs in the memory buffer.
1189 StringRef UsedPrefix
;
1190 StringRef AfterSuffix
;
1191 std::tie(UsedPrefix
, AfterSuffix
) =
1192 FindFirstMatchingPrefix(PrefixRE
, Buffer
, LineNumber
, CheckTy
);
1193 if (UsedPrefix
.empty())
1195 assert(UsedPrefix
.data() == Buffer
.data() &&
1196 "Failed to move Buffer's start forward, or pointed prefix outside "
1198 assert(AfterSuffix
.data() >= Buffer
.data() &&
1199 AfterSuffix
.data() < Buffer
.data() + Buffer
.size() &&
1200 "Parsing after suffix doesn't start inside of buffer!");
1202 // Location to use for error messages.
1203 const char *UsedPrefixStart
= UsedPrefix
.data();
1205 // Skip the buffer to the end of parsed suffix (or just prefix, if no good
1206 // suffix was processed).
1207 Buffer
= AfterSuffix
.empty() ? Buffer
.drop_front(UsedPrefix
.size())
1210 // Complain about useful-looking but unsupported suffixes.
1211 if (CheckTy
== Check::CheckBadNot
) {
1212 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Error
,
1213 "unsupported -NOT combo on prefix '" + UsedPrefix
+ "'");
1217 // Complain about invalid count specification.
1218 if (CheckTy
== Check::CheckBadCount
) {
1219 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Error
,
1220 "invalid count in -COUNT specification on prefix '" +
1225 // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
1226 // leading whitespace.
1227 if (!(Req
.NoCanonicalizeWhiteSpace
&& Req
.MatchFullLines
))
1228 Buffer
= Buffer
.substr(Buffer
.find_first_not_of(" \t"));
1230 // Scan ahead to the end of line.
1231 size_t EOL
= Buffer
.find_first_of("\n\r");
1233 // Remember the location of the start of the pattern, for diagnostics.
1234 SMLoc PatternLoc
= SMLoc::getFromPointer(Buffer
.data());
1236 // Parse the pattern.
1237 FileCheckPattern
P(CheckTy
, &PatternContext
, LineNumber
);
1238 if (P
.parsePattern(Buffer
.substr(0, EOL
), UsedPrefix
, SM
, Req
))
1241 // Verify that CHECK-LABEL lines do not define or use variables
1242 if ((CheckTy
== Check::CheckLabel
) && P
.hasVariable()) {
1244 SMLoc::getFromPointer(UsedPrefixStart
), SourceMgr::DK_Error
,
1245 "found '" + UsedPrefix
+ "-LABEL:'"
1246 " with variable definition or use");
1250 Buffer
= Buffer
.substr(EOL
);
1252 // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
1253 if ((CheckTy
== Check::CheckNext
|| CheckTy
== Check::CheckSame
||
1254 CheckTy
== Check::CheckEmpty
) &&
1255 CheckStrings
.empty()) {
1256 StringRef Type
= CheckTy
== Check::CheckNext
1258 : CheckTy
== Check::CheckEmpty
? "EMPTY" : "SAME";
1259 SM
.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart
),
1260 SourceMgr::DK_Error
,
1261 "found '" + UsedPrefix
+ "-" + Type
+
1262 "' without previous '" + UsedPrefix
+ ": line");
1266 // Handle CHECK-DAG/-NOT.
1267 if (CheckTy
== Check::CheckDAG
|| CheckTy
== Check::CheckNot
) {
1268 DagNotMatches
.push_back(P
);
1272 // Okay, add the string we captured to the output vector and move on.
1273 CheckStrings
.emplace_back(P
, UsedPrefix
, PatternLoc
);
1274 std::swap(DagNotMatches
, CheckStrings
.back().DagNotStrings
);
1275 DagNotMatches
= ImplicitNegativeChecks
;
1278 // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first
1279 // prefix as a filler for the error message.
1280 if (!DagNotMatches
.empty()) {
1281 CheckStrings
.emplace_back(
1282 FileCheckPattern(Check::CheckEOF
, &PatternContext
, LineNumber
+ 1),
1283 *Req
.CheckPrefixes
.begin(), SMLoc::getFromPointer(Buffer
.data()));
1284 std::swap(DagNotMatches
, CheckStrings
.back().DagNotStrings
);
1287 if (CheckStrings
.empty()) {
1288 errs() << "error: no check strings found with prefix"
1289 << (Req
.CheckPrefixes
.size() > 1 ? "es " : " ");
1290 auto I
= Req
.CheckPrefixes
.begin();
1291 auto E
= Req
.CheckPrefixes
.end();
1293 errs() << "\'" << *I
<< ":'";
1297 errs() << ", \'" << *I
<< ":'";
1306 static void PrintMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1307 StringRef Prefix
, SMLoc Loc
, const FileCheckPattern
&Pat
,
1308 int MatchedCount
, StringRef Buffer
, size_t MatchPos
,
1309 size_t MatchLen
, const FileCheckRequest
&Req
,
1310 std::vector
<FileCheckDiag
> *Diags
) {
1311 bool PrintDiag
= true;
1312 if (ExpectedMatch
) {
1315 if (!Req
.VerboseVerbose
&& Pat
.getCheckTy() == Check::CheckEOF
)
1317 // Due to their verbosity, we don't print verbose diagnostics here if we're
1318 // gathering them for a different rendering, but we always print other
1322 SMRange MatchRange
= ProcessMatchResult(
1323 ExpectedMatch
? FileCheckDiag::MatchFoundAndExpected
1324 : FileCheckDiag::MatchFoundButExcluded
,
1325 SM
, Loc
, Pat
.getCheckTy(), Buffer
, MatchPos
, MatchLen
, Diags
);
1329 std::string Message
= formatv("{0}: {1} string found in input",
1330 Pat
.getCheckTy().getDescription(Prefix
),
1331 (ExpectedMatch
? "expected" : "excluded"))
1333 if (Pat
.getCount() > 1)
1334 Message
+= formatv(" ({0} out of {1})", MatchedCount
, Pat
.getCount()).str();
1337 Loc
, ExpectedMatch
? SourceMgr::DK_Remark
: SourceMgr::DK_Error
, Message
);
1338 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
, "found here",
1340 Pat
.printSubstitutions(SM
, Buffer
, MatchRange
);
1343 static void PrintMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1344 const FileCheckString
&CheckStr
, int MatchedCount
,
1345 StringRef Buffer
, size_t MatchPos
, size_t MatchLen
,
1346 FileCheckRequest
&Req
,
1347 std::vector
<FileCheckDiag
> *Diags
) {
1348 PrintMatch(ExpectedMatch
, SM
, CheckStr
.Prefix
, CheckStr
.Loc
, CheckStr
.Pat
,
1349 MatchedCount
, Buffer
, MatchPos
, MatchLen
, Req
, Diags
);
1352 static void PrintNoMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1353 StringRef Prefix
, SMLoc Loc
,
1354 const FileCheckPattern
&Pat
, int MatchedCount
,
1355 StringRef Buffer
, bool VerboseVerbose
,
1356 std::vector
<FileCheckDiag
> *Diags
, Error MatchErrors
) {
1357 assert(MatchErrors
&& "Called on successful match");
1358 bool PrintDiag
= true;
1359 if (!ExpectedMatch
) {
1360 if (!VerboseVerbose
) {
1361 consumeError(std::move(MatchErrors
));
1364 // Due to their verbosity, we don't print verbose diagnostics here if we're
1365 // gathering them for a different rendering, but we always print other
1370 // If the current position is at the end of a line, advance to the start of
1372 Buffer
= Buffer
.substr(Buffer
.find_first_not_of(" \t\n\r"));
1373 SMRange SearchRange
= ProcessMatchResult(
1374 ExpectedMatch
? FileCheckDiag::MatchNoneButExpected
1375 : FileCheckDiag::MatchNoneAndExcluded
,
1376 SM
, Loc
, Pat
.getCheckTy(), Buffer
, 0, Buffer
.size(), Diags
);
1378 consumeError(std::move(MatchErrors
));
1383 handleErrors(std::move(MatchErrors
),
1384 [](const FileCheckErrorDiagnostic
&E
) { E
.log(errs()); });
1386 // No problem matching the string per se.
1389 consumeError(std::move(MatchErrors
));
1391 // Print "not found" diagnostic.
1392 std::string Message
= formatv("{0}: {1} string not found in input",
1393 Pat
.getCheckTy().getDescription(Prefix
),
1394 (ExpectedMatch
? "expected" : "excluded"))
1396 if (Pat
.getCount() > 1)
1397 Message
+= formatv(" ({0} out of {1})", MatchedCount
, Pat
.getCount()).str();
1399 Loc
, ExpectedMatch
? SourceMgr::DK_Error
: SourceMgr::DK_Remark
, Message
);
1401 // Print the "scanning from here" line.
1402 SM
.PrintMessage(SearchRange
.Start
, SourceMgr::DK_Note
, "scanning from here");
1404 // Allow the pattern to print additional information if desired.
1405 Pat
.printSubstitutions(SM
, Buffer
);
1408 Pat
.printFuzzyMatch(SM
, Buffer
, Diags
);
1411 static void PrintNoMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1412 const FileCheckString
&CheckStr
, int MatchedCount
,
1413 StringRef Buffer
, bool VerboseVerbose
,
1414 std::vector
<FileCheckDiag
> *Diags
, Error MatchErrors
) {
1415 PrintNoMatch(ExpectedMatch
, SM
, CheckStr
.Prefix
, CheckStr
.Loc
, CheckStr
.Pat
,
1416 MatchedCount
, Buffer
, VerboseVerbose
, Diags
,
1417 std::move(MatchErrors
));
1420 /// Counts the number of newlines in the specified range.
1421 static unsigned CountNumNewlinesBetween(StringRef Range
,
1422 const char *&FirstNewLine
) {
1423 unsigned NumNewLines
= 0;
1425 // Scan for newline.
1426 Range
= Range
.substr(Range
.find_first_of("\n\r"));
1432 // Handle \n\r and \r\n as a single newline.
1433 if (Range
.size() > 1 && (Range
[1] == '\n' || Range
[1] == '\r') &&
1434 (Range
[0] != Range
[1]))
1435 Range
= Range
.substr(1);
1436 Range
= Range
.substr(1);
1438 if (NumNewLines
== 1)
1439 FirstNewLine
= Range
.begin();
1443 size_t FileCheckString::Check(const SourceMgr
&SM
, StringRef Buffer
,
1444 bool IsLabelScanMode
, size_t &MatchLen
,
1445 FileCheckRequest
&Req
,
1446 std::vector
<FileCheckDiag
> *Diags
) const {
1448 std::vector
<const FileCheckPattern
*> NotStrings
;
1450 // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
1451 // bounds; we have not processed variable definitions within the bounded block
1452 // yet so cannot handle any final CHECK-DAG yet; this is handled when going
1453 // over the block again (including the last CHECK-LABEL) in normal mode.
1454 if (!IsLabelScanMode
) {
1455 // Match "dag strings" (with mixed "not strings" if any).
1456 LastPos
= CheckDag(SM
, Buffer
, NotStrings
, Req
, Diags
);
1457 if (LastPos
== StringRef::npos
)
1458 return StringRef::npos
;
1461 // Match itself from the last position after matching CHECK-DAG.
1462 size_t LastMatchEnd
= LastPos
;
1463 size_t FirstMatchPos
= 0;
1464 // Go match the pattern Count times. Majority of patterns only match with
1466 assert(Pat
.getCount() != 0 && "pattern count can not be zero");
1467 for (int i
= 1; i
<= Pat
.getCount(); i
++) {
1468 StringRef MatchBuffer
= Buffer
.substr(LastMatchEnd
);
1469 size_t CurrentMatchLen
;
1470 // get a match at current start point
1471 Expected
<size_t> MatchResult
= Pat
.match(MatchBuffer
, CurrentMatchLen
, SM
);
1475 PrintNoMatch(true, SM
, *this, i
, MatchBuffer
, Req
.VerboseVerbose
, Diags
,
1476 MatchResult
.takeError());
1477 return StringRef::npos
;
1479 size_t MatchPos
= *MatchResult
;
1480 PrintMatch(true, SM
, *this, i
, MatchBuffer
, MatchPos
, CurrentMatchLen
, Req
,
1483 FirstMatchPos
= LastPos
+ MatchPos
;
1485 // move start point after the match
1486 LastMatchEnd
+= MatchPos
+ CurrentMatchLen
;
1488 // Full match len counts from first match pos.
1489 MatchLen
= LastMatchEnd
- FirstMatchPos
;
1491 // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
1493 if (!IsLabelScanMode
) {
1494 size_t MatchPos
= FirstMatchPos
- LastPos
;
1495 StringRef MatchBuffer
= Buffer
.substr(LastPos
);
1496 StringRef SkippedRegion
= Buffer
.substr(LastPos
, MatchPos
);
1498 // If this check is a "CHECK-NEXT", verify that the previous match was on
1499 // the previous line (i.e. that there is one newline between them).
1500 if (CheckNext(SM
, SkippedRegion
)) {
1501 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine
, SM
, Loc
,
1502 Pat
.getCheckTy(), MatchBuffer
, MatchPos
, MatchLen
,
1503 Diags
, Req
.Verbose
);
1504 return StringRef::npos
;
1507 // If this check is a "CHECK-SAME", verify that the previous match was on
1508 // the same line (i.e. that there is no newline between them).
1509 if (CheckSame(SM
, SkippedRegion
)) {
1510 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine
, SM
, Loc
,
1511 Pat
.getCheckTy(), MatchBuffer
, MatchPos
, MatchLen
,
1512 Diags
, Req
.Verbose
);
1513 return StringRef::npos
;
1516 // If this match had "not strings", verify that they don't exist in the
1518 if (CheckNot(SM
, SkippedRegion
, NotStrings
, Req
, Diags
))
1519 return StringRef::npos
;
1522 return FirstMatchPos
;
1525 bool FileCheckString::CheckNext(const SourceMgr
&SM
, StringRef Buffer
) const {
1526 if (Pat
.getCheckTy() != Check::CheckNext
&&
1527 Pat
.getCheckTy() != Check::CheckEmpty
)
1532 Twine(Pat
.getCheckTy() == Check::CheckEmpty
? "-EMPTY" : "-NEXT");
1534 // Count the number of newlines between the previous match and this one.
1535 const char *FirstNewLine
= nullptr;
1536 unsigned NumNewLines
= CountNumNewlinesBetween(Buffer
, FirstNewLine
);
1538 if (NumNewLines
== 0) {
1539 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
1540 CheckName
+ ": is on the same line as previous match");
1541 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
1542 "'next' match was here");
1543 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
1544 "previous match ended here");
1548 if (NumNewLines
!= 1) {
1549 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
1551 ": is not on the line after the previous match");
1552 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
1553 "'next' match was here");
1554 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
1555 "previous match ended here");
1556 SM
.PrintMessage(SMLoc::getFromPointer(FirstNewLine
), SourceMgr::DK_Note
,
1557 "non-matching line after previous match is here");
1564 bool FileCheckString::CheckSame(const SourceMgr
&SM
, StringRef Buffer
) const {
1565 if (Pat
.getCheckTy() != Check::CheckSame
)
1568 // Count the number of newlines between the previous match and this one.
1569 const char *FirstNewLine
= nullptr;
1570 unsigned NumNewLines
= CountNumNewlinesBetween(Buffer
, FirstNewLine
);
1572 if (NumNewLines
!= 0) {
1573 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
1575 "-SAME: is not on the same line as the previous match");
1576 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
1577 "'next' match was here");
1578 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
1579 "previous match ended here");
1586 bool FileCheckString::CheckNot(
1587 const SourceMgr
&SM
, StringRef Buffer
,
1588 const std::vector
<const FileCheckPattern
*> &NotStrings
,
1589 const FileCheckRequest
&Req
, std::vector
<FileCheckDiag
> *Diags
) const {
1590 for (const FileCheckPattern
*Pat
: NotStrings
) {
1591 assert((Pat
->getCheckTy() == Check::CheckNot
) && "Expect CHECK-NOT!");
1593 size_t MatchLen
= 0;
1594 Expected
<size_t> MatchResult
= Pat
->match(Buffer
, MatchLen
, SM
);
1597 PrintNoMatch(false, SM
, Prefix
, Pat
->getLoc(), *Pat
, 1, Buffer
,
1598 Req
.VerboseVerbose
, Diags
, MatchResult
.takeError());
1601 size_t Pos
= *MatchResult
;
1603 PrintMatch(false, SM
, Prefix
, Pat
->getLoc(), *Pat
, 1, Buffer
, Pos
, MatchLen
,
1613 FileCheckString::CheckDag(const SourceMgr
&SM
, StringRef Buffer
,
1614 std::vector
<const FileCheckPattern
*> &NotStrings
,
1615 const FileCheckRequest
&Req
,
1616 std::vector
<FileCheckDiag
> *Diags
) const {
1617 if (DagNotStrings
.empty())
1620 // The start of the search range.
1621 size_t StartPos
= 0;
1627 // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
1628 // ranges are erased from this list once they are no longer in the search
1630 std::list
<MatchRange
> MatchRanges
;
1632 // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
1633 // group, so we don't use a range-based for loop here.
1634 for (auto PatItr
= DagNotStrings
.begin(), PatEnd
= DagNotStrings
.end();
1635 PatItr
!= PatEnd
; ++PatItr
) {
1636 const FileCheckPattern
&Pat
= *PatItr
;
1637 assert((Pat
.getCheckTy() == Check::CheckDAG
||
1638 Pat
.getCheckTy() == Check::CheckNot
) &&
1639 "Invalid CHECK-DAG or CHECK-NOT!");
1641 if (Pat
.getCheckTy() == Check::CheckNot
) {
1642 NotStrings
.push_back(&Pat
);
1646 assert((Pat
.getCheckTy() == Check::CheckDAG
) && "Expect CHECK-DAG!");
1648 // CHECK-DAG always matches from the start.
1649 size_t MatchLen
= 0, MatchPos
= StartPos
;
1651 // Search for a match that doesn't overlap a previous match in this
1653 for (auto MI
= MatchRanges
.begin(), ME
= MatchRanges
.end(); true; ++MI
) {
1654 StringRef MatchBuffer
= Buffer
.substr(MatchPos
);
1655 Expected
<size_t> MatchResult
= Pat
.match(MatchBuffer
, MatchLen
, SM
);
1656 // With a group of CHECK-DAGs, a single mismatching means the match on
1657 // that group of CHECK-DAGs fails immediately.
1659 PrintNoMatch(true, SM
, Prefix
, Pat
.getLoc(), Pat
, 1, MatchBuffer
,
1660 Req
.VerboseVerbose
, Diags
, MatchResult
.takeError());
1661 return StringRef::npos
;
1663 size_t MatchPosBuf
= *MatchResult
;
1664 // Re-calc it as the offset relative to the start of the original string.
1665 MatchPos
+= MatchPosBuf
;
1666 if (Req
.VerboseVerbose
)
1667 PrintMatch(true, SM
, Prefix
, Pat
.getLoc(), Pat
, 1, Buffer
, MatchPos
,
1668 MatchLen
, Req
, Diags
);
1669 MatchRange M
{MatchPos
, MatchPos
+ MatchLen
};
1670 if (Req
.AllowDeprecatedDagOverlap
) {
1671 // We don't need to track all matches in this mode, so we just maintain
1672 // one match range that encompasses the current CHECK-DAG group's
1674 if (MatchRanges
.empty())
1675 MatchRanges
.insert(MatchRanges
.end(), M
);
1677 auto Block
= MatchRanges
.begin();
1678 Block
->Pos
= std::min(Block
->Pos
, M
.Pos
);
1679 Block
->End
= std::max(Block
->End
, M
.End
);
1683 // Iterate previous matches until overlapping match or insertion point.
1684 bool Overlap
= false;
1685 for (; MI
!= ME
; ++MI
) {
1686 if (M
.Pos
< MI
->End
) {
1687 // !Overlap => New match has no overlap and is before this old match.
1688 // Overlap => New match overlaps this old match.
1689 Overlap
= MI
->Pos
< M
.End
;
1694 // Insert non-overlapping match into list.
1695 MatchRanges
.insert(MI
, M
);
1698 if (Req
.VerboseVerbose
) {
1699 // Due to their verbosity, we don't print verbose diagnostics here if
1700 // we're gathering them for a different rendering, but we always print
1701 // other diagnostics.
1703 SMLoc OldStart
= SMLoc::getFromPointer(Buffer
.data() + MI
->Pos
);
1704 SMLoc OldEnd
= SMLoc::getFromPointer(Buffer
.data() + MI
->End
);
1705 SMRange
OldRange(OldStart
, OldEnd
);
1706 SM
.PrintMessage(OldStart
, SourceMgr::DK_Note
,
1707 "match discarded, overlaps earlier DAG match here",
1710 Diags
->rbegin()->MatchTy
= FileCheckDiag::MatchFoundButDiscarded
;
1714 if (!Req
.VerboseVerbose
)
1715 PrintMatch(true, SM
, Prefix
, Pat
.getLoc(), Pat
, 1, Buffer
, MatchPos
,
1716 MatchLen
, Req
, Diags
);
1718 // Handle the end of a CHECK-DAG group.
1719 if (std::next(PatItr
) == PatEnd
||
1720 std::next(PatItr
)->getCheckTy() == Check::CheckNot
) {
1721 if (!NotStrings
.empty()) {
1722 // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
1723 // CHECK-DAG, verify that there are no 'not' strings occurred in that
1725 StringRef SkippedRegion
=
1726 Buffer
.slice(StartPos
, MatchRanges
.begin()->Pos
);
1727 if (CheckNot(SM
, SkippedRegion
, NotStrings
, Req
, Diags
))
1728 return StringRef::npos
;
1729 // Clear "not strings".
1732 // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
1733 // end of this CHECK-DAG group's match range.
1734 StartPos
= MatchRanges
.rbegin()->End
;
1735 // Don't waste time checking for (impossible) overlaps before that.
1736 MatchRanges
.clear();
1743 // A check prefix must contain only alphanumeric, hyphens and underscores.
1744 static bool ValidateCheckPrefix(StringRef CheckPrefix
) {
1745 Regex
Validator("^[a-zA-Z0-9_-]*$");
1746 return Validator
.match(CheckPrefix
);
1749 bool FileCheck::ValidateCheckPrefixes() {
1750 StringSet
<> PrefixSet
;
1752 for (StringRef Prefix
: Req
.CheckPrefixes
) {
1753 // Reject empty prefixes.
1757 if (!PrefixSet
.insert(Prefix
).second
)
1760 if (!ValidateCheckPrefix(Prefix
))
1767 Regex
FileCheck::buildCheckPrefixRegex() {
1768 // I don't think there's a way to specify an initial value for cl::list,
1769 // so if nothing was specified, add the default
1770 if (Req
.CheckPrefixes
.empty())
1771 Req
.CheckPrefixes
.push_back("CHECK");
1773 // We already validated the contents of CheckPrefixes so just concatenate
1774 // them as alternatives.
1775 SmallString
<32> PrefixRegexStr
;
1776 for (StringRef Prefix
: Req
.CheckPrefixes
) {
1777 if (Prefix
!= Req
.CheckPrefixes
.front())
1778 PrefixRegexStr
.push_back('|');
1780 PrefixRegexStr
.append(Prefix
);
1783 return Regex(PrefixRegexStr
);
1786 Error
FileCheckPatternContext::defineCmdlineVariables(
1787 std::vector
<std::string
> &CmdlineDefines
, SourceMgr
&SM
) {
1788 assert(GlobalVariableTable
.empty() && GlobalNumericVariableTable
.empty() &&
1789 "Overriding defined variable with command-line variable definitions");
1791 if (CmdlineDefines
.empty())
1792 return Error::success();
1794 // Create a string representing the vector of command-line definitions. Each
1795 // definition is on its own line and prefixed with a definition number to
1796 // clarify which definition a given diagnostic corresponds to.
1798 Error Errs
= Error::success();
1799 std::string CmdlineDefsDiag
;
1800 SmallVector
<std::pair
<size_t, size_t>, 4> CmdlineDefsIndices
;
1801 for (StringRef CmdlineDef
: CmdlineDefines
) {
1802 std::string DefPrefix
= ("Global define #" + Twine(++I
) + ": ").str();
1803 size_t EqIdx
= CmdlineDef
.find('=');
1804 if (EqIdx
== StringRef::npos
) {
1805 CmdlineDefsIndices
.push_back(std::make_pair(CmdlineDefsDiag
.size(), 0));
1808 // Numeric variable definition.
1809 if (CmdlineDef
[0] == '#') {
1810 // Append a copy of the command-line definition adapted to use the same
1811 // format as in the input file to be able to reuse
1812 // parseNumericSubstitutionBlock.
1813 CmdlineDefsDiag
+= (DefPrefix
+ CmdlineDef
+ " (parsed as: [[").str();
1814 std::string SubstitutionStr
= CmdlineDef
;
1815 SubstitutionStr
[EqIdx
] = ':';
1816 CmdlineDefsIndices
.push_back(
1817 std::make_pair(CmdlineDefsDiag
.size(), SubstitutionStr
.size()));
1818 CmdlineDefsDiag
+= (SubstitutionStr
+ Twine("]])\n")).str();
1820 CmdlineDefsDiag
+= DefPrefix
;
1821 CmdlineDefsIndices
.push_back(
1822 std::make_pair(CmdlineDefsDiag
.size(), CmdlineDef
.size()));
1823 CmdlineDefsDiag
+= (CmdlineDef
+ "\n").str();
1827 // Create a buffer with fake command line content in order to display
1828 // parsing diagnostic with location information and point to the
1829 // global definition with invalid syntax.
1830 std::unique_ptr
<MemoryBuffer
> CmdLineDefsDiagBuffer
=
1831 MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag
, "Global defines");
1832 StringRef CmdlineDefsDiagRef
= CmdLineDefsDiagBuffer
->getBuffer();
1833 SM
.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer
), SMLoc());
1835 for (std::pair
<size_t, size_t> CmdlineDefIndices
: CmdlineDefsIndices
) {
1836 StringRef CmdlineDef
= CmdlineDefsDiagRef
.substr(CmdlineDefIndices
.first
,
1837 CmdlineDefIndices
.second
);
1838 if (CmdlineDef
.empty()) {
1841 FileCheckErrorDiagnostic::get(
1842 SM
, CmdlineDef
, "missing equal sign in global definition"));
1846 // Numeric variable definition.
1847 if (CmdlineDef
[0] == '#') {
1848 // Now parse the definition both to check that the syntax is correct and
1849 // to create the necessary class instance.
1850 StringRef CmdlineDefExpr
= CmdlineDef
.substr(1);
1851 Optional
<FileCheckNumericVariable
*> DefinedNumericVariable
;
1852 Expected
<std::unique_ptr
<FileCheckExpressionAST
>> ExpressionASTResult
=
1853 FileCheckPattern::parseNumericSubstitutionBlock(
1854 CmdlineDefExpr
, DefinedNumericVariable
, false, None
, this, SM
);
1855 if (!ExpressionASTResult
) {
1856 Errs
= joinErrors(std::move(Errs
), ExpressionASTResult
.takeError());
1859 std::unique_ptr
<FileCheckExpressionAST
> ExpressionAST
=
1860 std::move(*ExpressionASTResult
);
1861 // Now evaluate the expression whose value this variable should be set
1862 // to, since the expression of a command-line variable definition should
1863 // only use variables defined earlier on the command-line. If not, this
1864 // is an error and we report it.
1865 Expected
<uint64_t> Value
= ExpressionAST
->eval();
1867 Errs
= joinErrors(std::move(Errs
), Value
.takeError());
1871 assert(DefinedNumericVariable
&& "No variable defined");
1872 (*DefinedNumericVariable
)->setValue(*Value
);
1874 // Record this variable definition.
1875 GlobalNumericVariableTable
[(*DefinedNumericVariable
)->getName()] =
1876 *DefinedNumericVariable
;
1878 // String variable definition.
1879 std::pair
<StringRef
, StringRef
> CmdlineNameVal
= CmdlineDef
.split('=');
1880 StringRef CmdlineName
= CmdlineNameVal
.first
;
1881 StringRef OrigCmdlineName
= CmdlineName
;
1882 Expected
<FileCheckPattern::VariableProperties
> ParseVarResult
=
1883 FileCheckPattern::parseVariable(CmdlineName
, SM
);
1884 if (!ParseVarResult
) {
1885 Errs
= joinErrors(std::move(Errs
), ParseVarResult
.takeError());
1888 // Check that CmdlineName does not denote a pseudo variable is only
1889 // composed of the parsed numeric variable. This catches cases like
1890 // "FOO+2" in a "FOO+2=10" definition.
1891 if (ParseVarResult
->IsPseudo
|| !CmdlineName
.empty()) {
1892 Errs
= joinErrors(std::move(Errs
),
1893 FileCheckErrorDiagnostic::get(
1894 SM
, OrigCmdlineName
,
1895 "invalid name in string variable definition '" +
1896 OrigCmdlineName
+ "'"));
1899 StringRef Name
= ParseVarResult
->Name
;
1901 // Detect collisions between string and numeric variables when the former
1902 // is created later than the latter.
1903 if (GlobalNumericVariableTable
.find(Name
) !=
1904 GlobalNumericVariableTable
.end()) {
1905 Errs
= joinErrors(std::move(Errs
), FileCheckErrorDiagnostic::get(
1907 "numeric variable with name '" +
1908 Name
+ "' already exists"));
1911 GlobalVariableTable
.insert(CmdlineNameVal
);
1912 // Mark the string variable as defined to detect collisions between
1913 // string and numeric variables in defineCmdlineVariables when the latter
1914 // is created later than the former. We cannot reuse GlobalVariableTable
1915 // for this by populating it with an empty string since we would then
1916 // lose the ability to detect the use of an undefined variable in
1918 DefinedVariableTable
[Name
] = true;
1925 void FileCheckPatternContext::clearLocalVars() {
1926 SmallVector
<StringRef
, 16> LocalPatternVars
, LocalNumericVars
;
1927 for (const StringMapEntry
<StringRef
> &Var
: GlobalVariableTable
)
1928 if (Var
.first()[0] != '$')
1929 LocalPatternVars
.push_back(Var
.first());
1931 // Numeric substitution reads the value of a variable directly, not via
1932 // GlobalNumericVariableTable. Therefore, we clear local variables by
1933 // clearing their value which will lead to a numeric substitution failure. We
1934 // also mark the variable for removal from GlobalNumericVariableTable since
1935 // this is what defineCmdlineVariables checks to decide that no global
1936 // variable has been defined.
1937 for (const auto &Var
: GlobalNumericVariableTable
)
1938 if (Var
.first()[0] != '$') {
1939 Var
.getValue()->clearValue();
1940 LocalNumericVars
.push_back(Var
.first());
1943 for (const auto &Var
: LocalPatternVars
)
1944 GlobalVariableTable
.erase(Var
);
1945 for (const auto &Var
: LocalNumericVars
)
1946 GlobalNumericVariableTable
.erase(Var
);
1949 bool FileCheck::CheckInput(SourceMgr
&SM
, StringRef Buffer
,
1950 ArrayRef
<FileCheckString
> CheckStrings
,
1951 std::vector
<FileCheckDiag
> *Diags
) {
1952 bool ChecksFailed
= false;
1954 unsigned i
= 0, j
= 0, e
= CheckStrings
.size();
1956 StringRef CheckRegion
;
1958 CheckRegion
= Buffer
;
1960 const FileCheckString
&CheckLabelStr
= CheckStrings
[j
];
1961 if (CheckLabelStr
.Pat
.getCheckTy() != Check::CheckLabel
) {
1966 // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
1967 size_t MatchLabelLen
= 0;
1968 size_t MatchLabelPos
=
1969 CheckLabelStr
.Check(SM
, Buffer
, true, MatchLabelLen
, Req
, Diags
);
1970 if (MatchLabelPos
== StringRef::npos
)
1971 // Immediately bail if CHECK-LABEL fails, nothing else we can do.
1974 CheckRegion
= Buffer
.substr(0, MatchLabelPos
+ MatchLabelLen
);
1975 Buffer
= Buffer
.substr(MatchLabelPos
+ MatchLabelLen
);
1979 // Do not clear the first region as it's the one before the first
1980 // CHECK-LABEL and it would clear variables defined on the command-line
1981 // before they get used.
1982 if (i
!= 0 && Req
.EnableVarScope
)
1983 PatternContext
.clearLocalVars();
1985 for (; i
!= j
; ++i
) {
1986 const FileCheckString
&CheckStr
= CheckStrings
[i
];
1988 // Check each string within the scanned region, including a second check
1989 // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
1990 size_t MatchLen
= 0;
1992 CheckStr
.Check(SM
, CheckRegion
, false, MatchLen
, Req
, Diags
);
1994 if (MatchPos
== StringRef::npos
) {
1995 ChecksFailed
= true;
2000 CheckRegion
= CheckRegion
.substr(MatchPos
+ MatchLen
);
2007 // Success if no checks failed.
2008 return !ChecksFailed
;