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/FileCheck/FileCheck.h"
17 #include "FileCheckImpl.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/StringSet.h"
21 #include "llvm/ADT/Twine.h"
22 #include "llvm/Support/CheckedArithmetic.h"
23 #include "llvm/Support/FormatVariadic.h"
32 StringRef
ExpressionFormat::toString() const {
35 return StringRef("<none>");
37 return StringRef("%u");
39 return StringRef("%d");
41 return StringRef("%X");
43 return StringRef("%x");
45 llvm_unreachable("unknown expression format");
48 Expected
<std::string
> ExpressionFormat::getWildcardRegex() const {
49 StringRef AlternateFormPrefix
= AlternateForm
? StringRef("0x") : StringRef();
51 auto CreatePrecisionRegex
= [&](StringRef S
) {
52 return (Twine(AlternateFormPrefix
) + S
+ Twine('{') + Twine(Precision
) +
60 return CreatePrecisionRegex("([1-9][0-9]*)?[0-9]");
61 return std::string("[0-9]+");
64 return CreatePrecisionRegex("-?([1-9][0-9]*)?[0-9]");
65 return std::string("-?[0-9]+");
68 return CreatePrecisionRegex("([1-9A-F][0-9A-F]*)?[0-9A-F]");
69 return (Twine(AlternateFormPrefix
) + Twine("[0-9A-F]+")).str();
72 return CreatePrecisionRegex("([1-9a-f][0-9a-f]*)?[0-9a-f]");
73 return (Twine(AlternateFormPrefix
) + Twine("[0-9a-f]+")).str();
75 return createStringError(std::errc::invalid_argument
,
76 "trying to match value with invalid format");
81 ExpressionFormat::getMatchingString(APInt IntValue
) const {
82 if (Value
!= Kind::Signed
&& IntValue
.isNegative())
83 return make_error
<OverflowError
>();
86 bool UpperCase
= false;
87 SmallString
<8> AbsoluteValueStr
;
88 StringRef SignPrefix
= IntValue
.isNegative() ? "-" : "";
103 return createStringError(std::errc::invalid_argument
,
104 "trying to match value with invalid format");
106 IntValue
.abs().toString(AbsoluteValueStr
, Radix
, /*Signed=*/false,
107 /*formatAsCLiteral=*/false,
108 /*UpperCase=*/UpperCase
);
110 StringRef AlternateFormPrefix
= AlternateForm
? StringRef("0x") : StringRef();
112 if (Precision
> AbsoluteValueStr
.size()) {
113 unsigned LeadingZeros
= Precision
- AbsoluteValueStr
.size();
114 return (Twine(SignPrefix
) + Twine(AlternateFormPrefix
) +
115 std::string(LeadingZeros
, '0') + AbsoluteValueStr
)
119 return (Twine(SignPrefix
) + Twine(AlternateFormPrefix
) + AbsoluteValueStr
)
123 static unsigned nextAPIntBitWidth(unsigned BitWidth
) {
124 return (BitWidth
< APInt::APINT_BITS_PER_WORD
) ? APInt::APINT_BITS_PER_WORD
128 static APInt
toSigned(APInt AbsVal
, bool Negative
) {
129 if (AbsVal
.isSignBitSet())
130 AbsVal
= AbsVal
.zext(nextAPIntBitWidth(AbsVal
.getBitWidth()));
131 APInt Result
= AbsVal
;
137 APInt
ExpressionFormat::valueFromStringRepr(StringRef StrVal
,
138 const SourceMgr
&SM
) const {
139 bool ValueIsSigned
= Value
== Kind::Signed
;
140 bool Negative
= StrVal
.consume_front("-");
141 bool Hex
= Value
== Kind::HexUpper
|| Value
== Kind::HexLower
;
142 bool MissingFormPrefix
=
143 !ValueIsSigned
&& AlternateForm
&& !StrVal
.consume_front("0x");
144 (void)MissingFormPrefix
;
145 assert(!MissingFormPrefix
&& "missing alternate form prefix");
147 [[maybe_unused
]] bool ParseFailure
=
148 StrVal
.getAsInteger(Hex
? 16 : 10, ResultValue
);
149 // Both the FileCheck utility and library only call this method with a valid
150 // value in StrVal. This is guaranteed by the regex returned by
151 // getWildcardRegex() above.
152 assert(!ParseFailure
&& "unable to represent numeric value");
153 return toSigned(ResultValue
, Negative
);
156 Expected
<APInt
> llvm::exprAdd(const APInt
&LeftOperand
,
157 const APInt
&RightOperand
, bool &Overflow
) {
158 return LeftOperand
.sadd_ov(RightOperand
, Overflow
);
161 Expected
<APInt
> llvm::exprSub(const APInt
&LeftOperand
,
162 const APInt
&RightOperand
, bool &Overflow
) {
163 return LeftOperand
.ssub_ov(RightOperand
, Overflow
);
166 Expected
<APInt
> llvm::exprMul(const APInt
&LeftOperand
,
167 const APInt
&RightOperand
, bool &Overflow
) {
168 return LeftOperand
.smul_ov(RightOperand
, Overflow
);
171 Expected
<APInt
> llvm::exprDiv(const APInt
&LeftOperand
,
172 const APInt
&RightOperand
, bool &Overflow
) {
173 // Check for division by zero.
174 if (RightOperand
.isZero())
175 return make_error
<OverflowError
>();
177 return LeftOperand
.sdiv_ov(RightOperand
, Overflow
);
180 Expected
<APInt
> llvm::exprMax(const APInt
&LeftOperand
,
181 const APInt
&RightOperand
, bool &Overflow
) {
183 return LeftOperand
.slt(RightOperand
) ? RightOperand
: LeftOperand
;
186 Expected
<APInt
> llvm::exprMin(const APInt
&LeftOperand
,
187 const APInt
&RightOperand
, bool &Overflow
) {
189 if (cantFail(exprMax(LeftOperand
, RightOperand
, Overflow
)) == LeftOperand
)
195 Expected
<APInt
> NumericVariableUse::eval() const {
196 std::optional
<APInt
> Value
= Variable
->getValue();
200 return make_error
<UndefVarError
>(getExpressionStr());
203 Expected
<APInt
> BinaryOperation::eval() const {
204 Expected
<APInt
> MaybeLeftOp
= LeftOperand
->eval();
205 Expected
<APInt
> MaybeRightOp
= RightOperand
->eval();
207 // Bubble up any error (e.g. undefined variables) in the recursive
209 if (!MaybeLeftOp
|| !MaybeRightOp
) {
210 Error Err
= Error::success();
212 Err
= joinErrors(std::move(Err
), MaybeLeftOp
.takeError());
214 Err
= joinErrors(std::move(Err
), MaybeRightOp
.takeError());
215 return std::move(Err
);
218 APInt LeftOp
= *MaybeLeftOp
;
219 APInt RightOp
= *MaybeRightOp
;
221 // Ensure both operands have the same bitwidth.
222 unsigned LeftBitWidth
= LeftOp
.getBitWidth();
223 unsigned RightBitWidth
= RightOp
.getBitWidth();
224 unsigned NewBitWidth
= std::max(LeftBitWidth
, RightBitWidth
);
225 LeftOp
= LeftOp
.sext(NewBitWidth
);
226 RightOp
= RightOp
.sext(NewBitWidth
);
228 Expected
<APInt
> MaybeResult
= EvalBinop(LeftOp
, RightOp
, Overflow
);
230 return MaybeResult
.takeError();
235 NewBitWidth
= nextAPIntBitWidth(NewBitWidth
);
236 LeftOp
= LeftOp
.sext(NewBitWidth
);
237 RightOp
= RightOp
.sext(NewBitWidth
);
241 Expected
<ExpressionFormat
>
242 BinaryOperation::getImplicitFormat(const SourceMgr
&SM
) const {
243 Expected
<ExpressionFormat
> LeftFormat
= LeftOperand
->getImplicitFormat(SM
);
244 Expected
<ExpressionFormat
> RightFormat
= RightOperand
->getImplicitFormat(SM
);
245 if (!LeftFormat
|| !RightFormat
) {
246 Error Err
= Error::success();
248 Err
= joinErrors(std::move(Err
), LeftFormat
.takeError());
250 Err
= joinErrors(std::move(Err
), RightFormat
.takeError());
251 return std::move(Err
);
254 if (*LeftFormat
!= ExpressionFormat::Kind::NoFormat
&&
255 *RightFormat
!= ExpressionFormat::Kind::NoFormat
&&
256 *LeftFormat
!= *RightFormat
)
257 return ErrorDiagnostic::get(
258 SM
, getExpressionStr(),
259 "implicit format conflict between '" + LeftOperand
->getExpressionStr() +
260 "' (" + LeftFormat
->toString() + ") and '" +
261 RightOperand
->getExpressionStr() + "' (" + RightFormat
->toString() +
262 "), need an explicit format specifier");
264 return *LeftFormat
!= ExpressionFormat::Kind::NoFormat
? *LeftFormat
268 Expected
<std::string
> NumericSubstitution::getResult() const {
269 assert(ExpressionPointer
->getAST() != nullptr &&
270 "Substituting empty expression");
271 Expected
<APInt
> EvaluatedValue
= ExpressionPointer
->getAST()->eval();
273 return EvaluatedValue
.takeError();
274 ExpressionFormat Format
= ExpressionPointer
->getFormat();
275 return Format
.getMatchingString(*EvaluatedValue
);
278 Expected
<std::string
> StringSubstitution::getResult() const {
279 // Look up the value and escape it so that we can put it into the regex.
280 Expected
<StringRef
> VarVal
= Context
->getPatternVarValue(FromStr
);
282 return VarVal
.takeError();
283 return Regex::escape(*VarVal
);
286 bool Pattern::isValidVarNameStart(char C
) { return C
== '_' || isAlpha(C
); }
288 Expected
<Pattern::VariableProperties
>
289 Pattern::parseVariable(StringRef
&Str
, const SourceMgr
&SM
) {
291 return ErrorDiagnostic::get(SM
, Str
, "empty variable name");
294 bool IsPseudo
= Str
[0] == '@';
296 // Global vars start with '$'.
297 if (Str
[0] == '$' || IsPseudo
)
301 return ErrorDiagnostic::get(SM
, Str
.substr(I
),
302 StringRef("empty ") +
303 (IsPseudo
? "pseudo " : "global ") +
306 if (!isValidVarNameStart(Str
[I
++]))
307 return ErrorDiagnostic::get(SM
, Str
, "invalid variable name");
309 for (size_t E
= Str
.size(); I
!= E
; ++I
)
310 // Variable names are composed of alphanumeric characters and underscores.
311 if (Str
[I
] != '_' && !isAlnum(Str
[I
]))
314 StringRef Name
= Str
.take_front(I
);
316 return VariableProperties
{Name
, IsPseudo
};
319 // StringRef holding all characters considered as horizontal whitespaces by
320 // FileCheck input canonicalization.
321 constexpr StringLiteral SpaceChars
= " \t";
323 // Parsing helper function that strips the first character in S and returns it.
324 static char popFront(StringRef
&S
) {
330 char OverflowError::ID
= 0;
331 char UndefVarError::ID
= 0;
332 char ErrorDiagnostic::ID
= 0;
333 char NotFoundError::ID
= 0;
334 char ErrorReported::ID
= 0;
336 Expected
<NumericVariable
*> Pattern::parseNumericVariableDefinition(
337 StringRef
&Expr
, FileCheckPatternContext
*Context
,
338 std::optional
<size_t> LineNumber
, ExpressionFormat ImplicitFormat
,
339 const SourceMgr
&SM
) {
340 Expected
<VariableProperties
> ParseVarResult
= parseVariable(Expr
, SM
);
342 return ParseVarResult
.takeError();
343 StringRef Name
= ParseVarResult
->Name
;
345 if (ParseVarResult
->IsPseudo
)
346 return ErrorDiagnostic::get(
347 SM
, Name
, "definition of pseudo numeric variable unsupported");
349 // Detect collisions between string and numeric variables when the latter
350 // is created later than the former.
351 if (Context
->DefinedVariableTable
.contains(Name
))
352 return ErrorDiagnostic::get(
353 SM
, Name
, "string variable with name '" + Name
+ "' already exists");
355 Expr
= Expr
.ltrim(SpaceChars
);
357 return ErrorDiagnostic::get(
358 SM
, Expr
, "unexpected characters after numeric variable name");
360 NumericVariable
*DefinedNumericVariable
;
361 auto VarTableIter
= Context
->GlobalNumericVariableTable
.find(Name
);
362 if (VarTableIter
!= Context
->GlobalNumericVariableTable
.end()) {
363 DefinedNumericVariable
= VarTableIter
->second
;
364 if (DefinedNumericVariable
->getImplicitFormat() != ImplicitFormat
)
365 return ErrorDiagnostic::get(
366 SM
, Expr
, "format different from previous variable definition");
368 DefinedNumericVariable
=
369 Context
->makeNumericVariable(Name
, ImplicitFormat
, LineNumber
);
371 return DefinedNumericVariable
;
374 Expected
<std::unique_ptr
<NumericVariableUse
>> Pattern::parseNumericVariableUse(
375 StringRef Name
, bool IsPseudo
, std::optional
<size_t> LineNumber
,
376 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
377 if (IsPseudo
&& Name
!= "@LINE")
378 return ErrorDiagnostic::get(
379 SM
, Name
, "invalid pseudo numeric variable '" + Name
+ "'");
381 // Numeric variable definitions and uses are parsed in the order in which
382 // they appear in the CHECK patterns. For each definition, the pointer to the
383 // class instance of the corresponding numeric variable definition is stored
384 // in GlobalNumericVariableTable in parsePattern. Therefore, if the pointer
385 // we get below is null, it means no such variable was defined before. When
386 // that happens, we create a dummy variable so that parsing can continue. All
387 // uses of undefined variables, whether string or numeric, are then diagnosed
388 // in printNoMatch() after failing to match.
389 auto VarTableIter
= Context
->GlobalNumericVariableTable
.find(Name
);
390 NumericVariable
*NumericVariable
;
391 if (VarTableIter
!= Context
->GlobalNumericVariableTable
.end())
392 NumericVariable
= VarTableIter
->second
;
394 NumericVariable
= Context
->makeNumericVariable(
395 Name
, ExpressionFormat(ExpressionFormat::Kind::Unsigned
));
396 Context
->GlobalNumericVariableTable
[Name
] = NumericVariable
;
399 std::optional
<size_t> DefLineNumber
= NumericVariable
->getDefLineNumber();
400 if (DefLineNumber
&& LineNumber
&& *DefLineNumber
== *LineNumber
)
401 return ErrorDiagnostic::get(
403 "numeric variable '" + Name
+
404 "' defined earlier in the same CHECK directive");
406 return std::make_unique
<NumericVariableUse
>(Name
, NumericVariable
);
409 Expected
<std::unique_ptr
<ExpressionAST
>> Pattern::parseNumericOperand(
410 StringRef
&Expr
, AllowedOperand AO
, bool MaybeInvalidConstraint
,
411 std::optional
<size_t> LineNumber
, FileCheckPatternContext
*Context
,
412 const SourceMgr
&SM
) {
413 if (Expr
.starts_with("(")) {
414 if (AO
!= AllowedOperand::Any
)
415 return ErrorDiagnostic::get(
416 SM
, Expr
, "parenthesized expression not permitted here");
417 return parseParenExpr(Expr
, LineNumber
, Context
, SM
);
420 if (AO
== AllowedOperand::LineVar
|| AO
== AllowedOperand::Any
) {
421 // Try to parse as a numeric variable use.
422 Expected
<Pattern::VariableProperties
> ParseVarResult
=
423 parseVariable(Expr
, SM
);
424 if (ParseVarResult
) {
425 // Try to parse a function call.
426 if (Expr
.ltrim(SpaceChars
).starts_with("(")) {
427 if (AO
!= AllowedOperand::Any
)
428 return ErrorDiagnostic::get(SM
, ParseVarResult
->Name
,
429 "unexpected function call");
431 return parseCallExpr(Expr
, ParseVarResult
->Name
, LineNumber
, Context
,
435 return parseNumericVariableUse(ParseVarResult
->Name
,
436 ParseVarResult
->IsPseudo
, LineNumber
,
440 if (AO
== AllowedOperand::LineVar
)
441 return ParseVarResult
.takeError();
442 // Ignore the error and retry parsing as a literal.
443 consumeError(ParseVarResult
.takeError());
446 // Otherwise, parse it as a literal.
448 StringRef SaveExpr
= Expr
;
449 bool Negative
= Expr
.consume_front("-");
450 if (!Expr
.consumeInteger((AO
== AllowedOperand::LegacyLiteral
) ? 10 : 0,
452 LiteralValue
= toSigned(LiteralValue
, Negative
);
453 return std::make_unique
<ExpressionLiteral
>(SaveExpr
.drop_back(Expr
.size()),
456 return ErrorDiagnostic::get(
459 (MaybeInvalidConstraint
? "matching constraint or " : "") +
463 Expected
<std::unique_ptr
<ExpressionAST
>>
464 Pattern::parseParenExpr(StringRef
&Expr
, std::optional
<size_t> LineNumber
,
465 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
466 Expr
= Expr
.ltrim(SpaceChars
);
467 assert(Expr
.starts_with("("));
469 // Parse right operand.
470 Expr
.consume_front("(");
471 Expr
= Expr
.ltrim(SpaceChars
);
473 return ErrorDiagnostic::get(SM
, Expr
, "missing operand in expression");
475 // Note: parseNumericOperand handles nested opening parentheses.
476 Expected
<std::unique_ptr
<ExpressionAST
>> SubExprResult
= parseNumericOperand(
477 Expr
, AllowedOperand::Any
, /*MaybeInvalidConstraint=*/false, LineNumber
,
479 Expr
= Expr
.ltrim(SpaceChars
);
480 while (SubExprResult
&& !Expr
.empty() && !Expr
.starts_with(")")) {
481 StringRef OrigExpr
= Expr
;
482 SubExprResult
= parseBinop(OrigExpr
, Expr
, std::move(*SubExprResult
), false,
483 LineNumber
, Context
, SM
);
484 Expr
= Expr
.ltrim(SpaceChars
);
487 return SubExprResult
;
489 if (!Expr
.consume_front(")")) {
490 return ErrorDiagnostic::get(SM
, Expr
,
491 "missing ')' at end of nested expression");
493 return SubExprResult
;
496 Expected
<std::unique_ptr
<ExpressionAST
>>
497 Pattern::parseBinop(StringRef Expr
, StringRef
&RemainingExpr
,
498 std::unique_ptr
<ExpressionAST
> LeftOp
,
499 bool IsLegacyLineExpr
, std::optional
<size_t> LineNumber
,
500 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
501 RemainingExpr
= RemainingExpr
.ltrim(SpaceChars
);
502 if (RemainingExpr
.empty())
503 return std::move(LeftOp
);
505 // Check if this is a supported operation and select a function to perform
507 SMLoc OpLoc
= SMLoc::getFromPointer(RemainingExpr
.data());
508 char Operator
= popFront(RemainingExpr
);
509 binop_eval_t EvalBinop
;
518 return ErrorDiagnostic::get(
519 SM
, OpLoc
, Twine("unsupported operation '") + Twine(Operator
) + "'");
522 // Parse right operand.
523 RemainingExpr
= RemainingExpr
.ltrim(SpaceChars
);
524 if (RemainingExpr
.empty())
525 return ErrorDiagnostic::get(SM
, RemainingExpr
,
526 "missing operand in expression");
527 // The second operand in a legacy @LINE expression is always a literal.
529 IsLegacyLineExpr
? AllowedOperand::LegacyLiteral
: AllowedOperand::Any
;
530 Expected
<std::unique_ptr
<ExpressionAST
>> RightOpResult
=
531 parseNumericOperand(RemainingExpr
, AO
, /*MaybeInvalidConstraint=*/false,
532 LineNumber
, Context
, SM
);
534 return RightOpResult
;
536 Expr
= Expr
.drop_back(RemainingExpr
.size());
537 return std::make_unique
<BinaryOperation
>(Expr
, EvalBinop
, std::move(LeftOp
),
538 std::move(*RightOpResult
));
541 Expected
<std::unique_ptr
<ExpressionAST
>>
542 Pattern::parseCallExpr(StringRef
&Expr
, StringRef FuncName
,
543 std::optional
<size_t> LineNumber
,
544 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
545 Expr
= Expr
.ltrim(SpaceChars
);
546 assert(Expr
.starts_with("("));
548 auto OptFunc
= StringSwitch
<binop_eval_t
>(FuncName
)
549 .Case("add", exprAdd
)
550 .Case("div", exprDiv
)
551 .Case("max", exprMax
)
552 .Case("min", exprMin
)
553 .Case("mul", exprMul
)
554 .Case("sub", exprSub
)
558 return ErrorDiagnostic::get(
559 SM
, FuncName
, Twine("call to undefined function '") + FuncName
+ "'");
561 Expr
.consume_front("(");
562 Expr
= Expr
.ltrim(SpaceChars
);
564 // Parse call arguments, which are comma separated.
565 SmallVector
<std::unique_ptr
<ExpressionAST
>, 4> Args
;
566 while (!Expr
.empty() && !Expr
.starts_with(")")) {
567 if (Expr
.starts_with(","))
568 return ErrorDiagnostic::get(SM
, Expr
, "missing argument");
570 // Parse the argument, which is an arbitary expression.
571 StringRef OuterBinOpExpr
= Expr
;
572 Expected
<std::unique_ptr
<ExpressionAST
>> Arg
= parseNumericOperand(
573 Expr
, AllowedOperand::Any
, /*MaybeInvalidConstraint=*/false, LineNumber
,
575 while (Arg
&& !Expr
.empty()) {
576 Expr
= Expr
.ltrim(SpaceChars
);
577 // Have we reached an argument terminator?
578 if (Expr
.starts_with(",") || Expr
.starts_with(")"))
581 // Arg = Arg <op> <expr>
582 Arg
= parseBinop(OuterBinOpExpr
, Expr
, std::move(*Arg
), false, LineNumber
,
586 // Prefer an expression error over a generic invalid argument message.
588 return Arg
.takeError();
589 Args
.push_back(std::move(*Arg
));
591 // Have we parsed all available arguments?
592 Expr
= Expr
.ltrim(SpaceChars
);
593 if (!Expr
.consume_front(","))
596 Expr
= Expr
.ltrim(SpaceChars
);
597 if (Expr
.starts_with(")"))
598 return ErrorDiagnostic::get(SM
, Expr
, "missing argument");
601 if (!Expr
.consume_front(")"))
602 return ErrorDiagnostic::get(SM
, Expr
,
603 "missing ')' at end of call expression");
605 const unsigned NumArgs
= Args
.size();
607 return std::make_unique
<BinaryOperation
>(Expr
, *OptFunc
, std::move(Args
[0]),
610 // TODO: Support more than binop_eval_t.
611 return ErrorDiagnostic::get(SM
, FuncName
,
612 Twine("function '") + FuncName
+
613 Twine("' takes 2 arguments but ") +
614 Twine(NumArgs
) + " given");
617 Expected
<std::unique_ptr
<Expression
>> Pattern::parseNumericSubstitutionBlock(
618 StringRef Expr
, std::optional
<NumericVariable
*> &DefinedNumericVariable
,
619 bool IsLegacyLineExpr
, std::optional
<size_t> LineNumber
,
620 FileCheckPatternContext
*Context
, const SourceMgr
&SM
) {
621 std::unique_ptr
<ExpressionAST
> ExpressionASTPointer
= nullptr;
622 StringRef DefExpr
= StringRef();
623 DefinedNumericVariable
= std::nullopt
;
624 ExpressionFormat ExplicitFormat
= ExpressionFormat();
625 unsigned Precision
= 0;
627 // Parse format specifier (NOTE: ',' is also an argument separator).
628 size_t FormatSpecEnd
= Expr
.find(',');
629 size_t FunctionStart
= Expr
.find('(');
630 if (FormatSpecEnd
!= StringRef::npos
&& FormatSpecEnd
< FunctionStart
) {
631 StringRef FormatExpr
= Expr
.take_front(FormatSpecEnd
);
632 Expr
= Expr
.drop_front(FormatSpecEnd
+ 1);
633 FormatExpr
= FormatExpr
.trim(SpaceChars
);
634 if (!FormatExpr
.consume_front("%"))
635 return ErrorDiagnostic::get(
637 "invalid matching format specification in expression");
639 // Parse alternate form flag.
640 SMLoc AlternateFormFlagLoc
= SMLoc::getFromPointer(FormatExpr
.data());
641 bool AlternateForm
= FormatExpr
.consume_front("#");
644 if (FormatExpr
.consume_front(".")) {
645 if (FormatExpr
.consumeInteger(10, Precision
))
646 return ErrorDiagnostic::get(SM
, FormatExpr
,
647 "invalid precision in format specifier");
650 if (!FormatExpr
.empty()) {
651 // Check for unknown matching format specifier and set matching format in
652 // class instance representing this expression.
653 SMLoc FmtLoc
= SMLoc::getFromPointer(FormatExpr
.data());
654 switch (popFront(FormatExpr
)) {
657 ExpressionFormat(ExpressionFormat::Kind::Unsigned
, Precision
);
661 ExpressionFormat(ExpressionFormat::Kind::Signed
, Precision
);
664 ExplicitFormat
= ExpressionFormat(ExpressionFormat::Kind::HexLower
,
665 Precision
, AlternateForm
);
668 ExplicitFormat
= ExpressionFormat(ExpressionFormat::Kind::HexUpper
,
669 Precision
, AlternateForm
);
672 return ErrorDiagnostic::get(SM
, FmtLoc
,
673 "invalid format specifier in expression");
677 if (AlternateForm
&& ExplicitFormat
!= ExpressionFormat::Kind::HexLower
&&
678 ExplicitFormat
!= ExpressionFormat::Kind::HexUpper
)
679 return ErrorDiagnostic::get(
680 SM
, AlternateFormFlagLoc
,
681 "alternate form only supported for hex values");
683 FormatExpr
= FormatExpr
.ltrim(SpaceChars
);
684 if (!FormatExpr
.empty())
685 return ErrorDiagnostic::get(
687 "invalid matching format specification in expression");
690 // Save variable definition expression if any.
691 size_t DefEnd
= Expr
.find(':');
692 if (DefEnd
!= StringRef::npos
) {
693 DefExpr
= Expr
.substr(0, DefEnd
);
694 Expr
= Expr
.substr(DefEnd
+ 1);
697 // Parse matching constraint.
698 Expr
= Expr
.ltrim(SpaceChars
);
699 bool HasParsedValidConstraint
= Expr
.consume_front("==");
701 // Parse the expression itself.
702 Expr
= Expr
.ltrim(SpaceChars
);
704 if (HasParsedValidConstraint
)
705 return ErrorDiagnostic::get(
706 SM
, Expr
, "empty numeric expression should not have a constraint");
708 Expr
= Expr
.rtrim(SpaceChars
);
709 StringRef OuterBinOpExpr
= Expr
;
710 // The first operand in a legacy @LINE expression is always the @LINE
713 IsLegacyLineExpr
? AllowedOperand::LineVar
: AllowedOperand::Any
;
714 Expected
<std::unique_ptr
<ExpressionAST
>> ParseResult
= parseNumericOperand(
715 Expr
, AO
, !HasParsedValidConstraint
, LineNumber
, Context
, SM
);
716 while (ParseResult
&& !Expr
.empty()) {
717 ParseResult
= parseBinop(OuterBinOpExpr
, Expr
, std::move(*ParseResult
),
718 IsLegacyLineExpr
, LineNumber
, Context
, SM
);
719 // Legacy @LINE expressions only allow 2 operands.
720 if (ParseResult
&& IsLegacyLineExpr
&& !Expr
.empty())
721 return ErrorDiagnostic::get(
723 "unexpected characters at end of expression '" + Expr
+ "'");
726 return ParseResult
.takeError();
727 ExpressionASTPointer
= std::move(*ParseResult
);
730 // Select format of the expression, i.e. (i) its explicit format, if any,
731 // otherwise (ii) its implicit format, if any, otherwise (iii) the default
732 // format (unsigned). Error out in case of conflicting implicit format
733 // without explicit format.
734 ExpressionFormat Format
;
736 Format
= ExplicitFormat
;
737 else if (ExpressionASTPointer
) {
738 Expected
<ExpressionFormat
> ImplicitFormat
=
739 ExpressionASTPointer
->getImplicitFormat(SM
);
741 return ImplicitFormat
.takeError();
742 Format
= *ImplicitFormat
;
745 Format
= ExpressionFormat(ExpressionFormat::Kind::Unsigned
, Precision
);
747 std::unique_ptr
<Expression
> ExpressionPointer
=
748 std::make_unique
<Expression
>(std::move(ExpressionASTPointer
), Format
);
750 // Parse the numeric variable definition.
751 if (DefEnd
!= StringRef::npos
) {
752 DefExpr
= DefExpr
.ltrim(SpaceChars
);
753 Expected
<NumericVariable
*> ParseResult
= parseNumericVariableDefinition(
754 DefExpr
, Context
, LineNumber
, ExpressionPointer
->getFormat(), SM
);
757 return ParseResult
.takeError();
758 DefinedNumericVariable
= *ParseResult
;
761 return std::move(ExpressionPointer
);
764 bool Pattern::parsePattern(StringRef PatternStr
, StringRef Prefix
,
765 SourceMgr
&SM
, const FileCheckRequest
&Req
) {
766 bool MatchFullLinesHere
= Req
.MatchFullLines
&& CheckTy
!= Check::CheckNot
;
767 IgnoreCase
= Req
.IgnoreCase
;
769 PatternLoc
= SMLoc::getFromPointer(PatternStr
.data());
771 if (!(Req
.NoCanonicalizeWhiteSpace
&& Req
.MatchFullLines
))
772 // Ignore trailing whitespace.
773 PatternStr
= PatternStr
.rtrim(" \t");
775 // Check that there is something on the line.
776 if (PatternStr
.empty() && CheckTy
!= Check::CheckEmpty
) {
777 SM
.PrintMessage(PatternLoc
, SourceMgr::DK_Error
,
778 "found empty check string with prefix '" + Prefix
+ ":'");
782 if (!PatternStr
.empty() && CheckTy
== Check::CheckEmpty
) {
784 PatternLoc
, SourceMgr::DK_Error
,
785 "found non-empty check string for empty check with prefix '" + Prefix
+
790 if (CheckTy
== Check::CheckEmpty
) {
795 // If literal check, set fixed string.
796 if (CheckTy
.isLiteralMatch()) {
797 FixedStr
= PatternStr
;
801 // Check to see if this is a fixed string, or if it has regex pieces.
802 if (!MatchFullLinesHere
&&
803 (PatternStr
.size() < 2 ||
804 (!PatternStr
.contains("{{") && !PatternStr
.contains("[[")))) {
805 FixedStr
= PatternStr
;
809 if (MatchFullLinesHere
) {
811 if (!Req
.NoCanonicalizeWhiteSpace
)
815 // Paren value #0 is for the fully matched string. Any new parenthesized
816 // values add from there.
817 unsigned CurParen
= 1;
819 // Otherwise, there is at least one regex piece. Build up the regex pattern
820 // by escaping scary characters in fixed strings, building up one big regex.
821 while (!PatternStr
.empty()) {
823 if (PatternStr
.starts_with("{{")) {
824 // This is the start of a regex match. Scan for the }}.
825 size_t End
= PatternStr
.find("}}");
826 if (End
== StringRef::npos
) {
827 SM
.PrintMessage(SMLoc::getFromPointer(PatternStr
.data()),
829 "found start of regex string with no end '}}'");
833 // Enclose {{}} patterns in parens just like [[]] even though we're not
834 // capturing the result for any purpose. This is required in case the
835 // expression contains an alternation like: CHECK: abc{{x|z}}def. We
836 // want this to turn into: "abc(x|z)def" not "abcx|zdef".
837 bool HasAlternation
= PatternStr
.contains('|');
838 if (HasAlternation
) {
843 if (AddRegExToRegEx(PatternStr
.substr(2, End
- 2), CurParen
, SM
))
848 PatternStr
= PatternStr
.substr(End
+ 2);
852 // String and numeric substitution blocks. Pattern substitution blocks come
853 // in two forms: [[foo:.*]] and [[foo]]. The former matches .* (or some
854 // other regex) and assigns it to the string variable 'foo'. The latter
855 // substitutes foo's value. Numeric substitution blocks recognize the same
856 // form as string ones, but start with a '#' sign after the double
857 // brackets. They also accept a combined form which sets a numeric variable
858 // to the evaluation of an expression. Both string and numeric variable
859 // names must satisfy the regular expression "[a-zA-Z_][0-9a-zA-Z_]*" to be
860 // valid, as this helps catch some common errors. If there are extra '['s
861 // before the "[[", treat them literally.
862 if (PatternStr
.starts_with("[[") && !PatternStr
.starts_with("[[[")) {
863 StringRef UnparsedPatternStr
= PatternStr
.substr(2);
864 // Find the closing bracket pair ending the match. End is going to be an
865 // offset relative to the beginning of the match string.
866 size_t End
= FindRegexVarEnd(UnparsedPatternStr
, SM
);
867 StringRef MatchStr
= UnparsedPatternStr
.substr(0, End
);
868 bool IsNumBlock
= MatchStr
.consume_front("#");
870 if (End
== StringRef::npos
) {
871 SM
.PrintMessage(SMLoc::getFromPointer(PatternStr
.data()),
873 "Invalid substitution block, no ]] found");
876 // Strip the substitution block we are parsing. End points to the start
877 // of the "]]" closing the expression so account for it in computing the
878 // index of the first unparsed character.
879 PatternStr
= UnparsedPatternStr
.substr(End
+ 2);
881 bool IsDefinition
= false;
882 bool SubstNeeded
= false;
883 // Whether the substitution block is a legacy use of @LINE with string
884 // substitution block syntax.
885 bool IsLegacyLineExpr
= false;
888 StringRef MatchRegexp
;
889 std::string WildcardRegexp
;
890 size_t SubstInsertIdx
= RegExStr
.size();
892 // Parse string variable or legacy @LINE expression.
894 size_t VarEndIdx
= MatchStr
.find(':');
895 size_t SpacePos
= MatchStr
.substr(0, VarEndIdx
).find_first_of(" \t");
896 if (SpacePos
!= StringRef::npos
) {
897 SM
.PrintMessage(SMLoc::getFromPointer(MatchStr
.data() + SpacePos
),
898 SourceMgr::DK_Error
, "unexpected whitespace");
902 // Get the name (e.g. "foo") and verify it is well formed.
903 StringRef OrigMatchStr
= MatchStr
;
904 Expected
<Pattern::VariableProperties
> ParseVarResult
=
905 parseVariable(MatchStr
, SM
);
906 if (!ParseVarResult
) {
907 logAllUnhandledErrors(ParseVarResult
.takeError(), errs());
910 StringRef Name
= ParseVarResult
->Name
;
911 bool IsPseudo
= ParseVarResult
->IsPseudo
;
913 IsDefinition
= (VarEndIdx
!= StringRef::npos
);
914 SubstNeeded
= !IsDefinition
;
916 if ((IsPseudo
|| !MatchStr
.consume_front(":"))) {
917 SM
.PrintMessage(SMLoc::getFromPointer(Name
.data()),
919 "invalid name in string variable definition");
923 // Detect collisions between string and numeric variables when the
924 // former is created later than the latter.
925 if (Context
->GlobalNumericVariableTable
.contains(Name
)) {
927 SMLoc::getFromPointer(Name
.data()), SourceMgr::DK_Error
,
928 "numeric variable with name '" + Name
+ "' already exists");
932 MatchRegexp
= MatchStr
;
935 MatchStr
= OrigMatchStr
;
936 IsLegacyLineExpr
= IsNumBlock
= true;
938 if (!MatchStr
.empty()) {
939 SM
.PrintMessage(SMLoc::getFromPointer(Name
.data()),
941 "invalid name in string variable use");
949 // Parse numeric substitution block.
950 std::unique_ptr
<Expression
> ExpressionPointer
;
951 std::optional
<NumericVariable
*> DefinedNumericVariable
;
953 Expected
<std::unique_ptr
<Expression
>> ParseResult
=
954 parseNumericSubstitutionBlock(MatchStr
, DefinedNumericVariable
,
955 IsLegacyLineExpr
, LineNumber
, Context
,
958 logAllUnhandledErrors(ParseResult
.takeError(), errs());
961 ExpressionPointer
= std::move(*ParseResult
);
962 SubstNeeded
= ExpressionPointer
->getAST() != nullptr;
963 if (DefinedNumericVariable
) {
965 DefName
= (*DefinedNumericVariable
)->getName();
970 ExpressionFormat Format
= ExpressionPointer
->getFormat();
971 WildcardRegexp
= cantFail(Format
.getWildcardRegex());
972 MatchRegexp
= WildcardRegexp
;
976 // Handle variable definition: [[<def>:(...)]] and [[#(...)<def>:(...)]].
982 NumericVariableMatch NumericVariableDefinition
= {
983 *DefinedNumericVariable
, CurParen
};
984 NumericVariableDefs
[DefName
] = NumericVariableDefinition
;
985 // This store is done here rather than in match() to allow
986 // parseNumericVariableUse() to get the pointer to the class instance
987 // of the right variable definition corresponding to a given numeric
989 Context
->GlobalNumericVariableTable
[DefName
] =
990 *DefinedNumericVariable
;
992 VariableDefs
[DefName
] = CurParen
;
993 // Mark string variable as defined to detect collisions between
994 // string and numeric variables in parseNumericVariableUse() and
995 // defineCmdlineVariables() when the latter is created later than the
996 // former. We cannot reuse GlobalVariableTable for this by populating
997 // it with an empty string since we would then lose the ability to
998 // detect the use of an undefined variable in match().
999 Context
->DefinedVariableTable
[DefName
] = true;
1005 if (!MatchRegexp
.empty() && AddRegExToRegEx(MatchRegexp
, CurParen
, SM
))
1011 // Handle substitutions: [[foo]] and [[#<foo expr>]].
1013 // Handle substitution of string variables that were defined earlier on
1014 // the same line by emitting a backreference. Expressions do not
1015 // support substituting a numeric variable defined on the same line.
1016 if (!IsNumBlock
&& VariableDefs
.find(SubstStr
) != VariableDefs
.end()) {
1017 unsigned CaptureParenGroup
= VariableDefs
[SubstStr
];
1018 if (CaptureParenGroup
< 1 || CaptureParenGroup
> 9) {
1019 SM
.PrintMessage(SMLoc::getFromPointer(SubstStr
.data()),
1020 SourceMgr::DK_Error
,
1021 "Can't back-reference more than 9 variables");
1024 AddBackrefToRegEx(CaptureParenGroup
);
1026 // Handle substitution of string variables ([[<var>]]) defined in
1027 // previous CHECK patterns, and substitution of expressions.
1028 Substitution
*Substitution
=
1030 ? Context
->makeNumericSubstitution(
1031 SubstStr
, std::move(ExpressionPointer
), SubstInsertIdx
)
1032 : Context
->makeStringSubstitution(SubstStr
, SubstInsertIdx
);
1033 Substitutions
.push_back(Substitution
);
1040 // Handle fixed string matches.
1041 // Find the end, which is the start of the next regex.
1042 size_t FixedMatchEnd
=
1043 std::min(PatternStr
.find("{{", 1), PatternStr
.find("[[", 1));
1044 RegExStr
+= Regex::escape(PatternStr
.substr(0, FixedMatchEnd
));
1045 PatternStr
= PatternStr
.substr(FixedMatchEnd
);
1048 if (MatchFullLinesHere
) {
1049 if (!Req
.NoCanonicalizeWhiteSpace
)
1057 bool Pattern::AddRegExToRegEx(StringRef RS
, unsigned &CurParen
, SourceMgr
&SM
) {
1060 if (!R
.isValid(Error
)) {
1061 SM
.PrintMessage(SMLoc::getFromPointer(RS
.data()), SourceMgr::DK_Error
,
1062 "invalid regex: " + Error
);
1066 RegExStr
+= RS
.str();
1067 CurParen
+= R
.getNumMatches();
1071 void Pattern::AddBackrefToRegEx(unsigned BackrefNum
) {
1072 assert(BackrefNum
>= 1 && BackrefNum
<= 9 && "Invalid backref number");
1073 std::string Backref
= std::string("\\") + std::string(1, '0' + BackrefNum
);
1074 RegExStr
+= Backref
;
1077 Pattern::MatchResult
Pattern::match(StringRef Buffer
,
1078 const SourceMgr
&SM
) const {
1079 // If this is the EOF pattern, match it immediately.
1080 if (CheckTy
== Check::CheckEOF
)
1081 return MatchResult(Buffer
.size(), 0, Error::success());
1083 // If this is a fixed string pattern, just match it now.
1084 if (!FixedStr
.empty()) {
1086 IgnoreCase
? Buffer
.find_insensitive(FixedStr
) : Buffer
.find(FixedStr
);
1087 if (Pos
== StringRef::npos
)
1088 return make_error
<NotFoundError
>();
1089 return MatchResult(Pos
, /*MatchLen=*/FixedStr
.size(), Error::success());
1094 // If there are substitutions, we need to create a temporary string with the
1096 StringRef RegExToMatch
= RegExStr
;
1098 if (!Substitutions
.empty()) {
1101 Context
->LineVariable
->setValue(
1102 APInt(sizeof(*LineNumber
) * 8, *LineNumber
));
1104 size_t InsertOffset
= 0;
1105 // Substitute all string variables and expressions whose values are only
1106 // now known. Use of string variables defined on the same line are handled
1107 // by back-references.
1108 Error Errs
= Error::success();
1109 for (const auto &Substitution
: Substitutions
) {
1110 // Substitute and check for failure (e.g. use of undefined variable).
1111 Expected
<std::string
> Value
= Substitution
->getResult();
1113 // Convert to an ErrorDiagnostic to get location information. This is
1114 // done here rather than printMatch/printNoMatch since now we know which
1115 // substitution block caused the overflow.
1116 Errs
= joinErrors(std::move(Errs
),
1119 [&](const OverflowError
&E
) {
1120 return ErrorDiagnostic::get(
1121 SM
, Substitution
->getFromString(),
1122 "unable to substitute variable or "
1123 "numeric expression: overflow error");
1125 [&SM
](const UndefVarError
&E
) {
1126 return ErrorDiagnostic::get(SM
, E
.getVarName(),
1132 // Plop it into the regex at the adjusted offset.
1133 TmpStr
.insert(TmpStr
.begin() + Substitution
->getIndex() + InsertOffset
,
1134 Value
->begin(), Value
->end());
1135 InsertOffset
+= Value
->size();
1138 return std::move(Errs
);
1140 // Match the newly constructed regex.
1141 RegExToMatch
= TmpStr
;
1144 SmallVector
<StringRef
, 4> MatchInfo
;
1145 unsigned int Flags
= Regex::Newline
;
1147 Flags
|= Regex::IgnoreCase
;
1148 if (!Regex(RegExToMatch
, Flags
).match(Buffer
, &MatchInfo
))
1149 return make_error
<NotFoundError
>();
1151 // Successful regex match.
1152 assert(!MatchInfo
.empty() && "Didn't get any match");
1153 StringRef FullMatch
= MatchInfo
[0];
1155 // If this defines any string variables, remember their values.
1156 for (const auto &VariableDef
: VariableDefs
) {
1157 assert(VariableDef
.second
< MatchInfo
.size() && "Internal paren error");
1158 Context
->GlobalVariableTable
[VariableDef
.first
] =
1159 MatchInfo
[VariableDef
.second
];
1162 // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
1163 // the required preceding newline, which is consumed by the pattern in the
1164 // case of CHECK-EMPTY but not CHECK-NEXT.
1165 size_t MatchStartSkip
= CheckTy
== Check::CheckEmpty
;
1167 TheMatch
.Pos
= FullMatch
.data() - Buffer
.data() + MatchStartSkip
;
1168 TheMatch
.Len
= FullMatch
.size() - MatchStartSkip
;
1170 // If this defines any numeric variables, remember their values.
1171 for (const auto &NumericVariableDef
: NumericVariableDefs
) {
1172 const NumericVariableMatch
&NumericVariableMatch
=
1173 NumericVariableDef
.getValue();
1174 unsigned CaptureParenGroup
= NumericVariableMatch
.CaptureParenGroup
;
1175 assert(CaptureParenGroup
< MatchInfo
.size() && "Internal paren error");
1176 NumericVariable
*DefinedNumericVariable
=
1177 NumericVariableMatch
.DefinedNumericVariable
;
1179 StringRef MatchedValue
= MatchInfo
[CaptureParenGroup
];
1180 ExpressionFormat Format
= DefinedNumericVariable
->getImplicitFormat();
1181 APInt Value
= Format
.valueFromStringRepr(MatchedValue
, SM
);
1182 DefinedNumericVariable
->setValue(Value
, MatchedValue
);
1185 return MatchResult(TheMatch
, Error::success());
1188 unsigned Pattern::computeMatchDistance(StringRef Buffer
) const {
1189 // Just compute the number of matching characters. For regular expressions, we
1190 // just compare against the regex itself and hope for the best.
1192 // FIXME: One easy improvement here is have the regex lib generate a single
1193 // example regular expression which matches, and use that as the example
1195 StringRef
ExampleString(FixedStr
);
1196 if (ExampleString
.empty())
1197 ExampleString
= RegExStr
;
1199 // Only compare up to the first line in the buffer, or the string size.
1200 StringRef BufferPrefix
= Buffer
.substr(0, ExampleString
.size());
1201 BufferPrefix
= BufferPrefix
.split('\n').first
;
1202 return BufferPrefix
.edit_distance(ExampleString
);
1205 void Pattern::printSubstitutions(const SourceMgr
&SM
, StringRef Buffer
,
1207 FileCheckDiag::MatchType MatchTy
,
1208 std::vector
<FileCheckDiag
> *Diags
) const {
1209 // Print what we know about substitutions.
1210 if (!Substitutions
.empty()) {
1211 for (const auto &Substitution
: Substitutions
) {
1212 SmallString
<256> Msg
;
1213 raw_svector_ostream
OS(Msg
);
1215 Expected
<std::string
> MatchedValue
= Substitution
->getResult();
1216 // Substitution failures are handled in printNoMatch().
1217 if (!MatchedValue
) {
1218 consumeError(MatchedValue
.takeError());
1223 OS
.write_escaped(Substitution
->getFromString()) << "\" equal to \"";
1224 OS
.write_escaped(*MatchedValue
) << "\"";
1226 // We report only the start of the match/search range to suggest we are
1227 // reporting the substitutions as set at the start of the match/search.
1228 // Indicating a non-zero-length range might instead seem to imply that the
1229 // substitution matches or was captured from exactly that range.
1231 Diags
->emplace_back(SM
, CheckTy
, getLoc(), MatchTy
,
1232 SMRange(Range
.Start
, Range
.Start
), OS
.str());
1234 SM
.PrintMessage(Range
.Start
, SourceMgr::DK_Note
, OS
.str());
1239 void Pattern::printVariableDefs(const SourceMgr
&SM
,
1240 FileCheckDiag::MatchType MatchTy
,
1241 std::vector
<FileCheckDiag
> *Diags
) const {
1242 if (VariableDefs
.empty() && NumericVariableDefs
.empty())
1244 // Build list of variable captures.
1249 SmallVector
<VarCapture
, 2> VarCaptures
;
1250 for (const auto &VariableDef
: VariableDefs
) {
1252 VC
.Name
= VariableDef
.first
;
1253 StringRef Value
= Context
->GlobalVariableTable
[VC
.Name
];
1254 SMLoc Start
= SMLoc::getFromPointer(Value
.data());
1255 SMLoc End
= SMLoc::getFromPointer(Value
.data() + Value
.size());
1256 VC
.Range
= SMRange(Start
, End
);
1257 VarCaptures
.push_back(VC
);
1259 for (const auto &VariableDef
: NumericVariableDefs
) {
1261 VC
.Name
= VariableDef
.getKey();
1262 std::optional
<StringRef
> StrValue
=
1263 VariableDef
.getValue().DefinedNumericVariable
->getStringValue();
1266 SMLoc Start
= SMLoc::getFromPointer(StrValue
->data());
1267 SMLoc End
= SMLoc::getFromPointer(StrValue
->data() + StrValue
->size());
1268 VC
.Range
= SMRange(Start
, End
);
1269 VarCaptures
.push_back(VC
);
1271 // Sort variable captures by the order in which they matched the input.
1272 // Ranges shouldn't be overlapping, so we can just compare the start.
1273 llvm::sort(VarCaptures
, [](const VarCapture
&A
, const VarCapture
&B
) {
1276 assert(A
.Range
.Start
!= B
.Range
.Start
&&
1277 "unexpected overlapping variable captures");
1278 return A
.Range
.Start
.getPointer() < B
.Range
.Start
.getPointer();
1280 // Create notes for the sorted captures.
1281 for (const VarCapture
&VC
: VarCaptures
) {
1282 SmallString
<256> Msg
;
1283 raw_svector_ostream
OS(Msg
);
1284 OS
<< "captured var \"" << VC
.Name
<< "\"";
1286 Diags
->emplace_back(SM
, CheckTy
, getLoc(), MatchTy
, VC
.Range
, OS
.str());
1288 SM
.PrintMessage(VC
.Range
.Start
, SourceMgr::DK_Note
, OS
.str(), VC
.Range
);
1292 static SMRange
ProcessMatchResult(FileCheckDiag::MatchType MatchTy
,
1293 const SourceMgr
&SM
, SMLoc Loc
,
1294 Check::FileCheckType CheckTy
,
1295 StringRef Buffer
, size_t Pos
, size_t Len
,
1296 std::vector
<FileCheckDiag
> *Diags
,
1297 bool AdjustPrevDiags
= false) {
1298 SMLoc Start
= SMLoc::getFromPointer(Buffer
.data() + Pos
);
1299 SMLoc End
= SMLoc::getFromPointer(Buffer
.data() + Pos
+ Len
);
1300 SMRange
Range(Start
, End
);
1302 if (AdjustPrevDiags
) {
1303 SMLoc CheckLoc
= Diags
->rbegin()->CheckLoc
;
1304 for (auto I
= Diags
->rbegin(), E
= Diags
->rend();
1305 I
!= E
&& I
->CheckLoc
== CheckLoc
; ++I
)
1306 I
->MatchTy
= MatchTy
;
1308 Diags
->emplace_back(SM
, CheckTy
, Loc
, MatchTy
, Range
);
1313 void Pattern::printFuzzyMatch(const SourceMgr
&SM
, StringRef Buffer
,
1314 std::vector
<FileCheckDiag
> *Diags
) const {
1315 // Attempt to find the closest/best fuzzy match. Usually an error happens
1316 // because some string in the output didn't exactly match. In these cases, we
1317 // would like to show the user a best guess at what "should have" matched, to
1318 // save them having to actually check the input manually.
1319 size_t NumLinesForward
= 0;
1320 size_t Best
= StringRef::npos
;
1321 double BestQuality
= 0;
1323 // Use an arbitrary 4k limit on how far we will search.
1324 for (size_t i
= 0, e
= std::min(size_t(4096), Buffer
.size()); i
!= e
; ++i
) {
1325 if (Buffer
[i
] == '\n')
1328 // Patterns have leading whitespace stripped, so skip whitespace when
1329 // looking for something which looks like a pattern.
1330 if (Buffer
[i
] == ' ' || Buffer
[i
] == '\t')
1333 // Compute the "quality" of this match as an arbitrary combination of the
1334 // match distance and the number of lines skipped to get to this match.
1335 unsigned Distance
= computeMatchDistance(Buffer
.substr(i
));
1336 double Quality
= Distance
+ (NumLinesForward
/ 100.);
1338 if (Quality
< BestQuality
|| Best
== StringRef::npos
) {
1340 BestQuality
= Quality
;
1344 // Print the "possible intended match here" line if we found something
1345 // reasonable and not equal to what we showed in the "scanning from here"
1347 if (Best
&& Best
!= StringRef::npos
&& BestQuality
< 50) {
1348 SMRange MatchRange
=
1349 ProcessMatchResult(FileCheckDiag::MatchFuzzy
, SM
, getLoc(),
1350 getCheckTy(), Buffer
, Best
, 0, Diags
);
1351 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
,
1352 "possible intended match here");
1354 // FIXME: If we wanted to be really friendly we would show why the match
1355 // failed, as it can be hard to spot simple one character differences.
1360 FileCheckPatternContext::getPatternVarValue(StringRef VarName
) {
1361 auto VarIter
= GlobalVariableTable
.find(VarName
);
1362 if (VarIter
== GlobalVariableTable
.end())
1363 return make_error
<UndefVarError
>(VarName
);
1365 return VarIter
->second
;
1368 template <class... Types
>
1369 NumericVariable
*FileCheckPatternContext::makeNumericVariable(Types
... args
) {
1370 NumericVariables
.push_back(std::make_unique
<NumericVariable
>(args
...));
1371 return NumericVariables
.back().get();
1375 FileCheckPatternContext::makeStringSubstitution(StringRef VarName
,
1377 Substitutions
.push_back(
1378 std::make_unique
<StringSubstitution
>(this, VarName
, InsertIdx
));
1379 return Substitutions
.back().get();
1382 Substitution
*FileCheckPatternContext::makeNumericSubstitution(
1383 StringRef ExpressionStr
, std::unique_ptr
<Expression
> Expression
,
1385 Substitutions
.push_back(std::make_unique
<NumericSubstitution
>(
1386 this, ExpressionStr
, std::move(Expression
), InsertIdx
));
1387 return Substitutions
.back().get();
1390 size_t Pattern::FindRegexVarEnd(StringRef Str
, SourceMgr
&SM
) {
1391 // Offset keeps track of the current offset within the input Str
1393 // [...] Nesting depth
1394 size_t BracketDepth
= 0;
1396 while (!Str
.empty()) {
1397 if (Str
.starts_with("]]") && BracketDepth
== 0)
1399 if (Str
[0] == '\\') {
1400 // Backslash escapes the next char within regexes, so skip them both.
1401 Str
= Str
.substr(2);
1411 if (BracketDepth
== 0) {
1412 SM
.PrintMessage(SMLoc::getFromPointer(Str
.data()),
1413 SourceMgr::DK_Error
,
1414 "missing closing \"]\" for regex variable");
1420 Str
= Str
.substr(1);
1425 return StringRef::npos
;
1428 StringRef
FileCheck::CanonicalizeFile(MemoryBuffer
&MB
,
1429 SmallVectorImpl
<char> &OutputBuffer
) {
1430 OutputBuffer
.reserve(MB
.getBufferSize());
1432 for (const char *Ptr
= MB
.getBufferStart(), *End
= MB
.getBufferEnd();
1433 Ptr
!= End
; ++Ptr
) {
1434 // Eliminate trailing dosish \r.
1435 if (Ptr
<= End
- 2 && Ptr
[0] == '\r' && Ptr
[1] == '\n') {
1439 // If current char is not a horizontal whitespace or if horizontal
1440 // whitespace canonicalization is disabled, dump it to output as is.
1441 if (Req
.NoCanonicalizeWhiteSpace
|| (*Ptr
!= ' ' && *Ptr
!= '\t')) {
1442 OutputBuffer
.push_back(*Ptr
);
1446 // Otherwise, add one space and advance over neighboring space.
1447 OutputBuffer
.push_back(' ');
1448 while (Ptr
+ 1 != End
&& (Ptr
[1] == ' ' || Ptr
[1] == '\t'))
1452 // Add a null byte and then return all but that byte.
1453 OutputBuffer
.push_back('\0');
1454 return StringRef(OutputBuffer
.data(), OutputBuffer
.size() - 1);
1457 FileCheckDiag::FileCheckDiag(const SourceMgr
&SM
,
1458 const Check::FileCheckType
&CheckTy
,
1459 SMLoc CheckLoc
, MatchType MatchTy
,
1460 SMRange InputRange
, StringRef Note
)
1461 : CheckTy(CheckTy
), CheckLoc(CheckLoc
), MatchTy(MatchTy
), Note(Note
) {
1462 auto Start
= SM
.getLineAndColumn(InputRange
.Start
);
1463 auto End
= SM
.getLineAndColumn(InputRange
.End
);
1464 InputStartLine
= Start
.first
;
1465 InputStartCol
= Start
.second
;
1466 InputEndLine
= End
.first
;
1467 InputEndCol
= End
.second
;
1470 static bool IsPartOfWord(char c
) {
1471 return (isAlnum(c
) || c
== '-' || c
== '_');
1474 Check::FileCheckType
&Check::FileCheckType::setCount(int C
) {
1475 assert(Count
> 0 && "zero and negative counts are not supported");
1476 assert((C
== 1 || Kind
== CheckPlain
) &&
1477 "count supported only for plain CHECK directives");
1482 std::string
Check::FileCheckType::getModifiersDescription() const {
1483 if (Modifiers
.none())
1486 raw_string_ostream
OS(Ret
);
1488 if (isLiteralMatch())
1494 std::string
Check::FileCheckType::getDescription(StringRef Prefix
) const {
1495 // Append directive modifiers.
1496 auto WithModifiers
= [this, Prefix
](StringRef Str
) -> std::string
{
1497 return (Prefix
+ Str
+ getModifiersDescription()).str();
1501 case Check::CheckNone
:
1503 case Check::CheckMisspelled
:
1504 return "misspelled";
1505 case Check::CheckPlain
:
1507 return WithModifiers("-COUNT");
1508 return WithModifiers("");
1509 case Check::CheckNext
:
1510 return WithModifiers("-NEXT");
1511 case Check::CheckSame
:
1512 return WithModifiers("-SAME");
1513 case Check::CheckNot
:
1514 return WithModifiers("-NOT");
1515 case Check::CheckDAG
:
1516 return WithModifiers("-DAG");
1517 case Check::CheckLabel
:
1518 return WithModifiers("-LABEL");
1519 case Check::CheckEmpty
:
1520 return WithModifiers("-EMPTY");
1521 case Check::CheckComment
:
1522 return std::string(Prefix
);
1523 case Check::CheckEOF
:
1524 return "implicit EOF";
1525 case Check::CheckBadNot
:
1527 case Check::CheckBadCount
:
1530 llvm_unreachable("unknown FileCheckType");
1533 static std::pair
<Check::FileCheckType
, StringRef
>
1534 FindCheckType(const FileCheckRequest
&Req
, StringRef Buffer
, StringRef Prefix
,
1536 if (Buffer
.size() <= Prefix
.size())
1537 return {Check::CheckNone
, StringRef()};
1539 StringRef Rest
= Buffer
.drop_front(Prefix
.size());
1540 // Check for comment.
1541 if (llvm::is_contained(Req
.CommentPrefixes
, Prefix
)) {
1542 if (Rest
.consume_front(":"))
1543 return {Check::CheckComment
, Rest
};
1544 // Ignore a comment prefix if it has a suffix like "-NOT".
1545 return {Check::CheckNone
, StringRef()};
1548 auto ConsumeModifiers
= [&](Check::FileCheckType Ret
)
1549 -> std::pair
<Check::FileCheckType
, StringRef
> {
1550 if (Rest
.consume_front(":"))
1552 if (!Rest
.consume_front("{"))
1553 return {Check::CheckNone
, StringRef()};
1555 // Parse the modifiers, speparated by commas.
1557 // Allow whitespace in modifiers list.
1558 Rest
= Rest
.ltrim();
1559 if (Rest
.consume_front("LITERAL"))
1560 Ret
.setLiteralMatch();
1562 return {Check::CheckNone
, Rest
};
1563 // Allow whitespace in modifiers list.
1564 Rest
= Rest
.ltrim();
1565 } while (Rest
.consume_front(","));
1566 if (!Rest
.consume_front("}:"))
1567 return {Check::CheckNone
, Rest
};
1571 // Verify that the prefix is followed by directive modifiers or a colon.
1572 if (Rest
.consume_front(":"))
1573 return {Check::CheckPlain
, Rest
};
1574 if (Rest
.front() == '{')
1575 return ConsumeModifiers(Check::CheckPlain
);
1577 if (Rest
.consume_front("_"))
1579 else if (!Rest
.consume_front("-"))
1580 return {Check::CheckNone
, StringRef()};
1582 if (Rest
.consume_front("COUNT-")) {
1584 if (Rest
.consumeInteger(10, Count
))
1585 // Error happened in parsing integer.
1586 return {Check::CheckBadCount
, Rest
};
1587 if (Count
<= 0 || Count
> INT32_MAX
)
1588 return {Check::CheckBadCount
, Rest
};
1589 if (Rest
.front() != ':' && Rest
.front() != '{')
1590 return {Check::CheckBadCount
, Rest
};
1591 return ConsumeModifiers(
1592 Check::FileCheckType(Check::CheckPlain
).setCount(Count
));
1595 // You can't combine -NOT with another suffix.
1596 if (Rest
.starts_with("DAG-NOT:") || Rest
.starts_with("NOT-DAG:") ||
1597 Rest
.starts_with("NEXT-NOT:") || Rest
.starts_with("NOT-NEXT:") ||
1598 Rest
.starts_with("SAME-NOT:") || Rest
.starts_with("NOT-SAME:") ||
1599 Rest
.starts_with("EMPTY-NOT:") || Rest
.starts_with("NOT-EMPTY:"))
1600 return {Check::CheckBadNot
, Rest
};
1602 if (Rest
.consume_front("NEXT"))
1603 return ConsumeModifiers(Check::CheckNext
);
1605 if (Rest
.consume_front("SAME"))
1606 return ConsumeModifiers(Check::CheckSame
);
1608 if (Rest
.consume_front("NOT"))
1609 return ConsumeModifiers(Check::CheckNot
);
1611 if (Rest
.consume_front("DAG"))
1612 return ConsumeModifiers(Check::CheckDAG
);
1614 if (Rest
.consume_front("LABEL"))
1615 return ConsumeModifiers(Check::CheckLabel
);
1617 if (Rest
.consume_front("EMPTY"))
1618 return ConsumeModifiers(Check::CheckEmpty
);
1620 return {Check::CheckNone
, Rest
};
1623 static std::pair
<Check::FileCheckType
, StringRef
>
1624 FindCheckType(const FileCheckRequest
&Req
, StringRef Buffer
, StringRef Prefix
) {
1625 bool Misspelled
= false;
1626 auto Res
= FindCheckType(Req
, Buffer
, Prefix
, Misspelled
);
1627 if (Res
.first
!= Check::CheckNone
&& Misspelled
)
1628 return {Check::CheckMisspelled
, Res
.second
};
1632 // From the given position, find the next character after the word.
1633 static size_t SkipWord(StringRef Str
, size_t Loc
) {
1634 while (Loc
< Str
.size() && IsPartOfWord(Str
[Loc
]))
1639 static const char *DefaultCheckPrefixes
[] = {"CHECK"};
1640 static const char *DefaultCommentPrefixes
[] = {"COM", "RUN"};
1642 static void addDefaultPrefixes(FileCheckRequest
&Req
) {
1643 if (Req
.CheckPrefixes
.empty()) {
1644 for (const char *Prefix
: DefaultCheckPrefixes
)
1645 Req
.CheckPrefixes
.push_back(Prefix
);
1646 Req
.IsDefaultCheckPrefix
= true;
1648 if (Req
.CommentPrefixes
.empty())
1649 for (const char *Prefix
: DefaultCommentPrefixes
)
1650 Req
.CommentPrefixes
.push_back(Prefix
);
1653 struct PrefixMatcher
{
1654 /// Prefixes and their first occurrence past the current position.
1655 SmallVector
<std::pair
<StringRef
, size_t>> Prefixes
;
1658 PrefixMatcher(ArrayRef
<StringRef
> CheckPrefixes
,
1659 ArrayRef
<StringRef
> CommentPrefixes
, StringRef Input
)
1661 for (StringRef Prefix
: CheckPrefixes
)
1662 Prefixes
.push_back({Prefix
, Input
.find(Prefix
)});
1663 for (StringRef Prefix
: CommentPrefixes
)
1664 Prefixes
.push_back({Prefix
, Input
.find(Prefix
)});
1666 // Sort by descending length.
1667 llvm::sort(Prefixes
,
1668 [](auto A
, auto B
) { return A
.first
.size() > B
.first
.size(); });
1671 /// Find the next match of a prefix in Buffer.
1672 /// Returns empty StringRef if not found.
1673 StringRef
match(StringRef Buffer
) {
1674 assert(Buffer
.data() >= Input
.data() &&
1675 Buffer
.data() + Buffer
.size() == Input
.data() + Input
.size() &&
1676 "Buffer must be suffix of Input");
1678 size_t From
= Buffer
.data() - Input
.data();
1680 for (auto &[Prefix
, Pos
] : Prefixes
) {
1681 // If the last occurrence was before From, find the next one after From.
1683 Pos
= Input
.find(Prefix
, From
);
1684 // Find the first prefix with the lowest position.
1685 if (Pos
!= StringRef::npos
&&
1686 (Match
.empty() || size_t(Match
.data() - Input
.data()) > Pos
))
1687 Match
= StringRef(Input
.substr(Pos
, Prefix
.size()));
1693 /// Searches the buffer for the first prefix in the prefix regular expression.
1695 /// This searches the buffer using the provided regular expression, however it
1696 /// enforces constraints beyond that:
1697 /// 1) The found prefix must not be a suffix of something that looks like
1699 /// 2) The found prefix must be followed by a valid check type suffix using \c
1700 /// FindCheckType above.
1702 /// \returns a pair of StringRefs into the Buffer, which combines:
1703 /// - the first match of the regular expression to satisfy these two is
1705 /// otherwise an empty StringRef is returned to indicate failure.
1706 /// - buffer rewound to the location right after parsed suffix, for parsing
1707 /// to continue from
1709 /// If this routine returns a valid prefix, it will also shrink \p Buffer to
1710 /// start at the beginning of the returned prefix, increment \p LineNumber for
1711 /// each new line consumed from \p Buffer, and set \p CheckTy to the type of
1712 /// check found by examining the suffix.
1714 /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy
1716 static std::pair
<StringRef
, StringRef
>
1717 FindFirstMatchingPrefix(const FileCheckRequest
&Req
, PrefixMatcher
&Matcher
,
1718 StringRef
&Buffer
, unsigned &LineNumber
,
1719 Check::FileCheckType
&CheckTy
) {
1720 while (!Buffer
.empty()) {
1721 // Find the first (longest) prefix match.
1722 StringRef Prefix
= Matcher
.match(Buffer
);
1724 // No match at all, bail.
1725 return {StringRef(), StringRef()};
1727 assert(Prefix
.data() >= Buffer
.data() &&
1728 Prefix
.data() < Buffer
.data() + Buffer
.size() &&
1729 "Prefix doesn't start inside of buffer!");
1730 size_t Loc
= Prefix
.data() - Buffer
.data();
1731 StringRef Skipped
= Buffer
.substr(0, Loc
);
1732 Buffer
= Buffer
.drop_front(Loc
);
1733 LineNumber
+= Skipped
.count('\n');
1735 // Check that the matched prefix isn't a suffix of some other check-like
1737 // FIXME: This is a very ad-hoc check. it would be better handled in some
1738 // other way. Among other things it seems hard to distinguish between
1739 // intentional and unintentional uses of this feature.
1740 if (Skipped
.empty() || !IsPartOfWord(Skipped
.back())) {
1741 // Now extract the type.
1742 StringRef AfterSuffix
;
1743 std::tie(CheckTy
, AfterSuffix
) = FindCheckType(Req
, Buffer
, Prefix
);
1745 // If we've found a valid check type for this prefix, we're done.
1746 if (CheckTy
!= Check::CheckNone
)
1747 return {Prefix
, AfterSuffix
};
1750 // If we didn't successfully find a prefix, we need to skip this invalid
1751 // prefix and continue scanning. We directly skip the prefix that was
1752 // matched and any additional parts of that check-like word.
1753 Buffer
= Buffer
.drop_front(SkipWord(Buffer
, Prefix
.size()));
1756 // We ran out of buffer while skipping partial matches so give up.
1757 return {StringRef(), StringRef()};
1760 void FileCheckPatternContext::createLineVariable() {
1761 assert(!LineVariable
&& "@LINE pseudo numeric variable already created");
1762 StringRef LineName
= "@LINE";
1763 LineVariable
= makeNumericVariable(
1764 LineName
, ExpressionFormat(ExpressionFormat::Kind::Unsigned
));
1765 GlobalNumericVariableTable
[LineName
] = LineVariable
;
1768 FileCheck::FileCheck(FileCheckRequest Req
)
1769 : Req(Req
), PatternContext(std::make_unique
<FileCheckPatternContext
>()),
1770 CheckStrings(std::make_unique
<std::vector
<FileCheckString
>>()) {}
1772 FileCheck::~FileCheck() = default;
1774 bool FileCheck::readCheckFile(
1775 SourceMgr
&SM
, StringRef Buffer
,
1776 std::pair
<unsigned, unsigned> *ImpPatBufferIDRange
) {
1777 if (ImpPatBufferIDRange
)
1778 ImpPatBufferIDRange
->first
= ImpPatBufferIDRange
->second
= 0;
1781 PatternContext
->defineCmdlineVariables(Req
.GlobalDefines
, SM
);
1783 logAllUnhandledErrors(std::move(DefineError
), errs());
1787 PatternContext
->createLineVariable();
1789 std::vector
<FileCheckString::DagNotPrefixInfo
> ImplicitNegativeChecks
;
1790 for (StringRef PatternString
: Req
.ImplicitCheckNot
) {
1791 // Create a buffer with fake command line content in order to display the
1792 // command line option responsible for the specific implicit CHECK-NOT.
1793 std::string Prefix
= "-implicit-check-not='";
1794 std::string Suffix
= "'";
1795 std::unique_ptr
<MemoryBuffer
> CmdLine
= MemoryBuffer::getMemBufferCopy(
1796 (Prefix
+ PatternString
+ Suffix
).str(), "command line");
1798 StringRef PatternInBuffer
=
1799 CmdLine
->getBuffer().substr(Prefix
.size(), PatternString
.size());
1800 unsigned BufferID
= SM
.AddNewSourceBuffer(std::move(CmdLine
), SMLoc());
1801 if (ImpPatBufferIDRange
) {
1802 if (ImpPatBufferIDRange
->first
== ImpPatBufferIDRange
->second
) {
1803 ImpPatBufferIDRange
->first
= BufferID
;
1804 ImpPatBufferIDRange
->second
= BufferID
+ 1;
1806 assert(BufferID
== ImpPatBufferIDRange
->second
&&
1807 "expected consecutive source buffer IDs");
1808 ++ImpPatBufferIDRange
->second
;
1812 ImplicitNegativeChecks
.emplace_back(
1813 Pattern(Check::CheckNot
, PatternContext
.get()),
1814 StringRef("IMPLICIT-CHECK"));
1815 ImplicitNegativeChecks
.back().DagNotPat
.parsePattern(
1816 PatternInBuffer
, "IMPLICIT-CHECK", SM
, Req
);
1819 std::vector
<FileCheckString::DagNotPrefixInfo
> DagNotMatches
=
1820 ImplicitNegativeChecks
;
1821 // LineNumber keeps track of the line on which CheckPrefix instances are
1823 unsigned LineNumber
= 1;
1825 addDefaultPrefixes(Req
);
1826 PrefixMatcher
Matcher(Req
.CheckPrefixes
, Req
.CommentPrefixes
, Buffer
);
1827 std::set
<StringRef
> PrefixesNotFound(Req
.CheckPrefixes
.begin(),
1828 Req
.CheckPrefixes
.end());
1829 const size_t DistinctPrefixes
= PrefixesNotFound
.size();
1831 Check::FileCheckType CheckTy
;
1833 // See if a prefix occurs in the memory buffer.
1834 StringRef UsedPrefix
;
1835 StringRef AfterSuffix
;
1836 std::tie(UsedPrefix
, AfterSuffix
) =
1837 FindFirstMatchingPrefix(Req
, Matcher
, Buffer
, LineNumber
, CheckTy
);
1838 if (UsedPrefix
.empty())
1840 if (CheckTy
!= Check::CheckComment
)
1841 PrefixesNotFound
.erase(UsedPrefix
);
1843 assert(UsedPrefix
.data() == Buffer
.data() &&
1844 "Failed to move Buffer's start forward, or pointed prefix outside "
1846 assert(AfterSuffix
.data() >= Buffer
.data() &&
1847 AfterSuffix
.data() < Buffer
.data() + Buffer
.size() &&
1848 "Parsing after suffix doesn't start inside of buffer!");
1850 // Location to use for error messages.
1851 const char *UsedPrefixStart
= UsedPrefix
.data();
1853 // Skip the buffer to the end of parsed suffix (or just prefix, if no good
1854 // suffix was processed).
1855 Buffer
= AfterSuffix
.empty() ? Buffer
.drop_front(UsedPrefix
.size())
1858 // Complain about misspelled directives.
1859 if (CheckTy
== Check::CheckMisspelled
) {
1860 StringRef
UsedDirective(UsedPrefix
.data(),
1861 AfterSuffix
.data() - UsedPrefix
.data());
1862 SM
.PrintMessage(SMLoc::getFromPointer(UsedDirective
.data()),
1863 SourceMgr::DK_Error
,
1864 "misspelled directive '" + UsedDirective
+ "'");
1868 // Complain about useful-looking but unsupported suffixes.
1869 if (CheckTy
== Check::CheckBadNot
) {
1870 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Error
,
1871 "unsupported -NOT combo on prefix '" + UsedPrefix
+ "'");
1875 // Complain about invalid count specification.
1876 if (CheckTy
== Check::CheckBadCount
) {
1877 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Error
,
1878 "invalid count in -COUNT specification on prefix '" +
1883 // Okay, we found the prefix, yay. Remember the rest of the line, but ignore
1884 // leading whitespace.
1885 if (!(Req
.NoCanonicalizeWhiteSpace
&& Req
.MatchFullLines
))
1886 Buffer
= Buffer
.substr(Buffer
.find_first_not_of(" \t"));
1888 // Scan ahead to the end of line.
1889 size_t EOL
= Buffer
.find_first_of("\n\r");
1891 // Remember the location of the start of the pattern, for diagnostics.
1892 SMLoc PatternLoc
= SMLoc::getFromPointer(Buffer
.data());
1894 // Extract the pattern from the buffer.
1895 StringRef PatternBuffer
= Buffer
.substr(0, EOL
);
1896 Buffer
= Buffer
.substr(EOL
);
1898 // If this is a comment, we're done.
1899 if (CheckTy
== Check::CheckComment
)
1902 // Parse the pattern.
1903 Pattern
P(CheckTy
, PatternContext
.get(), LineNumber
);
1904 if (P
.parsePattern(PatternBuffer
, UsedPrefix
, SM
, Req
))
1907 // Verify that CHECK-LABEL lines do not define or use variables
1908 if ((CheckTy
== Check::CheckLabel
) && P
.hasVariable()) {
1910 SMLoc::getFromPointer(UsedPrefixStart
), SourceMgr::DK_Error
,
1911 "found '" + UsedPrefix
+ "-LABEL:'"
1912 " with variable definition or use");
1916 // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
1917 if ((CheckTy
== Check::CheckNext
|| CheckTy
== Check::CheckSame
||
1918 CheckTy
== Check::CheckEmpty
) &&
1919 CheckStrings
->empty()) {
1920 StringRef Type
= CheckTy
== Check::CheckNext
1922 : CheckTy
== Check::CheckEmpty
? "EMPTY" : "SAME";
1923 SM
.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart
),
1924 SourceMgr::DK_Error
,
1925 "found '" + UsedPrefix
+ "-" + Type
+
1926 "' without previous '" + UsedPrefix
+ ": line");
1930 // Handle CHECK-DAG/-NOT.
1931 if (CheckTy
== Check::CheckDAG
|| CheckTy
== Check::CheckNot
) {
1932 DagNotMatches
.emplace_back(P
, UsedPrefix
);
1936 // Okay, add the string we captured to the output vector and move on.
1937 CheckStrings
->emplace_back(P
, UsedPrefix
, PatternLoc
);
1938 std::swap(DagNotMatches
, CheckStrings
->back().DagNotStrings
);
1939 DagNotMatches
= ImplicitNegativeChecks
;
1942 // When there are no used prefixes we report an error except in the case that
1943 // no prefix is specified explicitly but -implicit-check-not is specified.
1944 const bool NoPrefixesFound
= PrefixesNotFound
.size() == DistinctPrefixes
;
1945 const bool SomePrefixesUnexpectedlyNotUsed
=
1946 !Req
.AllowUnusedPrefixes
&& !PrefixesNotFound
.empty();
1947 if ((NoPrefixesFound
|| SomePrefixesUnexpectedlyNotUsed
) &&
1948 (ImplicitNegativeChecks
.empty() || !Req
.IsDefaultCheckPrefix
)) {
1949 errs() << "error: no check strings found with prefix"
1950 << (PrefixesNotFound
.size() > 1 ? "es " : " ");
1952 for (StringRef MissingPrefix
: PrefixesNotFound
) {
1955 errs() << "\'" << MissingPrefix
<< ":'";
1962 // Add an EOF pattern for any trailing --implicit-check-not/CHECK-DAG/-NOTs,
1963 // and use the first prefix as a filler for the error message.
1964 if (!DagNotMatches
.empty()) {
1965 CheckStrings
->emplace_back(
1966 Pattern(Check::CheckEOF
, PatternContext
.get(), LineNumber
+ 1),
1967 *Req
.CheckPrefixes
.begin(), SMLoc::getFromPointer(Buffer
.data()));
1968 std::swap(DagNotMatches
, CheckStrings
->back().DagNotStrings
);
1974 /// Returns either (1) \c ErrorSuccess if there was no error or (2)
1975 /// \c ErrorReported if an error was reported, such as an unexpected match.
1976 static Error
printMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
1977 StringRef Prefix
, SMLoc Loc
, const Pattern
&Pat
,
1978 int MatchedCount
, StringRef Buffer
,
1979 Pattern::MatchResult MatchResult
,
1980 const FileCheckRequest
&Req
,
1981 std::vector
<FileCheckDiag
> *Diags
) {
1982 // Suppress some verbosity if there's no error.
1983 bool HasError
= !ExpectedMatch
|| MatchResult
.TheError
;
1984 bool PrintDiag
= true;
1987 return ErrorReported::reportedOrSuccess(HasError
);
1988 if (!Req
.VerboseVerbose
&& Pat
.getCheckTy() == Check::CheckEOF
)
1989 return ErrorReported::reportedOrSuccess(HasError
);
1990 // Due to their verbosity, we don't print verbose diagnostics here if we're
1991 // gathering them for Diags to be rendered elsewhere, but we always print
1992 // other diagnostics.
1996 // Add "found" diagnostic, substitutions, and variable definitions to Diags.
1997 FileCheckDiag::MatchType MatchTy
= ExpectedMatch
1998 ? FileCheckDiag::MatchFoundAndExpected
1999 : FileCheckDiag::MatchFoundButExcluded
;
2000 SMRange MatchRange
= ProcessMatchResult(MatchTy
, SM
, Loc
, Pat
.getCheckTy(),
2001 Buffer
, MatchResult
.TheMatch
->Pos
,
2002 MatchResult
.TheMatch
->Len
, Diags
);
2004 Pat
.printSubstitutions(SM
, Buffer
, MatchRange
, MatchTy
, Diags
);
2005 Pat
.printVariableDefs(SM
, MatchTy
, Diags
);
2008 assert(!HasError
&& "expected to report more diagnostics for error");
2009 return ErrorReported::reportedOrSuccess(HasError
);
2013 std::string Message
= formatv("{0}: {1} string found in input",
2014 Pat
.getCheckTy().getDescription(Prefix
),
2015 (ExpectedMatch
? "expected" : "excluded"))
2017 if (Pat
.getCount() > 1)
2018 Message
+= formatv(" ({0} out of {1})", MatchedCount
, Pat
.getCount()).str();
2020 Loc
, ExpectedMatch
? SourceMgr::DK_Remark
: SourceMgr::DK_Error
, Message
);
2021 SM
.PrintMessage(MatchRange
.Start
, SourceMgr::DK_Note
, "found here",
2024 // Print additional information, which can be useful even if there are errors.
2025 Pat
.printSubstitutions(SM
, Buffer
, MatchRange
, MatchTy
, nullptr);
2026 Pat
.printVariableDefs(SM
, MatchTy
, nullptr);
2028 // Print errors and add them to Diags. We report these errors after the match
2029 // itself because we found them after the match. If we had found them before
2030 // the match, we'd be in printNoMatch.
2031 handleAllErrors(std::move(MatchResult
.TheError
),
2032 [&](const ErrorDiagnostic
&E
) {
2035 Diags
->emplace_back(SM
, Pat
.getCheckTy(), Loc
,
2036 FileCheckDiag::MatchFoundErrorNote
,
2037 E
.getRange(), E
.getMessage().str());
2040 return ErrorReported::reportedOrSuccess(HasError
);
2043 /// Returns either (1) \c ErrorSuccess if there was no error, or (2)
2044 /// \c ErrorReported if an error was reported, such as an expected match not
2046 static Error
printNoMatch(bool ExpectedMatch
, const SourceMgr
&SM
,
2047 StringRef Prefix
, SMLoc Loc
, const Pattern
&Pat
,
2048 int MatchedCount
, StringRef Buffer
, Error MatchError
,
2049 bool VerboseVerbose
,
2050 std::vector
<FileCheckDiag
> *Diags
) {
2051 // Print any pattern errors, and record them to be added to Diags later.
2052 bool HasError
= ExpectedMatch
;
2053 bool HasPatternError
= false;
2054 FileCheckDiag::MatchType MatchTy
= ExpectedMatch
2055 ? FileCheckDiag::MatchNoneButExpected
2056 : FileCheckDiag::MatchNoneAndExcluded
;
2057 SmallVector
<std::string
, 4> ErrorMsgs
;
2059 std::move(MatchError
),
2060 [&](const ErrorDiagnostic
&E
) {
2061 HasError
= HasPatternError
= true;
2062 MatchTy
= FileCheckDiag::MatchNoneForInvalidPattern
;
2065 ErrorMsgs
.push_back(E
.getMessage().str());
2067 // NotFoundError is why printNoMatch was invoked.
2068 [](const NotFoundError
&E
) {});
2070 // Suppress some verbosity if there's no error.
2071 bool PrintDiag
= true;
2073 if (!VerboseVerbose
)
2074 return ErrorReported::reportedOrSuccess(HasError
);
2075 // Due to their verbosity, we don't print verbose diagnostics here if we're
2076 // gathering them for Diags to be rendered elsewhere, but we always print
2077 // other diagnostics.
2081 // Add "not found" diagnostic, substitutions, and pattern errors to Diags.
2083 // We handle Diags a little differently than the errors we print directly:
2084 // we add the "not found" diagnostic to Diags even if there are pattern
2085 // errors. The reason is that we need to attach pattern errors as notes
2086 // somewhere in the input, and the input search range from the "not found"
2087 // diagnostic is all we have to anchor them.
2088 SMRange SearchRange
= ProcessMatchResult(MatchTy
, SM
, Loc
, Pat
.getCheckTy(),
2089 Buffer
, 0, Buffer
.size(), Diags
);
2091 SMRange NoteRange
= SMRange(SearchRange
.Start
, SearchRange
.Start
);
2092 for (StringRef ErrorMsg
: ErrorMsgs
)
2093 Diags
->emplace_back(SM
, Pat
.getCheckTy(), Loc
, MatchTy
, NoteRange
,
2095 Pat
.printSubstitutions(SM
, Buffer
, SearchRange
, MatchTy
, Diags
);
2098 assert(!HasError
&& "expected to report more diagnostics for error");
2099 return ErrorReported::reportedOrSuccess(HasError
);
2102 // Print "not found" diagnostic, except that's implied if we already printed a
2104 if (!HasPatternError
) {
2105 std::string Message
= formatv("{0}: {1} string not found in input",
2106 Pat
.getCheckTy().getDescription(Prefix
),
2107 (ExpectedMatch
? "expected" : "excluded"))
2109 if (Pat
.getCount() > 1)
2111 formatv(" ({0} out of {1})", MatchedCount
, Pat
.getCount()).str();
2112 SM
.PrintMessage(Loc
,
2113 ExpectedMatch
? SourceMgr::DK_Error
: SourceMgr::DK_Remark
,
2115 SM
.PrintMessage(SearchRange
.Start
, SourceMgr::DK_Note
,
2116 "scanning from here");
2119 // Print additional information, which can be useful even after a pattern
2121 Pat
.printSubstitutions(SM
, Buffer
, SearchRange
, MatchTy
, nullptr);
2123 Pat
.printFuzzyMatch(SM
, Buffer
, Diags
);
2124 return ErrorReported::reportedOrSuccess(HasError
);
2127 /// Returns either (1) \c ErrorSuccess if there was no error, or (2)
2128 /// \c ErrorReported if an error was reported.
2129 static Error
reportMatchResult(bool ExpectedMatch
, const SourceMgr
&SM
,
2130 StringRef Prefix
, SMLoc Loc
, const Pattern
&Pat
,
2131 int MatchedCount
, StringRef Buffer
,
2132 Pattern::MatchResult MatchResult
,
2133 const FileCheckRequest
&Req
,
2134 std::vector
<FileCheckDiag
> *Diags
) {
2135 if (MatchResult
.TheMatch
)
2136 return printMatch(ExpectedMatch
, SM
, Prefix
, Loc
, Pat
, MatchedCount
, Buffer
,
2137 std::move(MatchResult
), Req
, Diags
);
2138 return printNoMatch(ExpectedMatch
, SM
, Prefix
, Loc
, Pat
, MatchedCount
, Buffer
,
2139 std::move(MatchResult
.TheError
), Req
.VerboseVerbose
,
2143 /// Counts the number of newlines in the specified range.
2144 static unsigned CountNumNewlinesBetween(StringRef Range
,
2145 const char *&FirstNewLine
) {
2146 unsigned NumNewLines
= 0;
2148 // Scan for newline.
2149 Range
= Range
.substr(Range
.find_first_of("\n\r"));
2155 // Handle \n\r and \r\n as a single newline.
2156 if (Range
.size() > 1 && (Range
[1] == '\n' || Range
[1] == '\r') &&
2157 (Range
[0] != Range
[1]))
2158 Range
= Range
.substr(1);
2159 Range
= Range
.substr(1);
2161 if (NumNewLines
== 1)
2162 FirstNewLine
= Range
.begin();
2166 size_t FileCheckString::Check(const SourceMgr
&SM
, StringRef Buffer
,
2167 bool IsLabelScanMode
, size_t &MatchLen
,
2168 FileCheckRequest
&Req
,
2169 std::vector
<FileCheckDiag
> *Diags
) const {
2171 std::vector
<const DagNotPrefixInfo
*> NotStrings
;
2173 // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
2174 // bounds; we have not processed variable definitions within the bounded block
2175 // yet so cannot handle any final CHECK-DAG yet; this is handled when going
2176 // over the block again (including the last CHECK-LABEL) in normal mode.
2177 if (!IsLabelScanMode
) {
2178 // Match "dag strings" (with mixed "not strings" if any).
2179 LastPos
= CheckDag(SM
, Buffer
, NotStrings
, Req
, Diags
);
2180 if (LastPos
== StringRef::npos
)
2181 return StringRef::npos
;
2184 // Match itself from the last position after matching CHECK-DAG.
2185 size_t LastMatchEnd
= LastPos
;
2186 size_t FirstMatchPos
= 0;
2187 // Go match the pattern Count times. Majority of patterns only match with
2189 assert(Pat
.getCount() != 0 && "pattern count can not be zero");
2190 for (int i
= 1; i
<= Pat
.getCount(); i
++) {
2191 StringRef MatchBuffer
= Buffer
.substr(LastMatchEnd
);
2192 // get a match at current start point
2193 Pattern::MatchResult MatchResult
= Pat
.match(MatchBuffer
, SM
);
2196 if (Error Err
= reportMatchResult(/*ExpectedMatch=*/true, SM
, Prefix
, Loc
,
2197 Pat
, i
, MatchBuffer
,
2198 std::move(MatchResult
), Req
, Diags
)) {
2199 cantFail(handleErrors(std::move(Err
), [&](const ErrorReported
&E
) {}));
2200 return StringRef::npos
;
2203 size_t MatchPos
= MatchResult
.TheMatch
->Pos
;
2205 FirstMatchPos
= LastPos
+ MatchPos
;
2207 // move start point after the match
2208 LastMatchEnd
+= MatchPos
+ MatchResult
.TheMatch
->Len
;
2210 // Full match len counts from first match pos.
2211 MatchLen
= LastMatchEnd
- FirstMatchPos
;
2213 // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
2215 if (!IsLabelScanMode
) {
2216 size_t MatchPos
= FirstMatchPos
- LastPos
;
2217 StringRef MatchBuffer
= Buffer
.substr(LastPos
);
2218 StringRef SkippedRegion
= Buffer
.substr(LastPos
, MatchPos
);
2220 // If this check is a "CHECK-NEXT", verify that the previous match was on
2221 // the previous line (i.e. that there is one newline between them).
2222 if (CheckNext(SM
, SkippedRegion
)) {
2223 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine
, SM
, Loc
,
2224 Pat
.getCheckTy(), MatchBuffer
, MatchPos
, MatchLen
,
2225 Diags
, Req
.Verbose
);
2226 return StringRef::npos
;
2229 // If this check is a "CHECK-SAME", verify that the previous match was on
2230 // the same line (i.e. that there is no newline between them).
2231 if (CheckSame(SM
, SkippedRegion
)) {
2232 ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine
, SM
, Loc
,
2233 Pat
.getCheckTy(), MatchBuffer
, MatchPos
, MatchLen
,
2234 Diags
, Req
.Verbose
);
2235 return StringRef::npos
;
2238 // If this match had "not strings", verify that they don't exist in the
2240 if (CheckNot(SM
, SkippedRegion
, NotStrings
, Req
, Diags
))
2241 return StringRef::npos
;
2244 return FirstMatchPos
;
2247 bool FileCheckString::CheckNext(const SourceMgr
&SM
, StringRef Buffer
) const {
2248 if (Pat
.getCheckTy() != Check::CheckNext
&&
2249 Pat
.getCheckTy() != Check::CheckEmpty
)
2254 Twine(Pat
.getCheckTy() == Check::CheckEmpty
? "-EMPTY" : "-NEXT");
2256 // Count the number of newlines between the previous match and this one.
2257 const char *FirstNewLine
= nullptr;
2258 unsigned NumNewLines
= CountNumNewlinesBetween(Buffer
, FirstNewLine
);
2260 if (NumNewLines
== 0) {
2261 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
2262 CheckName
+ ": is on the same line as previous match");
2263 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
2264 "'next' match was here");
2265 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
2266 "previous match ended here");
2270 if (NumNewLines
!= 1) {
2271 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
2273 ": is not on the line after the previous match");
2274 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
2275 "'next' match was here");
2276 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
2277 "previous match ended here");
2278 SM
.PrintMessage(SMLoc::getFromPointer(FirstNewLine
), SourceMgr::DK_Note
,
2279 "non-matching line after previous match is here");
2286 bool FileCheckString::CheckSame(const SourceMgr
&SM
, StringRef Buffer
) const {
2287 if (Pat
.getCheckTy() != Check::CheckSame
)
2290 // Count the number of newlines between the previous match and this one.
2291 const char *FirstNewLine
= nullptr;
2292 unsigned NumNewLines
= CountNumNewlinesBetween(Buffer
, FirstNewLine
);
2294 if (NumNewLines
!= 0) {
2295 SM
.PrintMessage(Loc
, SourceMgr::DK_Error
,
2297 "-SAME: is not on the same line as the previous match");
2298 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.end()), SourceMgr::DK_Note
,
2299 "'next' match was here");
2300 SM
.PrintMessage(SMLoc::getFromPointer(Buffer
.data()), SourceMgr::DK_Note
,
2301 "previous match ended here");
2308 bool FileCheckString::CheckNot(
2309 const SourceMgr
&SM
, StringRef Buffer
,
2310 const std::vector
<const DagNotPrefixInfo
*> &NotStrings
,
2311 const FileCheckRequest
&Req
, std::vector
<FileCheckDiag
> *Diags
) const {
2312 bool DirectiveFail
= false;
2313 for (auto NotInfo
: NotStrings
) {
2314 assert((NotInfo
->DagNotPat
.getCheckTy() == Check::CheckNot
) &&
2315 "Expect CHECK-NOT!");
2316 Pattern::MatchResult MatchResult
= NotInfo
->DagNotPat
.match(Buffer
, SM
);
2317 if (Error Err
= reportMatchResult(
2318 /*ExpectedMatch=*/false, SM
, NotInfo
->DagNotPrefix
,
2319 NotInfo
->DagNotPat
.getLoc(), NotInfo
->DagNotPat
, 1, Buffer
,
2320 std::move(MatchResult
), Req
, Diags
)) {
2321 cantFail(handleErrors(std::move(Err
), [&](const ErrorReported
&E
) {}));
2322 DirectiveFail
= true;
2326 return DirectiveFail
;
2330 FileCheckString::CheckDag(const SourceMgr
&SM
, StringRef Buffer
,
2331 std::vector
<const DagNotPrefixInfo
*> &NotStrings
,
2332 const FileCheckRequest
&Req
,
2333 std::vector
<FileCheckDiag
> *Diags
) const {
2334 if (DagNotStrings
.empty())
2337 // The start of the search range.
2338 size_t StartPos
= 0;
2344 // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
2345 // ranges are erased from this list once they are no longer in the search
2347 std::list
<MatchRange
> MatchRanges
;
2349 // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
2350 // group, so we don't use a range-based for loop here.
2351 for (auto PatItr
= DagNotStrings
.begin(), PatEnd
= DagNotStrings
.end();
2352 PatItr
!= PatEnd
; ++PatItr
) {
2353 const Pattern
&Pat
= PatItr
->DagNotPat
;
2354 const StringRef DNPrefix
= PatItr
->DagNotPrefix
;
2355 assert((Pat
.getCheckTy() == Check::CheckDAG
||
2356 Pat
.getCheckTy() == Check::CheckNot
) &&
2357 "Invalid CHECK-DAG or CHECK-NOT!");
2359 if (Pat
.getCheckTy() == Check::CheckNot
) {
2360 NotStrings
.push_back(&*PatItr
);
2364 assert((Pat
.getCheckTy() == Check::CheckDAG
) && "Expect CHECK-DAG!");
2366 // CHECK-DAG always matches from the start.
2367 size_t MatchLen
= 0, MatchPos
= StartPos
;
2369 // Search for a match that doesn't overlap a previous match in this
2371 for (auto MI
= MatchRanges
.begin(), ME
= MatchRanges
.end(); true; ++MI
) {
2372 StringRef MatchBuffer
= Buffer
.substr(MatchPos
);
2373 Pattern::MatchResult MatchResult
= Pat
.match(MatchBuffer
, SM
);
2374 // With a group of CHECK-DAGs, a single mismatching means the match on
2375 // that group of CHECK-DAGs fails immediately.
2376 if (MatchResult
.TheError
|| Req
.VerboseVerbose
) {
2377 if (Error Err
= reportMatchResult(/*ExpectedMatch=*/true, SM
, DNPrefix
,
2378 Pat
.getLoc(), Pat
, 1, MatchBuffer
,
2379 std::move(MatchResult
), Req
, Diags
)) {
2381 handleErrors(std::move(Err
), [&](const ErrorReported
&E
) {}));
2382 return StringRef::npos
;
2385 MatchLen
= MatchResult
.TheMatch
->Len
;
2386 // Re-calc it as the offset relative to the start of the original
2388 MatchPos
+= MatchResult
.TheMatch
->Pos
;
2389 MatchRange M
{MatchPos
, MatchPos
+ MatchLen
};
2390 if (Req
.AllowDeprecatedDagOverlap
) {
2391 // We don't need to track all matches in this mode, so we just maintain
2392 // one match range that encompasses the current CHECK-DAG group's
2394 if (MatchRanges
.empty())
2395 MatchRanges
.insert(MatchRanges
.end(), M
);
2397 auto Block
= MatchRanges
.begin();
2398 Block
->Pos
= std::min(Block
->Pos
, M
.Pos
);
2399 Block
->End
= std::max(Block
->End
, M
.End
);
2403 // Iterate previous matches until overlapping match or insertion point.
2404 bool Overlap
= false;
2405 for (; MI
!= ME
; ++MI
) {
2406 if (M
.Pos
< MI
->End
) {
2407 // !Overlap => New match has no overlap and is before this old match.
2408 // Overlap => New match overlaps this old match.
2409 Overlap
= MI
->Pos
< M
.End
;
2414 // Insert non-overlapping match into list.
2415 MatchRanges
.insert(MI
, M
);
2418 if (Req
.VerboseVerbose
) {
2419 // Due to their verbosity, we don't print verbose diagnostics here if
2420 // we're gathering them for a different rendering, but we always print
2421 // other diagnostics.
2423 SMLoc OldStart
= SMLoc::getFromPointer(Buffer
.data() + MI
->Pos
);
2424 SMLoc OldEnd
= SMLoc::getFromPointer(Buffer
.data() + MI
->End
);
2425 SMRange
OldRange(OldStart
, OldEnd
);
2426 SM
.PrintMessage(OldStart
, SourceMgr::DK_Note
,
2427 "match discarded, overlaps earlier DAG match here",
2430 SMLoc CheckLoc
= Diags
->rbegin()->CheckLoc
;
2431 for (auto I
= Diags
->rbegin(), E
= Diags
->rend();
2432 I
!= E
&& I
->CheckLoc
== CheckLoc
; ++I
)
2433 I
->MatchTy
= FileCheckDiag::MatchFoundButDiscarded
;
2438 if (!Req
.VerboseVerbose
)
2439 cantFail(printMatch(
2440 /*ExpectedMatch=*/true, SM
, DNPrefix
, Pat
.getLoc(), Pat
, 1, Buffer
,
2441 Pattern::MatchResult(MatchPos
, MatchLen
, Error::success()), Req
,
2444 // Handle the end of a CHECK-DAG group.
2445 if (std::next(PatItr
) == PatEnd
||
2446 std::next(PatItr
)->DagNotPat
.getCheckTy() == Check::CheckNot
) {
2447 if (!NotStrings
.empty()) {
2448 // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
2449 // CHECK-DAG, verify that there are no 'not' strings occurred in that
2451 StringRef SkippedRegion
=
2452 Buffer
.slice(StartPos
, MatchRanges
.begin()->Pos
);
2453 if (CheckNot(SM
, SkippedRegion
, NotStrings
, Req
, Diags
))
2454 return StringRef::npos
;
2455 // Clear "not strings".
2458 // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
2459 // end of this CHECK-DAG group's match range.
2460 StartPos
= MatchRanges
.rbegin()->End
;
2461 // Don't waste time checking for (impossible) overlaps before that.
2462 MatchRanges
.clear();
2469 static bool ValidatePrefixes(StringRef Kind
, StringSet
<> &UniquePrefixes
,
2470 ArrayRef
<StringRef
> SuppliedPrefixes
) {
2471 for (StringRef Prefix
: SuppliedPrefixes
) {
2472 if (Prefix
.empty()) {
2473 errs() << "error: supplied " << Kind
<< " prefix must not be the empty "
2477 static const Regex
Validator("^[a-zA-Z0-9_-]*$");
2478 if (!Validator
.match(Prefix
)) {
2479 errs() << "error: supplied " << Kind
<< " prefix must start with a "
2480 << "letter and contain only alphanumeric characters, hyphens, and "
2481 << "underscores: '" << Prefix
<< "'\n";
2484 if (!UniquePrefixes
.insert(Prefix
).second
) {
2485 errs() << "error: supplied " << Kind
<< " prefix must be unique among "
2486 << "check and comment prefixes: '" << Prefix
<< "'\n";
2493 bool FileCheck::ValidateCheckPrefixes() {
2494 StringSet
<> UniquePrefixes
;
2495 // Add default prefixes to catch user-supplied duplicates of them below.
2496 if (Req
.CheckPrefixes
.empty()) {
2497 for (const char *Prefix
: DefaultCheckPrefixes
)
2498 UniquePrefixes
.insert(Prefix
);
2500 if (Req
.CommentPrefixes
.empty()) {
2501 for (const char *Prefix
: DefaultCommentPrefixes
)
2502 UniquePrefixes
.insert(Prefix
);
2504 // Do not validate the default prefixes, or diagnostics about duplicates might
2505 // incorrectly indicate that they were supplied by the user.
2506 if (!ValidatePrefixes("check", UniquePrefixes
, Req
.CheckPrefixes
))
2508 if (!ValidatePrefixes("comment", UniquePrefixes
, Req
.CommentPrefixes
))
2513 Error
FileCheckPatternContext::defineCmdlineVariables(
2514 ArrayRef
<StringRef
> CmdlineDefines
, SourceMgr
&SM
) {
2515 assert(GlobalVariableTable
.empty() && GlobalNumericVariableTable
.empty() &&
2516 "Overriding defined variable with command-line variable definitions");
2518 if (CmdlineDefines
.empty())
2519 return Error::success();
2521 // Create a string representing the vector of command-line definitions. Each
2522 // definition is on its own line and prefixed with a definition number to
2523 // clarify which definition a given diagnostic corresponds to.
2525 Error Errs
= Error::success();
2526 std::string CmdlineDefsDiag
;
2527 SmallVector
<std::pair
<size_t, size_t>, 4> CmdlineDefsIndices
;
2528 for (StringRef CmdlineDef
: CmdlineDefines
) {
2529 std::string DefPrefix
= ("Global define #" + Twine(++I
) + ": ").str();
2530 size_t EqIdx
= CmdlineDef
.find('=');
2531 if (EqIdx
== StringRef::npos
) {
2532 CmdlineDefsIndices
.push_back(std::make_pair(CmdlineDefsDiag
.size(), 0));
2535 // Numeric variable definition.
2536 if (CmdlineDef
[0] == '#') {
2537 // Append a copy of the command-line definition adapted to use the same
2538 // format as in the input file to be able to reuse
2539 // parseNumericSubstitutionBlock.
2540 CmdlineDefsDiag
+= (DefPrefix
+ CmdlineDef
+ " (parsed as: [[").str();
2541 std::string SubstitutionStr
= std::string(CmdlineDef
);
2542 SubstitutionStr
[EqIdx
] = ':';
2543 CmdlineDefsIndices
.push_back(
2544 std::make_pair(CmdlineDefsDiag
.size(), SubstitutionStr
.size()));
2545 CmdlineDefsDiag
+= (SubstitutionStr
+ Twine("]])\n")).str();
2547 CmdlineDefsDiag
+= DefPrefix
;
2548 CmdlineDefsIndices
.push_back(
2549 std::make_pair(CmdlineDefsDiag
.size(), CmdlineDef
.size()));
2550 CmdlineDefsDiag
+= (CmdlineDef
+ "\n").str();
2554 // Create a buffer with fake command line content in order to display
2555 // parsing diagnostic with location information and point to the
2556 // global definition with invalid syntax.
2557 std::unique_ptr
<MemoryBuffer
> CmdLineDefsDiagBuffer
=
2558 MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag
, "Global defines");
2559 StringRef CmdlineDefsDiagRef
= CmdLineDefsDiagBuffer
->getBuffer();
2560 SM
.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer
), SMLoc());
2562 for (std::pair
<size_t, size_t> CmdlineDefIndices
: CmdlineDefsIndices
) {
2563 StringRef CmdlineDef
= CmdlineDefsDiagRef
.substr(CmdlineDefIndices
.first
,
2564 CmdlineDefIndices
.second
);
2565 if (CmdlineDef
.empty()) {
2568 ErrorDiagnostic::get(SM
, CmdlineDef
,
2569 "missing equal sign in global definition"));
2573 // Numeric variable definition.
2574 if (CmdlineDef
[0] == '#') {
2575 // Now parse the definition both to check that the syntax is correct and
2576 // to create the necessary class instance.
2577 StringRef CmdlineDefExpr
= CmdlineDef
.substr(1);
2578 std::optional
<NumericVariable
*> DefinedNumericVariable
;
2579 Expected
<std::unique_ptr
<Expression
>> ExpressionResult
=
2580 Pattern::parseNumericSubstitutionBlock(CmdlineDefExpr
,
2581 DefinedNumericVariable
, false,
2582 std::nullopt
, this, SM
);
2583 if (!ExpressionResult
) {
2584 Errs
= joinErrors(std::move(Errs
), ExpressionResult
.takeError());
2587 std::unique_ptr
<Expression
> Expression
= std::move(*ExpressionResult
);
2588 // Now evaluate the expression whose value this variable should be set
2589 // to, since the expression of a command-line variable definition should
2590 // only use variables defined earlier on the command-line. If not, this
2591 // is an error and we report it.
2592 Expected
<APInt
> Value
= Expression
->getAST()->eval();
2594 Errs
= joinErrors(std::move(Errs
), Value
.takeError());
2598 assert(DefinedNumericVariable
&& "No variable defined");
2599 (*DefinedNumericVariable
)->setValue(*Value
);
2601 // Record this variable definition.
2602 GlobalNumericVariableTable
[(*DefinedNumericVariable
)->getName()] =
2603 *DefinedNumericVariable
;
2605 // String variable definition.
2606 std::pair
<StringRef
, StringRef
> CmdlineNameVal
= CmdlineDef
.split('=');
2607 StringRef CmdlineName
= CmdlineNameVal
.first
;
2608 StringRef OrigCmdlineName
= CmdlineName
;
2609 Expected
<Pattern::VariableProperties
> ParseVarResult
=
2610 Pattern::parseVariable(CmdlineName
, SM
);
2611 if (!ParseVarResult
) {
2612 Errs
= joinErrors(std::move(Errs
), ParseVarResult
.takeError());
2615 // Check that CmdlineName does not denote a pseudo variable is only
2616 // composed of the parsed numeric variable. This catches cases like
2617 // "FOO+2" in a "FOO+2=10" definition.
2618 if (ParseVarResult
->IsPseudo
|| !CmdlineName
.empty()) {
2619 Errs
= joinErrors(std::move(Errs
),
2620 ErrorDiagnostic::get(
2621 SM
, OrigCmdlineName
,
2622 "invalid name in string variable definition '" +
2623 OrigCmdlineName
+ "'"));
2626 StringRef Name
= ParseVarResult
->Name
;
2628 // Detect collisions between string and numeric variables when the former
2629 // is created later than the latter.
2630 if (GlobalNumericVariableTable
.contains(Name
)) {
2631 Errs
= joinErrors(std::move(Errs
),
2632 ErrorDiagnostic::get(SM
, Name
,
2633 "numeric variable with name '" +
2634 Name
+ "' already exists"));
2637 GlobalVariableTable
.insert(CmdlineNameVal
);
2638 // Mark the string variable as defined to detect collisions between
2639 // string and numeric variables in defineCmdlineVariables when the latter
2640 // is created later than the former. We cannot reuse GlobalVariableTable
2641 // for this by populating it with an empty string since we would then
2642 // lose the ability to detect the use of an undefined variable in
2644 DefinedVariableTable
[Name
] = true;
2651 void FileCheckPatternContext::clearLocalVars() {
2652 SmallVector
<StringRef
, 16> LocalPatternVars
, LocalNumericVars
;
2653 for (const StringMapEntry
<StringRef
> &Var
: GlobalVariableTable
)
2654 if (Var
.first()[0] != '$')
2655 LocalPatternVars
.push_back(Var
.first());
2657 // Numeric substitution reads the value of a variable directly, not via
2658 // GlobalNumericVariableTable. Therefore, we clear local variables by
2659 // clearing their value which will lead to a numeric substitution failure. We
2660 // also mark the variable for removal from GlobalNumericVariableTable since
2661 // this is what defineCmdlineVariables checks to decide that no global
2662 // variable has been defined.
2663 for (const auto &Var
: GlobalNumericVariableTable
)
2664 if (Var
.first()[0] != '$') {
2665 Var
.getValue()->clearValue();
2666 LocalNumericVars
.push_back(Var
.first());
2669 for (const auto &Var
: LocalPatternVars
)
2670 GlobalVariableTable
.erase(Var
);
2671 for (const auto &Var
: LocalNumericVars
)
2672 GlobalNumericVariableTable
.erase(Var
);
2675 bool FileCheck::checkInput(SourceMgr
&SM
, StringRef Buffer
,
2676 std::vector
<FileCheckDiag
> *Diags
) {
2677 bool ChecksFailed
= false;
2679 unsigned i
= 0, j
= 0, e
= CheckStrings
->size();
2681 StringRef CheckRegion
;
2683 CheckRegion
= Buffer
;
2685 const FileCheckString
&CheckLabelStr
= (*CheckStrings
)[j
];
2686 if (CheckLabelStr
.Pat
.getCheckTy() != Check::CheckLabel
) {
2691 // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG
2692 size_t MatchLabelLen
= 0;
2693 size_t MatchLabelPos
=
2694 CheckLabelStr
.Check(SM
, Buffer
, true, MatchLabelLen
, Req
, Diags
);
2695 if (MatchLabelPos
== StringRef::npos
)
2696 // Immediately bail if CHECK-LABEL fails, nothing else we can do.
2699 CheckRegion
= Buffer
.substr(0, MatchLabelPos
+ MatchLabelLen
);
2700 Buffer
= Buffer
.substr(MatchLabelPos
+ MatchLabelLen
);
2704 // Do not clear the first region as it's the one before the first
2705 // CHECK-LABEL and it would clear variables defined on the command-line
2706 // before they get used.
2707 if (i
!= 0 && Req
.EnableVarScope
)
2708 PatternContext
->clearLocalVars();
2710 for (; i
!= j
; ++i
) {
2711 const FileCheckString
&CheckStr
= (*CheckStrings
)[i
];
2713 // Check each string within the scanned region, including a second check
2714 // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG)
2715 size_t MatchLen
= 0;
2717 CheckStr
.Check(SM
, CheckRegion
, false, MatchLen
, Req
, Diags
);
2719 if (MatchPos
== StringRef::npos
) {
2720 ChecksFailed
= true;
2725 CheckRegion
= CheckRegion
.substr(MatchPos
+ MatchLen
);
2732 // Success if no checks failed.
2733 return !ChecksFailed
;